<!--

 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.

-->

<body>
<p>Simple wrapper API around multiple logging APIs.</p>


<h3>Overview</h3>

<p>This package provides an API for logging in server-based applications that
can be used around a variety of different logging implementations, including
prebuilt support for the following:</p>
<ul>
<li><a href="http://logging.apache.org/log4j/">Log4J</a> (version 1.2 or later)
    from Apache's Logging project.  Each named <a href="Log.html">Log</a>
    instance is connected to a corresponding Log4J Logger.</li>
<li><a href="http://java.sun.com/j2se/1.4/docs/guide/util/logging/index.html">
    JDK Logging API</a>, included in JDK 1.4 or later systems.  Each named
    <a href="Log.html">Log</a> instance is connected to a corresponding
    <code>java.util.logging.Logger</code> instance.</li>
<li><a href="http://avalon.apache.org/logkit/">LogKit</a> from Apache's
    Avalon project.  Each named <a href="Log.html">Log</a> instance is
    connected to a corresponding LogKit <code>Logger</code>.</li>
<li><a href="impl/NoOpLog.html">NoOpLog</a> implementation that simply swallows
    all log output, for all named <a href="Log.html">Log</a> instances.</li>
<li><a href="impl/SimpleLog.html">SimpleLog</a> implementation that writes all
    log output, for all named <a href="Log.html">Log</a> instances, to
    System.err.</li>
</ul>


<h3>Quick Start Guide</h3>

<p>For those impatient to just get on with it, the following example
illustrates the typical declaration and use of a logger that is named (by
convention) after the calling class:

