Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2016-03-04 09:30:44 -0500
committerThomas Watson2017-06-16 08:38:08 -0400
commitc7fae461022cd049802023f56bb518b8a81ad02a (patch)
tree87276855dc7fc1b82f10c56d1a24af4fd25df758
parentf31b2c1056822bdc2e77b22f558a087943f7a22d (diff)
downloadrt.equinox.framework-c7fae461022cd049802023f56bb518b8a81ad02a.tar.gz
rt.equinox.framework-c7fae461022cd049802023f56bb518b8a81ad02a.tar.xz
rt.equinox.framework-c7fae461022cd049802023f56bb518b8a81ad02a.zip
Bug 486950 - [osgi R7] log service is being updated
- Add support for LoggerAdmin Change-Id: Iecd2675cfb7ddf7f7a10fbaa8a7f35e4f59d5615 Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogReaderServiceTest.java20
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogServiceTest.java24
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogReaderServiceTest.java18
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogServiceTest.java19
-rw-r--r--bundles/org.eclipse.osgi/META-INF/MANIFEST.MF2
-rw-r--r--bundles/org.eclipse.osgi/build.properties3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/SecureAction.java11
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/Arguments.java7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java53
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogEntryImpl.java13
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogReaderServiceFactory.java13
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java181
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceImpl.java90
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/FormatterLoggerImpl.java20
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java39
-rwxr-xr-xbundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerContextTargetMap.java154
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java69
-rwxr-xr-xbundles/org.eclipse.osgi/osgi/function.interface.jarbin0 -> 1110 bytes
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/FormatterLogger.java4
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogEntry.java24
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogLevel.java2
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogListener.java1
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java52
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/Logger.java9
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LoggerFactory.java44
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerAdmin.java77
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerContext.java114
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/package-info.java38
-rw-r--r--bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/packageinfo1
30 files changed, 988 insertions, 117 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogReaderServiceTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogReaderServiceTest.java
index ebafb8b25..5d4100855 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogReaderServiceTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogReaderServiceTest.java
@@ -8,12 +8,17 @@
package org.eclipse.equinox.log.test;
import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
import junit.framework.TestCase;
import org.eclipse.equinox.log.*;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.*;
+import org.osgi.service.log.Logger;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
public class ExtendedLogReaderServiceTest extends TestCase {
@@ -21,6 +26,10 @@ public class ExtendedLogReaderServiceTest extends TestCase {
private ServiceReference logReference;
private ExtendedLogReaderService reader;
private ServiceReference readerReference;
+ private ServiceReference<LoggerAdmin> loggerAdminReference;
+ private LoggerAdmin loggerAdmin;
+ LoggerContext rootLoggerContext;
+ Map<String, LogLevel> rootLogLevels;
boolean called;
public ExtendedLogReaderServiceTest(String name) {
@@ -30,12 +39,23 @@ public class ExtendedLogReaderServiceTest extends TestCase {
protected void setUp() throws Exception {
logReference = OSGiTestsActivator.getContext().getServiceReference(ExtendedLogService.class.getName());
readerReference = OSGiTestsActivator.getContext().getServiceReference(ExtendedLogReaderService.class.getName());
+ loggerAdminReference = OSGiTestsActivator.getContext().getServiceReference(LoggerAdmin.class);
log = (ExtendedLogService) OSGiTestsActivator.getContext().getService(logReference);
reader = (ExtendedLogReaderService) OSGiTestsActivator.getContext().getService(readerReference);
+ loggerAdmin = OSGiTestsActivator.getContext().getService(loggerAdminReference);
+
+ rootLoggerContext = loggerAdmin.getLoggerContext(null);
+ rootLogLevels = rootLoggerContext.getLogLevels();
+
+ Map<String, LogLevel> copyLogLevels = new HashMap<String, LogLevel>(rootLogLevels);
+ copyLogLevels.put(Logger.ROOT_LOGGER_NAME, LogLevel.TRACE);
+ rootLoggerContext.setLogLevels(copyLogLevels);
}
protected void tearDown() throws Exception {
+ rootLoggerContext.setLogLevels(rootLogLevels);
+ OSGiTestsActivator.getContext().ungetService(loggerAdminReference);
OSGiTestsActivator.getContext().ungetService(logReference);
OSGiTestsActivator.getContext().ungetService(readerReference);
}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogServiceTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogServiceTest.java
index 96448852f..8353d1984 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogServiceTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/ExtendedLogServiceTest.java
@@ -8,12 +8,18 @@
*******************************************************************************/
package org.eclipse.equinox.log.test;
+import java.util.HashMap;
+import java.util.Map;
import junit.framework.TestCase;
import org.eclipse.equinox.log.*;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogLevel;
import org.osgi.service.log.LogService;
+import org.osgi.service.log.Logger;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
public class ExtendedLogServiceTest extends TestCase {
@@ -22,6 +28,11 @@ public class ExtendedLogServiceTest extends TestCase {
private ServiceReference logReference;
private ExtendedLogReaderService reader;
private ServiceReference readerReference;
+ private ServiceReference<LoggerAdmin> loggerAdminReference;
+ private LoggerAdmin loggerAdmin;
+ LoggerContext rootLoggerContext;
+ Map<String, LogLevel> rootLogLevels;
+
private TestListener listener;
public ExtendedLogServiceTest(String name) {
@@ -32,16 +43,27 @@ public class ExtendedLogServiceTest extends TestCase {
bundle = OSGiTestsActivator.getContext().getBundle();
logReference = OSGiTestsActivator.getContext().getServiceReference(ExtendedLogService.class.getName());
readerReference = OSGiTestsActivator.getContext().getServiceReference(ExtendedLogReaderService.class.getName());
+ loggerAdminReference = OSGiTestsActivator.getContext().getServiceReference(LoggerAdmin.class);
log = (ExtendedLogService) OSGiTestsActivator.getContext().getService(logReference);
reader = (ExtendedLogReaderService) OSGiTestsActivator.getContext().getService(readerReference);
+ loggerAdmin = OSGiTestsActivator.getContext().getService(loggerAdminReference);
listener = new TestListener();
reader.addLogListener(listener);
+
+ rootLoggerContext = loggerAdmin.getLoggerContext(null);
+ rootLogLevels = rootLoggerContext.getLogLevels();
+
+ Map<String, LogLevel> copyLogLevels = new HashMap<String, LogLevel>(rootLogLevels);
+ copyLogLevels.put(Logger.ROOT_LOGGER_NAME, LogLevel.TRACE);
+ rootLoggerContext.setLogLevels(copyLogLevels);
}
protected void tearDown() throws Exception {
+ rootLoggerContext.setLogLevels(rootLogLevels);
reader.removeLogListener(listener);
+ OSGiTestsActivator.getContext().ungetService(loggerAdminReference);
OSGiTestsActivator.getContext().ungetService(logReference);
OSGiTestsActivator.getContext().ungetService(readerReference);
}
@@ -111,7 +133,7 @@ public class ExtendedLogServiceTest extends TestCase {
listener.waitForLogEntry();
}
ExtendedLogEntry entry = listener.getEntryX();
- assertTrue(entry.getLoggerName() == null);
+ assertEquals("Wrong logger name.", "LogService", entry.getLoggerName());
assertTrue(entry.getLevel() == 0);
assertTrue(entry.getMessage() == null);
assertTrue(entry.getException() == null);
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogReaderServiceTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogReaderServiceTest.java
index 04d90910e..6fad1d28f 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogReaderServiceTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogReaderServiceTest.java
@@ -16,6 +16,8 @@ import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.eclipse.osgi.tests.bundles.AbstractBundleTests;
import org.osgi.framework.*;
import org.osgi.service.log.*;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
public class LogReaderServiceTest extends AbstractBundleTests {
@@ -23,6 +25,10 @@ public class LogReaderServiceTest extends AbstractBundleTests {
private ServiceReference logReference;
private LogReaderService reader;
private ServiceReference readerReference;
+ private ServiceReference<LoggerAdmin> loggerAdminReference;
+ private LoggerAdmin loggerAdmin;
+ LoggerContext rootLoggerContext;
+ Map<String, LogLevel> rootLogLevels;
public LogReaderServiceTest(String name) {
setName(name);
@@ -32,12 +38,23 @@ public class LogReaderServiceTest extends AbstractBundleTests {
super.setUp();
logReference = OSGiTestsActivator.getContext().getServiceReference(LogService.class.getName());
readerReference = OSGiTestsActivator.getContext().getServiceReference(LogReaderService.class.getName());
+ loggerAdminReference = OSGiTestsActivator.getContext().getServiceReference(LoggerAdmin.class);
log = (LogService) OSGiTestsActivator.getContext().getService(logReference);
reader = (LogReaderService) OSGiTestsActivator.getContext().getService(readerReference);
+ loggerAdmin = OSGiTestsActivator.getContext().getService(loggerAdminReference);
+
+ rootLoggerContext = loggerAdmin.getLoggerContext(null);
+ rootLogLevels = rootLoggerContext.getLogLevels();
+
+ Map<String, LogLevel> copyLogLevels = new HashMap<String, LogLevel>(rootLogLevels);
+ copyLogLevels.put(Logger.ROOT_LOGGER_NAME, LogLevel.TRACE);
+ rootLoggerContext.setLogLevels(copyLogLevels);
}
protected void tearDown() throws Exception {
+ rootLoggerContext.setLogLevels(rootLogLevels);
+ OSGiTestsActivator.getContext().ungetService(loggerAdminReference);
OSGiTestsActivator.getContext().ungetService(logReference);
OSGiTestsActivator.getContext().ungetService(readerReference);
super.tearDown();
@@ -106,7 +123,6 @@ public class LogReaderServiceTest extends AbstractBundleTests {
}
public void testLogBundleEventInfo() throws Exception {
-
// this is just a bundle that is harmless to start/stop
Bundle testBundle = installer.installBundle("test.logging.a"); //$NON-NLS-1$
TestListener listener = new TestListener(testBundle);
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogServiceTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogServiceTest.java
index 12bb09608..5c16a48d7 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogServiceTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/LogServiceTest.java
@@ -8,10 +8,14 @@
*******************************************************************************/
package org.eclipse.equinox.log.test;
+import java.util.HashMap;
+import java.util.Map;
import junit.framework.TestCase;
import org.eclipse.osgi.tests.OSGiTestsActivator;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.*;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
public class LogServiceTest extends TestCase {
@@ -20,6 +24,10 @@ public class LogServiceTest extends TestCase {
private LogReaderService reader;
private ServiceReference readerReference;
private TestListener listener;
+ private ServiceReference<LoggerAdmin> loggerAdminReference;
+ private LoggerAdmin loggerAdmin;
+ LoggerContext rootLoggerContext;
+ Map<String, LogLevel> rootLogLevels;
public LogServiceTest(String name) {
super(name);
@@ -28,16 +36,27 @@ public class LogServiceTest extends TestCase {
protected void setUp() throws Exception {
logReference = OSGiTestsActivator.getContext().getServiceReference(LogService.class.getName());
readerReference = OSGiTestsActivator.getContext().getServiceReference(LogReaderService.class.getName());
+ loggerAdminReference = OSGiTestsActivator.getContext().getServiceReference(LoggerAdmin.class);
log = (LogService) OSGiTestsActivator.getContext().getService(logReference);
reader = (LogReaderService) OSGiTestsActivator.getContext().getService(readerReference);
+ loggerAdmin = OSGiTestsActivator.getContext().getService(loggerAdminReference);
listener = new TestListener();
reader.addLogListener(listener);
+
+ rootLoggerContext = loggerAdmin.getLoggerContext(null);
+ rootLogLevels = rootLoggerContext.getLogLevels();
+
+ Map<String, LogLevel> copyLogLevels = new HashMap<String, LogLevel>(rootLogLevels);
+ copyLogLevels.put(Logger.ROOT_LOGGER_NAME, LogLevel.TRACE);
+ rootLoggerContext.setLogLevels(copyLogLevels);
}
protected void tearDown() throws Exception {
+ rootLoggerContext.setLogLevels(rootLogLevels);
reader.removeLogListener(listener);
+ OSGiTestsActivator.getContext().ungetService(loggerAdminReference);
OSGiTestsActivator.getContext().ungetService(logReference);
OSGiTestsActivator.getContext().ungetService(readerReference);
}
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index 5ec09bbff..65ff2ba2e 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -68,6 +68,7 @@ Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.ru
org.osgi.resource.dto;version="1.0";uses:="org.osgi.dto",
org.osgi.service.condpermadmin;version="1.1.1";uses:="org.osgi.framework",
org.osgi.service.log;version="1.3";uses:="org.osgi.framework",
+ org.osgi.service.log.admin;version="1.0",
org.osgi.service.packageadmin;version="1.2";uses:="org.osgi.framework",
org.osgi.service.permissionadmin;version="1.2",
org.osgi.service.resolver;version="1.0.1";uses:="org.osgi.resource",
@@ -80,6 +81,7 @@ Export-Service: org.osgi.service.packageadmin.PackageAdmin,
org.eclipse.osgi.service.debug.DebugOptions
Provide-Capability: osgi.service; objectClass:List<String>="org.osgi.service.log.LogReaderService, org.eclipse.equinox.log.ExtendedLogReaderService",
osgi.service; objectClass:List<String>="org.osgi.service.log.LogService, org.eclipse.equinox.log.ExtendedLogService",
+ osgi.service; objectClass:List<String>="org.osgi.service.log.admin.LoggerAdmin",
osgi.service; objectClass:List<String>="org.eclipse.osgi.framework.log.FrameworkLog",
osgi.service; objectClass:List<String>="org.eclipse.osgi.service.datalocation.Location"; type="osgi.user.area",
osgi.service; objectClass:List<String>="org.eclipse.osgi.service.datalocation.Location"; type="osgi.instance.area",
diff --git a/bundles/org.eclipse.osgi/build.properties b/bundles/org.eclipse.osgi/build.properties
index 6cb7c3dcf..9ddb3ad0b 100644
--- a/bundles/org.eclipse.osgi/build.properties
+++ b/bundles/org.eclipse.osgi/build.properties
@@ -32,5 +32,6 @@ output.. = bin/
# customBuildCallbacks=customBuildCallbacks.xml
javacWarnings..=-raw,unchecked,hiding,unused,warningToken
-jars.extra.classpath = osgi/osgi.annotation.jar
+jars.extra.classpath = osgi/osgi.annotation.jar,\
+ osgi/function.interface.jar
jre.compilation.profile = JavaSE-1.7
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/SecureAction.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/SecureAction.java
index bb12a4c4a..795ab9e84 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/SecureAction.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/framework/util/SecureAction.java
@@ -493,4 +493,15 @@ public class SecureAction {
}
}, controlContext);
}
+
+ public String getLocation(final Bundle bundle) {
+ if (System.getSecurityManager() == null) {
+ return bundle.getLocation();
+ }
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return bundle.getLocation();
+ }
+ }, controlContext);
+ }
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/Arguments.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/Arguments.java
index 187b7b2a5..9eeb9883b 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/Arguments.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/Arguments.java
@@ -1,3 +1,10 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ ******************************************************************************/
package org.eclipse.osgi.internal.log;
import org.osgi.framework.ServiceReference;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
index de64ca670..985356d35 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
@@ -84,6 +84,9 @@ public class EquinoxLogServices {
logServiceManager = new LogServiceManager(logHistoryMax, logWriter, perfWriter);
eclipseLogFactory = new EquinoxLogFactory(logWriter, logServiceManager);
rootFrameworkLog = eclipseLogFactory.createFrameworkLog(null, logWriter);
+
+ logWriter.setLoggerAdmin(logServiceManager.getLoggerAdmin());
+ perfWriter.setLoggerAdmin(logServiceManager.getLoggerAdmin());
}
private ServiceRegistration<?> frameworkLogReg;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java
index 1520ab158..c07307a3e 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogWriter.java
@@ -12,18 +12,16 @@ package org.eclipse.osgi.internal.log;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
-import java.security.AccessController;
-import java.util.Calendar;
-import java.util.Date;
+import java.util.*;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.equinox.log.*;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
-import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
-import org.osgi.service.log.LogEntry;
-import org.osgi.service.log.LogService;
+import org.osgi.service.log.*;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
private static final String PASSWORD = "-password"; //$NON-NLS-1$
@@ -67,8 +65,6 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
/** The system property used to specify command line args should be omitted from the log */
private static final String PROP_LOG_INCLUDE_COMMAND_LINE = "eclipse.log.include.commandline"; //$NON-NLS-1$
- private static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
-
/** Indicates if the console messages should be printed to the console (System.out) */
private boolean consoleLog = false;
/** Indicates if the next log message is part of a new session */
@@ -94,6 +90,8 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
private int logLevel = FrameworkLogEntry.OK;
private boolean includeCommandLine = true;
+ private LoggerAdmin loggerAdmin = null;
+
/**
* Constructs an EclipseLog which uses the specified File to log messages to
* @param outFile a file to log messages to
@@ -244,7 +242,7 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
if (writer == null) {
if (outFile != null) {
try {
- writer = logForStream(secureAction.getFileOutputStream(outFile, true));
+ writer = logForStream(ExtendedLogServiceFactory.secureAction.getFileOutputStream(outFile, true));
} catch (IOException e) {
writer = logForErrorStream();
}
@@ -321,6 +319,11 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
environmentInfo.setConfiguration(EclipseStarter.PROP_LOGFILE, newFile == null ? "" : newFile.getAbsolutePath()); //$NON-NLS-1$
}
+ synchronized void setLoggerAdmin(LoggerAdmin loggerAdmin) {
+ this.loggerAdmin = loggerAdmin;
+ applyLogLevel();
+ }
+
public synchronized File getFile() {
return outFile;
}
@@ -350,7 +353,7 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
Reader fileIn = null;
try {
openFile();
- fileIn = new InputStreamReader(secureAction.getFileInputStream(oldOutFile), "UTF-8"); //$NON-NLS-1$
+ fileIn = new InputStreamReader(ExtendedLogServiceFactory.secureAction.getFileInputStream(oldOutFile), "UTF-8"); //$NON-NLS-1$
copyReader(fileIn, this.writer);
} catch (IOException e) {
copyFailed = true;
@@ -583,7 +586,7 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
boolean isBackupOK = true;
if (outFile != null) {
- if ((secureAction.length(outFile) >> 10) > maxLogSize) { // Use KB as file size unit.
+ if ((ExtendedLogServiceFactory.secureAction.length(outFile) >> 10) > maxLogSize) { // Use KB as file size unit.
String logFilename = outFile.getAbsolutePath();
// Delete old backup file that will be replaced.
@@ -669,6 +672,34 @@ class EquinoxLogWriter implements SynchronousLogListener, LogFilter {
}
includeCommandLine = "true".equals(environmentInfo.getConfiguration(PROP_LOG_INCLUDE_COMMAND_LINE, "true")); //$NON-NLS-1$//$NON-NLS-2$
+ applyLogLevel();
+ }
+
+ void applyLogLevel() {
+ if (loggerAdmin == null) {
+ return;
+ }
+ LoggerContext rootContext = loggerAdmin.getLoggerContext(null);
+ Map<String, LogLevel> rootLevels = rootContext.getLogLevels();
+ rootLevels.put(loggerName, getLogLevel());
+ rootContext.setLogLevels(rootLevels);
+ }
+
+ private LogLevel getLogLevel() {
+ if (logLevel == 0) {
+ return LogLevel.TRACE;
+ }
+ if ((logLevel & FrameworkLogEntry.INFO) != 0) {
+ return LogLevel.INFO;
+ }
+ if ((logLevel & FrameworkLogEntry.WARNING) != 0) {
+ return LogLevel.WARN;
+ }
+ if ((logLevel & FrameworkLogEntry.ERROR) != 0) {
+ return LogLevel.ERROR;
+ }
+ // not sure what to do here; it seems it would be an error
+ return LogLevel.AUDIT;
}
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogEntryImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogEntryImpl.java
index ee492f5f6..335acf19a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogEntryImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogEntryImpl.java
@@ -24,6 +24,7 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
private final String loggerName;
private final Bundle bundle;
private final int level;
+ private final LogLevel logLevelEnum;
private final String message;
private final Throwable throwable;
private final Object contextObject;
@@ -54,11 +55,12 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
return threadId.longValue();
}
- public ExtendedLogEntryImpl(Bundle bundle, String loggerName, Object contextObject, int level, String message, Throwable throwable) {
+ public ExtendedLogEntryImpl(Bundle bundle, String loggerName, Object contextObject, LogLevel logLevelEnum, int level, String message, Throwable throwable) {
this.time = System.currentTimeMillis();
this.loggerName = loggerName;
this.bundle = bundle;
this.level = level;
+ this.logLevelEnum = logLevelEnum;
this.message = message;
this.throwable = throwable;
this.contextObject = contextObject;
@@ -71,6 +73,7 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
this.sequenceNumber = nextSequenceNumber++;
}
+ // TODO need to find the calling stack here not just 2 up.
stackTraceElement = currentThread.getStackTrace()[2];
}
@@ -98,6 +101,7 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
return throwable;
}
+ @SuppressWarnings("deprecation")
public int getLevel() {
return level;
}
@@ -106,10 +110,9 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
return message;
}
- @SuppressWarnings("rawtypes")
- public ServiceReference getServiceReference() {
+ public ServiceReference<?> getServiceReference() {
if (contextObject != null && contextObject instanceof ServiceReference)
- return (ServiceReference) contextObject;
+ return (ServiceReference<?>) contextObject;
return null;
}
@@ -124,7 +127,7 @@ public class ExtendedLogEntryImpl implements ExtendedLogEntry, LogEntry {
@Override
public LogLevel getLogLevel() {
- return LogLevel.values()[getLevel()];
+ return logLevelEnum;
}
@Override
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogReaderServiceFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogReaderServiceFactory.java
index e018dd084..b6ef95760 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogReaderServiceFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogReaderServiceFactory.java
@@ -15,8 +15,7 @@ import org.eclipse.equinox.log.LogFilter;
import org.eclipse.equinox.log.SynchronousLogListener;
import org.eclipse.osgi.framework.util.ArrayMap;
import org.osgi.framework.*;
-import org.osgi.service.log.LogEntry;
-import org.osgi.service.log.LogListener;
+import org.osgi.service.log.*;
public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedLogReaderServiceImpl> {
@@ -177,21 +176,21 @@ public class ExtendedLogReaderServiceFactory implements ServiceFactory<ExtendedL
return count;
}
- void log(final Bundle bundle, final String name, final Object context, final int level, final String message, final Throwable exception) {
+ void log(final Bundle bundle, final String name, final Object context, final LogLevel logLevelEnum, final int level, final String message, final Throwable exception) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
- logPrivileged(bundle, name, context, level, message, exception);
+ logPrivileged(bundle, name, context, logLevelEnum, level, message, exception);
return null;
}
});
} else {
- logPrivileged(bundle, name, context, level, message, exception);
+ logPrivileged(bundle, name, context, logLevelEnum, level, message, exception);
}
}
- void logPrivileged(Bundle bundle, String name, Object context, int level, String message, Throwable exception) {
- LogEntry logEntry = new ExtendedLogEntryImpl(bundle, name, context, level, message, exception);
+ void logPrivileged(Bundle bundle, String name, Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) {
+ LogEntry logEntry = new ExtendedLogEntryImpl(bundle, name, context, logLevelEnum, level, message, exception);
storeEntry(logEntry);
ArrayMap<LogListener, Object[]> listenersCopy;
listenersLock.readLock();
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
index ab8bcf025..cf92c747e 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
@@ -7,21 +7,30 @@
******************************************************************************/
package org.eclipse.osgi.internal.log;
+import java.security.AccessController;
import java.security.Permission;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.eclipse.equinox.log.ExtendedLogService;
import org.eclipse.equinox.log.LogPermission;
+import org.eclipse.osgi.framework.util.SecureAction;
import org.osgi.framework.*;
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.Logger;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
public class ExtendedLogServiceFactory implements ServiceFactory<ExtendedLogService>, BundleListener {
-
+ static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
+ final ReentrantReadWriteLock contextsLock = new ReentrantReadWriteLock();
+ final LoggerContextTargetMap loggerContextTargetMap = new LoggerContextTargetMap();
private final Permission logPermission = new LogPermission("*", LogPermission.LOG); //$NON-NLS-1$
private final ExtendedLogReaderServiceFactory logReaderServiceFactory;
- private final Map<Bundle, ExtendedLogService> logServices = new HashMap<>();
+ private final LoggerAdmin loggerAdmin = new EquinoxLoggerAdmin();
public ExtendedLogServiceFactory(ExtendedLogReaderServiceFactory logReaderServiceFactory) {
this.logReaderServiceFactory = logReaderServiceFactory;
+
}
public ExtendedLogServiceImpl getService(Bundle bundle, ServiceRegistration<ExtendedLogService> registration) {
@@ -39,30 +48,40 @@ public class ExtendedLogServiceFactory implements ServiceFactory<ExtendedLogServ
removeLogService(event.getBundle());
}
- synchronized ExtendedLogServiceImpl getLogService(Bundle bundle) {
- ExtendedLogServiceImpl logService = (ExtendedLogServiceImpl) logServices.get(bundle);
- if (logService == null) {
- logService = new ExtendedLogServiceImpl(this, bundle);
- if (bundle != null && bundle.getState() != Bundle.UNINSTALLED)
- logServices.put(bundle, logService);
+ ExtendedLogServiceImpl getLogService(Bundle bundle) {
+ contextsLock.writeLock().lock();
+ try {
+ return loggerContextTargetMap.getLogService(bundle, this);
+ } finally {
+ contextsLock.writeLock().unlock();
}
- return logService;
}
- synchronized void shutdown() {
- logServices.clear();
+ void shutdown() {
+ contextsLock.writeLock().lock();
+ try {
+ loggerContextTargetMap.clear();
+ } finally {
+ contextsLock.writeLock().unlock();
+ }
+
}
- synchronized void removeLogService(Bundle bundle) {
- logServices.remove(bundle);
+ void removeLogService(Bundle bundle) {
+ contextsLock.writeLock().lock();
+ try {
+ loggerContextTargetMap.remove(bundle);
+ } finally {
+ contextsLock.writeLock().unlock();
+ }
}
boolean isLoggable(Bundle bundle, String name, int level) {
return logReaderServiceFactory.isLoggable(bundle, name, level);
}
- void log(Bundle bundle, String name, Object context, int level, String message, Throwable exception) {
- logReaderServiceFactory.log(bundle, name, context, level, message, exception);
+ void log(Bundle bundle, String name, Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) {
+ logReaderServiceFactory.log(bundle, name, context, logLevelEnum, level, message, exception);
}
void checkLogPermission() throws SecurityException {
@@ -70,4 +89,132 @@ public class ExtendedLogServiceFactory implements ServiceFactory<ExtendedLogServ
if (sm != null)
sm.checkPermission(logPermission);
}
+
+ EquinoxLoggerContext createEquinoxLoggerContext(String name) {
+ return new EquinoxLoggerContext(name);
+ }
+
+ LoggerAdmin getLoggerAdmin() {
+ return loggerAdmin;
+ }
+
+ class EquinoxLoggerAdmin implements LoggerAdmin {
+ @Override
+ public LoggerContext getLoggerContext(String name) {
+ contextsLock.writeLock().lock();
+ try {
+ return loggerContextTargetMap.createLoggerContext(name, ExtendedLogServiceFactory.this);
+ } finally {
+ contextsLock.writeLock().unlock();
+ }
+ }
+
+ }
+
+ class EquinoxLoggerContext implements LoggerContext {
+ final String contextName;
+ final Map<String, LogLevel> contextLogLevels = new HashMap<>();
+
+ EquinoxLoggerContext(String name) {
+ this.contextName = name;
+ }
+
+ @Override
+ public String getName() {
+ return contextName;
+ }
+
+ @Override
+ public LogLevel getEffectiveLogLevel(final String name) {
+ contextsLock.readLock().lock();
+ try {
+ LogLevel level = null;
+ String lookupName = name;
+ while ((level = contextLogLevels.get(lookupName)) == null) {
+ int lastDot = lookupName.lastIndexOf('.');
+ if (lastDot >= 0) {
+ lookupName = lookupName.substring(0, lastDot);
+ } else {
+ break;
+ }
+ }
+ if (level == null) {
+ level = contextLogLevels.get(Logger.ROOT_LOGGER_NAME);
+ }
+ if (level == null && contextName != null) {
+ // non-null context name is a non-root context;
+ // must not check the root context
+ EquinoxLoggerContext rootContext = loggerContextTargetMap.getRootLoggerContext();
+ if (rootContext != null) {
+ level = rootContext.getEffectiveLogLevel(name);
+ }
+ }
+ if (level == null) {
+ level = LogLevel.WARN;
+ }
+ return level;
+ } finally {
+ contextsLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public Map<String, LogLevel> getLogLevels() {
+ contextsLock.readLock().lock();
+ try {
+ return new HashMap<>(contextLogLevels);
+ } finally {
+ contextsLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public void setLogLevels(Map<String, LogLevel> logLevels) {
+ if (!setWithConfigAdmin(logLevels)) {
+ doSetLogLevels(logLevels);
+ }
+ }
+
+ private boolean setWithConfigAdmin(Map<String, LogLevel> logLevels) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private void doSetLogLevels(Map<String, LogLevel> logLevels) {
+ boolean readLocked = false;
+ try {
+ contextsLock.writeLock().lock();
+ try {
+ contextLogLevels.clear();
+ contextLogLevels.putAll(logLevels);
+ // downgrade to readlock
+ contextsLock.readLock().lock();
+ readLocked = true;
+ } finally {
+ contextsLock.writeLock().unlock();
+ }
+ loggerContextTargetMap.applyLogLevels(this);
+ } finally {
+ if (readLocked) {
+ contextsLock.readLock().unlock();
+ }
+ }
+ }
+
+ @Override
+ public void clear() {
+ doSetLogLevels(Collections.<String, LogLevel> emptyMap());
+ }
+
+ @Override
+ public boolean isEmpty() {
+ contextsLock.readLock().lock();
+ try {
+ return contextLogLevels.isEmpty();
+ } finally {
+ contextsLock.readLock().unlock();
+ }
+ }
+ }
+
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceImpl.java
index ab8dbb213..a2dd568d6 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2012 Cognos Incorporated, IBM Corporation and others
+ * Copyright (c) 2006, 2016 Cognos Incorporated, IBM Corporation and others
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
@@ -11,37 +11,42 @@ import java.util.HashMap;
import java.util.Map;
import org.eclipse.equinox.log.ExtendedLogService;
import org.eclipse.equinox.log.Logger;
+import org.eclipse.osgi.internal.log.ExtendedLogServiceFactory.EquinoxLoggerContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.FormatterLogger;
+import org.osgi.service.log.admin.LoggerContext;
public class ExtendedLogServiceImpl implements ExtendedLogService {
private final ExtendedLogServiceFactory factory;
private volatile Bundle bundle;
- private final Map<Class<? extends org.osgi.service.log.Logger>, Map<String, Logger>> loggerCache = new HashMap<>();
+ private final Map<Class<? extends org.osgi.service.log.Logger>, Map<String, LoggerImpl>> loggerCache = new HashMap<>();
public ExtendedLogServiceImpl(ExtendedLogServiceFactory factory, Bundle bundle) {
this.factory = factory;
this.bundle = bundle;
- loggerCache.put(org.osgi.service.log.Logger.class, new HashMap<String, Logger>());
- loggerCache.put(org.osgi.service.log.FormatterLogger.class, new HashMap<String, Logger>());
+ loggerCache.put(org.osgi.service.log.Logger.class, new HashMap<String, LoggerImpl>());
+ loggerCache.put(org.osgi.service.log.FormatterLogger.class, new HashMap<String, LoggerImpl>());
}
+ @SuppressWarnings("deprecation")
public void log(int level, String message) {
log(null, level, message, null);
}
+ @SuppressWarnings("deprecation")
public void log(int level, String message, Throwable exception) {
log(null, level, message, exception);
}
- @SuppressWarnings("rawtypes")
- public void log(ServiceReference sr, int level, String message) {
+ @SuppressWarnings("deprecation")
+ public void log(ServiceReference<?> sr, int level, String message) {
log(sr, level, message, null);
}
- @SuppressWarnings("rawtypes")
- public void log(ServiceReference sr, int level, String message, Throwable exception) {
+ @SuppressWarnings("deprecation")
+ public void log(ServiceReference<?> sr, int level, String message, Throwable exception) {
getLogger((String) null).log(sr, level, message, exception);
}
@@ -79,13 +84,23 @@ public class ExtendedLogServiceImpl implements ExtendedLogService {
return factory.isLoggable(bundle, name, level);
}
- // package private methods called from Logger
- void log(String name, Object context, int level, String message, Throwable exception) {
- factory.log(bundle, name, context, level, message, exception);
+ void setBundle(Bundle bundle) {
+ factory.contextsLock.writeLock().lock();
+ try {
+ Bundle previous = this.bundle;
+ this.bundle = bundle;
+ factory.loggerContextTargetMap.replaceSystemBundleLogService(previous, bundle);
+ } finally {
+ factory.contextsLock.writeLock().unlock();
+ }
}
- void setBundle(Bundle bundle) {
- this.bundle = bundle;
+ Bundle getBundle() {
+ return bundle;
+ }
+
+ ExtendedLogServiceFactory getFactory() {
+ return factory;
}
@Override
@@ -94,15 +109,42 @@ public class ExtendedLogServiceImpl implements ExtendedLogService {
}
@Override
- public synchronized <L extends org.osgi.service.log.Logger> L getLogger(String name, Class<L> loggerType) {
- Map<String, Logger> loggers = loggerCache.get(loggerType);
- if (loggers == null) {
- throw new IllegalArgumentException(loggerType.getName());
+ public <L extends org.osgi.service.log.Logger> L getLogger(String name, Class<L> loggerType) {
+ if (name == null) {
+ name = "LogService"; //$NON-NLS-1$
+ }
+ LoggerImpl logger = null;
+ Map<String, LoggerImpl> loggers = null;
+ factory.contextsLock.readLock().lock();
+ try {
+ loggers = loggerCache.get(loggerType);
+ if (loggers == null) {
+ throw new IllegalArgumentException(loggerType.getName());
+ }
+ logger = loggers.get(name);
+ } finally {
+ factory.contextsLock.readLock().unlock();
}
- Logger logger = loggers.get(name);
if (logger == null) {
- logger = new FormatterLoggerImpl(this, name);
- loggers.put(name, logger);
+ LoggerContext loggerContext = factory.loggerContextTargetMap.getEffectiveLoggerContext(bundle);
+ if (loggerType == FormatterLogger.class) {
+ logger = new FormatterLoggerImpl(this, name, loggerContext);
+ } else if (loggerType == org.osgi.service.log.Logger.class) {
+ logger = new LoggerImpl(this, name, loggerContext);
+ } else {
+ throw new IllegalArgumentException(loggerType.getName());
+ }
+ factory.contextsLock.writeLock().lock();
+ try {
+ LoggerImpl existing = loggers.get(name);
+ if (existing == null) {
+ loggers.put(name, logger);
+ } else {
+ logger = existing;
+ }
+ } finally {
+ factory.contextsLock.writeLock().unlock();
+ }
}
return loggerType.cast(logger);
}
@@ -256,4 +298,12 @@ public class ExtendedLogServiceImpl implements ExtendedLogService {
public void audit(String format, Object... arguments) {
getLogger((String) null).audit(format, arguments);
}
+
+ void applyLogLevels(EquinoxLoggerContext effectiveLoggerContext) {
+ for (Map<String, LoggerImpl> loggers : loggerCache.values()) {
+ for (LoggerImpl logger : loggers.values()) {
+ logger.applyLoggerContext(effectiveLoggerContext);
+ }
+ }
+ }
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/FormatterLoggerImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/FormatterLoggerImpl.java
index d3ab1e478..83cd5eed2 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/FormatterLoggerImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/FormatterLoggerImpl.java
@@ -1,17 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2016 IBM Corporation and others
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ ******************************************************************************/
package org.eclipse.osgi.internal.log;
import org.osgi.service.log.FormatterLogger;
-import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.admin.LoggerContext;
public class FormatterLoggerImpl extends LoggerImpl implements FormatterLogger {
- public FormatterLoggerImpl(ExtendedLogServiceImpl logServiceImpl, String name) {
- super(logServiceImpl, name);
+ public FormatterLoggerImpl(ExtendedLogServiceImpl logServiceImpl, String name, LoggerContext loggerContext) {
+ super(logServiceImpl, name, loggerContext);
}
@Override
- protected void log(LogLevel level, String format, Object... arguments) {
- Arguments processedArguments = new Arguments(arguments);
- String message = String.format(format, processedArguments.arguments());
- logServiceImpl.log(name, processedArguments.serviceReference(), level.ordinal(), message, processedArguments.throwable());
+ String formatMessage(String format, Arguments processedArguments) {
+ return String.format(format, processedArguments.arguments());
}
+
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
index 25a54c758..d14f5ab8e 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
@@ -16,14 +16,19 @@ import org.eclipse.equinox.log.*;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.osgi.framework.*;
import org.osgi.service.log.*;
+import org.osgi.service.log.admin.LoggerAdmin;
public class LogServiceManager implements BundleListener, FrameworkListener, ServiceListener {
+ private static final String LOGGER_FRAMEWORK_EVENT = "Events.Framework"; //$NON-NLS-1$
+ private static final String LOGGER_BUNDLE_EVENT = "Events.Bundle"; //$NON-NLS-1$
+ private static final String LOGGER_SERVICE_EVENT = "Events.Service"; //$NON-NLS-1$
- private static final String[] LOGSERVICE_CLASSES = {LogService.class.getName(), ExtendedLogService.class.getName()};
+ private static final String[] LOGSERVICE_CLASSES = {LogService.class.getName(), LoggerFactory.class.getName(), ExtendedLogService.class.getName()};
private static final String[] LOGREADERSERVICE_CLASSES = {LogReaderService.class.getName(), ExtendedLogReaderService.class.getName()};
private ServiceRegistration<?> logReaderServiceRegistration;
private ServiceRegistration<?> logServiceRegistration;
+ private ServiceRegistration<LoggerAdmin> loggerAdminRegistration;
private final ExtendedLogReaderServiceFactory logReaderServiceFactory;
private final ExtendedLogServiceFactory logServiceFactory;
private final ExtendedLogServiceImpl systemBundleLog;
@@ -51,6 +56,10 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
context.addBundleListener(logServiceFactory);
logReaderServiceRegistration = context.registerService(LOGREADERSERVICE_CLASSES, logReaderServiceFactory, null);
logServiceRegistration = context.registerService(LOGSERVICE_CLASSES, logServiceFactory, null);
+ Hashtable<String, Object> loggerAdminProps = new Hashtable<String, Object>();
+ // TODO the constant for log service id will like be defined
+ loggerAdminProps.put("osgi.log.service.id", logServiceRegistration.getReference().getProperty(Constants.SERVICE_ID)); //$NON-NLS-1$
+ loggerAdminRegistration = context.registerService(LoggerAdmin.class, logServiceFactory.getLoggerAdmin(), loggerAdminProps);
eventAdminAdapter = new EventAdminAdapter(context, logReaderServiceFactory);
eventAdminAdapter.start();
@@ -59,6 +68,8 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
public void stop(BundleContext context) {
eventAdminAdapter.stop();
eventAdminAdapter = null;
+ loggerAdminRegistration.unregister();
+ loggerAdminRegistration = null;
logServiceRegistration.unregister();
logServiceRegistration = null;
logReaderServiceRegistration.unregister();
@@ -73,14 +84,21 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
return systemBundleLog;
}
+ LoggerAdmin getLoggerAdmin() {
+ return logServiceFactory.getLoggerAdmin();
+ }
+
/**
* BundleListener.bundleChanged method.
*
*/
+ @SuppressWarnings("deprecation")
public void bundleChanged(BundleEvent event) {
Bundle bundle = event.getBundle();
- if (logReaderServiceFactory.isLoggable(bundle, null, LogService.LOG_INFO))
- logReaderServiceFactory.log(bundle, null, null, LogService.LOG_INFO, getBundleEventTypeName(event.getType()), null);
+ if (logReaderServiceFactory.isLoggable(bundle, LOGGER_BUNDLE_EVENT, LogService.LOG_INFO)) {
+ LoggerImpl logger = (LoggerImpl) systemBundleLog.getLogger(LOGGER_BUNDLE_EVENT);
+ logger.log(bundle, null, null, LogService.LOG_INFO, getBundleEventTypeName(event.getType()), null);
+ }
}
/**
@@ -91,9 +109,12 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
ServiceReference<?> reference = event.getServiceReference();
Bundle bundle = reference.getBundle();
int eventType = event.getType();
+ @SuppressWarnings("deprecation")
int logType = (eventType == ServiceEvent.MODIFIED) ? LogService.LOG_DEBUG : LogService.LOG_INFO;
- if (logReaderServiceFactory.isLoggable(bundle, null, logType))
- logReaderServiceFactory.log(bundle, null, reference, logType, getServiceEventTypeName(eventType), null);
+ if (logReaderServiceFactory.isLoggable(bundle, LOGGER_SERVICE_EVENT, logType)) {
+ LoggerImpl logger = (LoggerImpl) systemBundleLog.getLogger(LOGGER_SERVICE_EVENT);
+ logger.log(bundle, null, null, logType, getServiceEventTypeName(eventType), null);
+ }
}
/**
@@ -103,10 +124,12 @@ public class LogServiceManager implements BundleListener, FrameworkListener, Ser
public void frameworkEvent(FrameworkEvent event) {
Bundle bundle = event.getBundle();
int eventType = event.getType();
+ @SuppressWarnings("deprecation")
int logType = (eventType == FrameworkEvent.ERROR) ? LogService.LOG_ERROR : LogService.LOG_INFO;
- Throwable throwable = (eventType == FrameworkEvent.ERROR) ? event.getThrowable() : null;
- if (logReaderServiceFactory.isLoggable(bundle, null, logType))
- logReaderServiceFactory.log(bundle, null, null, logType, getFrameworkEventTypeName(eventType), throwable);
+ if (logReaderServiceFactory.isLoggable(bundle, LOGGER_FRAMEWORK_EVENT, logType)) {
+ LoggerImpl logger = (LoggerImpl) systemBundleLog.getLogger(LOGGER_FRAMEWORK_EVENT);
+ logger.log(bundle, null, null, logType, getFrameworkEventTypeName(eventType), event.getThrowable());
+ }
}
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerContextTargetMap.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerContextTargetMap.java
new file mode 100755
index 000000000..f22ff956a
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerContextTargetMap.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.internal.log;
+
+import java.util.*;
+import org.eclipse.osgi.internal.log.ExtendedLogServiceFactory.EquinoxLoggerContext;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.service.log.admin.LoggerContext;
+
+public class LoggerContextTargetMap {
+ private final Map<Bundle, ExtendedLogServiceImpl> logServices = new HashMap<Bundle, ExtendedLogServiceImpl>();
+ private final Map<String, EquinoxLoggerContext> loggerContexts = new HashMap<String, EquinoxLoggerContext>();
+ private final Map<Bundle, List<String>> targetToQualifiedNames = new HashMap<Bundle, List<String>>();
+ private final Map<String, Collection<Bundle>> qualifiedNameToTargets = new HashMap<String, Collection<Bundle>>();
+
+ List<String> add(Bundle b) {
+ String bsn = b.getSymbolicName();
+ if (bsn == null) {
+ bsn = ""; //$NON-NLS-1$
+ }
+ Version v = b.getVersion();
+ String version = v == null ? "" : v.toString(); //$NON-NLS-1$
+ String location = ExtendedLogServiceFactory.secureAction.getLocation(b);
+
+ List<String> result = new ArrayList<String>(3);
+
+ StringBuilder sb = new StringBuilder(bsn);
+ getTargetsInternal(bsn).add(b);
+
+ sb.append('|').append(version);
+ String bsnVersion = sb.toString();
+ getTargetsInternal(bsnVersion).add(b);
+
+ sb.append('|').append(location);
+ String bsnVersionLocation = sb.toString();
+ getTargetsInternal(bsnVersionLocation).add(b);
+
+ result.add(bsnVersionLocation);
+ result.add(bsnVersion);
+ result.add(bsn);
+
+ List<String> unmodifiable = Collections.unmodifiableList(result);
+ targetToQualifiedNames.put(b, unmodifiable);
+ return unmodifiable;
+ }
+
+ void remove(Bundle b) {
+ List<String> qualifiedNames = targetToQualifiedNames.remove(b);
+ if (qualifiedNames != null) {
+ for (String qualifiedName : qualifiedNames) {
+ Collection<Bundle> targets = qualifiedNameToTargets.get(qualifiedName);
+ if (targets != null) {
+ targets.remove(b);
+ if (targets.isEmpty()) {
+ qualifiedNameToTargets.remove(qualifiedName);
+ }
+ }
+ }
+ }
+ logServices.remove(b);
+ }
+
+ private Collection<Bundle> getTargetsInternal(String pid) {
+ Collection<Bundle> targets = qualifiedNameToTargets.get(pid);
+ if (targets == null) {
+ targets = new ArrayList<Bundle>(1);
+ qualifiedNameToTargets.put(pid, targets);
+ }
+ return targets;
+ }
+
+ ExtendedLogServiceImpl getLogService(Bundle bundle, ExtendedLogServiceFactory factory) {
+ ExtendedLogServiceImpl logService = logServices.get(bundle);
+ if (logService == null) {
+ // add bundle to target maps before constructing
+ add(bundle);
+ logService = new ExtendedLogServiceImpl(factory, bundle);
+ if (bundle != null && bundle.getState() != Bundle.UNINSTALLED)
+ logServices.put(bundle, logService);
+ }
+ return logService;
+ }
+
+ void replaceSystemBundleLogService(Bundle previousBundle, Bundle currentBundle) {
+ ExtendedLogServiceImpl existing = logServices.get(previousBundle);
+ if (existing != null) {
+ remove(previousBundle);
+ add(currentBundle);
+ logServices.put(currentBundle, existing);
+ existing.applyLogLevels(getEffectiveLoggerContext(currentBundle));
+ }
+ }
+
+ void clear() {
+ logServices.clear();
+ qualifiedNameToTargets.clear();
+ targetToQualifiedNames.clear();
+ }
+
+ LoggerContext createLoggerContext(String name, ExtendedLogServiceFactory factory) {
+ EquinoxLoggerContext loggerContext = loggerContexts.get(name);
+ if (loggerContext == null) {
+ loggerContext = factory.createEquinoxLoggerContext(name);
+ loggerContexts.put(null, loggerContext);
+ }
+ return loggerContext;
+ }
+
+ EquinoxLoggerContext getRootLoggerContext() {
+ return loggerContexts.get(null);
+ }
+
+ void applyLogLevels(EquinoxLoggerContext loggerContext) {
+ Collection<Bundle> matching;
+ boolean isRoot = loggerContext.getName() == null;
+ if (isRoot) {
+ // root applies to all loggers
+ matching = logServices.keySet();
+ } else {
+ matching = qualifiedNameToTargets.get(loggerContext.getName());
+ }
+ for (Bundle bundle : matching) {
+ ExtendedLogServiceImpl logService = logServices.get(bundle);
+ if (logService != null) {
+ // Always apply the effective log context.
+ // This may be more costly but it is more simple than checking
+ // if the changed context overrides the existing settings
+ logService.applyLogLevels(getEffectiveLoggerContext(bundle));
+ }
+ }
+ }
+
+ EquinoxLoggerContext getEffectiveLoggerContext(Bundle bundle) {
+ List<String> qualifiedNames = targetToQualifiedNames.get(bundle);
+ if (qualifiedNames != null) {
+ for (String qualifiedName : qualifiedNames) {
+ EquinoxLoggerContext loggerContext = loggerContexts.get(qualifiedName);
+ if (loggerContext != null && !loggerContext.isEmpty()) {
+ return loggerContext;
+ }
+ }
+ }
+ return getRootLoggerContext();
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
index 792bbd087..bf2f385b4 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
@@ -10,17 +10,23 @@ package org.eclipse.osgi.internal.log;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.equinox.log.Logger;
+import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.LogService;
+import org.osgi.service.log.admin.LoggerContext;
public class LoggerImpl implements Logger {
protected final ExtendedLogServiceImpl logServiceImpl;
protected final String name;
- public LoggerImpl(ExtendedLogServiceImpl logServiceImpl, String name) {
+ private LogLevel enabledLevel = LogLevel.TRACE;
+
+ public LoggerImpl(ExtendedLogServiceImpl logServiceImpl, String name, LoggerContext loggerContext) {
this.logServiceImpl = logServiceImpl;
this.name = name;
+ applyLoggerContext(loggerContext);
}
public String getName() {
@@ -46,7 +52,7 @@ public class LoggerImpl implements Logger {
@SuppressWarnings("rawtypes")
public void log(ServiceReference sr, int level, String message, Throwable exception) {
- logServiceImpl.log(name, sr, level, message, exception);
+ log(sr, null, level, message, exception);
}
public void log(Object context, int level, String message) {
@@ -54,12 +60,41 @@ public class LoggerImpl implements Logger {
}
public void log(Object context, int level, String message, Throwable exception) {
- logServiceImpl.log(name, context, level, message, exception);
+ log(context, null, level, message, exception);
+ }
+
+ private void log(Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) {
+ log(logServiceImpl.getBundle(), context, logLevelEnum, level, message, exception);
+ }
+
+ void log(Bundle entryBundle, Object context, LogLevel logLevelEnum, int level, String message, Throwable exception) {
+ if (logLevelEnum == null) {
+ logLevelEnum = getLogLevel(level);
+ }
+ if (enabledLevel.implies(logLevelEnum)) {
+ logServiceImpl.getFactory().log(entryBundle, name, context, logLevelEnum, level, message, exception);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private LogLevel getLogLevel(int level) {
+ switch (level) {
+ case LogService.LOG_DEBUG :
+ return LogLevel.DEBUG;
+ case LogService.LOG_ERROR :
+ return LogLevel.ERROR;
+ case LogService.LOG_INFO :
+ return LogLevel.INFO;
+ case LogService.LOG_WARNING :
+ return LogLevel.WARN;
+ default :
+ return LogLevel.TRACE;
+ }
}
@Override
public boolean isTraceEnabled() {
- return isLoggable(LogLevel.TRACE.ordinal());
+ return enabledLevel.implies(LogLevel.TRACE);
}
@Override
@@ -84,7 +119,7 @@ public class LoggerImpl implements Logger {
@Override
public boolean isDebugEnabled() {
- return isLoggable(LogLevel.DEBUG.ordinal());
+ return enabledLevel.implies(LogLevel.DEBUG);
}
@Override
@@ -109,7 +144,7 @@ public class LoggerImpl implements Logger {
@Override
public boolean isInfoEnabled() {
- return isLoggable(LogLevel.INFO.ordinal());
+ return enabledLevel.implies(LogLevel.INFO);
}
@Override
@@ -134,7 +169,7 @@ public class LoggerImpl implements Logger {
@Override
public boolean isWarnEnabled() {
- return isLoggable(LogLevel.WARN.ordinal());
+ return enabledLevel.implies(LogLevel.WARN);
}
@Override
@@ -159,7 +194,7 @@ public class LoggerImpl implements Logger {
@Override
public boolean isErrorEnabled() {
- return isLoggable(LogLevel.ERROR.ordinal());
+ return enabledLevel.implies(LogLevel.ERROR);
}
@Override
@@ -204,12 +239,16 @@ public class LoggerImpl implements Logger {
private static final Pattern pattern = Pattern.compile("(\\\\?)(\\\\?)(\\{\\})"); //$NON-NLS-1$
- protected void log(LogLevel level, String format, Object... arguments) {
- Arguments processedArguments = new Arguments(arguments);
- if (processedArguments.isEmpty()) {
- logServiceImpl.log(name, processedArguments.serviceReference(), level.ordinal(), format, processedArguments.throwable());
+ private void log(LogLevel level, String format, Object... arguments) {
+ if (!enabledLevel.implies(level)) {
return;
}
+ Arguments processedArguments = new Arguments(arguments);
+ String message = processedArguments.isEmpty() ? format : formatMessage(format, processedArguments);
+ logServiceImpl.getFactory().log(logServiceImpl.getBundle(), name, processedArguments.serviceReference(), level, level.ordinal(), message.toString(), processedArguments.throwable());
+ }
+
+ String formatMessage(String format, Arguments processedArguments) {
Matcher matcher = pattern.matcher(format);
char[] chars = format.toCharArray();
int offset = 0;
@@ -235,7 +274,7 @@ public class LoggerImpl implements Logger {
}
}
message.append(chars, offset, chars.length - offset);
- logServiceImpl.log(name, processedArguments.serviceReference(), level.ordinal(), message.toString(), processedArguments.throwable());
+ return message.toString();
}
private static int append(StringBuilder builder, Matcher matcher, char[] chars, int offset, int length, Object argument) {
@@ -243,4 +282,8 @@ public class LoggerImpl implements Logger {
builder.append(argument);
return matcher.end(3);
}
+
+ void applyLoggerContext(LoggerContext loggerContext) {
+ enabledLevel = loggerContext == null ? LogLevel.WARN : loggerContext.getEffectiveLogLevel(name);
+ }
}
diff --git a/bundles/org.eclipse.osgi/osgi/function.interface.jar b/bundles/org.eclipse.osgi/osgi/function.interface.jar
new file mode 100755
index 000000000..d2f08316f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/function.interface.jar
Binary files differ
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/FormatterLogger.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/FormatterLogger.java
index 964972b75..637d34fb8 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/FormatterLogger.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/FormatterLogger.java
@@ -31,8 +31,8 @@ import org.osgi.annotation.versioning.ProviderType;
* additional arguments. If the last argument is a {@code Throwable} or
* {@code ServiceReference}, it is added to the generated {@link LogEntry} and
* then if the next to last argument is a {@code ServiceReference} or
- * {@code Throwable}, it is added to the generated {@link LogEntry}. For
- * example:
+ * {@code Throwable} and not the same type as the last argument, it is added to
+ * the generated {@link LogEntry}. For example:
*
* <pre>
* logger.info("Found service %s.", serviceReference, serviceReference);
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogEntry.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogEntry.java
index 1b252eb63..6b3ee59f7 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogEntry.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogEntry.java
@@ -54,12 +54,14 @@ public interface LogEntry {
ServiceReference< ? > getServiceReference();
/**
- * Returns the level of this {@code LogEntry} object.
+ * Returns the integer level of this {@code LogEntry} object.
* <p>
- * This is one of the severity levels defined by the {@code LogService}
- * interface.
+ * If one of the {@code log} methods of {@link LogService} was used, this is
+ * the specified integer level. Otherwise, this is the
+ * {@link LogLevel#ordinal() ordinal} value of the {@link #getLogLevel() log
+ * level}.
*
- * @return Level of this {@code LogEntry} object.
+ * @return Integer level of this {@code LogEntry} object.
* @deprecated Since 1.4. Replaced by {@link #getLogLevel()}.
*/
@Deprecated
@@ -116,9 +118,7 @@ public interface LogEntry {
* {@code LogEntry} object.
*
* @return The name of the {@link Logger} object used to create this
- * {@code LogEntry} object or {@code ""} if this {@code LogEntry}
- * object was created using one of the original {@code LogService}
- * {@code log} methods.
+ * {@code LogEntry} object.
* @since 1.4
*/
String getLoggerName();
@@ -126,10 +126,9 @@ public interface LogEntry {
/**
* Returns the sequence number for this {@code LogEntry} object.
* <p>
- * The {@code LogService} assigns a unique, non-negative value that is
- * larger than all previously assigned values since the {@code LogService}
- * was started. These values are transient and are reused upon restart of
- * the {@code LogService}.
+ * A unique, non-negative value that is larger than all previously assigned
+ * values since the log implementation was started. These values are
+ * transient and are reused upon restart of the log implementation.
*
* @return The sequence number for this {@code LogEntry} object.
* @since 1.4
@@ -140,7 +139,8 @@ public interface LogEntry {
* Returns a string representing the thread which created this
* {@code LogEntry} object.
* <p>
- * This string contains the name of the thread.
+ * This string must contain the name of the thread and may contain other
+ * information about the thread.
*
* @return A string representing the thread which created this
* {@code LogEntry} object.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogLevel.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogLevel.java
index 94053969d..ebc1f14a4 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogLevel.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogLevel.java
@@ -61,6 +61,6 @@ public enum LogLevel {
* {@code false} otherwise.
*/
public boolean implies(LogLevel other) {
- return ordinal() <= other.ordinal();
+ return ordinal() >= other.ordinal();
}
}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogListener.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogListener.java
index 49bb6b7e4..4e6f645f4 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogListener.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogListener.java
@@ -37,6 +37,7 @@ import org.osgi.annotation.versioning.ConsumerType;
* @author $Id$
*/
@ConsumerType
+@FunctionalInterface
public interface LogListener extends EventListener {
/**
* Listener method called for each LogEntry object created.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
index 983c2b524..55d10697b 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LogService.java
@@ -74,6 +74,19 @@ public interface LogService extends LoggerFactory {
* <p>
* The {@code ServiceReference} field and the {@code Throwable} field of the
* {@code LogEntry} object will be set to {@code null}.
+ * <p>
+ * This method will log to the {@link Logger} named {@code "LogService"} for
+ * the bundle. The specified level is mapped to a {@link LogLevel} as
+ * follows:
+ * <ul>
+ * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
+ * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
+ * <li>{@link #LOG_INFO} - {@link LogLevel#INFO}</li>
+ * <li>{@link #LOG_DEBUG} - {@link LogLevel#DEBUG}</li>
+ * <li>Any other value - {@link LogLevel#TRACE}</li>
+ * </ul>
+ * In the generated log entry, {@link LogEntry#getLevel()} must return the
+ * specified level.
*
* @param level The severity of the message. This should be one of the
* defined log levels but may be any integer that is interpreted
@@ -91,6 +104,19 @@ public interface LogService extends LoggerFactory {
* <p>
* The {@code ServiceReference} field of the {@code LogEntry} object will be
* set to {@code null}.
+ * <p>
+ * This method will log to the {@link Logger} named {@code "LogService"} for
+ * the bundle. The specified level is mapped to a {@link LogLevel} as
+ * follows:
+ * <ul>
+ * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
+ * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
+ * <li>{@link #LOG_INFO} - {@link LogLevel#INFO}</li>
+ * <li>{@link #LOG_DEBUG} - {@link LogLevel#DEBUG}</li>
+ * <li>Any other value - {@link LogLevel#TRACE}</li>
+ * </ul>
+ * In the generated log entry, {@link LogEntry#getLevel()} must return the
+ * specified level.
*
* @param level The severity of the message. This should be one of the
* defined log levels but may be any integer that is interpreted
@@ -111,6 +137,19 @@ public interface LogService extends LoggerFactory {
* <p>
* The {@code Throwable} field of the {@code LogEntry} will be set to
* {@code null}.
+ * <p>
+ * This method will log to the {@link Logger} named {@code "LogService"} for
+ * the bundle. The specified level is mapped to a {@link LogLevel} as
+ * follows:
+ * <ul>
+ * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
+ * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
+ * <li>{@link #LOG_INFO} - {@link LogLevel#INFO}</li>
+ * <li>{@link #LOG_DEBUG} - {@link LogLevel#DEBUG}</li>
+ * <li>Any other value - {@link LogLevel#TRACE}</li>
+ * </ul>
+ * In the generated log entry, {@link LogEntry#getLevel()} must return the
+ * specified level.
*
* @param sr The {@code ServiceReference} object of the service that this
* message is associated with or {@code null}.
@@ -128,6 +167,19 @@ public interface LogService extends LoggerFactory {
/**
* Logs a message with an exception associated and a
* {@code ServiceReference} object.
+ * <p>
+ * This method will log to the {@link Logger} named {@code "LogService"} for
+ * the bundle. The specified level is mapped to a {@link LogLevel} as
+ * follows:
+ * <ul>
+ * <li>{@link #LOG_ERROR} - {@link LogLevel#ERROR}</li>
+ * <li>{@link #LOG_WARNING} - {@link LogLevel#WARN}</li>
+ * <li>{@link #LOG_INFO} - {@link LogLevel#INFO}</li>
+ * <li>{@link #LOG_DEBUG} - {@link LogLevel#DEBUG}</li>
+ * <li>Any other value - {@link LogLevel#TRACE}</li>
+ * </ul>
+ * In the generated log entry, {@link LogEntry#getLevel()} must return the
+ * specified level.
*
* @param sr The {@code ServiceReference} object of the service that this
* message is associated with.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/Logger.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/Logger.java
index 564a0ad19..790a664f4 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/Logger.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/Logger.java
@@ -34,8 +34,9 @@ import org.osgi.annotation.versioning.ProviderType;
* additional arguments. If the last argument is a {@code Throwable} or
* {@code ServiceReference}, it is added to the generated {@link LogEntry} and
* then if the next to last argument is a {@code ServiceReference} or
- * {@code Throwable}, it is added to the generated {@link LogEntry}. These
- * arguments will not be used for place holders. For example:
+ * {@code Throwable} and not the same type as the last argument, it is added to
+ * the generated {@link LogEntry}. These arguments will not be used for place
+ * holders. For example:
*
* <pre>
* logger.info("Found service {}.", serviceReference, serviceReference);
@@ -50,6 +51,10 @@ import org.osgi.annotation.versioning.ProviderType;
*/
@ProviderType
public interface Logger {
+ /**
+ * Root Logger Name.
+ */
+ static String ROOT_LOGGER_NAME = "ROOT";
/**
* Return the name of this Logger.
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LoggerFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LoggerFactory.java
index df1835468..3d17ce95f 100644
--- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LoggerFactory.java
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/LoggerFactory.java
@@ -23,6 +23,26 @@ import org.osgi.annotation.versioning.ProviderType;
* <p>
* Provides methods for bundles to obtain named {@link Logger}s that can be used
* to write messages to the log.
+ * <p>
+ * Logger names should be in the form of a fully qualified Java class names with
+ * segments separated by full stop ({@code '.'} &#92;u002E). For example:
+ *
+ * <pre>
+ * com.foo.Bar
+ * </pre>
+ *
+ * Logger names exist in a hierarchy. A logger name is said to be an ancestor of
+ * another logger name if the logger name followed by a full stop ({@code '.'}
+ * &#92;u002E) is a prefix of the descendant logger name. The
+ * {@link Logger#ROOT_LOGGER_NAME root logger name} is the top ancestor of the
+ * logger name hierarchy. For example:
+ *
+ * <pre>
+ * com.foo.Bar
+ * com.foo
+ * com
+ * ROOT
+ * </pre>
*
* @ThreadSafe
* @since 1.4
@@ -32,44 +52,50 @@ import org.osgi.annotation.versioning.ProviderType;
public interface LoggerFactory {
/**
- * Return a {@link Logger} named with the specified name.
+ * Return the {@link Logger} named with the specified name.
*
* @param name The name to use for the logger name.
- * @return A {@link Logger} named with the specified name.
+ * @return The {@link Logger} named with the specified name. If the name
+ * parameter is equal to {@link Logger#ROOT_LOGGER_NAME}, then the
+ * root logger is returned.
*/
Logger getLogger(String name);
/**
- * Return a {@link Logger} named with the specified class.
+ * Return the {@link Logger} named with the specified class.
*
* @param clazz The class to use for the logger name.
- * @return A {@link Logger} named with the specified class.
+ * @return The {@link Logger} named with the name of the specified class.
*/
Logger getLogger(Class< ? > clazz);
/**
- * Return a {@link Logger} of the specified type named with the specified
+ * Return the {@link Logger} of the specified type named with the specified
* name.
*
- * @param <L> A Logger type.
+ * @param <L> The Logger type.
* @param name The name to use for the logger name.
* @param loggerType The type of Logger. Can be {@link Logger} or
* {@link FormatterLogger}.
- * @return A {@link Logger} named with the specified name.
+ * @return The {@link Logger} or {@link FormatterLogger} named with the
+ * specified name. If the name parameter is equal to
+ * {@link Logger#ROOT_LOGGER_NAME}, then the root logger is
+ * returned.
* @throws IllegalArgumentException If the specified type is not a supported
* Logger type.
*/
<L extends Logger> L getLogger(String name, Class<L> loggerType);
/**
- * Return a {@link Logger} of the specified type named with the specified
+ * Return the {@link Logger} of the specified type named with the specified
* class.
*
* @param <L> A Logger type.
* @param clazz The class to use for the logger name.
* @param loggerType The type of Logger. Can be {@link Logger} or
* {@link FormatterLogger}.
- * @return A {@link Logger} named with the specified class.
+ * @return The {@link Logger} or {@link FormatterLogger} named with the name
+ * of the specified class.
* @throws IllegalArgumentException If the specified type is not a supported
* Logger type.
*/
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerAdmin.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerAdmin.java
new file mode 100644
index 000000000..37c8ef2cf
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerAdmin.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) OSGi Alliance (2016). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.log.admin;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.service.log.LoggerFactory;
+
+/**
+ * LoggerAdmin service for configuring loggers.
+ * <p>
+ * Each bundle may have its own named {@link LoggerContext} based upon its
+ * bundle symbolic name, bundle version, and bundle location. There is also a
+ * root Logger Context from which each named Logger Context inherits. The root
+ * Logger Context has no name.
+ * <p>
+ * When a bundle logs, the logger implementation must locate the Logger Context
+ * for the bundle to determine the
+ * {@link LoggerContext#getEffectiveLogLevel(String) effective log level} of the
+ * logger name. The <i>best matching name</i> for the Logger Context is the
+ * longest name, which has a non-empty Logger Context, according to this syntax:
+ *
+ * <pre>
+ * name ::= symbolic-name ( ’|’ version ( ’|’ location )? )?
+ * </pre>
+ *
+ * The version must be formatted canonically, that is, according to the
+ * {@code toString()} method of the {@code Version} class. So the Logger Context
+ * for a bundle is searched for using the following names in the given order:
+ *
+ * <pre>
+ * &lt;symbolic-name&gt;|&lt;version&gt;|&lt;location&gt;
+ * &lt;symbolic-name&gt;|&lt;version&gt;
+ * &lt;symbolic-name&gt;
+ * </pre>
+ *
+ * If a non-empty Logger Context is not found, the Logger Context with the name
+ * {@code <symbolic-name>} is used for the bundle.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface LoggerAdmin {
+ /**
+ * Logger Admin service property to associate the Logger Admin service with
+ * a {@link LoggerFactory} service.
+ * <p>
+ * This service property is set to the {@code service.id} for the
+ * {@link LoggerFactory} service administered by this Logger Admin.
+ * <p>
+ * The value of this service property must be of type {@code Long}.
+ */
+ static String LOG_SERVICE_ID = "osgi.log.service.id";
+
+ /**
+ * Get the Logger Context for the specified name.
+ *
+ * @param name The name of the Logger Context. Can be {@code null} to
+ * specify the root Logger Context.
+ * @return The Logger Context for the specified name.
+ */
+ LoggerContext getLoggerContext(String name);
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerContext.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerContext.java
new file mode 100644
index 000000000..33b9e4b6f
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/LoggerContext.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) OSGi Alliance (2016). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.log.admin;
+
+import java.util.Map;
+
+import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.service.log.LogLevel;
+
+/**
+ * Logger Context for a bundle.
+ * <p>
+ * Any change to the configuration of this Logger Context must be effective
+ * immediately for all loggers that would rely upon the configuration of this
+ * Logger Context.
+ *
+ * @ThreadSafe
+ * @author $Id$
+ */
+@ProviderType
+public interface LoggerContext {
+ /**
+ * Returns the name for this Logger Context.
+ *
+ * @return The name for this Logger Context. The root Logger Context has no
+ * name and returns {@code null}.
+ */
+ String getName();
+
+ /**
+ * Returns the effective log level of the logger name in this Logger
+ * Context.
+ * <p>
+ * The effective log level for a logger name is found by the following
+ * steps:
+ * <ol>
+ * <li>If the specified logger name is configured with a non-null log level
+ * in this Logger Context, return the configured log level.</li>
+ * <li>For each ancestor logger name of the specified logger name, if the
+ * ancestor logger name is configured with a non-null log level in this
+ * Logger Context, return the configured log level.</li>
+ * <li>If the specified logger name is configured with a non-null log level
+ * in the root Logger Context, return the configured log level.</li>
+ * <li>For each ancestor logger name of the specified logger name, if the
+ * ancestor logger name is configured with a non-null log level in the root
+ * Logger Context, return the configured log level.</li>
+ * <li>Return {@link LogLevel#WARN} because no non-null log level has been
+ * found for the specified logger name or any of its ancestor logger names.
+ * </li>
+ * </ol>
+ *
+ * @param name The logger name.
+ * @return The effective log level of the logger name in this Logger
+ * Context.
+ */
+ LogLevel getEffectiveLogLevel(String name);
+
+ /**
+ * Returns the configured log levels for this Logger Context.
+ *
+ * @return The configured log levels for this Logger Context. The keys are
+ * the logger names and the values are the log levels. The returned
+ * map may be empty if no logger names are configured for this
+ * Logger Context. The log level value can be {@code null}. The
+ * returned map is the property of the caller who can modify the map
+ * and use it as input to {@link #setLogLevels(Map)}. The returned
+ * map must support all optional Map operations.
+ */
+ Map<String,LogLevel> getLogLevels();
+
+ /**
+ * Configure the log levels for this Logger Context.
+ * <p>
+ * All previous log levels configured for this Logger Context are cleared
+ * and then the log levels in the specified map are configured.
+ *
+ * @param logLevels The log levels to configure for this Logger Context. The
+ * keys are the logger names and the values are the log levels.
+ * The log level value can be {@code null}. The specified map is
+ * the property of the caller and this method must not modify or
+ * retain the specified map.
+ */
+ void setLogLevels(Map<String,LogLevel> logLevels);
+
+ /**
+ * Clear the configuration of this Logger Context.
+ * <p>
+ * The configured log levels will be cleared.
+ */
+ void clear();
+
+ /**
+ * Returns whether the configuration of this Logger Context is empty.
+ *
+ * @return {@code true} if this Logger Context has no configuration. That
+ * is, the configured log levels are empty. Otherwise {@code false}
+ * is returned.
+ */
+ boolean isEmpty();
+}
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/package-info.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/package-info.java
new file mode 100644
index 000000000..21f2c3493
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/package-info.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) OSGi Alliance (2016). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Log Admin Package Version 1.0.
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.log.admin; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.log.admin; version="[1.0,1.1)"}
+ *
+ * @author $Id$
+ */
+@Version("1.0")
+package org.osgi.service.log.admin;
+
+import org.osgi.annotation.versioning.Version;
diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/packageinfo b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/packageinfo
new file mode 100644
index 000000000..7c8de0324
--- /dev/null
+++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/log/admin/packageinfo
@@ -0,0 +1 @@
+version 1.0

Back to the top