You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ro...@apache.org on 2018/07/02 21:27:41 UTC
svn commit: r1834903 - in /felix/trunk/log: ./
src/main/java/org/apache/felix/log/
Author: rotty3000
Date: Mon Jul 2 21:27:40 2018
New Revision: 1834903
URL: http://svn.apache.org/viewvc?rev=1834903&view=rev
Log:
FELIX-5876 Update to Log Service Specification 1.4
Doesn't yet implement LogStreamProvider but otherwise passes the org.osgi.test.cases.log and org.osgi.test.cases.log.launch CTs
Signed-off-by: Raymond Auge <ro...@apache.org>
Added:
felix/trunk/log/src/main/java/org/apache/felix/log/FormatterLoggerImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/LoggerAdminImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/LoggerContextImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/LoggerImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/RootLoggerContextImpl.java
Modified:
felix/trunk/log/pom.xml
felix/trunk/log/src/main/java/org/apache/felix/log/Activator.java
felix/trunk/log/src/main/java/org/apache/felix/log/Log.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogEntryImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogException.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogListenerThread.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogNodeEnumeration.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceFactory.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceImpl.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceFactory.java
felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceImpl.java
Modified: felix/trunk/log/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/log/pom.xml?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/pom.xml (original)
+++ felix/trunk/log/pom.xml Mon Jul 2 21:27:40 2018
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.felix</groupId>
<artifactId>felix-parent</artifactId>
- <version>1.2.1</version>
+ <version>5</version>
<relativePath>../pom/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -31,52 +31,68 @@
</description>
<version>1.1.0-SNAPSHOT</version>
<artifactId>org.apache.felix.log</artifactId>
+
+ <properties>
+ <maven.compiler.source>1.7</maven.compiler.source>
+ <maven.compiler.target>1.7</maven.compiler.target>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <version>4.1.0</version>
+ <artifactId>osgi.core</artifactId>
+ <version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- <version>4.1.0</version>
+ <artifactId>org.osgi.service.cm</artifactId>
+ <version>1.6.0</version>
</dependency>
- </dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.log</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+ </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.4</version>
+ <version>3.5.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
- <Export-Package>org.osgi.service.log</Export-Package>
+ <Export-Package>org.osgi.service.log,org.osgi.service.log.admin</Export-Package>
<Private-Package>org.apache.felix.log</Private-Package>
<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Activator>${pom.artifactId}.Activator</Bundle-Activator>
<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
<Export-Service>org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService</Export-Service>
<Include-Resource>META-INF/LICENSE=LICENSE,META-INF/NOTICE=NOTICE,META-INF/DEPENDENCIES=DEPENDENCIES</Include-Resource>
+ <Provide-Capability><![CDATA[
+ osgi.service;objectClass:List<String>="org.osgi.service.log.admin.LoggerAdmin";uses:="org.osgi.service.log,org.osgi.service.log.admin",
+ osgi.service;objectClass:List<String>="org.osgi.service.log.LogReaderService";uses:="org.osgi.service.log,org.osgi.service.log.admin",
+ osgi.service;objectClass:List<String>="org.osgi.service.log.LogService,org.osgi.service.log.LoggerFactory";uses:="org.osgi.service.log,org.osgi.service.log.admin"
+ ]]></Provide-Capability>
</instructions>
</configuration>
</plugin>
<plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>rat-maven-plugin</artifactId>
- <configuration>
- <excludeSubProjects>false</excludeSubProjects>
- <useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
- <useMavenDefaultExcludes>true</useMavenDefaultExcludes>
- <excludes>
- <param>doc/*</param>
- <param>maven-eclipse.xml</param>
- <param>.checkstyle</param>
- <param>.externalToolBuilders/*</param>
- </excludes>
- </configuration>
- </plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <configuration>
+ <excludeSubProjects>false</excludeSubProjects>
+ <useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
+ <useMavenDefaultExcludes>true</useMavenDefaultExcludes>
+ <excludes>
+ <param>doc/*</param>
+ <param>maven-eclipse.xml</param>
+ <param>.checkstyle</param>
+ <param>.externalToolBuilders/*</param>
+ </excludes>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/Activator.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/Activator.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/Activator.java Mon Jul 2 21:27:40 2018
@@ -18,10 +18,28 @@
*/
package org.apache.felix.log;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+import org.osgi.service.log.LogLevel;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.log.LogService;
+import org.osgi.service.log.LoggerFactory;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* The bundle activator for the OSGi log service (see section 101 of the service
@@ -57,6 +75,10 @@ public final class Activator implements
private static final boolean DEFAULT_STORE_DEBUG = false;
/** The log. */
private Log m_log;
+ /** The LoggerAdmin. */
+ private LoggerAdminImpl m_loggerAdmin;
+ /** ConfigurationAdmin tracker */
+ private ServiceTracker<ConfigurationAdmin, ConfigurationAdmin> m_cmtracker;
/**
* Returns the maximum size for the log.
@@ -102,6 +124,15 @@ public final class Activator implements
}
/**
+ * Return the default log level.
+ * @param context
+ * @return the default log level
+ */
+ private static String getDefaultLogLevel(final BundleContext context) {
+ return context.getProperty(LoggerContext.LOGGER_CONTEXT_DEFAULT_LOGLEVEL);
+ }
+
+ /**
* Called by the OSGi framework when the bundle is started.
* Used to register the service implementations with the framework.
* @param context the bundle context
@@ -111,6 +142,8 @@ public final class Activator implements
{
// create the log instance
m_log = new Log(getMaxSize(context), getStoreDebug(context));
+ // create the LoggerAdmin instance
+ m_loggerAdmin = new LoggerAdminImpl(getDefaultLogLevel(context), m_log);
// register the listeners
context.addBundleListener(m_log);
@@ -118,11 +151,54 @@ public final class Activator implements
context.addServiceListener(m_log);
// register the services with the framework
- context.registerService(LogService.class.getName(),
- new LogServiceFactory(m_log), null);
+ ServiceRegistration<?> serviceRegistration = context.registerService(
+ new String[] {LogService.class.getName(), LoggerFactory.class.getName()},
+ new LogServiceFactory(m_loggerAdmin), null);
context.registerService(LogReaderService.class.getName(),
new LogReaderServiceFactory(m_log), null);
+
+ Dictionary<String, Object> properties = new Hashtable<>();
+ properties.put(
+ LoggerAdmin.LOG_SERVICE_ID,
+ serviceRegistration.getReference().getProperty(Constants.SERVICE_ID));
+ context.registerService(LoggerAdmin.class.getName(), m_loggerAdmin, properties);
+
+ // create the cm tracker
+ m_cmtracker = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>(
+ context, ConfigurationAdmin.class, new CMLogCustomizer(context));
+
+ m_cmtracker.open();
+
+ context.registerService(
+ ConfigurationListener.class.getName(),
+ new ConfigurationListener() {
+
+ @Override
+ public void configurationEvent(ConfigurationEvent event) {
+ String pid = event.getPid();
+ String configName = null;
+ if (pid.startsWith("org.osgi.service.log.admin|")) {
+ configName = pid.substring("org.osgi.service.log.admin|".length());
+ }
+
+ switch (event.getType()) {
+ case ConfigurationEvent.CM_DELETED:
+ m_loggerAdmin.updateConfiguration(configName, null);
+ break;
+ case ConfigurationEvent.CM_LOCATION_CHANGED:
+ case ConfigurationEvent.CM_UPDATED:
+ ConfigurationAdmin cm = m_cmtracker.getService(event.getReference());
+ try {
+ Configuration configuration = cm.getConfiguration(pid);
+ m_loggerAdmin.updateConfiguration(configName, configuration.getProperties());
+ } catch (IOException e) {
+ m_log.log(Activator.class.getName(), context.getBundle(), null, LogLevel.ERROR, "An error occured while LogService was getting configuration from cm.", e);
+ }
+ }
+ }
+
+ }, null);
}
/**
@@ -132,7 +208,61 @@ public final class Activator implements
*/
public void stop(final BundleContext context) throws Exception
{
+ // close the cm tracker
+ m_cmtracker.close();
// close the log
m_log.close();
}
+
+ class CMLogCustomizer implements ServiceTrackerCustomizer<ConfigurationAdmin, ConfigurationAdmin> {
+
+ private final BundleContext m_context;
+
+ public CMLogCustomizer(BundleContext context) {
+ m_context = context;
+ }
+
+ @Override
+ public ConfigurationAdmin addingService(ServiceReference<ConfigurationAdmin> reference) {
+ ConfigurationAdmin cm = m_context.getService(reference);
+ // configure ROOT context
+ updateContext(null, "org.osgi.service.log.admin", cm, false);
+ // configure bundle contexts
+ for (String name : m_loggerAdmin.getLoggerContextNames()) {
+ String pid = "org.osgi.service.log.admin|" + name;
+ updateContext(name, pid, cm, false);
+ }
+ return cm;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<ConfigurationAdmin> reference, ConfigurationAdmin service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<ConfigurationAdmin> reference, ConfigurationAdmin cm) {
+ // un-configure bundle contexts
+ for (String name : m_loggerAdmin.getLoggerContextNames()) {
+ String pid = "org.osgi.service.log.admin|" + name;
+ updateContext(name, pid, cm, true);
+ }
+ // un-configure ROOT context
+ updateContext(null, "org.osgi.service.log.admin", cm, true);
+ }
+
+ private void updateContext(String name, String pid, ConfigurationAdmin cm, boolean delete) {
+ try {
+ Configuration[] configurations = cm.listConfigurations(String.format("(%s=%s)", Constants.SERVICE_PID, pid));
+
+ if (configurations != null && configurations.length > 0) {
+ m_loggerAdmin.updateConfiguration(name, delete ? null : configurations[0].getProperties());
+ }
+ }
+ catch (IOException | InvalidSyntaxException e) {
+ m_log.log(Activator.class.getName(), m_context.getBundle(), null, LogLevel.ERROR, "An error occured while LogService was getting configuration from cm.", e);
+ }
+ }
+
+ }
+
}
\ No newline at end of file
Added: felix/trunk/log/src/main/java/org/apache/felix/log/FormatterLoggerImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/FormatterLoggerImpl.java?rev=1834903&view=auto
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/FormatterLoggerImpl.java (added)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/FormatterLoggerImpl.java Mon Jul 2 21:27:40 2018
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.log;
+
+import java.util.Formatter;
+import java.util.Locale;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.FormatterLogger;
+
+public class FormatterLoggerImpl extends LoggerImpl implements FormatterLogger {
+
+ public FormatterLoggerImpl(
+ final String name, final Bundle bundle, final Log log, final LoggerAdminImpl loggerAdmin) {
+
+ super(name, bundle, log, loggerAdmin);
+ }
+
+ String format(String format, LogParameters logParameters) {
+ StringBuilder sb = new StringBuilder();
+
+ try (Formatter formatter = new Formatter(sb, Locale.getDefault())) {
+ formatter.format(format, logParameters.args);
+
+ return sb.toString();
+ }
+ }
+
+}
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/Log.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/Log.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/Log.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/Log.java Mon Jul 2 21:27:40 2018
@@ -20,15 +20,17 @@ package org.apache.felix.log;
import java.util.Enumeration;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogLevel;
import org.osgi.service.log.LogListener;
-import org.osgi.service.log.LogService;
/**
* Class used to represent the log. This class is used by the implementations
@@ -79,6 +81,17 @@ final class Log implements BundleListene
m_size = 0;
}
+ void log(
+ final String name,
+ final Bundle bundle,
+ final ServiceReference<?> sr,
+ final LogLevel level,
+ final String message,
+ final Throwable exception) {
+
+ addEntry(new LogEntryImpl(name, bundle, sr, level, message, exception, getStackTraceElement()));
+ }
+
/**
* Adds the entry to the log.
* @param entry the entry to add to the log
@@ -88,7 +101,7 @@ final class Log implements BundleListene
if (m_maxSize != 0)
{
// add the entry to the historic log
- if (m_storeDebug || entry.getLevel() != LogService.LOG_DEBUG)
+ if (m_storeDebug || entry.getLogLevel() != LogLevel.DEBUG)
{
// create a new node for the entry
LogNode node = new LogNode(entry);
@@ -172,7 +185,7 @@ final class Log implements BundleListene
* Returns an enumeration of all the entries in the log most recent first.
* @return an enumeration of all the entries in the log most recent first
*/
- synchronized Enumeration getEntries()
+ synchronized Enumeration<LogEntry> getEntries()
{
return new LogNodeEnumeration(m_head, m_tail);
}
@@ -205,13 +218,13 @@ final class Log implements BundleListene
}
}
- LogEntry entry = new LogEntryImpl(event.getBundle(),
+ log(
+ "Events.Framework",
+ event.getBundle(),
null,
- (eventType == FrameworkEvent.ERROR) ? LogService.LOG_ERROR : LogService.LOG_INFO,
+ (eventType == FrameworkEvent.ERROR) ? LogLevel.ERROR : LogLevel.INFO,
message,
event.getThrowable());
-
- addEntry(entry);
}
/** The messages returned for the bundle events. */
@@ -245,14 +258,27 @@ final class Log implements BundleListene
if (message != null)
{
- LogEntry entry = new LogEntryImpl(event.getBundle(),
+ log(
+ "Events.Bundle",
+ event.getBundle(),
null,
- LogService.LOG_INFO,
+ LogLevel.INFO,
message,
null);
+ }
+ }
- addEntry(entry);
+ public static StackTraceElement getStackTraceElement() {
+ StackTraceElement[] elements = Thread.currentThread().getStackTrace();
+ if (elements.length == 0) {
+ return null;
+ }
+ for (int i = 1; i < elements.length; i++) {
+ if (!elements[i].getClassName().startsWith("org.apache.felix.log")) {
+ return elements[i];
+ }
}
+ return elements[1];
}
/** The messages returned for the service events. */
@@ -280,12 +306,12 @@ final class Log implements BundleListene
}
}
- LogEntry entry = new LogEntryImpl(event.getServiceReference().getBundle(),
+ log(
+ "Events.Service",
+ event.getServiceReference().getBundle(),
event.getServiceReference(),
- (eventType == ServiceEvent.MODIFIED) ? LogService.LOG_DEBUG : LogService.LOG_INFO,
+ (eventType == ServiceEvent.MODIFIED) ? LogLevel.DEBUG : LogLevel.INFO,
message,
null);
-
- addEntry(entry);
}
}
\ No newline at end of file
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogEntryImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogEntryImpl.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogEntryImpl.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogEntryImpl.java Mon Jul 2 21:27:40 2018
@@ -18,9 +18,15 @@
*/
package org.apache.felix.log;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.concurrent.atomic.AtomicLong;
+
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.LogService;
/**
* Implementation of the OSGi {@link LogEntry} interface. See section 101
@@ -37,39 +43,99 @@ import org.osgi.service.log.LogEntry;
*/
final class LogEntryImpl implements LogEntry
{
+ /** The sequence number generator. */
+ private static final AtomicLong m_sequenceGenerator = new AtomicLong();
+
+ /** The name of the logger used to create the LogEntry. */
+ private final String m_name;
/** The bundle that created the LogEntry object. */
private final Bundle m_bundle;
/** The exception associated with this LogEntry object. */
private final Throwable m_exception;
/** The severity level of this LogEntry object. */
- private final int m_level;
+ private final LogLevel m_level;
+ private final int m_legacyLevel;
/** The message associated with this LogEntry object. */
private final String m_message;
/** The service reference associated with this LogEntry object. */
- private final ServiceReference m_serviceReference;
+ private final ServiceReference<?> m_serviceReference;
/** The system time in milliseconds when this LogEntry object was created. */
private final long m_time;
+ /** The sequence of the LogEntry. */
+ private final long m_sequence;
+ /** The information about the Thread which logged the message. */
+ private final String m_threadInfo;
+ /** The StackTraceElement where the message was originally logged. */
+ private final StackTraceElement m_stackTraceElement;
+
+ private volatile String _toString;
/**
* Create a new instance.
+ * @param name the name of the logger used to create the LogEntry
* @param bundle the bundle that created the LogEntry object
* @param sr the service reference to associate with this LogEntry object
* @param level the severity level for this LogEntry object
* @param message the message to associate with this LogEntry object
* @param exception the exception to associate with this LogEntry object
*/
- LogEntryImpl(final Bundle bundle,
- final ServiceReference sr,
- final int level,
+ LogEntryImpl(
+ final String name,
+ final Bundle bundle,
+ final ServiceReference<?> sr,
+ final LogLevel level,
+ final String message,
+ final Throwable exception,
+ final StackTraceElement stackTraceElement)
+ {
+ this.m_name = name;
+ this.m_bundle = bundle;
+ this.m_exception = LogException.getException(exception);
+ this.m_level = level;
+ this.m_legacyLevel = level.ordinal();
+ this.m_message = message;
+ this.m_serviceReference = sr;
+ this.m_time = System.currentTimeMillis();
+ this.m_sequence = m_sequenceGenerator.getAndIncrement();
+ this.m_threadInfo = Thread.currentThread().getName();
+ this.m_stackTraceElement = stackTraceElement;
+ }
+
+ @SuppressWarnings("deprecation")
+ LogEntryImpl(
+ final String name,
+ final Bundle bundle,
+ final ServiceReference<?> sr,
+ final int legacyLevel,
final String message,
- final Throwable exception)
+ final Throwable exception,
+ final StackTraceElement stackTraceElement)
{
+ this.m_name = name;
this.m_bundle = bundle;
this.m_exception = LogException.getException(exception);
+ LogLevel level = LogLevel.TRACE;
+ switch (legacyLevel) {
+ case LogService.LOG_ERROR:
+ level = LogLevel.ERROR;
+ break;
+ case LogService.LOG_WARNING:
+ level = LogLevel.WARN;
+ break;
+ case LogService.LOG_INFO:
+ level = LogLevel.INFO;
+ break;
+ case LogService.LOG_DEBUG:
+ level = LogLevel.DEBUG;
+ }
this.m_level = level;
+ this.m_legacyLevel = ((level == LogLevel.TRACE) ? legacyLevel : level.ordinal());
this.m_message = message;
this.m_serviceReference = sr;
this.m_time = System.currentTimeMillis();
+ this.m_sequence = m_sequenceGenerator.getAndIncrement();
+ this.m_threadInfo = Thread.currentThread().getName();
+ this.m_stackTraceElement = stackTraceElement;
}
/**
@@ -89,7 +155,7 @@ final class LogEntryImpl implements LogE
* this LogEntry object; <code>null</code> if no {@link ServiceReference} object
* was provided
*/
- public ServiceReference getServiceReference()
+ public ServiceReference<?> getServiceReference()
{
return m_serviceReference;
}
@@ -107,7 +173,11 @@ final class LogEntryImpl implements LogE
*/
public int getLevel()
{
- return m_level;
+ if (m_legacyLevel != m_level.ordinal()) {
+ return m_legacyLevel;
+ }
+
+ return m_level.ordinal();
}
/**
@@ -147,4 +217,49 @@ final class LogEntryImpl implements LogE
{
return m_time;
}
+
+ @Override
+ public LogLevel getLogLevel() {
+ return m_level;
+ }
+
+ @Override
+ public String getLoggerName() {
+ return m_name;
+ }
+
+ @Override
+ public long getSequence() {
+ return m_sequence;
+ }
+
+ @Override
+ public String getThreadInfo() {
+ return m_threadInfo;
+ }
+
+ @Override
+ public StackTraceElement getLocation() {
+ return m_stackTraceElement;
+ }
+
+ @Override
+ public String toString() {
+ if (_toString == null) {
+ _toString = m_time + "#" + m_sequence + " [" + m_threadInfo + "] " + m_level +
+ " (" + m_legacyLevel + ") [" + m_bundle.getBundleId() + ":" + m_name + "] " +
+ m_stackTraceElement.getClassName() + ":" +
+ m_stackTraceElement.getLineNumber() + " > " + m_message +
+ (m_exception != null ? "\n" + exceptionString(m_exception) : "");
+ }
+ return _toString;
+ }
+
+ String exceptionString(Throwable t) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ return sw.toString();
+ }
+
}
\ No newline at end of file
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogException.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogException.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogException.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogException.java Mon Jul 2 21:27:40 2018
@@ -28,6 +28,9 @@ package org.apache.felix.log;
*/
final class LogException extends Exception
{
+
+ private static final long serialVersionUID = 1296580652284691039L;
+
/** The class name of the original exception. */
private final String m_className;
/** The message from the original exception. */
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogListenerThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogListenerThread.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogListenerThread.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogListenerThread.java Mon Jul 2 21:27:40 2018
@@ -34,9 +34,9 @@ import org.osgi.service.log.LogListener;
final class LogListenerThread extends Thread
{
// The list of entries waiting to be delivered to the log listeners.
- private final List m_entriesToDeliver = new ArrayList();
+ private final List<LogEntry> m_entriesToDeliver = new ArrayList<>();
// The list of listeners.
- private final List m_listeners = new ArrayList();
+ private final List<LogListener> m_listeners = new ArrayList<>();
LogListenerThread() {
super("FelixLogListener");
@@ -110,7 +110,7 @@ final class LogListenerThread extends Th
{
while (!isInterrupted())
{
- List entriesToDeliver = new ArrayList();
+ List<LogEntry> entriesToDeliver = new ArrayList<>();
synchronized (m_entriesToDeliver)
{
if (m_entriesToDeliver.isEmpty())
@@ -121,46 +121,47 @@ final class LogListenerThread extends Th
}
catch (InterruptedException e)
{
- // the interrupt-flag is cleared; so, let's play nice and
+ // the interrupt-flag is cleared; so, let's play nice and
// interrupt this thread again to stop it...
interrupt();
}
}
- else
+ else
{
// Copy all current entries and deliver them in a single go...
entriesToDeliver.addAll(m_entriesToDeliver);
m_entriesToDeliver.clear();
}
}
-
+
if (!entriesToDeliver.isEmpty())
{
// Take a snapshot of all current listeners and deliver all
// pending messages to them...
- List listeners = new ArrayList();
- synchronized (m_listeners)
+ List<LogListener> listeners = new ArrayList<>();
+ synchronized (m_listeners)
{
listeners.addAll(m_listeners);
}
- Iterator entriesIt = entriesToDeliver.iterator();
- while (entriesIt.hasNext())
+ Iterator<LogEntry> entriesIt = entriesToDeliver.iterator();
+ while (entriesIt.hasNext())
{
- LogEntry entry = (LogEntry) entriesIt.next();
-
- Iterator listenerIt = listeners.iterator();
+ LogEntry entry = entriesIt.next();
+
+ Iterator<LogListener> listenerIt = listeners.iterator();
while (listenerIt.hasNext())
{
- LogListener listener = (LogListener) listenerIt.next();
-
+ LogListener listener = listenerIt.next();
+
try
{
listener.logged(entry);
}
catch (Throwable t)
{
- // catch and discard any exceptions thrown by the listener
+ System.err.println("Logger failed to log with " + t.getMessage());
+ t.printStackTrace(System.err);
}
}
}
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogNodeEnumeration.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogNodeEnumeration.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogNodeEnumeration.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogNodeEnumeration.java Mon Jul 2 21:27:40 2018
@@ -26,7 +26,7 @@ import org.osgi.service.log.LogEntry;
* Implementation of the {@link Enumeration} interface for a linked list of
* {@link LogNode} entries.
*/
-final class LogNodeEnumeration implements Enumeration
+final class LogNodeEnumeration implements Enumeration<LogEntry>
{
/** The next node. */
private LogNode m_next;
@@ -57,7 +57,7 @@ final class LogNodeEnumeration implement
* Returns the current element and moves onto the next element.
* @return the current element
*/
- public Object nextElement()
+ public LogEntry nextElement()
{
LogEntry result = null;
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceFactory.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceFactory.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceFactory.java Mon Jul 2 21:27:40 2018
@@ -21,12 +21,13 @@ package org.apache.felix.log;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogReaderService;
/**
* {@link ServiceFactory} implementation for {@link LogReaderService}. Associates
* an individual {@link LogReaderService} with a {@link Bundle}.
*/
-final class LogReaderServiceFactory implements ServiceFactory
+final class LogReaderServiceFactory implements ServiceFactory<LogReaderService>
{
/** The log to associate the service implementations with. */
private final Log m_log;
@@ -46,8 +47,8 @@ final class LogReaderServiceFactory impl
* @param registration the service registration
* @return the log reader service implementation for the specified bundle
*/
- public Object getService(final Bundle bundle,
- final ServiceRegistration registration)
+ public LogReaderService getService(final Bundle bundle,
+ final ServiceRegistration<LogReaderService> registration)
{
return new LogReaderServiceImpl(m_log);
}
@@ -60,8 +61,8 @@ final class LogReaderServiceFactory impl
* @param service the service to release
*/
public void ungetService(final Bundle bundle,
- final ServiceRegistration registration,
- final Object service)
+ final ServiceRegistration<LogReaderService> registration,
+ final LogReaderService service)
{
((LogReaderServiceImpl) service).removeAllLogListeners();
}
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceImpl.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceImpl.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogReaderServiceImpl.java Mon Jul 2 21:27:40 2018
@@ -23,6 +23,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Vector;
+import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
@@ -41,7 +42,7 @@ final class LogReaderServiceImpl impleme
/** The log implementation. */
private final Log m_log;
/** The listeners associated with this service. */
- private final List m_listeners = new Vector();
+ private final List<LogListener> m_listeners = new Vector<>();
/**
* Create a new instance.
@@ -87,7 +88,7 @@ final class LogReaderServiceImpl impleme
* entry first.
* @return an enumeration of the {@link LogEntry} objects that have been stored
*/
- public Enumeration getLog()
+ public Enumeration<LogEntry> getLog()
{
return m_log.getEntries();
}
@@ -97,10 +98,10 @@ final class LogReaderServiceImpl impleme
*/
synchronized void removeAllLogListeners()
{
- Iterator listenerIt = m_listeners.iterator();
+ Iterator<LogListener> listenerIt = m_listeners.iterator();
while (listenerIt.hasNext())
{
- LogListener listener = (LogListener) listenerIt.next();
+ LogListener listener = listenerIt.next();
m_log.removeListener(listener);
}
}
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceFactory.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceFactory.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceFactory.java Mon Jul 2 21:27:40 2018
@@ -21,23 +21,24 @@ package org.apache.felix.log;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
/**
* {@link ServiceFactory} implementation for {@link LogService}. Associates
* an individual {@link LogService} with a {@link Bundle}.
*/
-final class LogServiceFactory implements ServiceFactory
+final class LogServiceFactory implements ServiceFactory<LogService>
{
- /** The log to associate the service implementations with. */
- private final Log m_log;
+ /** The logger admin impl. */
+ private final LoggerAdminImpl m_loggerAdminImpl;
/**
* Create a new instance.
* @param log the log to associate the service implementations with.,
*/
- LogServiceFactory(final Log log)
+ LogServiceFactory(final LoggerAdminImpl loggerAdminImpl)
{
- m_log = log;
+ m_loggerAdminImpl = loggerAdminImpl;
}
/**
@@ -46,10 +47,10 @@ final class LogServiceFactory implements
* @param registration the service registration
* @return the log service implementation for the specified bundle
*/
- public Object getService(final Bundle bundle,
- final ServiceRegistration registration)
+ public LogService getService(final Bundle bundle,
+ final ServiceRegistration<LogService> registration)
{
- return new LogServiceImpl(m_log, bundle);
+ return new LogServiceImpl(bundle, m_loggerAdminImpl);
}
/**
@@ -60,8 +61,8 @@ final class LogServiceFactory implements
* @param service the service to release
*/
public void ungetService(final Bundle bundle,
- final ServiceRegistration registration,
- final Object service)
+ final ServiceRegistration<LogService> registration,
+ final LogService service)
{
// do nothing
}
Modified: felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceImpl.java?rev=1834903&r1=1834902&r2=1834903&view=diff
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceImpl.java (original)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LogServiceImpl.java Mon Jul 2 21:27:40 2018
@@ -19,28 +19,32 @@
package org.apache.felix.log;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
+import org.osgi.service.log.Logger;
/**
* Implementation of the OSGi {@link LogService}.
*/
final class LogServiceImpl implements LogService
{
- /** The log implementation. */
- private final Log m_log;
/** The bundle associated with this implementation. */
private final Bundle m_bundle;
+ /** The logger admin impl. */
+ private final LoggerAdminImpl m_loggerAdminImpl;
/**
* Create a new instance.
* @param log the log implementation
* @param bundle the bundle associated with this implementation
+ * @param serviceReference
*/
- LogServiceImpl(final Log log, final Bundle bundle)
+ LogServiceImpl(final Bundle bundle, final LoggerAdminImpl loggerAdminImpl)
{
- this.m_log = log;
this.m_bundle = bundle;
+ this.m_loggerAdminImpl = loggerAdminImpl;
}
/**
@@ -74,7 +78,7 @@ final class LogServiceImpl implements Lo
* @param level the level to log the message at
* @param message the message to log
*/
- public void log(final ServiceReference sr,
+ public void log(final ServiceReference<?> sr,
final int level,
final String message)
{
@@ -89,15 +93,73 @@ final class LogServiceImpl implements Lo
* @param message the message to log
* @param exception the exception to log
*/
- public void log(final ServiceReference sr,
+ @SuppressWarnings("deprecation")
+ public void log(final ServiceReference<?> sr,
final int level,
final String message,
final Throwable exception)
{
- m_log.addEntry(new LogEntryImpl((sr != null) ? sr.getBundle() : m_bundle,
- sr,
- level,
- message,
- exception));
+ LoggerImpl logger = (LoggerImpl)m_loggerAdminImpl.getLogger(m_bundle, "LogService", Logger.class);
+
+ switch (level) {
+ case LogService.LOG_DEBUG:
+ logger.debug(message, sr, exception);
+ break;
+ case LogService.LOG_ERROR:
+ logger.error(message, sr, exception);
+ break;
+ case LogService.LOG_INFO:
+ logger.info(message, sr, exception);
+ break;
+ case LogService.LOG_WARNING:
+ logger.warn(message, sr, exception);
+ break;
+ default:
+ logger.log(level, message, sr, exception);
+ }
+ }
+
+ @Override
+ public Logger getLogger(String name) {
+ return m_loggerAdminImpl.getLogger(m_bundle, name, Logger.class);
+ }
+
+ @Override
+ public Logger getLogger(Class<?> clazz) {
+ LogService logService = getLogService(clazz);
+ return logService.getLogger(clazz.getName());
+ }
+
+ @Override
+ public <L extends Logger> L getLogger(String name, Class<L> loggerType) {
+ return m_loggerAdminImpl.getLogger(m_bundle, name, loggerType);
+ }
+
+ @Override
+ public <L extends Logger> L getLogger(Class<?> clazz, Class<L> loggerType) {
+ LogService logService = getLogService(clazz);
+ return logService.getLogger(clazz.getName(), loggerType);
+ }
+
+ @Override
+ public <L extends Logger> L getLogger(Bundle bundle, String name, Class<L> loggerType) {
+ LogService logService = getLogService(bundle);
+ return logService.getLogger(name, loggerType);
+ }
+
+ private LogService getLogService(Bundle bundle) {
+ if (((bundle.getState() & Bundle.ACTIVE) != Bundle.ACTIVE) &&
+ ((bundle.getState() & Bundle.RESOLVED) != Bundle.RESOLVED)) {
+ throw new IllegalArgumentException("Bundle " + bundle + " is not resolved.");
+ }
+ BundleContext bundleContext = bundle.getBundleContext();
+ ServiceReference<LogService> serviceReference = bundleContext.getServiceReference(LogService.class);
+ return bundleContext.getService(serviceReference);
+ }
+
+ private LogService getLogService(Class<?> clazz) {
+ Bundle bundle = FrameworkUtil.getBundle(clazz);
+ return getLogService(bundle);
}
+
}
\ No newline at end of file
Added: felix/trunk/log/src/main/java/org/apache/felix/log/LoggerAdminImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LoggerAdminImpl.java?rev=1834903&view=auto
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LoggerAdminImpl.java (added)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LoggerAdminImpl.java Mon Jul 2 21:27:40 2018
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.log;
+
+import java.util.Dictionary;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.FormatterLogger;
+import org.osgi.service.log.Logger;
+import org.osgi.service.log.admin.LoggerAdmin;
+import org.osgi.service.log.admin.LoggerContext;
+
+public class LoggerAdminImpl implements LoggerAdmin {
+
+ private final Log m_log;
+ private final LoggerContext m_rootContext;
+ private final ConcurrentMap<String, LoggerContext> m_contexts = new ConcurrentHashMap<>();
+ private final ConcurrentMap<LoggerKey, Logger> _loggers = new ConcurrentHashMap<>();
+
+ public LoggerAdminImpl(final String defaultLogLevelString, final Log log) {
+ m_rootContext = new RootLoggerContextImpl(defaultLogLevelString, this);
+ m_log = log;
+ }
+
+ @Override
+ public LoggerContext getLoggerContext(String name) {
+ return getOrCreateLoggerContext(name);
+ }
+
+ public Set<String> getLoggerContextNames() {
+ return m_contexts.keySet();
+ }
+
+ protected void updateConfiguration(String name, Dictionary<String, Object> properties) {
+ LoggerContext loggerContext = getOrCreateLoggerContext(name);
+
+ LoggerContextImpl contextImpl = (LoggerContextImpl)loggerContext;
+
+ contextImpl.updateLoggerContext(properties);
+ }
+
+ protected LoggerContext getOrCreateLoggerContext(String name) {
+ if (name == null) {
+ return m_rootContext;
+ }
+
+ LoggerContext loggerContext = m_contexts.get(name);
+
+ if (loggerContext == null) {
+ loggerContext = new LoggerContextImpl(name, this, m_rootContext);
+ }
+
+ return loggerContext;
+ }
+
+ public void keepLoggerContext(String name, LoggerContextImpl loggerContext) {
+ if (loggerContext instanceof RootLoggerContextImpl) return;
+ m_contexts.put(name, loggerContext);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <L extends Logger> L getLogger(
+ final Bundle bundle, final String name, final Class<L> loggerType) {
+
+ LoggerKey key = new LoggerKey(bundle, name, loggerType);
+
+ L logger = (L)_loggers.get(key);
+
+ if (logger == null) {
+ if (loggerType.equals(FormatterLogger.class)) {
+ logger = (L)new FormatterLoggerImpl(name, bundle, m_log, this);
+ }
+ else {
+ logger = (L)new LoggerImpl(name, bundle, m_log, this);
+ }
+
+ L previous = (L)_loggers.putIfAbsent(key, logger);
+
+ if (previous != null) {
+ logger = previous;
+ }
+ }
+
+ return logger;
+ }
+
+ LoggerContext getLoggerContext(Bundle bundle, String name) {
+ String loggerContextName = String.format(
+ "%s|%s|%s", bundle.getSymbolicName(), bundle.getVersion(), bundle.getLocation());
+
+ LoggerContext loggerContext = getLoggerContext(loggerContextName);
+
+ if (loggerContext.isEmpty()) {
+ loggerContextName = String.format(
+ "%s|%s", bundle.getSymbolicName(), bundle.getVersion());
+
+ loggerContext = getLoggerContext(loggerContextName);
+ }
+
+ if (loggerContext.isEmpty()) {
+ loggerContext = getLoggerContext(bundle.getSymbolicName());
+ }
+
+ return loggerContext;
+ }
+
+ static class LoggerKey {
+
+ public LoggerKey(Bundle bundle, String name, Class<? extends Logger> loggerType) {
+ this.m_bundle = bundle;
+ this.m_name = name;
+ this.m_loggerType = loggerType;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((m_bundle == null) ? 0 : m_bundle.hashCode());
+ result = prime * result + ((m_loggerType == null) ? 0 : m_loggerType.hashCode());
+ result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
+ return result;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ LoggerKey other = (LoggerKey) obj;
+ if (m_bundle == null) {
+ if (other.m_bundle != null)
+ return false;
+ } else if (m_bundle.getBundleId() != other.m_bundle.getBundleId())
+ return false;
+ if (m_loggerType == null) {
+ if (other.m_loggerType != null)
+ return false;
+ } else if (!m_loggerType.equals(other.m_loggerType))
+ return false;
+ if (m_name == null) {
+ if (other.m_name != null)
+ return false;
+ } else if (!m_name.equals(other.m_name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (m_string == null) {
+ m_string = getClass().getSimpleName() + "[" + m_bundle + "#" + m_name + "!" + m_loggerType.getSimpleName() + "]";
+ }
+ return m_string;
+ }
+
+ private final Bundle m_bundle;
+ private final String m_name;
+ private final Class<? extends Logger> m_loggerType;
+ private volatile String m_string;
+
+ }
+
+}
Added: felix/trunk/log/src/main/java/org/apache/felix/log/LoggerContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LoggerContextImpl.java?rev=1834903&view=auto
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LoggerContextImpl.java (added)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LoggerContextImpl.java Mon Jul 2 21:27:40 2018
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.log;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.admin.LoggerContext;
+
+public class LoggerContextImpl implements LoggerContext {
+
+ static final String ROOT = "ROOT";
+
+ private final String _name;
+ protected volatile Map<String, LogLevel> _levels;
+ protected final Lock _lock = new ReentrantLock();
+ protected final LoggerAdminImpl _loggerAdminImpl;
+ protected final LoggerContext _rootContext;
+
+ private volatile String _toString;
+
+ public LoggerContextImpl(String name, LoggerAdminImpl loggerAdminImpl, LoggerContext rootLoggerContext) {
+ _name = name;
+ _loggerAdminImpl = loggerAdminImpl;
+ _rootContext = rootLoggerContext;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public LogLevel getEffectiveLogLevel(String name) {
+ _lock.lock();
+ try {
+ if (_levels != null && !_levels.isEmpty()) {
+ String copy = name;
+ LogLevel level;
+ while (copy.length() > 0) {
+ level = _levels.get(copy);
+ if (level != null) {
+ return level;
+ }
+ if (ROOT.equals(copy))
+ break;
+ copy = ancestor(copy);
+ }
+ }
+ return _rootContext.getEffectiveLogLevel(name);
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ public Map<String, LogLevel> getLogLevels() {
+ _lock.lock();
+ try {
+ if (_levels == null) {
+ return new HashMap<>();
+ }
+ return new HashMap<>(_levels);
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ public void setLogLevels(Map<String, LogLevel> logLevels) {
+ _lock.lock();
+ try {
+ _levels = new HashMap<>(logLevels);
+ _loggerAdminImpl.keepLoggerContext(_name, this);
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ public void clear() {
+ _lock.lock();
+ try {
+ _levels = null;
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ public boolean isEmpty() {
+ _lock.lock();
+ try {
+ return _levels == null || _levels.isEmpty();
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ void updateLoggerContext(Dictionary<String, Object> properties) {
+ _lock.lock();
+ try {
+ _levels = new HashMap<>();
+ if (properties != null) {
+ for (Enumeration<String> enu = properties.keys(); enu.hasMoreElements();) {
+ String key = enu.nextElement();
+ Object object = properties.get(key);
+ if (object instanceof String) {
+ String value = (String)object;
+ for (LogLevel level : LogLevel.values()) {
+ if (level.name().equalsIgnoreCase(value)) {
+ _levels.put(key, level);
+ break;
+ }
+ }
+ }
+ }
+ }
+ _loggerAdminImpl.keepLoggerContext(_name, this);
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
+ public String toString() {
+ if (_toString == null) {
+ _toString = getClass().getSimpleName() + "[" + _name + "]";
+ }
+ return _toString;
+ }
+
+ protected String ancestor(String name) {
+ int position = name.lastIndexOf('.');
+ if (position == -1) {
+ return ROOT;
+ }
+ return name.substring(0, position);
+ }
+
+}
Added: felix/trunk/log/src/main/java/org/apache/felix/log/LoggerImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/LoggerImpl.java?rev=1834903&view=auto
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/LoggerImpl.java (added)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/LoggerImpl.java Mon Jul 2 21:27:40 2018
@@ -0,0 +1,377 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.Logger;
+import org.osgi.service.log.LoggerConsumer;
+
+public class LoggerImpl implements Logger {
+
+ private static final String ESCAPE = "\\";
+ private static final String MAX_CHAR = "\uFFFF";
+ private static final String BRACE_CLOSE = "}";
+ private static final String BRACE_OPEN = "{";
+
+ protected final String m_name;
+ protected final Bundle m_bundle;
+ protected final Log m_log;
+ protected final LoggerAdminImpl m_loggerAdmin;
+
+ public LoggerImpl(final String name, final Bundle bundle, final Log log, final LoggerAdminImpl loggerAdmin) {
+ m_name = name;
+ m_bundle = bundle;
+ m_log = log;
+ m_loggerAdmin = loggerAdmin;
+ }
+
+ @Override
+ public String getName() {
+ return m_name;
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return m_loggerAdmin.getLoggerContext(m_bundle, m_name).getEffectiveLogLevel(m_name).implies(LogLevel.TRACE);
+ }
+
+ void trace(String message, ServiceReference<?> serviceReference, Throwable t) {
+ if (!isTraceEnabled()) return;
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.TRACE, message, t);
+ }
+
+ @Override
+ public void trace(String message) {
+ trace(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void trace(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ trace(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void trace(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ trace(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ trace(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public <E extends Exception> void trace(LoggerConsumer<E> consumer) throws E {
+ if (isTraceEnabled()) {
+ consumer.accept(this);
+ }
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return m_loggerAdmin.getLoggerContext(m_bundle, m_name).getEffectiveLogLevel(m_name).implies(LogLevel.DEBUG);
+ }
+
+ void debug(String message, ServiceReference<?> serviceReference, Throwable t) {
+ if (!isDebugEnabled()) return;
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.DEBUG, message, t);
+ }
+
+ @Override
+ public void debug(String message) {
+ debug(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void debug(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ debug(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void debug(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ debug(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ debug(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public <E extends Exception> void debug(LoggerConsumer<E> consumer) throws E {
+ if (isDebugEnabled()) {
+ consumer.accept(this);
+ }
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return m_loggerAdmin.getLoggerContext(m_bundle, m_name).getEffectiveLogLevel(m_name).implies(LogLevel.INFO);
+ }
+
+ void info(String message, ServiceReference<?> serviceReference, Throwable t) {
+ if (!isInfoEnabled()) return;
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.INFO, message, t);
+ }
+
+ @Override
+ public void info(String message) {
+ info(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void info(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ info(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void info(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ info(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ info(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public <E extends Exception> void info(LoggerConsumer<E> consumer) throws E {
+ if (isInfoEnabled()) {
+ consumer.accept(this);
+ }
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return m_loggerAdmin.getLoggerContext(m_bundle, m_name).getEffectiveLogLevel(m_name).implies(LogLevel.WARN);
+ }
+
+ void warn(String message, ServiceReference<?> serviceReference, Throwable t) {
+ if (!isWarnEnabled()) return;
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.WARN, message, t);
+ }
+
+ @Override
+ public void warn(String message) {
+ warn(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void warn(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ warn(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void warn(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ warn(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ warn(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public <E extends Exception> void warn(LoggerConsumer<E> consumer) throws E {
+ if (isWarnEnabled()) {
+ consumer.accept(this);
+ }
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return m_loggerAdmin.getLoggerContext(m_bundle, m_name).getEffectiveLogLevel(m_name).implies(LogLevel.ERROR);
+ }
+
+ void error(String message, ServiceReference<?> serviceReference, Throwable t) {
+ if (!isErrorEnabled()) return;
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.ERROR, message, t);
+ }
+
+ @Override
+ public void error(String message) {
+ error(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void error(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ error(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void error(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ error(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ error(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public <E extends Exception> void error(LoggerConsumer<E> consumer) throws E {
+ if (isErrorEnabled()) {
+ consumer.accept(this);
+ }
+ }
+
+ public void audit(String message, ServiceReference<?> serviceReference, Throwable t) {
+ m_log.log(m_name, m_bundle, serviceReference, LogLevel.AUDIT, message, t);
+ }
+
+ @Override
+ public void audit(String message) {
+ audit(message, (ServiceReference<?>)null, null);
+ }
+
+ @Override
+ public void audit(String format, Object arg) {
+ LogParameters logParameters = getLogParameters(arg);
+ audit(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void audit(String format, Object arg1, Object arg2) {
+ LogParameters logParameters = getLogParameters(arg1, arg2);
+ audit(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ @Override
+ public void audit(String format, Object... arguments) {
+ LogParameters logParameters = getLogParameters(arguments);
+ audit(format(format, logParameters), logParameters.sr, logParameters.t);
+ }
+
+ public void log(
+ final int level,
+ final String message,
+ final ServiceReference<?> sr,
+ final Throwable exception) {
+
+ m_log.addEntry(new LogEntryImpl(m_name, m_bundle, sr, level, message, exception, Log.getStackTraceElement()));
+ }
+
+ LogParameters getLogParameters(Object arg) {
+ return getLogParameters0(arg);
+ }
+
+ LogParameters getLogParameters(Object arg1, Object arg2) {
+ return getLogParameters0(arg1, arg2);
+ }
+
+ LogParameters getLogParameters(Object... arguments) {
+ return getLogParameters0(arguments);
+ }
+
+ LogParameters getLogParameters0(Object... arguments) {
+ if (arguments == null || arguments.length == 0) {
+ return new LogParameters(null, null, null);
+ }
+ ServiceReference<?> sr = null;
+ Throwable t = null;
+ List<Object> args = new ArrayList<>();
+ for (Object arg : arguments) {
+ if (t == null && arg instanceof Throwable) {
+ t = (Throwable)arg;
+ }
+ else if (sr == null && arg instanceof ServiceReference) {
+ sr = (ServiceReference<?>)arg;
+ }
+ else if (arg != null) {
+ args.add(arg);
+ }
+ }
+ return new LogParameters(args.toArray(), sr, t);
+ }
+
+ String format(String format, LogParameters logParameters) {
+ StringBuilder sb = new StringBuilder();
+ int offset = 0;
+ int length = format.length();
+ String previous = MAX_CHAR;
+ boolean escape = false;
+ int argIndex = 0;
+ while (offset < length) {
+ int curChar = format.codePointAt(offset);
+ offset += Character.charCount(curChar);
+ String cur = new String(Character.toChars(curChar));
+
+ if (argIndex == logParameters.args.length) {
+ sb.append(cur);
+ }
+ else if (escape) {
+ escape = false;
+ sb.append(cur);
+ previous = MAX_CHAR;
+ }
+ else if (ESCAPE.equals(cur)) {
+ escape = true;
+ previous = ESCAPE;
+ }
+ else if (BRACE_OPEN.equals(cur)) {
+ if (BRACE_OPEN.equals(previous)) {
+ sb.append(previous);
+ }
+ previous = BRACE_OPEN;
+ }
+ else if (BRACE_CLOSE.equals(cur) && BRACE_OPEN.equals(previous)) {
+ sb.append(logParameters.args[argIndex++]);
+ previous = MAX_CHAR;
+ }
+ else {
+ sb.append(cur);
+ previous = MAX_CHAR;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ static class LogParameters {
+ public LogParameters(Object[] args, ServiceReference<?> sr, Throwable t) {
+ this.args = args;
+ this.sr = sr;
+ this.t = t;
+ }
+ final Object[] args;
+ final ServiceReference<?> sr;
+ final Throwable t;
+ }
+
+}
Added: felix/trunk/log/src/main/java/org/apache/felix/log/RootLoggerContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/log/src/main/java/org/apache/felix/log/RootLoggerContextImpl.java?rev=1834903&view=auto
==============================================================================
--- felix/trunk/log/src/main/java/org/apache/felix/log/RootLoggerContextImpl.java (added)
+++ felix/trunk/log/src/main/java/org/apache/felix/log/RootLoggerContextImpl.java Mon Jul 2 21:27:40 2018
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.felix.log;
+
+import java.util.Dictionary;
+import java.util.Map;
+
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.Logger;
+
+public class RootLoggerContextImpl extends LoggerContextImpl {
+
+ private final LogLevel _defaultLevel;
+
+ public RootLoggerContextImpl(String defaultLogLevelString, LoggerAdminImpl loggerAdminImpl) {
+ super(null, loggerAdminImpl, null);
+
+ LogLevel defaultLogLevel = LogLevel.WARN;
+ if (defaultLogLevelString != null) {
+ for (LogLevel level : LogLevel.values()) {
+ if (level.name().equalsIgnoreCase(defaultLogLevelString)) {
+ defaultLogLevel = level;
+ break;
+ }
+ }
+ }
+
+ _defaultLevel = defaultLogLevel;
+ }
+
+ public LogLevel getEffectiveLogLevel(String name) {
+ _lock.lock();
+ try {
+ if (_levels != null && !_levels.isEmpty()) {
+ LogLevel level;
+ while (name.length() > 0) {
+ level = _levels.get(name);
+ if (level != null) {
+ return level;
+ }
+ if (ROOT.equals(name))
+ break;
+ name = ancestor(name);
+ }
+ }
+ return getEffectiveRootLogLevel();
+ }
+ finally {
+ _lock.unlock();
+ }
+ }
+
+ @Override
+ public void setLogLevels(Map<String, LogLevel> logLevels) {
+ super.setLogLevels(logLevels);
+ }
+
+ @Override
+ void updateLoggerContext(Dictionary<String, Object> properties) {
+ super.updateLoggerContext(properties);
+ }
+
+ private LogLevel getEffectiveRootLogLevel() {
+ if (_levels == null) return _defaultLevel;
+ LogLevel logLevel = _levels.get(Logger.ROOT_LOGGER_NAME);
+ return (logLevel == null)? _defaultLevel : logLevel;
+ }
+
+}