| /* |
| * 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.ipojo.util; |
| |
| import org.apache.felix.ipojo.ComponentInstance; |
| import org.apache.felix.ipojo.ErrorHandler; |
| import org.apache.felix.ipojo.extender.internal.Extender; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.log.LogService; |
| |
| /** |
| * iPOJO Logger. |
| * This class is an helper class implementing a simple log system. |
| * This logger sends log messages to a log service if available. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class Logger implements Log { |
| |
| /** |
| * The iPOJO default log level property. |
| */ |
| public static final String IPOJO_LOG_LEVEL_PROP = "ipojo.log.level"; |
| /** |
| * iPOJO log level manifest header. |
| * The uppercase 'I' is important as BND removes all headers that do not |
| * start with an uppercase are not added to the bundle. |
| * Use an upper case to support bnd. |
| */ |
| public static final String IPOJO_LOG_LEVEL_HEADER = "IPOJO-log-level"; |
| /** |
| * A shared log service implementation writing messages on the console. |
| */ |
| private static final LogService m_defaultLogger = new ConsoleLogService(); |
| private static final String DEBUG_HEADER = "[DEBUG]"; |
| private static final String INFO_HEADER = "[INFO]"; |
| private static final String WARNING_HEADER = "[WARNING]"; |
| private static final String ERROR_HEADER = "[ERROR]"; |
| private static final String UNKNOWN_HEADER = "[UNKNOWN]"; |
| /** |
| * The Bundle Context used to get the |
| * log service. |
| */ |
| private final BundleContext m_context; |
| /** |
| * The name of the logger. |
| */ |
| private final String m_name; |
| /** |
| * The trace level of this logger. |
| */ |
| private final int m_level; |
| /** |
| * The instance associated to the logger if any. |
| */ |
| private ComponentInstance m_instance; |
| |
| /** |
| * Creates a logger. |
| * |
| * @param context the bundle context |
| * @param name the name of the logger |
| * @param level the trace level |
| */ |
| public Logger(BundleContext context, String name, int level) { |
| m_name = name; |
| m_level = level; |
| m_context = context; |
| } |
| |
| /** |
| * Creates a logger. |
| * |
| * @param context the bundle context |
| * @param instance the instance |
| * @param level the trace level |
| */ |
| public Logger(BundleContext context, ComponentInstance instance, int level) { |
| this(context, instance.getInstanceName(), level); |
| m_instance = instance; |
| } |
| |
| /** |
| * Create a logger. |
| * Uses the default logger level. |
| * |
| * @param context the bundle context |
| * @param name the name of the logger |
| */ |
| public Logger(BundleContext context, String name) { |
| this(context, name, getDefaultLevel(context)); |
| } |
| |
| /** |
| * Create a logger. |
| * Uses the default logger level. |
| * |
| * @param context the bundle context |
| * @param instance the instance |
| */ |
| public Logger(BundleContext context, ComponentInstance instance) { |
| this(context, instance, getDefaultLevel(context)); |
| } |
| |
| /** |
| * Gets the default logger level. |
| * The property is searched inside the framework properties, |
| * the system properties, and in the manifest from the given |
| * bundle context. By default, set the level to {@link Logger#WARNING}. |
| * |
| * @param context the bundle context. |
| * @return the default log level. |
| */ |
| private static int getDefaultLevel(BundleContext context) { |
| // First check in the framework and in the system properties |
| String level = context.getProperty(IPOJO_LOG_LEVEL_PROP); |
| |
| // If null, look in the bundle manifest |
| if (level == null) { |
| String key = IPOJO_LOG_LEVEL_PROP.replace('.', '-'); |
| level = (String) context.getBundle().getHeaders().get(key); |
| } |
| |
| // if still null try the second header |
| if (level == null) { |
| level = (String) context.getBundle().getHeaders().get(IPOJO_LOG_LEVEL_HEADER); |
| } |
| |
| if (level != null) { |
| if (level.equalsIgnoreCase("info")) { |
| return INFO; |
| } else if (level.equalsIgnoreCase("debug")) { |
| return DEBUG; |
| } else if (level.equalsIgnoreCase("warning")) { |
| return WARNING; |
| } else if (level.equalsIgnoreCase("error")) { |
| return ERROR; |
| } |
| } |
| |
| // Either l is null, either the specified log level was unknown |
| // Set the default to WARNING |
| return WARNING; |
| |
| } |
| |
| private static String getLogHeaderForLevel(int level) { |
| switch (level) { |
| case DEBUG: |
| return DEBUG_HEADER; |
| case INFO: |
| return INFO_HEADER; |
| case WARNING: |
| return WARNING_HEADER; |
| case ERROR: |
| return ERROR_HEADER; |
| default: |
| return UNKNOWN_HEADER; |
| } |
| } |
| |
| /** |
| * Logs a message. |
| * |
| * @param level the level of the message |
| * @param msg the the message to log |
| */ |
| public void log(int level, String msg) { |
| if (m_level >= level) { |
| dispatch(level, msg, null); |
| } |
| invokeErrorHandler(level, msg, null); |
| } |
| |
| /** |
| * Logs a message with an exception. |
| * |
| * @param level the level of the message |
| * @param msg the message to log |
| * @param exception the exception attached to the message |
| */ |
| public void log(int level, String msg, Throwable exception) { |
| if (m_level >= level) { |
| dispatch(level, msg, exception); |
| } |
| invokeErrorHandler(level, msg, exception); |
| } |
| |
| /** |
| * Internal log method. |
| * |
| * @param level the level of the message. |
| * @param msg the message to log |
| * @param exception the exception attached to the message |
| */ |
| private void dispatch(int level, String msg, Throwable exception) { |
| LogService log = null; |
| ServiceReference ref = null; |
| try { |
| // Security Check |
| if (SecurityHelper.hasPermissionToGetService(LogService.class.getName(), m_context)) { |
| ref = m_context.getServiceReference(LogService.class.getName()); |
| } else { |
| Extender.getIPOJOBundleContext().getServiceReference(LogService.class.getName()); |
| } |
| |
| if (ref != null) { |
| log = (LogService) m_context.getService(ref); |
| } |
| } catch (IllegalStateException e) { |
| // Handle the case where the iPOJO bundle is stopping, or the log service already ran away. |
| } |
| |
| if (log == null) { |
| log = m_defaultLogger; |
| } |
| |
| String name = m_name; |
| if (name == null) { |
| name = ""; |
| } |
| |
| String message = String.format("%s %s : %s", getLogHeaderForLevel(level), name, msg); |
| switch (level) { |
| case DEBUG: |
| log.log(LogService.LOG_DEBUG, message, exception); |
| break; |
| case INFO: |
| log.log(LogService.LOG_INFO, message, exception); |
| break; |
| case WARNING: |
| log.log(LogService.LOG_WARNING, message, exception); |
| break; |
| case ERROR: |
| log.log(LogService.LOG_ERROR, message, exception); |
| break; |
| default: |
| log.log(LogService.LOG_INFO, message, exception); |
| break; |
| } |
| |
| if (ref != null) { |
| m_context.ungetService(ref); |
| } |
| } |
| |
| /** |
| * Invokes the error handler service is present. |
| * |
| * @param level the log level |
| * @param msg the message |
| * @param error the error |
| */ |
| private void invokeErrorHandler(int level, String msg, Throwable error) { |
| // First check the level |
| if (level > WARNING) { |
| return; // Others levels are not supported. |
| } |
| // Try to get the error handler service |
| try { |
| ServiceReference ref = m_context.getServiceReference(ErrorHandler.class.getName()); |
| if (ref != null) { |
| ErrorHandler handler = (ErrorHandler) m_context.getService(ref); |
| if (level == ERROR) { |
| handler.onError(m_instance, msg, error); |
| } else if (level == WARNING) { |
| handler.onWarning(m_instance, msg, error); |
| } // The others case are not supported |
| m_context.ungetService(ref); |
| } // Else do nothing... |
| } catch (IllegalStateException e) { |
| // Ignore |
| // The iPOJO bundle is stopping. |
| } |
| } |
| |
| /** |
| * A simple log service implementation writing the messages and stack trace on System.err. |
| */ |
| private static class ConsoleLogService implements LogService { |
| |
| public void log(int i, String s) { |
| log(i, s, null); |
| } |
| |
| public void log(int level, String message, Throwable exception) { |
| System.err.println(message); |
| if (exception != null) { |
| exception.printStackTrace(); |
| } |
| } |
| |
| public void log(ServiceReference serviceReference, int i, String s) { |
| // not used. |
| } |
| |
| public void log(ServiceReference serviceReference, int i, String s, Throwable throwable) { |
| // not used. |
| } |
| } |
| } |