Skip to content

Commit edc814d

Browse files
committed
AbstractLogService: extract class DefaultLogger
This provides an implementation of Logger that can be used independently from AbstractLogService. It will be useful for the implementation of sub loggers.
1 parent 9b908a7 commit edc814d

File tree

5 files changed

+177
-14
lines changed

5 files changed

+177
-14
lines changed

src/main/java/org/scijava/log/AbstractLogService.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@
3333
package org.scijava.log;
3434

3535
import java.util.HashMap;
36-
import java.util.List;
3736
import java.util.Map;
3837
import java.util.Properties;
39-
import java.util.concurrent.CopyOnWriteArrayList;
4038

4139
import org.scijava.service.AbstractService;
4240

@@ -45,6 +43,7 @@
4543
*
4644
* @author Johannes Schindelin
4745
* @author Curtis Rueden
46+
* @author Matthias Arzt
4847
*/
4948
@IgnoreAsCallingClass
5049
public abstract class AbstractLogService extends AbstractService implements
@@ -55,7 +54,7 @@ public abstract class AbstractLogService extends AbstractService implements
5554

5655
private final Map<String, Integer> classAndPackageLevels;
5756

58-
private final List<LogListener> listeners = new CopyOnWriteArrayList<>();
57+
private final Logger rootLogger;
5958

6059
// -- constructor --
6160

@@ -64,6 +63,7 @@ public AbstractLogService() {
6463
}
6564

6665
public AbstractLogService(final Properties properties) {
66+
rootLogger = new RootLogger();
6767
// provide this constructor to enable unit tests
6868
final int level = LogLevel.value(properties.getProperty(
6969
LogService.LOG_LEVEL_PROPERTY));
@@ -74,10 +74,7 @@ public AbstractLogService(final Properties properties) {
7474

7575
// -- AbstractLogService methods --
7676

77-
protected void notifyListeners(LogMessage message) {
78-
for (LogListener listener : listeners)
79-
listener.messageLogged(message);
80-
}
77+
abstract void notifyListeners(LogMessage message);
8178

8279
// -- Logger methods --
8380

@@ -100,17 +97,17 @@ public void setLevel(final String classOrPackageName, final int level) {
10097

10198
@Override
10299
public void alwaysLog(final int level, final Object msg, final Throwable t) {
103-
notifyListeners(new LogMessage(level, msg, t));
100+
rootLogger.alwaysLog(level, msg, t);
104101
}
105102

106103
@Override
107104
public void addListener(final LogListener listener) {
108-
listeners.add(listener);
105+
rootLogger.addListener(listener);
109106
}
110107

111108
@Override
112109
public void removeListener(final LogListener listener) {
113-
listeners.remove(listener);
110+
rootLogger.removeListener(listener);
114111
}
115112

116113
// -- Deprecated --
@@ -155,4 +152,24 @@ private Map<String, Integer> setupMapFromProperties(Properties properties,
155152
}
156153
return map;
157154
}
155+
156+
// -- Helper classes --
157+
158+
@IgnoreAsCallingClass
159+
private class RootLogger extends DefaultLogger {
160+
161+
public RootLogger() {
162+
super(LogLevel.NONE);
163+
}
164+
165+
@Override
166+
public int getLevel() {
167+
return AbstractLogService.this.getLevel();
168+
}
169+
170+
@Override
171+
protected void messageLogged(LogMessage message) {
172+
AbstractLogService.this.notifyListeners(message);
173+
}
174+
}
158175
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* #%L
3+
* SciJava Common shared library for SciJava software.
4+
* %%
5+
* Copyright (C) 2009 - 2017 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
32+
package org.scijava.log;
33+
34+
import java.util.List;
35+
import java.util.concurrent.CopyOnWriteArrayList;
36+
37+
/**
38+
* Default implementation of {@link Logger}.
39+
*
40+
* @author Matthias Arzt
41+
*/
42+
@IgnoreAsCallingClass
43+
public class DefaultLogger implements Logger {
44+
45+
private final int level;
46+
47+
private final List<LogListener> listeners = new CopyOnWriteArrayList<>();
48+
49+
public DefaultLogger(final int level)
50+
{
51+
this.level = level;
52+
}
53+
54+
// -- DefaultLogger methods --
55+
56+
protected void messageLogged(final LogMessage message) {
57+
for (LogListener listener : listeners)
58+
listener.messageLogged(message);
59+
}
60+
61+
// -- Logger methods --
62+
63+
@Override
64+
public int getLevel() {
65+
return level;
66+
}
67+
68+
@Override
69+
public void alwaysLog(final int level, final Object msg, final Throwable t) {
70+
messageLogged(new LogMessage(level, msg, t));
71+
}
72+
73+
@Override
74+
public void addListener(final LogListener listener) {
75+
listeners.add(listener);
76+
}
77+
78+
@Override
79+
public void removeListener(final LogListener listener) {
80+
listeners.remove(listener);
81+
}
82+
}

src/main/java/org/scijava/log/StderrLogService.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public class StderrLogService extends AbstractLogService {
5454

5555
@Override
5656
public void notifyListeners(final LogMessage message) {
57-
super.notifyListeners(message);
5857
final PrintStream out = (message.level() <= LogLevel.WARN) ? System.err
5958
: System.out;
6059
out.print(message);
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* #%L
3+
* SciJava Common shared library for SciJava software.
4+
* %%
5+
* Copyright (C) 2009 - 2017 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
32+
package org.scijava.log;
33+
34+
import static org.junit.Assert.assertTrue;
35+
36+
import org.junit.Before;
37+
import org.junit.Test;
38+
39+
/**
40+
* Tests {@link DefaultLogger}
41+
*
42+
* @author Matthias Arzt
43+
*/
44+
public class DefaultLoggerTest {
45+
46+
private Logger logger;
47+
private TestLogListener listener;
48+
49+
@Before
50+
public void setup() {
51+
logger = new DefaultLogger(LogLevel.INFO);
52+
listener = new TestLogListener();
53+
logger.addListener(listener);
54+
}
55+
56+
@Test
57+
public void test() {
58+
listener.clear();
59+
60+
logger.error("Hello World!");
61+
62+
assertTrue(listener.hasLogged(m -> m.text().equals("Hello World!")));
63+
assertTrue(listener.hasLogged(m -> m.level() == LogLevel.ERROR));
64+
}
65+
}

src/test/java/org/scijava/log/LogServiceTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ public Throwable exception() {
219219
}
220220

221221
@Override
222-
public void alwaysLog(int level, Object msg, Throwable t) {
223-
this.message = LogLevel.prefix(level) + msg;
224-
this.exception = t;
222+
void notifyListeners(LogMessage message) {
223+
this.message = message.toString();
224+
this.exception = message.throwable();
225225
}
226226
}
227227
}

0 commit comments

Comments
 (0)