/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2011-2015 ForgeRock AS. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://forgerock.org/license/CDDLv1.0.html
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at http://forgerock.org/license/CDDLv1.0.html
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
*/
package org.forgerock.openidm.logging;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Directs OSGi logging service entries into the slf4j logger
*
*/
public class OsgiLogHandler {
final static Logger logger = LoggerFactory.getLogger(OsgiLogHandler.class);
ServiceTracker tracker;
public OsgiLogHandler(final BundleContext context) {
tracker = new LogServiceTracker(context, LogReaderService.class.getName(), null);
tracker.open();
logger.debug("Log service tracker opened");
}
}
/**
* Attach log listeners to log reader services to re-direct to slf4j
*/
class LogServiceTracker extends ServiceTracker {
final static Logger logger = LoggerFactory.getLogger(LogServiceTracker.class);
// Logger to use for OSGi log entries
final static Logger defaultEntryLogger = LoggerFactory.getLogger("org.forgerock.openidm.Framework");
Map<LogReaderService, LogListener> logReaderServices =
Collections.synchronizedMap(new HashMap<LogReaderService, LogListener>());
public LogServiceTracker(BundleContext context, String clazz, ServiceTrackerCustomizer customizer) {
super(context, clazz, customizer);
}
@Override
public Object addingService(ServiceReference reference) {
LogReaderService svc = (LogReaderService)context.getService(reference);
addLogReaderService(svc);
return reference;
}
@Override
public void removedService(ServiceReference reference, Object service) {
LogReaderService svc = (LogReaderService)context.getService(reference);
removeLogReaderService(svc);
}
private void addLogReaderService(LogReaderService reader) {
logger.trace("Adding log reader service");
LogListener existing = logReaderServices.get(reader);
if (existing == null) {
LogListener logListener = new LogListener() {
@Override
public void logged(LogEntry entry) {
logEntry(entry);
}
};
reader.addLogListener(logListener);
// This dumps the existing log entries.
// These entries may appear out of chronological order
// if services already started logging to slf4j directly
java.util.Enumeration entries = reader.getLog();
while (entries.hasMoreElements()) {
logEntry((LogEntry) entries.nextElement());
}
// Redirects all new log entries
logReaderServices.put(reader, logListener);
}
}
/**
* Log the OSGi entry using the slf4j logger
* @param entry
*/
void logEntry(LogEntry entry) {
StringBuilder logMessage = new StringBuilder("Bundle: ");
logMessage.append(entry.getBundle());
if (entry.getServiceReference() != null) {
logMessage.append(" - ");
logMessage.append(entry.getServiceReference());
}
logMessage.append(" ");
logMessage.append(entry.getMessage());
Throwable ex = entry.getException();
switch (entry.getLevel()) {
case LogService.LOG_ERROR: {
defaultEntryLogger.error(logMessage.toString(), ex);
break;
}
case LogService.LOG_WARNING: {
defaultEntryLogger.warn(logMessage.toString(), ex);
break;
}
case LogService.LOG_INFO: {
defaultEntryLogger.info(logMessage.toString(), ex);
break;
}
case LogService.LOG_DEBUG: {
defaultEntryLogger.debug(logMessage.toString(), ex);
break;
}
default: {
defaultEntryLogger.warn("Unknown OSGi log level [" + entry.getLevel() + "] for" + logMessage.toString(), ex);
}
}
}
private void removeLogReaderService(LogReaderService reader) {
logger.trace("Removing log reader service");
LogListener logListener = logReaderServices.remove(reader);
if (logListener != null) {
reader.removeLogListener(logListener);
}
}
}