All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.felix.framework.Logger Maven / Gradle / Ivy

There is a newer version: 0.40.13
Show newest version
/*
 * 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.framework;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.osgi.framework.*;

/**
 * 

* This class mimics the standard OSGi LogService interface. An * instance of this class is used by the framework for all logging. By default * this class logs messages to standard out. The log level can be set to * control the amount of logging performed, where a higher number results in * more logging. A log level of zero turns off logging completely. *

*

* The log levels match those specified in the OSGi Log Service (i.e., 1 = error, * 2 = warning, 3 = information, and 4 = debug). The default value is 1. *

*

* This class also uses the System Bundle's context to track log services * and will use the highest ranking log service, if present, as a back end * instead of printing to standard out. The class uses reflection to invoking * the log service's method to avoid a dependency on the log interface. *

**/ public class Logger implements ServiceListener { public static final int LOG_ERROR = 1; public static final int LOG_WARNING = 2; public static final int LOG_INFO = 3; public static final int LOG_DEBUG = 4; private int m_logLevel = 1; private BundleContext m_context = null; private final static int LOGGER_OBJECT_IDX = 0; private final static int LOGGER_METHOD_IDX = 1; private ServiceReference m_logRef = null; private Object[] m_logger = null; public Logger() { } public final synchronized void setLogLevel(int i) { m_logLevel = i; } public final synchronized int getLogLevel() { return m_logLevel; } protected void setSystemBundleContext(BundleContext context) { // TODO: Find a way to log to a log service inside the framework. // The issue is that we log messages while holding framework // internal locks -- hence, when a log service calls back into // the framework (e.g., by loading a class) we might deadlock. // One instance of this problem is tracked in FELIX-536. // For now we just disable logging to log services inside the // framework. // m_context = context; // startListeningForLogService(); } public final void log(int level, String msg) { _log(null, null, level, msg, null); } public final void log(int level, String msg, Throwable throwable) { _log(null, null, level, msg, throwable); } public final void log(ServiceReference sr, int level, String msg) { _log(null, sr, level, msg, null); } public final void log(ServiceReference sr, int level, String msg, Throwable throwable) { _log(null, sr, level, msg, throwable); } public final void log(Bundle bundle, int level, String msg) { _log(bundle, null, level, msg, null); } public final void log(Bundle bundle, int level, String msg, Throwable throwable) { _log(bundle, null, level, msg, throwable); } protected void doLog( Bundle bundle, ServiceReference sr, int level, String msg, Throwable throwable) { String s = ""; if (sr != null) { s = s + "SvcRef " + sr + " "; } else if (bundle != null) { s = s + "Bundle " + bundle.toString() + " "; } s = s + msg; if (throwable != null) { s = s + " (" + throwable + ")"; } switch (level) { case LOG_DEBUG: System.out.println("DEBUG: " + s); break; case LOG_ERROR: System.out.println("ERROR: " + s); if (throwable != null) { if ((throwable instanceof BundleException) && (((BundleException) throwable).getNestedException() != null)) { throwable = ((BundleException) throwable).getNestedException(); } throwable.printStackTrace(); } break; case LOG_INFO: System.out.println("INFO: " + s); break; case LOG_WARNING: System.out.println("WARNING: " + s); break; default: System.out.println("UNKNOWN[" + level + "]: " + s); } } private void _log( Bundle bundle, ServiceReference sr, int level, String msg, Throwable throwable) { // Save our own copy just in case it changes. We could try to do // more conservative locking here, but let's be optimistic. Object[] logger = m_logger; if (m_logLevel >= level) { // Use the log service if available. if (logger != null) { _logReflectively(logger, sr, level, msg, throwable); } // Otherwise, default logging action. else { doLog(bundle, sr, level, msg, throwable); } } } private void _logReflectively( Object[] logger, ServiceReference sr, int level, String msg, Throwable throwable) { if (logger != null) { Object[] params = { sr, new Integer(level), msg, throwable }; try { ((Method) logger[LOGGER_METHOD_IDX]).invoke(logger[LOGGER_OBJECT_IDX], params); } catch (InvocationTargetException ex) { System.err.println("Logger: " + ex); } catch (IllegalAccessException ex) { System.err.println("Logger: " + ex); } } } /** * This method is called when the system bundle context is set; * it simply adds a service listener so that the system bundle can track * log services to be used as the back end of the logging mechanism. It also * attempts to get an existing log service, if present, but in general * there will never be a log service present since the system bundle is * started before every other bundle. **/ private synchronized void startListeningForLogService() { // Add a service listener for log services. try { m_context.addServiceListener( this, "(objectClass=org.osgi.service.log.LogService)"); } catch (InvalidSyntaxException ex) { // This will never happen since the filter is hard coded. } // Try to get an existing log service. m_logRef = m_context.getServiceReference("org.osgi.service.log.LogService"); // Get the service object if available and set it in the logger. if (m_logRef != null) { setLogger(m_context.getService(m_logRef)); } } /** * This method implements the callback for the ServiceListener interface. * It is public as a byproduct of implementing the interface and should * not be called directly. This method tracks run-time changes to log * service availability. If the log service being used by the framework's * logging mechanism goes away, then this will try to find an alternative. * If a higher ranking log service is registered, then this will switch * to the higher ranking log service. **/ public final synchronized void serviceChanged(ServiceEvent event) { // If no logger is in use, then grab this one. if ((event.getType() == ServiceEvent.REGISTERED) && (m_logRef == null)) { m_logRef = event.getServiceReference(); // Get the service object and set it in the logger. setLogger(m_context.getService(m_logRef)); } // If a logger is in use, but this one has a higher ranking, then swap // it for the existing logger. else if ((event.getType() == ServiceEvent.REGISTERED) && (m_logRef != null)) { ServiceReference ref = m_context.getServiceReference("org.osgi.service.log.LogService"); if (!ref.equals(m_logRef)) { m_context.ungetService(m_logRef); m_logRef = ref; setLogger(m_context.getService(m_logRef)); } } // If the current logger is going away, release it and try to // find another one. else if ((event.getType() == ServiceEvent.UNREGISTERING) && m_logRef.equals(event.getServiceReference())) { // Unget the service object. m_context.ungetService(m_logRef); // Try to get an existing log service. m_logRef = m_context.getServiceReference( "org.osgi.service.log.LogService"); // Get the service object if available and set it in the logger. if (m_logRef != null) { setLogger(m_context.getService(m_logRef)); } else { setLogger(null); } } } /** * This method sets the new log service object. It also caches the method to * invoke. The service object and method are stored in array to optimistically * eliminate the need to locking when logging. **/ private void setLogger(Object logObj) { if (logObj == null) { m_logger = null; } else { Class[] formalParams = { ServiceReference.class, Integer.TYPE, String.class, Throwable.class }; try { Method logMethod = logObj.getClass().getMethod("log", formalParams); logMethod.setAccessible(true); m_logger = new Object[] { logObj, logMethod }; } catch (NoSuchMethodException ex) { System.err.println("Logger: " + ex); m_logger = null; } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy