diff options
author | Thomas Watson | 2016-03-04 14:30:44 +0000 |
---|---|---|
committer | Thomas Watson | 2017-06-16 12:38:08 +0000 |
commit | c7fae461022cd049802023f56bb518b8a81ad02a (patch) | |
tree | 87276855dc7fc1b82f10c56d1a24af4fd25df758 /bundles/org.eclipse.osgi/container/src/org/eclipse | |
parent | f31b2c1056822bdc2e77b22f558a087943f7a22d (diff) | |
download | rt.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>
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse')
12 files changed, 565 insertions, 88 deletions
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); + } } |