LogSource.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.logging;

  18. import java.lang.reflect.Constructor;
  19. import java.util.Hashtable;

  20. import org.apache.commons.logging.impl.NoOpLog;

  21. /**
  22.  * Factory for creating {@link Log} instances.  Applications should call
  23.  * the {@code makeNewLogInstance()} method to instantiate new instances
  24.  * of the configured {@link Log} implementation class.
  25.  * <p>
  26.  * By default, calling {@code getInstance()} will use the following
  27.  * algorithm:
  28.  * <ul>
  29.  * <li>If Log4J is available, return an instance of
  30.  *     {@code org.apache.commons.logging.impl.Log4JLogger}.</li>
  31.  * <li>If JDK 1.4 or later is available, return an instance of
  32.  *     {@code org.apache.commons.logging.impl.Jdk14Logger}.</li>
  33.  * <li>Otherwise, return an instance of
  34.  *     {@code org.apache.commons.logging.impl.NoOpLog}.</li>
  35.  * </ul>
  36.  * <p>
  37.  * You can change the default behavior in one of two ways:
  38.  * <ul>
  39.  * <li>On the startup command line, set the system property
  40.  *     {@code org.apache.commons.logging.log} to the name of the
  41.  *     {@code org.apache.commons.logging.Log} implementation class
  42.  *     you want to use.</li>
  43.  * <li>At runtime, call {@code LogSource.setLogImplementation()}.</li>
  44.  * </ul>
  45.  *
  46.  * @deprecated Use {@link LogFactory} instead - The default factory
  47.  *  implementation performs exactly the same algorithm as this class did
  48.  */
  49. @Deprecated
  50. public class LogSource {

  51.     /**
  52.      * Logs.
  53.      */
  54.     static protected Hashtable<String, Log> logs = new Hashtable<>();

  55.     /** Is Log4j available (in the current classpath) */
  56.     static protected boolean log4jIsAvailable;

  57.     /**
  58.      * Is JDK 1.4 logging available, always true.
  59.      *
  60.      * @deprecated Java 8 is the baseline and includes JUL.
  61.      */
  62.     @Deprecated
  63.     static protected boolean jdk14IsAvailable = true;

  64.     /** Constructor for current log class */
  65.     static protected Constructor<?> logImplctor;

  66.     /**
  67.      * An empty immutable {@code String} array.
  68.      */
  69.     private static final String[] EMPTY_STRING_ARRAY = {};

  70.     static {

  71.         // Is Log4J Available?
  72.         log4jIsAvailable = isClassForName("org.apache.log4j.Logger");

  73.         // Set the default Log implementation
  74.         String name = null;
  75.         try {
  76.             name = System.getProperty("org.apache.commons.logging.log");
  77.             if (name == null) {
  78.                 name = System.getProperty("org.apache.commons.logging.Log");
  79.             }
  80.         } catch (final Throwable ignore) {
  81.             // Ignore
  82.         }
  83.         if (name != null) {
  84.             try {
  85.                 setLogImplementation(name);
  86.             } catch (final Throwable t) {
  87.                 try {
  88.                     setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
  89.                 } catch (final Throwable ignore) {
  90.                     // Ignore
  91.                 }
  92.             }
  93.         } else {
  94.             try {
  95.                 if (log4jIsAvailable) {
  96.                     setLogImplementation("org.apache.commons.logging.impl.Log4JLogger");
  97.                 } else {
  98.                     setLogImplementation("org.apache.commons.logging.impl.Jdk14Logger");
  99.                 }
  100.             } catch (final Throwable t) {
  101.                 try {
  102.                     setLogImplementation("org.apache.commons.logging.impl.NoOpLog");
  103.                 } catch (final Throwable ignore) {
  104.                     // Ignore
  105.                 }
  106.             }
  107.         }

  108.     }

  109.     /**
  110.      * Gets a {@code Log} instance by class.
  111.      *
  112.      * @param clazz a Class.
  113.      * @return a {@code Log} instance.
  114.      */
  115.     static public Log getInstance(final Class<?> clazz) {
  116.         return getInstance(clazz.getName());
  117.     }

  118.     /**
  119.      * Gets a {@code Log} instance by class name.
  120.      *
  121.      * @param name Class name.
  122.      * @return a {@code Log} instance.
  123.      */
  124.     static public Log getInstance(final String name) {
  125.         return logs.computeIfAbsent(name, k -> makeNewLogInstance(name));
  126.     }

  127.     /**
  128.      * Returns a {@link String} array containing the names of
  129.      * all logs known to me.
  130.      *
  131.      * @return a {@link String} array containing the names of
  132.      * all logs known to me.
  133.      */
  134.     static public String[] getLogNames() {
  135.         return logs.keySet().toArray(EMPTY_STRING_ARRAY);
  136.     }

  137.     private static boolean isClassForName(final String className) {
  138.         try {
  139.             Class.forName(className);
  140.             return true;
  141.         } catch (final Throwable e) {
  142.             return false;
  143.         }
  144.     }

  145.     /**
  146.      * Create a new {@link Log} implementation, based on the given <em>name</em>.
  147.      * <p>
  148.      * The specific {@link Log} implementation returned is determined by the
  149.      * value of the {@code org.apache.commons.logging.log} property. The value
  150.      * of {@code org.apache.commons.logging.log} may be set to the fully specified
  151.      * name of a class that implements the {@link Log} interface. This class must
  152.      * also have a public constructor that takes a single {@link String} argument
  153.      * (containing the <em>name</em> of the {@link Log} to be constructed.
  154.      * <p>
  155.      * When {@code org.apache.commons.logging.log} is not set, or when no corresponding
  156.      * class can be found, this method will return a Log4JLogger if the Log4j Logger
  157.      * class is available in the {@link LogSource}'s classpath, or a Jdk14Logger if we
  158.      * are on a JDK 1.4 or later system, or NoOpLog if neither of the above conditions is true.
  159.      *
  160.      * @param name the log name (or category)
  161.      * @return a new instance.
  162.      */
  163.     static public Log makeNewLogInstance(final String name) {
  164.         Log log;
  165.         try {
  166.             final Object[] args = { name };
  167.             log = (Log) logImplctor.newInstance(args);
  168.         } catch (final Throwable t) {
  169.             log = null;
  170.         }
  171.         if (null == log) {
  172.             log = new NoOpLog(name);
  173.         }
  174.         return log;
  175.     }

  176.     /**
  177.      * Sets the log implementation/log implementation factory by class. The given class must implement {@link Log}, and provide a constructor that takes a single
  178.      * {@link String} argument (containing the name of the log).
  179.      *
  180.      * @param logClass class.
  181.      * @throws LinkageError                if there is missing dependency.
  182.      * @throws ExceptionInInitializerError unexpected exception has occurred in a static initializer.
  183.      * @throws NoSuchMethodException       if a matching method is not found.
  184.      * @throws SecurityException           If a security manager, <em>s</em>, is present and the caller's class loader is not the same as or an ancestor of the
  185.      *                                     class loader for the current class and invocation of {@link SecurityManager#checkPackageAccess
  186.      *                                     s.checkPackageAccess()} denies access to the package of this class.
  187.      */
  188.     static public void setLogImplementation(final Class<?> logClass)
  189.             throws LinkageError, ExceptionInInitializerError, NoSuchMethodException, SecurityException {
  190.         logImplctor = logClass.getConstructor(String.class);
  191.     }

  192.     /**
  193.      * Sets the log implementation/log implementation factory by the name of the class. The given class must implement {@link Log}, and provide a constructor
  194.      * that takes a single {@link String} argument (containing the name of the log).
  195.      *
  196.      * @param className class name.
  197.      * @throws LinkageError           if there is missing dependency.
  198.      * @throws SecurityException      If a security manager, <em>s</em>, is present and the caller's class loader is not the same as or an ancestor of the class
  199.      *                                loader for the current class and invocation of {@link SecurityManager#checkPackageAccess s.checkPackageAccess()} denies
  200.      *                                access to the package of this class.
  201.      */
  202.     static public void setLogImplementation(final String className) throws LinkageError, SecurityException {
  203.         try {
  204.             final Class<?> logClass = Class.forName(className);
  205.             logImplctor = logClass.getConstructor(String.class);
  206.         } catch (final Throwable t) {
  207.             logImplctor = null;
  208.         }
  209.     }

  210.     /** Don't allow others to create instances. */
  211.     private LogSource() {
  212.     }
  213. }