<pre>
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    public class Foo {

        private Log log = LogFactory.getLog(Foo.class);

        public void foo() {
            ...
            try {
                if (log.isDebugEnabled()) {
                    log.debug("About to do something to object " + name);
                }
                name.bar();
            } catch (IllegalStateException e) {
                log.error("Something bad happened to " + name, e);
            }
            ...
        }
</pre>

<p>Unless you configure things differently, all log output will be written
to System.err.  Therefore, you really will want to review the remainder of
this page in order to understand how to configure logging for your
application.</p>


<h3>Configuring the Commons Logging Package</h3>


<h4>Choosing a <code>LogFactory</code> Implementation</h4>

<p>From an application perspective, the first requirement is to retrieve an
object reference to the <code>LogFactory</code> instance that will be used
to create <code><a href="Log.html">Log</a></code> instances for this
application.  This is normally accomplished by calling the static
<code>getFactory()</code> method.  This method implements the following
discovery algorithm to select the name of the <code>LogFactory</code>
implementation class this application wants to use:</p>
<ul>
<li>Check for a system property named
   <code>org.apache.commons.logging.LogFactory</code>.</li>
<li>Use the JDK 1.3 JAR Services Discovery mechanism (see
    <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html">
    http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html</a> for
    more information) to look for a resource named
    <code>META-INF/services/org.apache.commons.logging.LogFactory</code>
    whose first line is assumed to contain the desired class name.</li>
<li>Look for a properties file named <code>commons-logging.properties</code>
    visible in the application class path, with a property named
    <code>org.apache.commons.logging.LogFactory</code> defining the
    desired implementation class name.</li>
<li>Fall back to a default implementation, which is described
    further below.</li>
</ul>

<p>If a <code>commons-logging.properties</code> file is found, all of the
properties defined there are also used to set configuration attributes on
the instantiated <code>LogFactory</code> instance.</p>

<p>Once an implementation class name is selected, the corresponding class is
loaded from the current Thread context class loader (if there is one), or
from the class loader that loaded the <code>LogFactory</code> class itself
otherwise.  This allows a copy of <code>commons-logging.jar</code> to be
shared in a multiple class loader environment (such as a servlet container),
but still allow each web application to provide its own <code>LogFactory</code>
implementation, if it so desires.  An instance of this class will then be
created, and cached per class loader.


<h4>The Default <code>LogFactory</code> Implementation</h4>

<p>The Logging Package APIs include a default <code>LogFactory</code>
implementation class (<a href="impl/LogFactoryImpl.html">
org.apache.commons.logging.impl.LogFactoryImpl</a>) that is selected if no
other implementation class name can be discovered.  Its primary purpose is
to create (as necessary) and return <a href="Log.html">Log</a> instances
in response to calls to the <code>getInstance()</code> method.  The default
implementation uses the following rules:</p>
<ul>
<li>At most one <code>Log</code> instance of the same name will be created.
    Subsequent <code>getInstance()</code> calls to the same
    <code>LogFactory</code> instance, with the same name or <code>Class</code>
    parameter, will return the same <code>Log</code> instance.</li>
<li>When a new <code>Log</code> instance must be created, the default
    <code>LogFactory</code> implementation uses the following discovery
    process:
    <ul>
    <li>Look for a configuration attribute of this factory named
        <code>org.apache.commons.logging.Log</code> (for backwards
        compatibility to pre-1.0 versions of this API, an attribute
        <code>org.apache.commons.logging.log</code> is also consulted).</li>
    <li>Look for a system property named
        <code>org.apache.commons.logging.Log</code> (for backwards
        compatibility to pre-1.0 versions of this API, a system property
        <code>org.apache.commons.logging.log</code> is also consulted).</li>
    <li>If the Log4J logging system is available in the application
        class path, use the corresponding wrapper class
        (<a href="impl/Log4JLogger.html">Log4JLogger</a>).</li>
    <li>If the application is executing on a JDK 1.4 system, use
        the corresponding wrapper class
        (<a href="impl/Jdk14Logger.html">Jdk14Logger</a>).</li>
    <li>Fall back to the default simple logging implementation
        (<a href="impl/SimpleLog.html">SimpleLog</a>).</li>
    </ul></li>
<li>Load the class of the specified name from the thread context class
    loader (if any), or from the class loader that loaded the
    <code>LogFactory</code> class otherwise.</li>
<li>Instantiate an instance of the selected <code>Log</code>
    implementation class, passing the specified name as the single
    argument to its constructor.</li>
</ul>

<p>See the <a href="impl/SimpleLog.html">SimpleLog</a> Javadocs for detailed
configuration information for this default implementation.</p>


<h4>Configuring the Underlying Logging System</h4>

<p>The basic principle is that the user is totally responsible for the
configuration of the underlying logging system.
Commons-logging should not change the existing configuration.</p>

<p>Each individual <a href="Log.html">Log</a> implementation may
support its own configuration properties.  These will be documented in the
class descriptions for the corresponding implementation class.</p>

<p>Finally, some <code>Log</code> implementations (such as the one for Log4J)
require an external configuration file for the entire logging environment.
This file should be prepared in a manner that is specific to the actual logging
technology being used.</p>


<h3>Using the Logging Package APIs</h3>

<p>Use of the Logging Package APIs, from the perspective of an application
component, consists of the following steps:</p>
<ol>
<li>Acquire a reference to an instance of
    <a href="Log.html">org.apache.commons.logging.Log</a>, by calling the
    factory method
    <a href="LogFactory.html#getInstance(java.lang.String)">
    LogFactory.getInstance(String name)</a>.  Your application can contain
    references to multiple loggers that are used for different
    purposes.  A typical scenario for a server application is to have each
    major component of the server use its own Log instance.</li>
<li>Cause messages to be logged (if the corresponding detail level is enabled)
    by calling appropriate methods (<code>trace()</code>, <code>debug()</code>,
    <code>info()</code>, <code>warn()</code>, <code>error</code>, and
    <code>fatal()</code>).</li>
</ol>

<p>For convenience, <code>LogFactory</code> also offers a static method
<code>getLog()</code> that combines the typical two-step pattern:</p>
<pre>
  Log log = LogFactory.getFactory().getInstance(Foo.class);
</pre>
<p>into a single method call:</p>
<pre>
  Log log = LogFactory.getLog(Foo.class);
</pre>

<p>For example, you might use the following technique to initialize and
use a <a href="Log.html">Log</a> instance in an application component:</p>
<pre>
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MyComponent {

  protected Log log =
    LogFactory.getLog(MyComponent.class);

  // Called once at startup time
  public void start() {
    ...
    log.info("MyComponent started");
    ...
  }

  // Called once at shutdown time
  public void stop() {
    ...
    log.info("MyComponent stopped");
    ...
  }

  // Called repeatedly to process a particular argument value
  // which you want logged if debugging is enabled
  public void process(String value) {
    ...
    // Do the string concatenation only if logging is enabled
    if (log.isDebugEnabled())
      log.debug("MyComponent processing " + value);
    ...
  }

}
</pre>

</body>
