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

org.apache.commons.logging.impl.LogFactoryImpl Maven / Gradle / Ivy

/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed 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.commons.logging.impl;


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogConfigurationException;
import org.apache.commons.logging.LogFactory;


/**
 * 

Concrete subclass of {@link LogFactory} that implements the * following algorithm to dynamically select a logging implementation * class to instantiate a wrapper for.

*
    *
  • Use a factory configuration attribute named * org.apache.commons.logging.Log to identify the * requested implementation class.
  • *
  • Use the org.apache.commons.logging.Log system property * to identify the requested implementation class.
  • *
  • If Log4J is available, return an instance of * org.apache.commons.logging.impl.Log4JLogger.
  • *
  • If JDK 1.4 or later is available, return an instance of * org.apache.commons.logging.impl.Jdk14Logger.
  • *
  • Otherwise, return an instance of * org.apache.commons.logging.impl.SimpleLog.
  • *
* *

If the selected {@link Log} implementation class has a * setLogFactory() method that accepts a {@link LogFactory} * parameter, this method will be called on each newly created instance * to identify the associated factory. This makes factory configuration * attributes available to the Log instance, if it so desires.

* *

This factory will remember previously created Log instances * for the same name, and will return them on repeated requests to the * getInstance() method. This implementation ignores any * configured attributes.

* * @author Rod Waldhoff * @author Craig R. McClanahan * @author Richard A. Sitze * @version $Revision: 1.33 $ $Date: 2004/03/06 21:52:59 $ */ public class LogFactoryImpl extends LogFactory { // ----------------------------------------------------------- Constructors /** * Public no-arguments constructor required by the lookup mechanism. */ public LogFactoryImpl() { super(); } // ----------------------------------------------------- Manifest Constants /** * The name of the system property identifying our {@link Log} * implementation class. */ public static final String LOG_PROPERTY = "org.apache.commons.logging.Log"; /** * The deprecated system property used for backwards compatibility with * the old {@link org.apache.commons.logging.LogSource} class. */ protected static final String LOG_PROPERTY_OLD = "org.apache.commons.logging.log"; /** *

The name of the {@link Log} interface class.

*/ private static final String LOG_INTERFACE = "org.apache.commons.logging.Log"; // ----------------------------------------------------- Instance Variables /** * Configuration attributes. */ protected Hashtable attributes = new Hashtable(); /** * The {@link org.apache.commons.logging.Log} instances that have * already been created, keyed by logger name. */ protected Hashtable instances = new Hashtable(); /** * Name of the class implementing the Log interface. */ private String logClassName; /** * The one-argument constructor of the * {@link org.apache.commons.logging.Log} * implementation class that will be used to create new instances. * This value is initialized by getLogConstructor(), * and then returned repeatedly. */ protected Constructor logConstructor = null; /** * The signature of the Constructor to be used. */ protected Class logConstructorSignature[] = { java.lang.String.class }; /** * The one-argument setLogFactory method of the selected * {@link org.apache.commons.logging.Log} method, if it exists. */ protected Method logMethod = null; /** * The signature of the setLogFactory method to be used. */ protected Class logMethodSignature[] = { LogFactory.class }; // --------------------------------------------------------- Public Methods /** * Return the configuration attribute with the specified name (if any), * or null if there is no such attribute. * * @param name Name of the attribute to return */ public Object getAttribute(String name) { return (attributes.get(name)); } /** * Return an array containing the names of all currently defined * configuration attributes. If there are no such attributes, a zero * length array is returned. */ public String[] getAttributeNames() { Vector names = new Vector(); Enumeration keys = attributes.keys(); while (keys.hasMoreElements()) { names.addElement((String) keys.nextElement()); } String results[] = new String[names.size()]; for (int i = 0; i < results.length; i++) { results[i] = (String) names.elementAt(i); } return (results); } /** * Convenience method to derive a name from the specified class and * call getInstance(String) with it. * * @param clazz Class for which a suitable Log name will be derived * * @exception LogConfigurationException if a suitable Log * instance cannot be returned */ public Log getInstance(Class clazz) throws LogConfigurationException { return (getInstance(clazz.getName())); } /** *

Construct (if necessary) and return a Log instance, * using the factory's current set of configuration attributes.

* *

NOTE - Depending upon the implementation of * the LogFactory you are using, the Log * instance you are returned may or may not be local to the current * application, and may or may not be returned again on a subsequent * call with the same name argument.

* * @param name Logical name of the Log instance to be * returned (the meaning of this name is only known to the underlying * logging implementation that is being wrapped) * * @exception LogConfigurationException if a suitable Log * instance cannot be returned */ public Log getInstance(String name) throws LogConfigurationException { Log instance = (Log) instances.get(name); if (instance == null) { instance = newInstance(name); instances.put(name, instance); } return (instance); } /** * Release any internal references to previously created * {@link org.apache.commons.logging.Log} * instances returned by this factory. This is useful in environments * like servlet containers, which implement application reloading by * throwing away a ClassLoader. Dangling references to objects in that * class loader would prevent garbage collection. */ public void release() { instances.clear(); } /** * Remove any configuration attribute associated with the specified name. * If there is no such attribute, no action is taken. * * @param name Name of the attribute to remove */ public void removeAttribute(String name) { attributes.remove(name); } /** * Set the configuration attribute with the specified name. Calling * this with a null value is equivalent to calling * removeAttribute(name). * * @param name Name of the attribute to set * @param value Value of the attribute to set, or null * to remove any setting for this attribute */ public void setAttribute(String name, Object value) { if (value == null) { attributes.remove(name); } else { attributes.put(name, value); } } // ------------------------------------------------------ Protected Methods /** * Return the fully qualified Java classname of the {@link Log} * implementation we will be using. */ protected String getLogClassName() { // Return the previously identified class name (if any) if (logClassName != null) { return logClassName; } logClassName = (String) getAttribute(LOG_PROPERTY); if (logClassName == null) { // @deprecated logClassName = (String) getAttribute(LOG_PROPERTY_OLD); } if (logClassName == null) { try { logClassName = System.getProperty(LOG_PROPERTY); } catch (SecurityException e) { ; } } if (logClassName == null) { // @deprecated try { logClassName = System.getProperty(LOG_PROPERTY_OLD); } catch (SecurityException e) { ; } } if ((logClassName == null) && isLog4JAvailable()) { logClassName = "org.apache.commons.logging.impl.Log4JLogger"; } if ((logClassName == null) && isJdk14Available()) { logClassName = "org.apache.commons.logging.impl.Jdk14Logger"; } if ((logClassName == null) && isJdk13LumberjackAvailable()) { logClassName = "org.apache.commons.logging.impl.Jdk13LumberjackLogger"; } if (logClassName == null) { logClassName = "org.apache.commons.logging.impl.SimpleLog"; } return (logClassName); } /** *

Return the Constructor that can be called to instantiate * new {@link org.apache.commons.logging.Log} instances.

* *

IMPLEMENTATION NOTE - Race conditions caused by * calling this method from more than one thread are ignored, because * the same Constructor instance will ultimately be derived * in all circumstances.

* * @exception LogConfigurationException if a suitable constructor * cannot be returned */ protected Constructor getLogConstructor() throws LogConfigurationException { // Return the previously identified Constructor (if any) if (logConstructor != null) { return logConstructor; } String logClassName = getLogClassName(); // Attempt to load the Log implementation class Class logClass = null; Class logInterface = null; try { logInterface = this.getClass().getClassLoader().loadClass (LOG_INTERFACE); logClass = loadClass(logClassName); if (logClass == null) { throw new LogConfigurationException ("No suitable Log implementation for " + logClassName); } if (!logInterface.isAssignableFrom(logClass)) { Class interfaces[] = logClass.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (LOG_INTERFACE.equals(interfaces[i].getName())) { throw new LogConfigurationException ("Invalid class loader hierarchy. " + "You have more than one version of '" + LOG_INTERFACE + "' visible, which is " + "not allowed."); } } throw new LogConfigurationException ("Class " + logClassName + " does not implement '" + LOG_INTERFACE + "'."); } } catch (Throwable t) { throw new LogConfigurationException(t); } // Identify the setLogFactory method (if there is one) try { logMethod = logClass.getMethod("setLogFactory", logMethodSignature); } catch (Throwable t) { logMethod = null; } // Identify the corresponding constructor to be used try { logConstructor = logClass.getConstructor(logConstructorSignature); return (logConstructor); } catch (Throwable t) { throw new LogConfigurationException ("No suitable Log constructor " + logConstructorSignature+ " for " + logClassName, t); } } /** * MUST KEEP THIS METHOD PRIVATE. * *

Exposing this method outside of * org.apache.commons.logging.LogFactoryImpl * will create a security violation: * This method uses AccessController.doPrivileged(). *

* * Load a class, try first the thread class loader, and * if it fails use the loader that loaded this class. */ private static Class loadClass( final String name ) throws ClassNotFoundException { Object result = AccessController.doPrivileged( new PrivilegedAction() { public Object run() { ClassLoader threadCL = getContextClassLoader(); if (threadCL != null) { try { return threadCL.loadClass(name); } catch( ClassNotFoundException ex ) { // ignore } } try { return Class.forName( name ); } catch (ClassNotFoundException e) { return e; } } }); if (result instanceof Class) return (Class)result; throw (ClassNotFoundException)result; } /** * Is JDK 1.3 with Lumberjack logging available? */ protected boolean isJdk13LumberjackAvailable() { try { loadClass("java.util.logging.Logger"); loadClass("org.apache.commons.logging.impl.Jdk13LumberjackLogger"); return (true); } catch (Throwable t) { return (false); } } /** *

Return true if JDK 1.4 or later logging * is available. Also checks that the Throwable class * supports getStackTrace(), which is required by * Jdk14Logger.

*/ protected boolean isJdk14Available() { try { loadClass("java.util.logging.Logger"); loadClass("org.apache.commons.logging.impl.Jdk14Logger"); Class throwable = loadClass("java.lang.Throwable"); if (throwable.getDeclaredMethod("getStackTrace", null) == null) { return (false); } return (true); } catch (Throwable t) { return (false); } } /** * Is a Log4J implementation available? */ protected boolean isLog4JAvailable() { try { loadClass("org.apache.log4j.Logger"); loadClass("org.apache.commons.logging.impl.Log4JLogger"); return (true); } catch (Throwable t) { return (false); } } /** * Create and return a new {@link org.apache.commons.logging.Log} * instance for the specified name. * * @param name Name of the new logger * * @exception LogConfigurationException if a new instance cannot * be created */ protected Log newInstance(String name) throws LogConfigurationException { Log instance = null; try { Object params[] = new Object[1]; params[0] = name; instance = (Log) getLogConstructor().newInstance(params); if (logMethod != null) { params[0] = this; logMethod.invoke(instance, params); } return (instance); } catch (InvocationTargetException e) { Throwable c = e.getTargetException(); if (c != null) { throw new LogConfigurationException(c); } else { throw new LogConfigurationException(e); } } catch (Throwable t) { throw new LogConfigurationException(t); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy