Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>

<artifactId>scijava-common</artifactId>
<version>2.65.1-SNAPSHOT</version>
<version>2.66.0-SNAPSHOT</version>

<name>SciJava Common</name>
<description>SciJava Common is a shared library for SciJava software. It provides a plugin framework, with an extensible mechanism for service discovery, backed by its own annotation processor, so that plugins can be loaded dynamically. It is used by downstream projects in the SciJava ecosystem, such as ImageJ and SCIFIO.</description>
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/org/scijava/Listenable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* #%L
* SciJava Common shared library for SciJava software.
* %%
* Copyright (C) 2009 - 2017 Board of Regents of the University of
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
* Institute of Molecular Cell Biology and Genetics.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package org.scijava;

/**
* Interface for event listeners.
*
* @author Curtis Rueden
* @param <L> type of listener
* @param <E> type of event
*/
public interface Listenable<L, E> {

/** Adds an item to the list of registered listeners. */
void addListener(L listener);

/** Removes an item from the list of registered listeners. */
void removeListener(L listener);

/** Informs the registered list of listeners that an event has occurred. */
void notifyListeners(E event);
}
1 change: 1 addition & 0 deletions src/main/java/org/scijava/console/ConsoleService.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
*/
public interface ConsoleService extends
HandlerService<LinkedList<String>, ConsoleArgument>, SciJavaService
// TODO: SJC3: Extend Listenable<OutputListener, OutputEvent>
{

/** Handles arguments from an external source such as the command line. */
Expand Down
74 changes: 70 additions & 4 deletions src/main/java/org/scijava/log/AbstractLogService.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
*
* @author Johannes Schindelin
* @author Curtis Rueden
* @author Matthias Arzt
*/
@IgnoreAsCallingClass
public abstract class AbstractLogService extends AbstractService implements
Expand All @@ -53,23 +54,54 @@ public abstract class AbstractLogService extends AbstractService implements

private final Map<String, Integer> classAndPackageLevels;

private final Logger rootLogger;

// -- constructor --

public AbstractLogService() {
this(System.getProperties());
}

public AbstractLogService(final Properties properties) {
rootLogger = new RootLogger();
// provide this constructor to enable unit tests
final int level = LogLevel.value(properties.getProperty(
LogService.LOG_LEVEL_PROPERTY));
if (level >= 0) currentLevel = level;
classAndPackageLevels = setupMapFromProperties(properties,
LogService.LOG_LEVEL_PROPERTY + ":");
initLogSourceLevels(properties);
}

// -- AbstractLogService methods --

@Override
public void setLevel(final int level) {
currentLevel = level;
}

@Override
public void setLevel(final String classOrPackageName, final int level) {
classAndPackageLevels.put(classOrPackageName, level);
}

@Override
public void setLevelForLogger(final String source, final int level) {
rootLogger.getSource().subSource(source).setLogLevel(level);
}

// -- Logger methods --

@Override
public void alwaysLog(final int level, final Object msg, final Throwable t) {
rootLogger.alwaysLog(level, msg, t);
}

@Override
public LogSource getSource() {
return rootLogger.getSource();
}

@Override
public int getLevel() {
if (classAndPackageLevels.isEmpty()) return currentLevel;
Expand All @@ -78,13 +110,25 @@ public int getLevel() {
}

@Override
public void setLevel(final int level) {
currentLevel = level;
public Logger subLogger(String name, int level) {
return rootLogger.subLogger(name, level);
}

// -- Listenable methods --

@Override
public void setLevel(final String classOrPackageName, final int level) {
classAndPackageLevels.put(classOrPackageName, level);
public void addListener(final LogListener listener) {
rootLogger.addListener(listener);
}

@Override
public void removeListener(final LogListener listener) {
rootLogger.removeListener(listener);
}

@Override
public void notifyListeners(final LogMessage event) {
rootLogger.notifyListeners(event);
}

// -- Deprecated --
Expand All @@ -97,6 +141,12 @@ protected String getPrefix(final int level) {

// -- Helper methods --

private void initLogSourceLevels(Properties properties) {
Map<String, Integer> nameLevels = setupMapFromProperties(properties,
LOG_LEVEL_BY_SOURCE_PROPERTY + ":");
nameLevels.forEach(this::setLevelForLogger);
}

private int getLevelForClass(String classOrPackageName, int defaultLevel) {
// check for a custom log level for calling class or its parent packages
while (classOrPackageName != null) {
Expand Down Expand Up @@ -129,4 +179,20 @@ private Map<String, Integer> setupMapFromProperties(Properties properties,
}
return map;
}

// -- Helper classes --

@IgnoreAsCallingClass
private class RootLogger extends DefaultLogger {

public RootLogger() {
super(AbstractLogService.this::notifyListeners, LogSource.newRoot(),
LogLevel.NONE);
}

@Override
public int getLevel() {
return AbstractLogService.this.getLevel();
}
}
}
110 changes: 110 additions & 0 deletions src/main/java/org/scijava/log/DefaultLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* #%L
* SciJava Common shared library for SciJava software.
* %%
* Copyright (C) 2009 - 2017 Board of Regents of the University of
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
* Institute of Molecular Cell Biology and Genetics.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package org.scijava.log;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* Default implementation of {@link Logger}.
*
* @author Matthias Arzt
* @author Curtis Rueden
*/
@IgnoreAsCallingClass
public class DefaultLogger implements Logger, LogListener {

private final LogListener destination;

private final LogSource source;

private final int level;

private final List<LogListener> listeners = new CopyOnWriteArrayList<>();

public DefaultLogger(final LogListener destination,
final LogSource source, final int level)
{
this.destination = destination;
this.source = source;
this.level = level;
}

// -- Logger methods --

@Override
public LogSource getSource() {
return source;
}

@Override
public int getLevel() {
return level;
}

@Override
public void alwaysLog(final int level, final Object msg, final Throwable t) {
messageLogged(new LogMessage(source, level, msg, t));
}

public Logger subLogger(final String name, final int level) {
LogSource source = getSource().subSource(name);
int actualLevel = source.hasLogLevel() ? source.logLevel() : level;
return new DefaultLogger(this, source, actualLevel);
}

// -- Listenable methods --

@Override
public void addListener(final LogListener listener) {
listeners.add(listener);
}

@Override
public void removeListener(final LogListener listener) {
listeners.remove(listener);
}

@Override
public void notifyListeners(final LogMessage message) {
for (LogListener listener : listeners)
listener.messageLogged(message);
}

// -- LogListener methods --

@Override
public void messageLogged(final LogMessage message) {
notifyListeners(message);
destination.messageLogged(message);
}
}
49 changes: 49 additions & 0 deletions src/main/java/org/scijava/log/LogListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* #%L
* SciJava Common shared library for SciJava software.
* %%
* Copyright (C) 2009 - 2017 Board of Regents of the University of
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
* Institute of Molecular Cell Biology and Genetics.
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package org.scijava.log;

/**
* Callback function used by {@link Logger}.
*
* @author Matthias Arzt
* @see Logger
* @see LogMessage
*/
public interface LogListener {

/**
* This method is normally called from many threads in parallel. It must be
* implemented highly thread safe and must not use any kind of locks.
*/
void messageLogged(LogMessage message);

}
Loading