/* * Copyright (c) 2012, grossmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the jo-widgets.org nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL jo-widgets.org BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ package org.jowidgets.logging.api; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ServiceLoader; import org.jowidgets.classloading.api.SharedClassLoader; import org.jowidgets.logging.tools.ConsoleLoggerProvider; import org.jowidgets.logging.tools.DefaultLoggerProvider; import org.jowidgets.logging.tools.ILoggerFactory; import org.jowidgets.logging.tools.LoggerFactoryComposite; import org.jowidgets.logging.tools.LoggerProviderToFactoryAdapter; import org.jowidgets.logging.tools.LoggerWrapper; import org.jowidgets.util.Assert; /** * This class gets the access to the currently set logger provider * and can be used to set a new logger provider. */ public final class LoggerProvider { static final String DEFAULT_LOGGER_WARNING = "No logging adapter found for " + ILoggerProvider.class.getName() + ". Using default logging adapter that will log errors and warnings to the console and ignore all other log levels."; private static final List<ILoggerProvider> REGISTERED_PROVIDERS = createRegisteredLoggerProviders(); private static final List<ILoggerProvider> MANUALLY_ADDED_PROVIDERS = new LinkedList<ILoggerProvider>(); private static ILoggerProvider loggerProvider; private LoggerProvider() {} /** * Sets a new logger provider implementation. * * Remark: Use this method with care. This will remove all previously set providers and * all java service loader registered providers. * * @param factory The logger provider to set, may be null if default should be used */ public static synchronized void setLoggerProvider(final ILoggerProvider provider) { LoggerProvider.loggerProvider = null; REGISTERED_PROVIDERS.clear(); MANUALLY_ADDED_PROVIDERS.clear(); if (provider != null) { MANUALLY_ADDED_PROVIDERS.add(provider); } } /** * Adds a new logger provider implementation. * * Remark: Use this method with care. This will not remove the previously set providers and registered providers * * @param factory The logger provider to add, must not be null */ public static synchronized void addLoggerProvider(final ILoggerProvider provider) { Assert.paramNotNull(provider, "provider"); LoggerProvider.loggerProvider = null; MANUALLY_ADDED_PROVIDERS.add(provider); } /** * Removes a new logger provider implementation. * * Remark: Only the previously added providers can be removed * * @param factory The logger provider to remove, must not be null * * @return true if the logger provider was removed */ public static synchronized boolean removeLoggerProvider(final ILoggerProvider provider) { Assert.paramNotNull(provider, "provider"); LoggerProvider.loggerProvider = null; return MANUALLY_ADDED_PROVIDERS.remove(provider); } /** * Gets the logger for the given name or creates a new one if not already exists * * @param name The name to get the logger for * * @return The logger for the given name, never null */ public static ILogger get(final String name) { return instance().get(name, null); } /** * Gets the logger with the given class or crates one if not exists * * @param clazz The class to get the logger for * * @return The logger for the given class, never null */ public static ILogger get(final Class<?> clazz) { Assert.paramNotNull(clazz, "clazz"); return instance().get(clazz.getName(), null); } /** * Gets the logger for the given name and callerFQCN or creates a new one if not already exists * * @param name The name to get the logger for * @param wrapperFQCN The full qualified class name of the wrapper if the created logger will be * used by a logger wrapper. May be null. The wrapper class name will be used to correctly * determine the calling method of the logger log method omitting the wrapper class * * @return The logger for the given name, never null */ public static ILogger get(final String name, final String wrapperFQCN) { return instance().get(name, wrapperFQCN); } /** * Gets the logger for the given name and callerFQCN or creates a new one if not already exists * * @param clazz The class to get the logger for * @param wrapperClazz The class of the wrapper if the created logger will be * used by a logger wrapper. The wrapper class name will be used to correctly determine the calling * method of the log methods omitting the wrapper class * * @return The logger for the given name, never null */ public static ILogger get(final Class<?> clazz, final Class<?> wrapperClazz) { return instance().get(clazz.getName(), wrapperClazz.getName()); } /** * Gets the logger for the given name or creates a new one if not already exists * * @param name The name to get the logger for * * @return The logger for the given name, never null */ public static IDecoratingLogger getDecoratingLogger(final String name) { return getDecoratingLogger(name, null); } /** * Gets the logger with the given class or crates one if not exists * * @param clazz The class to get the logger for * * @return The logger for the given class, never null */ public static IDecoratingLogger getDecoratingLogger(final Class<?> clazz) { Assert.paramNotNull(clazz, "clazz"); return getDecoratingLogger(clazz.getName(), null); } /** * Gets the logger for the given name and callerFQCN or creates a new one if not already exists * * @param name The name to get the logger for * @param wrapperFQCN The full qualified class name of the wrapper if the created logger will be * used by a logger wrapper. May be null. The wrapper class name will be used to correctly * determine the calling method of the logger log method omitting the wrapper class * * @return The logger for the given name, never null */ public static IDecoratingLogger getDecoratingLogger(final String name, final String wrapperFQCN) { return new DecoratingLoggerImpl(name, wrapperFQCN); } /** * Gets the logger for the given name and callerFQCN or creates a new one if not already exists * * @param clazz The class to get the logger for * @param wrapperClazz The class of the wrapper if the created logger will be * used by a logger wrapper. The wrapper class name will be used to correctly determine the calling * method of the log methods omitting the wrapper class * * @return The logger for the given name, never null */ public static IDecoratingLogger getDecoratingLogger(final Class<?> clazz, final Class<?> wrapperClazz) { Assert.paramNotNull(clazz, "clazz"); Assert.paramNotNull(wrapperClazz, "wrapperClazz"); return getDecoratingLogger(clazz.getName(), wrapperClazz.getName()); } /** * Gets the currently set logger provider instance or creates one * * @return The logger provider instance, never null */ static ILoggerProvider instance() { if (loggerProvider == null) { loggerProvider = createLoggerProvider(); } return loggerProvider; } /** * Checks if the logger provider is initialized * * @return true if initialized, false otherwise */ static boolean isInitialized() { return loggerProvider != null; } private static synchronized ILoggerProvider createLoggerProvider() { final List<ILoggerProvider> loggerProviders = getAllLoggerProviders(); if (loggerProviders.size() > 1) { return new DefaultLoggerProvider(new LoggerFactoryComposite(createLoggerFactoriesForProviders(loggerProviders))); } else { return loggerProviders.iterator().next(); } } private static List<ILoggerFactory> createLoggerFactoriesForProviders(final List<ILoggerProvider> providers) { final List<ILoggerFactory> result = new ArrayList<ILoggerFactory>(); for (final ILoggerProvider provider : providers) { result.add(new LoggerProviderToFactoryAdapter(provider)); } return result; } private static synchronized List<ILoggerProvider> getAllLoggerProviders() { final List<ILoggerProvider> result = new LinkedList<ILoggerProvider>(REGISTERED_PROVIDERS); result.addAll(MANUALLY_ADDED_PROVIDERS); if (result.isEmpty()) { printNoLoggingAdapterFound(); result.add(ConsoleLoggerProvider.warnLoggerProvider()); } return result; } private static void printNoLoggingAdapterFound() { //CHECKSTYLE:OFF System.err.println(DEFAULT_LOGGER_WARNING); //CHECKSTYLE:ON } private static synchronized List<ILoggerProvider> createRegisteredLoggerProviders() { final List<ILoggerProvider> result = new LinkedList<ILoggerProvider>(); final ServiceLoader<ILoggerProvider> loader = ServiceLoader.load( ILoggerProvider.class, SharedClassLoader.getCompositeClassLoader()); final Iterator<ILoggerProvider> iterator = loader.iterator(); while (iterator.hasNext()) { result.add(iterator.next()); } return result; } private static final class DecoratingLoggerImpl extends LoggerWrapper implements IDecoratingLogger { private final ILogger original; DecoratingLoggerImpl(final String name, final String wrapperFQCN) { super(get(name, wrapperFQCN != null ? wrapperFQCN : DecoratingLoggerImpl.class.getName())); this.original = getOriginal(); } @Override public void error(final ILogMessageDecorator decorator, final String message) { decorator.error(message, original); } @Override public void error(final ILogMessageDecorator decorator, final Throwable throwable) { decorator.error(throwable, original); } @Override public void error(final ILogMessageDecorator decorator, final String message, final Throwable throwable) { decorator.error(message, throwable, original); } @Override public void warn(final ILogMessageDecorator decorator, final String message) { decorator.warn(message, original); } @Override public void warn(final ILogMessageDecorator decorator, final Throwable throwable) { decorator.warn(throwable, original); } @Override public void warn(final ILogMessageDecorator decorator, final String message, final Throwable throwable) { decorator.warn(message, throwable, original); } @Override public void info(final ILogMessageDecorator decorator, final String message) { decorator.info(message, original); } @Override public void info(final ILogMessageDecorator decorator, final Throwable throwable) { decorator.info(throwable, original); } @Override public void info(final ILogMessageDecorator decorator, final String message, final Throwable throwable) { decorator.info(message, throwable, original); } @Override public void debug(final ILogMessageDecorator decorator, final String message) { decorator.debug(message, original); } @Override public void debug(final ILogMessageDecorator decorator, final Throwable throwable) { decorator.debug(throwable, original); } @Override public void debug(final ILogMessageDecorator decorator, final String message, final Throwable throwable) { decorator.debug(message, throwable, original); } @Override public void trace(final ILogMessageDecorator decorator, final String message) { decorator.trace(message, original); } @Override public void trace(final ILogMessageDecorator decorator, final Throwable throwable) { decorator.trace(throwable, original); } @Override public void trace(final ILogMessageDecorator decorator, final String message, final Throwable throwable) { decorator.trace(message, throwable, original); } } }