[logback-dev] svn commit: r1756 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic logback-site/src/site/pages/css logback-site/src/site/pages/manual
noreply.ceki at qos.ch
noreply.ceki at qos.ch
Thu Aug 14 18:02:21 CEST 2008
Author: ceki
Date: Thu Aug 14 18:02:21 2008
New Revision: 1756
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java
logback/trunk/logback-site/src/site/pages/css/site.css
logback/trunk/logback-site/src/site/pages/manual/joran.html
Log:
- improving the docs
- added chapter numbering by CSS (firefox only)
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/BasicConfigurator.java Thu Aug 14 18:02:21 2008
@@ -17,6 +17,14 @@
import ch.qos.logback.core.status.InfoStatus;
import ch.qos.logback.core.status.StatusManager;
+/**
+ * BasicConfigurator configures logback-classic by attaching a
+ * {@link ConsoleAppender} to the root logger. The console appender's layout
+ * is set to a {@link PatternLayout} with the pattern
+ * "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n".
+ *
+ * @author Ceki Gulcu
+ */
public class BasicConfigurator {
final static BasicConfigurator hiddenSingleton = new BasicConfigurator();
Modified: logback/trunk/logback-site/src/site/pages/css/site.css
==============================================================================
--- logback/trunk/logback-site/src/site/pages/css/site.css (original)
+++ logback/trunk/logback-site/src/site/pages/css/site.css Thu Aug 14 18:02:21 2008
@@ -9,6 +9,7 @@
color: #000;
padding: 0px;
margin: 0px;
+ counter-reset: example; /* Create an example counter scope */
}
a {
@@ -166,6 +167,7 @@
#content {
+ min-width:50em;
margin: 0px 15em 0px 15em;
padding: 0px;
background-color: #ffffff;
@@ -304,4 +306,10 @@
.quote {
align: right;
padding-left: 12em;
+}
+
+/* --------- numbering --------- */
+.autoEx:before {
+ counter-increment: example; /* Add 1 to example */
+ content: counter(example)
}
\ No newline at end of file
Modified: logback/trunk/logback-site/src/site/pages/manual/joran.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/joran.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/joran.html Thu Aug 14 18:02:21 2008
@@ -18,7 +18,7 @@
<div id="right">
<script src="index_menu.js"></script>
</div>
-<div id="content">
+<div id="content" class="chapter">
<h1>Chapter 3: Logback configuration & Joran</h1>
@@ -43,7 +43,7 @@
<p>In the first part, we start by presenting ways for configuring
logback, with many example configuration scripts. In the <a
href="#Joran">second part</a>, we present Joran, a generic
- configuration framework, that you can put into use in order to
+ configuration framework, which you can put into use in order to
configure your own applications.
</p>
@@ -56,8 +56,8 @@
approximately four percent of code is dedicated to
logging. Consequently, even moderately sized applications will
contain thousands of logging statements embedded within its
- code. Given their number, we need powerful tools to manage these
- log statements.
+ code. Given their number, we need tools to manage these log
+ statements.
</p>
<p>Logback can be configured either programmatically or with
@@ -85,8 +85,7 @@
<li><p>In case neither file is found, logback configures itself
automatically using the <a
href="../xref/ch/qos/logback/classic/BasicConfigurator.html"><code>BasicConfigurator</code></a>
- which will cause logging output to be directed on the
- console.
+ which will cause logging output to be directed on the console.
</p>
</li>
@@ -103,7 +102,7 @@
won't be included in the artifact produced. Thus, you can use a
different configuration file, namely <em>logback-test.xml</em>
during testing, and another file, namely, <em>logback.xml</em>, in
- production. The same principle could apply by analogy for Ant.
+ production. The same principle applies by analogy for Ant.
</p>
@@ -115,9 +114,11 @@
<code>MyApp1</code>.
</p>
-<em>Example 3.1: Simple example of <code>BasicConfigurator</code> usage
-<a href="../xref/chapter3/MyApp1.html">(logback-examples/src/main/java/chapter3/MyApp1.java)</a></em>
-<div class="source"><pre>package chapter3;
+ <em>Example 3.<span class="autoEx"/>: Simple example of
+ <code>BasicConfigurator</code> usage <a
+ href="../xref/chapter3/MyApp1.html">(logback-examples/src/main/java/chapter3/MyApp1.java)</a></em>
+
+ <div class="source"><pre>package chapter3;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -138,7 +139,7 @@
instantiates a Foo object. The Foo class is listed below:
</p>
- <em>Example 3.2: Small class doing logging
+ <em>Example 3.<span class="autoEx"/>: Small class doing logging
<a href="../xref/chapter3/Foo.html">(logback-examples/src/main/java/chapter3/Foo.java)</a>
</em>
@@ -156,34 +157,33 @@
}</pre></div>
-
- <p>In order to run the examples in this chapter, you need to make
- sure that certain jar files are present on the classpath. Please
- refer to the <a href="../setup.html">setup page</a> for further
- details.
- </p>
+ <p>In order to run the examples in this chapter, you need to make
+ sure that certain jar files are present on the classpath. Please
+ refer to the <a href="../setup.html">setup page</a> for further
+ details.
+ </p>
<p>Assuming the configuration files <em>logback-test.xml</em> or
<em>logback.xml</em> could not be found, logback will default to a
- minimal configuration hardwired to attaching a
- <code>ConsoleAppender</code> to the root logger. The output is
- formatted using a <code>PatternLayout</code> set to the pattern
- <em>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -
- %msg%n</em>. Moreover, by default the root logger is assigned to
- the <code>DEBUG</code> level.
- </p>
+ minimal configuration mentioned earlier. This configuration is
+ hardwired to attaching a <code>ConsoleAppender</code> to the root
+ logger. The output is formatted using a
+ <code>PatternLayout</code> set to the pattern <em>%d{HH:mm:ss.SSS}
+ [%thread] %-5level %logger{36} - %msg%n</em>. Moreover, by default
+ the root logger is assigned to the <code>DEBUG</code> level.
+ </p>
- <p>Thus, the output of the command <em>java chapter3.MyApp1</em>
- should be similar to:
- </p>
+ <p>Thus, the output of the command <em>java chapter3.MyApp1</em>
+ should be similar to:
+ </p>
<div class="source"><pre>16:06:09.031 [main] INFO chapter3.MyApp1 - Entering application.
16:06:09.046 [main] DEBUG chapter3.Foo - Did it again!
16:06:09.046 [main] INFO chapter3.MyApp1 - Exiting application.</pre></div>
- <p>The <code>MyApp1</code> application links to logback through
+ <p>The <code>MyApp1</code> application links to logback via
calls <code>org.slf4j.LoggerFactory</code> and
<code>org.slf4j.Logger</code> classes, retrieve the loggers it
wishes to use, and chugs on. Note that the only dependence of the
@@ -196,18 +196,85 @@
bodies of code from one logging system to another.
</p>
-
- <h3>The same with <code>JoranConfigurator</code></h3>
+ <h3>Automatic configuration with <em>logback-test.xml</em> or
+ <em>logback.xml</em></h3>
+
+ <p>As mentioned earlier, logback will try to configure itself using
+ the files <em>logback-test.xml</em> or <em>logback.xml</em> if
+ found on the classpath. Here is a configuration file equivalent to
+ the one established by <code>BasicConfigrator</code> we've just
+ seen.
+ </p>
+
+ <p><em>Example 3.<span class="autoEx"/>: Basic configuration file
+ (logback-examples/src/main/java/chapter3/sample0.xml)</em></p>
+
+ <div class="source"><pre><configuration>
+
+ <appender name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <layout class="ch.qos.logback.classic.PatternLayout">
+ <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="debug" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration></pre></div>
+
+ <p>After you have renamed <em>sample0.xml</em> as
+ <em>logback.xml</em> (or <em>logback-test.xml</em>) place it into a
+ directory accesible from the classpath. Running the <em>MyApp1</em>
+ application should give identical results to its previous run.</p>
+
+ <p>If you are having problems with this example, you might want to
+ inspect logback's internal status. This is done invoking the
+ <code>print()</code> of the <code>StatusPrinter</code> class. The
+ <em>MyApp2</em> application shown below is identical to
+ <em>MyApp1</em> except the addition of two lines of code for
+ printing internal status data.</p>
+
+ <em>Example 3.<span class="autoEx"/>: Print logback's internal status information
+ <a
+ href="../xref/chapter3/MyApp2.html">(logback-examples/src/main/java/chapter3/MyApp2.java)</a></em>
+
+ <div class="source"><pre>
+ public static void main(String[] args) {
+ logger.info("Entering application.");
+ <b>// print logback's internal status
+ LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+ StatusPrinter.print(lc);</b>
+ ...
+ }</pre></div>
+
+ <p>If everything goes well, you should see the following output on the console</p>
+
+ <div class="source"><pre>17:58:31.328 [main] INFO chapter3.MyApp2 - Entering application.
+17:58:31,171 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Ignoring debug attribute.
+17:58:31,171 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
+17:58:31,171 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
+17:58:31,328 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack
+17:58:31,328 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
+17:58:31,328 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root]
+
+17:58:31.343 [main] DEBUG chapter3.Foo - Did it again!
+17:58:31.343 [main] INFO chapter3.MyApp2 - Exiting application.
+</pre></div>
+
+
+ <h3>Invoking <code>JoranConfigurator</code> programmatically</h3>
<p>The previous example outputs logging information always in the
- same fixed manner. How boring! It takes few easy steps to modify
+ same fixed manner. How boring! It takes few simple steps to modify
<code>MyApp1</code> so that the log output can be controlled at
runtime. Here is a slightly modified application called
<code>MyApp2</code>.
</p>
- <p><em>Example 3.2: Simple example of
+ <p><em>Example 3.<span class="autoEx"/>: Simple example of
<code>BasicConfigurator</code> usage <a
href="../xref/chapter3/MyApp2.html">(logback-examples/src/main/java/chapter3/MyApp2.java)</a></em></p>
@@ -253,7 +320,7 @@
below:
</p>
- <p><em>Example 3.3: Basic configuration file
+ <p><em>Example 3.<span class="autoEx"/>: Basic configuration file
(logback-examples/src/main/java/chapter3/sample0.xml)</em></p>
<div class="source"><pre><configuration>
@@ -312,7 +379,7 @@
above:
wec</p>
-<em>Example 3.4: Basic configuration file using debug mode (logback-examples/src/main/java/chapter3/sample1.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Basic configuration file using debug mode (logback-examples/src/main/java/chapter3/sample1.xml)</em>
<div class="source"><pre><configuration <b>debug="true"</b>>
<appender name="STDOUT"
@@ -370,54 +437,57 @@
<h4>Configuring Loggers</h4>
-<p>
-Loggers are configured using <em>logger</em> elements. A <em>logger</em> element takes exactly
-one mandatory name atttribute and an optional additivity attribute, which takes values
-<em>true</em> or <em>false</em>. The <em>logger</em> element admits at most one <em>level</em>
-element which is discussed next. It may also contain zero or more <em>appender-ref</em> elements;
-each appender thus referenced is added to the named logger. It is important to keep mind that
-each named logger that is declared with a <em>logger</em> element first has all its
-appenders removed and only then are the referenced appenders attached to it.
-In particular, if there are no appender references, then the named logger will
-lose all its appenders.
-</p>
-
-<p>
-The <em>level</em> element is used to set logger levels. It admits two attributes
-<em>value</em> and <em>class</em>. The value attribute can be one of the strings <em>DEBUG</em>,
-<em>INFO</em>, <em>WARN</em> <em>ERROR</em>, <em>ALL</em> or <em>OFF</em>.
-The special case-insensitive value <em>INHERITED</em>, or its synonym <em>NULL</em>,
-will force the level of the logger to be inherited from higher up in the hierarchy.
-Note that the level of the root logger cannot be inherited.
-If you set the level of a logger and later decide that it should inherit
-its level, then you need to specify <em>INHERITED</em> or its synonym <em>NULL</em>
-as the level value. The class attribute allows you to specify a custom
-level where the value of the attribute is the fully qualified name of a
-custom level class. You may alternatively use the <em>level#classname</em> syntax within
-the value attribute. The <em>level</em> element has no children.
-</p>
-
-<p>
-The <em>root</em> element configures the root logger. It does not admit
-any attributes because the additivity flag does not apply to the root logger.
-Moreover, since the root logger cannot be named, it does not admit a name
-attribute either. The <em>root</em> element admits at most one <em>level</em>
-element and zero or more <em>appender-ref</em> elements.
-Similar to the <em>logger</em> element, declaring a <em>root</em> element
-will have the effect of first closing and then detaching all its current
-appenders and only subsequently will referenced appenders, if any, will be added.
-In particular, if it has no appender references, then the root logger
-will lose all its appenders.
-</p>
-
-<p>
-Setting the level of a logger is as simple as declaring it and setting
-its level, as the next example illustrates. Suppose we are no longer interested
-in seeing any <code>DEBUG</code> level logs from any component
-belonging to the chapter3 package. The following configuration file shows how to achieve that.
-</p>
+<p>Loggers are configured using <em>logger</em> elements. A
+<em>logger</em> element takes exactly one mandatory name atttribute
+and an optional additivity attribute, which takes values <em>true</em>
+or <em>false</em>. The <em>logger</em> element admits at most one
+<em>level</em> element which is discussed next. It may also contain
+zero or more <em>appender-ref</em> elements; each appender thus
+referenced is added to the named logger. It is important to keep mind
+that each named logger that is declared with a <em>logger</em> element
+first has all its appenders removed and only then are the referenced
+appenders attached to it. In particular, if there are no appender
+references, then the named logger will lose all its appenders.
+</p>
+
+<p>The <em>level</em> element is used to set logger levels. It admits
+two attributes <em>value</em> and <em>class</em>. The value attribute
+can be one of the strings <em>DEBUG</em>, <em>INFO</em>, <em>WARN</em>
+<em>ERROR</em>, <em>ALL</em> or <em>OFF</em>. The special
+case-insensitive value <em>INHERITED</em>, or its synonym
+<em>NULL</em>, will force the level of the logger to be inherited from
+higher up in the hierarchy. Note that the level of the root logger
+cannot be inherited. If you set the level of a logger and later
+decide that it should inherit its level, then you need to specify
+<em>INHERITED</em> or its synonym <em>NULL</em> as the level
+value. The class attribute allows you to specify a custom level where
+the value of the attribute is the fully qualified name of a custom
+level class. You may alternatively use the <em>level#classname</em>
+syntax within the value attribute. The <em>level</em> element has no
+children.
+</p>
+
+<p>The <em>root</em> element configures the root logger. It does not
+admit any attributes because the additivity flag does not apply to the
+root logger. Moreover, since the root logger cannot be named, it does
+not admit a name attribute either. The <em>root</em> element admits at
+most one <em>level</em> element and zero or more <em>appender-ref</em>
+elements. Similar to the <em>logger</em> element, declaring a
+<em>root</em> element will have the effect of first closing and then
+detaching all its current appenders and only subsequently will
+referenced appenders, if any, will be added. In particular, if it has
+no appender references, then the root logger will lose all its
+appenders.
+</p>
+
+ <p>Setting the level of a logger is as simple as declaring it and
+ setting its level, as the next example illustrates. Suppose we are
+ no longer interested in seeing any <code>DEBUG</code> level logs
+ from any component belonging to the chapter3 package. The following
+ configuration file shows how to achieve that.
+ </p>
-<em>Example 3.5: Setting the level of a logger (logback-examples/src/main/java/chapter3/sample2.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Setting the level of a logger (logback-examples/src/main/java/chapter3/sample2.xml)</em>
<div class="source"><pre><configuration>
<appender name="STDOUT"
@@ -440,22 +510,20 @@
</configuration></pre></div>
-<p>
-This new configuration will yield the following output, when used with the
-same <code>chapter3.MyApp2</code> class.
+<p>This new configuration will yield the following output, when used
+with the same <code>chapter3.MyApp2</code> class.
</p>
<div class="source"><pre>17:34:07.578 [main] INFO chapter3.MyApp2 - Entering application.
17:34:07.578 [main] INFO chapter3.MyApp2 - Exiting application.</pre></div>
-<p>
-Obviously, you can configure the levels of as many loggers as you wish.
-In the next configuration file we set the level of the <em>chapter3</em> logger to
-<code>INFO</code> but at the same time set the level of the <em>chapter3.Foo</em> logger
-to <code>DEBUG</code>.
+<p>Obviously, you can configure the levels of as many loggers as you
+wish. In the next configuration file we set the level of the
+<em>chapter3</em> logger to <code>INFO</code> but at the same time set
+the level of the <em>chapter3.Foo</em> logger to <code>DEBUG</code>.
</p>
-<em>Example 3.6: Setting the level of multiple loggers (logback-examples/src/main/java/chapter3/sample3.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Setting the level of multiple loggers (logback-examples/src/main/java/chapter3/sample3.xml)</em>
<div class="source"><pre><configuration>
<appender name="STDOUT"
@@ -484,9 +552,8 @@
</configuration></pre></div>
-<p>
-Running <code>MyApp2</code> with this configuration file will result in the
-following output on the console:
+<p>Running <code>MyApp2</code> with this configuration file will
+result in the following output on the console:
</p>
<div class="source"><pre>17:39:27.593 [main] INFO chapter3.MyApp2 - Entering application.
@@ -526,16 +593,18 @@
</tr>
</table>
-<p>
-It follows that the two logging statements of level <code>INFO</code> in the <code>MyApp2</code>
-class are enabled while the <code>debug</code> statement in <code>Foo.doIt()</code> method
-will also print without hindrance. Note that the level of the root logger is always
-set to a non-null value, which is <code>DEBUG</code> by default.
-One rather important point to remember is that the logger-level filter depends
-on the effective level of the logger being invoked, not the level of the logger
-where the appenders are attached. The configuration file <em>sample4.xml</em> is a case in point:
+<p>It follows that the two logging statements of level
+<code>INFO</code> in the <code>MyApp2</code> class are enabled while
+the <code>debug</code> statement in <code>Foo.doIt()</code> method
+will also print without hindrance. Note that the level of the root
+logger is always set to a non-null value, which is <code>DEBUG</code>
+by default. One rather important point to remember is that the
+logger-level filter depends on the effective level of the logger being
+invoked, not the level of the logger where the appenders are
+attached. The configuration file <em>sample4.xml</em> is a case in
+point:
</p>
-<em>Example 3.7: Logger level sample (logback-examples/src/main/java/chapter3/sample4.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Logger level sample (logback-examples/src/main/java/chapter3/sample4.xml)</em>
<div class="source"><pre><configuration>
<appender name="STDOUT"
@@ -591,24 +660,23 @@
</tr>
</table>
-<p>
-The ConsoleAppender named <em>STDOUT</em>, the only configured appender in
-<em>sample4.xml</em>, is attached to the root logger whose level is set to
-<code>OFF</code>. However, running MyApp2 with configuration script
-<em>sample4.xml</em> will output:
+<p>The ConsoleAppender named <em>STDOUT</em>, the only configured
+appender in <em>sample4.xml</em>, is attached to the root logger whose
+level is set to <code>OFF</code>. However, running MyApp2 with
+configuration script <em>sample4.xml</em> will output:
</p>
<div class="source"><pre>17:52:23.609 [main] INFO chapter3.MyApp2 - Entering application.
17:52:23.609 [main] INFO chapter3.MyApp2 - Exiting application.</pre></div>
-<p>
-Thus, the level of the root logger has no apparent effect because the loggers in
-<code>chapter3.MyApp2</code> and <code>chapter3.Foo</code> classes, namely
-<em>chapter3.MyApp2</em> and <em>chapter3.Foo</em>, inherit their level from the
-<em>chapter3</em> logger which has its level set to <code>INFO</code>.
-As noted previously, the <em>chapter3</em> logger exists by virtue of its
-declaration in the configuration file - even if the Java source code does not
-directly refer to it.
+<p>Thus, the level of the root logger has no apparent effect because
+the loggers in <code>chapter3.MyApp2</code> and
+<code>chapter3.Foo</code> classes, namely <em>chapter3.MyApp2</em> and
+<em>chapter3.Foo</em>, inherit their level from the <em>chapter3</em>
+logger which has its level set to <code>INFO</code>. As noted
+previously, the <em>chapter3</em> logger exists by virtue of its
+declaration in the configuration file - even if the Java source code
+does not directly refer to it.
</p>
<h4>Configuring Appenders</h4>
@@ -637,7 +705,7 @@
and referencing them in a logger, as the next configuration file illustrates:
</p>
-<em>Example 3.8: Multiple loggers (logback-examples/src/main/java/chapter3/multiple.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Multiple loggers (logback-examples/src/main/java/chapter3/multiple.xml)</em>
<div class="source"><pre><configuration>
<appender name="<b>FILE</b>"
@@ -674,32 +742,33 @@
</root>
</configuration></pre></div>
-<p>
-This configuration scripts defines two appenders called <em>FILE</em> and <em>STDOUT</em>.
-The <em>FILE</em> appender logs to a file called <em>myApp.log</em>. The layout for this appender
-is a <code>PatternLayout</code> that outputs the date, level, thread name, logger name,
-file name and line number where the log request is located,
-the message and line separator character(s).
-The second appender called <code>STDOUT</code> outputs to the console.
-The layout for this appender outputs only the message string followed by a line separator.
-</p>
+ <p>This configuration scripts defines two appenders called
+ <em>FILE</em> and <em>STDOUT</em>. The <em>FILE</em> appender logs
+ to a file called <em>myApp.log</em>. The layout for this appender is
+ a <code>PatternLayout</code> that outputs the date, level, thread
+ name, logger name, file name and line number where the log request
+ is located, the message and line separator character(s). The second
+ appender called <code>STDOUT</code> outputs to the console. The
+ layout for this appender outputs only the message string followed by
+ a line separator.
+ </p>
-<p>
-The appenders are attached to the root logger by referencing
-them by name within an <em>appender-ref</em> element. Note that each appender
-has its own layout. Layouts are usually not designed to be shared by multiple
-appenders. XML configuration files do not provide any syntactical
-means for sharing layouts.
-</p>
+ <p>The appenders are attached to the root logger by referencing them
+ by name within an <em>appender-ref</em> element. Note that each
+ appender has its own layout. Layouts are usually not designed to be
+ shared by multiple appenders. XML configuration files do not provide
+ any syntactical means for sharing layouts.
+ </p>
-<p>
-By default, <b>appenders are cumulative</b>: a logger will log to the appenders
-attached to itself (if any) as well as all the appenders attached to its ancestors.
-Thus, attaching the same appender to multiple loggers will cause
-logging output to be duplicated.
-</p>
+ <p>By default, <b>appenders are cumulative</b>: a logger will log to
+ the appenders attached to itself (if any) as well as all the
+ appenders attached to its ancestors. Thus, attaching the same
+ appender to multiple loggers will cause logging output to be
+ duplicated.
+ </p>
-<em>Example 3.9: Duplicate appender (logback-examples/src/main/java/chapter3/duplicate.xml)</em>
+ <em>Example 3.<span class="autoEx"/>: Duplicate appender
+ (logback-examples/src/main/java/chapter3/duplicate.xml)</em>
<div class="source"><pre><configuration>
<appender name="STDOUT"
@@ -721,9 +790,9 @@
</root>
</configuration></pre></div>
-<p>
-Running <code>MyApp2</code> with <em>duplicate.xml</em> will yield the following output:
-</p>
+ <p>Running <code>MyApp2</code> with <em>duplicate.xml</em> will
+ yield the following output:
+ </p>
<div class="source"><pre>14:25:36.343 [main] INFO chapter3.MyApp2 - Entering application.
14:25:36.343 [main] INFO chapter3.MyApp2 - Entering application.
@@ -732,24 +801,25 @@
14:25:36.359 [main] INFO chapter3.MyApp2 - Exiting application.
14:25:36.359 [main] INFO chapter3.MyApp2 - Exiting application.</pre></div>
-<p>
-Notice the duplicated output. The appender named <em>STDOUT</em> is attached to
-two loggers, to root and to <em>chapter3</em>. Since the root logger is the
-ancestor of all loggers and <em>chapter3</em> is the parent of <em>chapter3.MyApp2</em>
-and <em>chapter3.Foo</em>, logging request made with these two loggers
-will be output twice, once because <em>STDOUT</em> is attached to <em>chapter3</em>
-and once because it is attached to <em>root</em>.
-</p>
+ <p>Notice the duplicated output. The appender named <em>STDOUT</em>
+ is attached to two loggers, to root and to <em>chapter3</em>. Since
+ the root logger is the ancestor of all loggers and <em>chapter3</em>
+ is the parent of <em>chapter3.MyApp2</em> and <em>chapter3.Foo</em>,
+ logging request made with these two loggers will be output twice,
+ once because <em>STDOUT</em> is attached to <em>chapter3</em> and
+ once because it is attached to <em>root</em>.
+ </p>
-<p>
-Appender additivity is not intended as a trap for new users.
-It is a quite convenient logback feature. For instance, you can configure
-logging such that log messages appear on the console (for all loggers in the system)
-while messages only from some specific set of loggers flow into a specific appender.
-</p>
+ <p>Appender additivity is not intended as a trap for new users. It
+ is a quite convenient logback feature. For instance, you can
+ configure logging such that log messages appear on the console (for
+ all loggers in the system) while messages only from some specific
+ set of loggers flow into a specific appender.
+ </p>
-<em>Example 3.10: Multiple appender (logback-examples/src/main/java/chapter3/restricted.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: Multiple appender
+ (logback-examples/src/main/java/chapter3/restricted.xml)</em>
+ <div class="source"><pre><configuration>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
@@ -784,21 +854,21 @@
</root>
</configuration></pre></div>
-<p>
-In this example, the console appender will log all the messages (for all loggers in the system)
-whereas only logs under the <em>chapter3</em> tree go into the <em>myApp.log</em> file.
-</p>
+ <p>In this example, the console appender will log all the messages
+ (for all loggers in the system) whereas only logs under the
+ <em>chapter3</em> tree go into the <em>myApp.log</em> file.
+ </p>
-<h4>Overriding the default cumulative behaviour</h4>
+ <h4>Overriding the default cumulative behaviour</h4>
-<p>
-In case the default cumulative behavior turns out to be unsuitable for
-one's needs, one can override it by setting the additivity flag to false.
-Thus, a branch in your logger tree may direct output to a set of appenders
-different than those of the rest of the tree.
-</p>
+ <p>In case the default cumulative behavior turns out to be
+ unsuitable for one's needs, one can override it by setting the
+ additivity flag to false. Thus, a branch in your logger tree may
+ direct output to a set of appenders different than those of the rest
+ of the tree.
+ </p>
-<em>Example 3.11: Additivity flag (logback-examples/src/main/java/chapter3/additivityFlag.xml)</em>
+<em>Example 3.<span class="autoEx"/>: Additivity flag (logback-examples/src/main/java/chapter3/additivityFlag.xml)</em>
<div class="source"><pre><configuration>
<appender name="FILE"
@@ -834,44 +904,46 @@
</root>
</configuration></pre></div>
-<p>
-This example, the appender named <em>FILE</em> is attached to the <em>chapter3.Foo</em>
-logger. Moreover, the <em>chapter3.Foo</em> logger has its additivity flag set to false
-such that its logging output will be sent to the appender named <em>FILE</em> but
-not to any appender attached higher in the hierarchy. Other loggers remain
-oblivious to the additivity setting of the <em>chapter3.Foo</em> logger.
-Running the <code>MyApp2</code> application with the <em>additivityFlag.xml</em>
-configuration file will output results on the console from the <em>chapter3.MyApp2</em>
-logger.
-However, output from the <em>chapter3.Foo</em> logger will appear in the <em>foo.log</em> file
-and only in that file.
-</p>
+ <p>This example, the appender named <em>FILE</em> is attached to the
+ <em>chapter3.Foo</em> logger. Moreover, the <em>chapter3.Foo</em>
+ logger has its additivity flag set to false such that its logging
+ output will be sent to the appender named <em>FILE</em> but not to
+ any appender attached higher in the hierarchy. Other loggers remain
+ oblivious to the additivity setting of the <em>chapter3.Foo</em>
+ logger. Running the <code>MyApp2</code> application with the
+ <em>additivityFlag.xml</em> configuration file will output results
+ on the console from the <em>chapter3.MyApp2</em> logger. However,
+ output from the <em>chapter3.Foo</em> logger will appear in the
+ <em>foo.log</em> file and only in that file.
+ </p>
-<h4>Variable substitution</h4>
+ <h4>Variable substitution</h4>
-<p>
-All option <em>values</em> admit variable substitution. The syntax of variable
-substitution is similar to that of Unix shells. The string between an
-opening <em>${</em> and closing <em>}</em> is interpreted as a key.
-The value of the substituted variable can be defined as a system property
-in the configuration file itself or in a separate file linked to the
-configuration file. The value of the key
-is first searched in configuration file or linked properties file,
-and if not found there, it is then searched in system properties.
-The corresponding value replaces <em>${aKey}</em> sequence. For example,
-if <em>java.home.dir</em> system property is set to <em>/home/xyz</em>,
-then every occurrence of the sequence <em>${java.home.dir}</em> will be
-interpreted as <em>/home/xyz</em>.
-</p>
+ <p>All option <em>values</em> admit variable substitution. The
+ syntax of variable substitution is similar to that of Unix
+ shells. The string between an opening <em>${</em> and closing
+ <em>}</em> is interpreted as a key. The value of the substituted
+ variable can be defined as a system property in the configuration
+ file itself or in a separate file linked to the configuration
+ file. The value of the key is first searched in configuration file
+ or linked properties file, and if not found there, it is then
+ searched in system properties. The corresponding value replaces
+ <em>${aKey}</em> sequence. For example, if <em>java.home.dir</em>
+ system property is set to <em>/home/xyz</em>, then every occurrence
+ of the sequence <em>${java.home.dir}</em> will be interpreted as
+ <em>/home/xyz</em>.
+ </p>
-<p>
-The first example shows a declared property at the beginning of the
-configuration file. It is then used further down the file to specify
-the place to create the output file.
-</p>
+ <p>The first example shows a declared property at the beginning of the
+ configuration file. It is then used further down the file to specify
+ the place to create the output file.
+ </p>
-<em>Example 3.12: Simple Variable substitution (logback-examples/src/main/java/chapter3/variableSubstitution1.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: Simple Variable substitution
+ (logback-examples/src/main/java/chapter3/variableSubstitution1.xml)
+ </em>
+
+ <div class="source"><pre><configuration>
<b><substitutionProperty name="user.home.dir" value="/Users/seb" /></b>
@@ -898,13 +970,15 @@
</configuration></pre></div>
-<p>
-The next example shows the use of a System property to achieve the same result. The
-property is not declared anywhere, thus logback will look for it in the System properties.
-</p>
+ <p>The next example shows the use of a System property to achieve the same result. The
+ property is not declared anywhere, thus logback will look for it in the System properties.
+ </p>
-<em>Example 3.13: System Variable substitution (logback-examples/src/main/java/chapter3/variableSubstitution2.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: System Variable substitution
+ (logback-examples/src/main/java/chapter3/variableSubstitution2.xml)
+ </em>
+
+ <div class="source"><pre><configuration>
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
@@ -928,14 +1002,17 @@
</root>
</configuration></pre></div>
-<p>
-When many variables are used, it is often more convenient to create
-a separate file that will contain all the variables. Here is how one can
-do such a setup.
-</p>
+ <p>When many variables are used, it is often more convenient to
+ create a separate file that will contain all the variables. Here is
+ how one can do such a setup.
+ </p>
-<em>Example 3.14: Variable substitution using a separate file (logback-examples/src/main/java/chapter3/variableSubstitution3.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: Variable substitution using a
+ separate file
+ (logback-examples/src/main/java/chapter3/variableSubstitution3.xml)
+ </em>
+
+ <div class="source"><pre><configuration>
<b><substitutionProperty file="variables1.properties" /></b>
@@ -967,7 +1044,7 @@
logback configuration file. Here is what the <em>variable.properties</em> file looks like.
</p>
-<em>Example 3.15: Variable file (logback-examples/src/main/java/chapter3/variables1.properties)</em>
+<em>Example 3.<span class="autoEx"/>: Variable file (logback-examples/src/main/java/chapter3/variables1.properties)</em>
<div class="source"><pre>user.home.dir=/Users/seb</pre></div>
<p>
@@ -981,18 +1058,20 @@
</p>
-<em>Example 3.16: Recursive use of variables (logback-examples/src/main/java/chapter3/variables2.properties)</em>
+<em>Example 3.<span class="autoEx"/>: Recursive use of variables
+(logback-examples/src/main/java/chapter3/variables2.properties)</em>
<div class="source"><pre>user.home.dir=/Users/seb
fileName=myApp.log
destination=${user.home.dir}/${fileName}</pre></div>
-<p>
-In the configuration file, only the last variable, <em>${destination}</em> will
-be used, as shown below:
-</p>
+ <p>In the configuration file, only the last variable,
+ <em>${destination}</em> will be used, as shown below:
+ </p>
-<em>Example 3.17: Variable substitution using a separate file (logback-examples/src/main/java/chapter3/variableSubstitution4.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: Variable substitution using a separate file
+ (logback-examples/src/main/java/chapter3/variableSubstitution4.xml)</em>
+
+ <div class="source"><pre><configuration>
<substitutionProperty file="variables1.properties" />
@@ -1018,27 +1097,30 @@
</root>
</configuration></pre></div>
-<a name="Include"></a>
-<h3>File inclusion</h3>
+ <a name="Include"></a>
+ <h3>File inclusion</h3>
-<p>
-It is possible to include configuration elements into a <em>logback.xml</em>
-configuration file. This is done by using a <em>include</em> element, as shown
-in the example below:
-</p>
+ <p> It is possible to include configuration elements into a
+ <em>logback.xml</em> configuration file. This is done by using a
+ <em>include</em> element, as shown in the example below:
+ </p>
-<em>Example 3.18: File include (logback-examples/src/main/java/chapter3/redirectConfig.xml)</em>
-<div class="source"><pre><configuration>
+ <em>Example 3.<span class="autoEx"/>: File include
+ (logback-examples/src/main/java/chapter3/redirectConfig.xml)</em>
+
+ <div class="source"><pre><configuration>
<b><include file="path/to/configuration/file"/></b>
-</configuration></pre></div>
+ </configuration></pre></div>
-<p>
-The target file must have its elements nested inside an <em>included</em>
-element. For example, a <code>ConsoleAppender</code> would be declared this way:
-</p>
+ <p>The target file must have its elements nested inside an
+ <em>included</em> element. For example, a
+ <code>ConsoleAppender</code> would be declared this way:
+ </p>
-<em>Example 3.18: File include (logback-examples/src/main/java/chapter3/includedConfig.xml)</em>
-<div class="source"><pre><included>
+ <em>Example 3.<span class="autoEx"/>: File include
+ (logback-examples/src/main/java/chapter3/includedConfig.xml)</em>
+
+ <div class="source"><pre><included>
<appender name="redirectConsole"
class="ch.qos.logback.core.ConsoleAppender">
@@ -1054,118 +1136,121 @@
</included></pre></div>
-<p>The file to be included can be referenced as a URL or as a
-resource. To reference a URL use the <code>url</code> attribute
-instead of the file attribute in the previous example. To reference a
-resource, use the <code>resource</code> attribute instead of the file
-attribute in the previous example.
-</p>
+ <p>The file to be included can be referenced as a URL or as a
+ resource. To reference a URL use the <code>url</code> attribute
+ instead of the file attribute in the previous example. To reference
+ a resource, use the <code>resource</code> attribute instead of the
+ file attribute in the previous example.
+ </p>
-<a name="Joran"></a>
-<h2>Using Joran in your own application</h2>
-<p>As we've seen, logback relies on Joran, a
-mature, flexible and powerful configuration framework. Many of the
-capabilities offered by logback modules are possible with the help of Joran.
-</p>
+ <a name="Joran"></a>
+ <h2>Using Joran in your own application</h2>
-<p>Joran is actually a generic configuration system which can be used
-independently of logging. To emphaises this point, we should mention
-that the logback-core module does not have a notion of loggers. In
-that spirit, many of the examples related to this tutorial, have
-nothing to do with loggers, appenders or layouts.
-</p>
+ <p>As we've seen, logback relies on Joran, a mature, flexible and
+ powerful configuration framework. Many of the capabilities offered
+ by logback modules are possible with the help of Joran.
+ </p>
-<p>The examples for this chapter can be found under
-<em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
-</p>
+ <p>Joran is actually a generic configuration system which can be
+ used independently of logging. To emphaises this point, we should
+ mention that the logback-core module does not have a notion of
+ loggers. In that spirit, many of the examples related to this
+ tutorial, have nothing to do with loggers, appenders or layouts.
+ </p>
-<p>To install joran, simply <a href="../download.html">download</a>
-logback and add <em>logback-core-VERSION.jar</em> to your classpath.</p>
+ <p>The examples for this chapter can be found under
+ <em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
+ </p>
-<h2>Historical perspective</h2>
+ <p>To install joran, simply <a href="../download.html">download</a>
+ logback and add <em>logback-core-VERSION.jar</em> to your classpath.</p>
+
+ <h2>Historical perspective</h2>
-<p>One of the most powerful features of the Java language is
-reflection. Reflection makes it possible to configure software systems
-declaratively. For example, many important properties of an EJB are
-configured with the <em>ejb.xml</em> file. While EJBs are written in Java, many
-of their properties are specified within the <em>ejb.xml</em> file. Similarly,
-logback settings can be specified in a configuration file, expressed
-in XML format.
-</p>
+ <p>One of the most powerful features of the Java language is
+ reflection. Reflection makes it possible to configure software systems
+ declaratively. For example, many important properties of an EJB are
+ configured with the <em>ejb.xml</em> file. While EJBs are written in Java, many
+ of their properties are specified within the <em>ejb.xml</em> file. Similarly,
+ logback settings can be specified in a configuration file, expressed
+ in XML format.
+ </p>
-<p>In log4j, logback's predecessor, <code>DOMConfigurator</code> that
-shipped with log4j version 1.2.x can parse configuration files written
-in XML. The <code>DOMConfigurator</code> was written in a way that
-forced to tweak it each time the structure of the configuration file
-changed. The modified code had to be recompiled and redeployed. Just
-as importantly, the code of the DOMConfigurator consists of loops
-dealing with children elements containing many interspersed if/else
-statements. One could not help but notice that that particular code
-reeked of redundancy. The <a
-href="http://jakarta.apache.org/commons/digester/">digester
-project</a> has shown that it is possible to parse XML files using
-pattern matching rules. At parse time, digester will apply the rules
-that match previously stated patterns. Rule classes are usually quite
-small and specialized. Consequently, they are relatively easy to
-understand and to maintain.
-</p>
+ <p>In log4j, logback's predecessor, <code>DOMConfigurator</code>
+ that shipped with log4j version 1.2.x can parse configuration files
+ written in XML. The <code>DOMConfigurator</code> was written in a
+ way that forced to tweak it each time the structure of the
+ configuration file changed. The modified code had to be recompiled
+ and redeployed. Just as importantly, the code of the DOMConfigurator
+ consists of loops dealing with children elements containing many
+ interspersed if/else statements. One could not help but notice that
+ that particular code reeked of redundancy. The <a
+ href="http://jakarta.apache.org/commons/digester/">digester
+ project</a> has shown that it is possible to parse XML files using
+ pattern matching rules. At parse time, digester will apply the rules
+ that match previously stated patterns. Rule classes are usually
+ quite small and specialized. Consequently, they are relatively easy
+ to understand and to maintain.
+ </p>
-<p>Joran is heavily inspired by the commons-digester project but uses
-a slightly different terminology. In commons-digester, a rule can be
-seen as consisting of a pattern and a rule, as shown by the
-<code>Digester.addRule(String pattern, Rule rule)</code> method. We
-find it unnecessarily confusing to have a rule to consist of itself,
-not recursively but with a different meaning. In Joran, a rule
-consists of a pattern and an action. An action is invoked when a match
-occurs for the corresponding pattern. This relation between patterns
-and actions lies at the core of Joran. Quite remarkably, one can deal
-with quite complex requirements by using simple patterns, or more
-precisely with exact matches and wildcard matches. For example, the
-pattern <em>a/b</em> will match a <code><b></code> element nested within
-an <code><a></code> element but not a <code><c></code> element,
-even if nested within a <code><b></code> element. It is also
-possible to match a particular XML element, regardless of its nesting
-level, by using the <em>*</em> wildcard character. For example, the pattern
-<em>*/a</em> will match an <code><a></code> element at any nesting
-position within the document. Other types of patterns, for example
-<em>a/*</em>, are not currently supported by Joran.
-</p>
+ <p>Joran is heavily inspired by the commons-digester project but
+ uses a slightly different terminology. In commons-digester, a rule
+ can be seen as consisting of a pattern and a rule, as shown by the
+ <code>Digester.addRule(String pattern, Rule rule)</code> method. We
+ find it unnecessarily confusing to have a rule to consist of itself,
+ not recursively but with a different meaning. In Joran, a rule
+ consists of a pattern and an action. An action is invoked when a
+ match occurs for the corresponding pattern. This relation between
+ patterns and actions lies at the core of Joran. Quite remarkably,
+ one can deal with quite complex requirements by using simple
+ patterns, or more precisely with exact matches and wildcard
+ matches. For example, the pattern <em>a/b</em> will match a
+ <code><b></code> element nested within an <code><a></code>
+ element but not a <code><c></code> element, even if nested within
+ a <code><b></code> element. It is also possible to match a
+ particular XML element, regardless of its nesting level, by using
+ the <em>*</em> wildcard character. For example, the pattern
+ <em>*/a</em> will match an <code><a></code> element at any
+ nesting position within the document. Other types of patterns, for
+ example <em>a/*</em>, are not currently supported by Joran.
+ </p>
-<h2>SAX or DOM?</h2>
+ <h2>SAX or DOM?</h2>
-<p>Due to the event-based architecture of the SAX API, a tool based on
-SAX cannot easily deal with forward references, that is, references to
-elements which are defined later than the current element being
-processed. Elements with cyclical references are equally
-problematic. More generally, the DOM API allows the user to perform
-searches on all the elements and make forward jumps.
-</p>
+ <p>Due to the event-based architecture of the SAX API, a tool based
+ on SAX cannot easily deal with forward references, that is,
+ references to elements which are defined later than the current
+ element being processed. Elements with cyclical references are
+ equally problematic. More generally, the DOM API allows the user to
+ perform searches on all the elements and make forward jumps.
+ </p>
-<p>This extra flexibility initially led us to choose the DOM API as
-the underlying parsing API for Joran. After some experimentation, it
-quickly became clear that dealing with jumps to distant elements while
-parsing the DOM tree did not make sense when the interpretation rules
-were expressed in the form of patterns and actions. <em>Joran only
-needs to be given the elements in the XML document in a sequential,
-depth-first order.</em>
-</p>
+ <p>This extra flexibility initially led us to choose the DOM API as
+ the underlying parsing API for Joran. After some experimentation, it
+ quickly became clear that dealing with jumps to distant elements
+ while parsing the DOM tree did not make sense when the
+ interpretation rules were expressed in the form of patterns and
+ actions. <em>Joran only needs to be given the elements in the XML
+ document in a sequential, depth-first order.</em>
+ </p>
-<p>Joran was first implemented in DOM. However, the author migrated to
-SAX in order to benefit form the location information provided to the
-user, that is, to an <code>org.w3.sax.ContentHandler</code>. With the
-help of location information, it becomes possible to display essential
-error reports to the user which include exact line and column. This
-extra information turns out to be handy in hunting down problems.
-</p>
+ <p>Joran was first implemented in DOM. However, the author migrated
+ to SAX in order to benefit form the location information provided to
+ the user, that is, to an
+ <code>org.w3.sax.ContentHandler</code>. With the help of location
+ information, it becomes possible to display essential error reports
+ to the user which include exact line and column. This extra
+ information turns out to be handy in hunting down problems.
+ </p>
-<h2>Actions</h2>
+ <h2>Actions</h2>
-<p>Actions extend the
-<code>ch.qos.logback.core.joran.action.Action</code> class which
-consists of the following abstract methods.
-</p>
+ <p>Actions extend the
+ <code>ch.qos.logback.core.joran.action.Action</code> class which
+ consists of the following abstract methods.
+ </p>
<div class="source"><pre>package ch.qos.logback.core.joran.action;
@@ -1191,139 +1276,155 @@
public abstract void end(ExecutionContext ec, String name);
}</pre></div>
-<p>Thus, every action must implement the begin and end methods.</p>
+ <p>Thus, every action must implement the begin and end methods.</p>
-<h2>Execution context</h2>
+ <h2>Execution context</h2>
-<p>To allow various actions to collaborate, the invocation of begin
-and end methods include an execution context as the first
-parameter. The execution context includes an object stack, an object
-map, an error list and a reference to the Joran interpreter invoking
-the action. Please see the
-<code>ch.qos.logback.core.joran.spi.ExecutionContext</code> class for
-the exact list of fields contained in the execution context.
-</p>
+ <p>To allow various actions to collaborate, the invocation of begin
+ and end methods include an execution context as the first
+ parameter. The execution context includes an object stack, an object
+ map, an error list and a reference to the Joran interpreter invoking
+ the action. Please see the
+ <code>ch.qos.logback.core.joran.spi.ExecutionContext</code> class
+ for the exact list of fields contained in the execution context.
+ </p>
-<p>Actions can collaborate together by fetching, pushing or popping
-objects from the common object stack, or by putting and fetching keyed
-objects on the common object map. Actions can report any error
-conditions by adding error items on the execution context's
-<code>StatusManager</code>.
-</p>
+ <p>Actions can collaborate together by fetching, pushing or popping
+ objects from the common object stack, or by putting and fetching
+ keyed objects on the common object map. Actions can report any error
+ conditions by adding error items on the execution context's
+ <code>StatusManager</code>.
+ </p>
-<a name="helloWorld"></a>
-<h3>A hello world example</h3>
+ <a name="helloWorld"></a>
+ <h3>A hello world example</h3>
-<p>The <em>logback-examples/src/main/java/chapter3/helloWorld/</em> directory includes a
-trivial action and Joran interpreter setup which just displays <em>Hello
-World</em> when a <hello-world> element is encountered in an XML file.
-It also includes the basic steps which are
-necessary to set up and invoke a Joran interpreter.
-</p>
-<p>
-The <em>hello.xml</em> file contains only one element, without any
-other nested elements. The <a href="../xref/chapter3/helloWorld/HelloWorldAction.html">
-<code>HelloWorldAction</code></a> class is
-a trivial implementation: it only prints "Hello World" in the console when
-it's <code>begin()</code> method is called.
-</p>
-<p>
-<a href="../xref/chapter3/helloWorld/HelloWorld.html"><code>HelloWorld</code></a>
-is a class that sets up the Joran interpreter,
-with the minimal steps necessary:
-</p>
+ <p>The <em>logback-examples/src/main/java/chapter3/helloWorld/</em>
+ directory includes a trivial action and Joran interpreter setup
+ which just displays <em>Hello World</em> when a <hello-world>
+ element is encountered in an XML file. It also includes the basic
+ steps which are necessary to set up and invoke a Joran interpreter.
+ </p>
-<ul>
- <p>It creates a <code>RuleStore</code> and a <code>Context</code></p>
- <p>It adds the <em>hello-world</em> pattern, with it's corresponding action</p>
- <p>It creates a Joran interpreter, and passes the <code>RuleStore</code></p>
- <p>It creates a SAX parser and parses the given file, specifying the newly created
- Joran interpreter as the <code>ContentHandler</code></p>
-</ul>
+ <p>The <em>hello.xml</em> file contains only one element, without
+ any other nested elements. The <a
+ href="../xref/chapter3/helloWorld/HelloWorldAction.html">
+ <code>HelloWorldAction</code></a> class is a trivial implementation:
+ it only prints "Hello World" in the console when it's
+ <code>begin()</code> method is called.
+ </p>
-<p>
-It's last step is to print the content of the <code>Context</code>.
-Since Joran uses logback's powerfull <code>Status</code> objects for
-error reporting, one can have a good feedback on what happened during
-the parsing.
-</p>
+ <p> <a
+ href="../xref/chapter3/helloWorld/HelloWorld.html"><code>HelloWorld</code></a>
+ is a class that sets up the Joran interpreter, with the minimal
+ steps necessary:
+ </p>
-<p>
-In this example, the parsing is rather simple. The <em>hello-world</em> element
-will activate <code>HelloWorldAction</code>'s <code>begin()</code> and
-<code>end()</code> methods.
-In the first method, a simple call to <code>System.out.println()</code>
-will be issued, displaying <em>Hello World</em> in the console.
-</p>
+ <ul>
+ <li>It creates a <code>RuleStore</code> and a <code>Context</code></li>
+ <li>It adds the <em>hello-world</em> pattern, with it's corresponding action</li>
+ <li>It creates a Joran interpreter, and passes the <code>RuleStore</code></li>
+ <li>It creates a SAX parser and parses the given file, specifying the newly created
+ Joran interpreter as the <code>ContentHandler</code></li>
+ </ul>
+
+ <p>It's last step is to print the content of the
+ <code>Context</code>. Since Joran uses logback's powerfull
+ <code>Status</code> objects for error reporting, one can have a good
+ feedback on what happened during the parsing.
+ </p>
-<a name="calculator"></a>
-<h3>Collaborating actions</h3>
-<p>
-The <em>logback-examples/src/main/java/joran/calculator/</em> directory includes several actions
-which collaborate together through the common object stack in order
-to accomplish simple computations.
-</p>
-<p>
-The <em>calculator1.xml</em> file contains a <code>computation</code> element,
-with a nested <code>literal</code> element.
-</p>
-<p>
-In the <a href="../xref/chapter3/calculator/Calculator1.html">
-<code>Calculator1</code></a> class, we declare various patterns and actions,
-that will collaborate and calculate a result based on the xml file. The simple
-<em>calculator1.xml</em> file only creates a computation and declares a literal
-value. The resulting parsing is pretty simple:
-</p>
-<ul>
- <p>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
- <code>ComputationAction1</code></a> class' <code>begin()</code> method
- is called</p>
- <p>The <a href="../xref/chapter3/calculator/LiteralAction.html">
- <code>LiteralAction</code></a> class' <code>begin()</code> and <code>end()</code>
- methods are called</p>
- <p>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
- <code>ComputationAction1</code></a> class' <code>end()</code> method
- is called</p>
-</ul>
-<p>
-What is interesting here is the way that the Actions collaborate.
-The <code>LiteralAction</code> reads a literal value and pushes it in the
-object stack maintained by the <code>ExecutionContext</code>. Once done,
-any other action can pop the value to read or modify it. Here, the
-<code>end()</code> method of the <code>ComputationAction1</code> class pops
-the value from the stack and prints it.
-</p>
-<p>The <em>calculator2.xml</em> file is a bit more complex, but much more interesting.</p>
-<p>It contains the following elements:</p>
+ <p>In this example, the parsing is rather simple. The
+ <em>hello-world</em> element will activate
+ <code>HelloWorldAction</code>'s <code>begin()</code> and
+ <code>end()</code> methods. In the first method, a simple call to
+ <code>System.out.println()</code> will be issued, displaying
+ <em>Hello World</em> in the console.
+ </p>
-<em>Example 3.19: Calculator configuration file (logback-examples/src/main/java/chapter3/calculator/calculator2.xml)</em>
-<div class="source"><pre><computation name="toto">
+ <a name="calculator"></a>
+ <h3>Collaborating actions</h3>
+
+ <p>The <em>logback-examples/src/main/java/joran/calculator/</em>
+ directory includes several actions which collaborate together
+ through the common object stack in order to accomplish simple
+ computations.
+ </p>
+
+ <p>The <em>calculator1.xml</em> file contains a <code>computation</code>
+ element, with a nested <code>literal</code> element.
+ </p>
+
+ <p>In the <a href="../xref/chapter3/calculator/Calculator1.html">
+ <code>Calculator1</code></a> class, we declare various patterns and
+ actions, that will collaborate and calculate a result based on the
+ xml file. The simple <em>calculator1.xml</em> file only creates a
+ computation and declares a literal value. The resulting parsing is
+ pretty simple:
+ </p>
+
+ <ul>
+ <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
+ <code>ComputationAction1</code></a> class' <code>begin()</code> method
+ is called</li>
+ <li>The <a href="../xref/chapter3/calculator/LiteralAction.html">
+ <code>LiteralAction</code></a> class' <code>begin()</code> and <code>end()</code>
+ methods are called</li>
+ <li>The <a href="../xref/chapter3/calculator/ComputationAction1.html">
+ <code>ComputationAction1</code></a> class' <code>end()</code> method
+ is called</li>
+ </ul>
+ <p>What is interesting here is the way that the Actions collaborate.
+ The <code>LiteralAction</code> reads a literal value and pushes it
+ in the object stack maintained by the
+ <code>ExecutionContext</code>. Once done, any other action can pop
+ the value to read or modify it. Here, the <code>end()</code> method
+ of the <code>ComputationAction1</code> class pops the value from the
+ stack and prints it.
+ </p>
+
+ <p>The <em>calculator2.xml</em> file is a bit more complex, but much
+ more interesting.</p>
+
+ <p>It contains the following elements:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Calculator configuration file (logback-examples/src/main/java/chapter3/calculator/calculator2.xml)</em>
+ <div class="source"><pre><computation name="toto">
<literal value="7"/>
<literal value="3"/>
<add/>
<literal value="3"/>
<multiply/>
</computation></pre></div>
-<p>
-Here, there are obviously more actions that will be part of the computation.
-</p>
-<p>When called, the <a href="../xref/chapter3/calculator/AddAction.html">
-<code>AddAction</code></a> class will remove the two integers at
-the bottom of the stack, add them and push the resulting integer at the
-top of the stack, for further use.</p>
-<p>Later in the computation, the <a href="../xref/chapter3/calculator/MultiplyAction.html">
-<code>MultiplyAction</code></a> class will be called.
-It will take the last two integers from the stack, multiply them and
-push the result in the stack.</p>
-<p>We have here two examples of action whose <code>begin()</code> method behaves in
-a certain, predictable way, but whose <code>end()</code> methods are empty.</p>
-
-<p>Finally, a <em>calculator3.xml</em> is also provided, to demonstrate the possibility
-elements that contain instances of the same element. Here's the content of
-<em>calculator3.xml</em>:</p>
-<em>Example 3.20: Calculator configuration file (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
+ <p>Here, there are obviously more actions that will be part of the
+ computation.
+ </p>
+
+ <p>When called, the <a
+ href="../xref/chapter3/calculator/AddAction.html">
+ <code>AddAction</code></a> class will remove the two integers at the
+ bottom of the stack, add them and push the resulting integer at the
+ top of the stack, for further use.</p>
+
+ <p>Later in the computation, the <a
+ href="../xref/chapter3/calculator/MultiplyAction.html">
+ <code>MultiplyAction</code></a> class will be called. It will take
+ the last two integers from the stack, multiply them and push the
+ result in the stack.</p>
+
+ <p>We have here two examples of action whose <code>begin()</code>
+ method behaves in a certain, predictable way, but whose
+ <code>end()</code> methods are empty.</p>
+
+ <p>Finally, a <em>calculator3.xml</em> is also provided, to
+ demonstrate the possibility elements that contain instances of the
+ same element. Here's the content of <em>calculator3.xml</em>:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Calculator configuration file
+ (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
+
<div class="source"><pre><computation name="toto">
<computation>
<literal value="7"/>
@@ -1335,43 +1436,56 @@
<multiply/>
</computation></pre></div>
-<p>Much like the use of parentheses in an algebrical equation, the presence of
-a <code>computation</code> element nested in another is managed by the
-<a href="../xref/chapter3/calculator/ComputationAction2.html">
-<code>ComputationAction2</code></a> class using an internal stack. The well-formedness
-of XML will guarantee that a value saved by one <code>begin()</code> will be consumed
-only by the matching <code>end()</code> method.</p>
-
-<a name="newRule"></a>
-<h3>New-rule action</h3>
-<p>Joran includes an action which allows the Joran interpreter to lean
-new rules on the fly while interpreting the XML file containing the
-new rules. See the <em>logback-examples/src/main/java/joran/newRule/</em>
-directory for sample code.
-</p>
-<p>In this package, the <a href="../xref/chapter3/newRule/NewRuleCalculator.html">
-<code>NewRuleCalculator</code></a> class contains
-the same setup as we have seen so far, but for one line:</p>
-
-<source>ruleStore.addRule(new Pattern("/computation/new-rule"), new NewRuleAction());</source>
-
-<p>By adding this line, we ask Joran to allow new rules to be learnt
-at parsing time. It works pretty much like the other rules: it has a
-<code>begin()</code> and <code>end()</code> method, and is called each time
-the parser finds a <em>new-rule</em> element.</p>
-
-<p>When called, the <code>begin()</code> method looks for a <em>pattern</em>
-and a <em>actionClass</em> attribute. The action class is then instanciated
-and added to the <code>RuleStore</code>, along with its corresponding pattern.</p>
-
-<p>Here is how new rules can be declared in an xml file:</p>
-
-<div class="source"><pre><new-rule pattern="*/computation/literal" actionClass="chapter3.calculator.LiteralAction"/></pre></div>
+ <p>Much like the use of parentheses in an algebrical equation, the
+ presence of a <code>computation</code> element nested in another is
+ managed by the <a
+ href="../xref/chapter3/calculator/ComputationAction2.html">
+ <code>ComputationAction2</code></a> class using an internal
+ stack. The well-formedness of XML will guarantee that a value saved
+ by one <code>begin()</code> will be consumed only by the matching
+ <code>end()</code> method.</p>
+
+ <a name="newRule"></a>
+
+ <h3>New-rule action</h3>
+
+ <p>Joran includes an action which allows the Joran interpreter to
+ lean new rules on the fly while interpreting the XML file containing
+ the new rules. See the
+ <em>logback-examples/src/main/java/joran/newRule/</em> directory for
+ sample code.
+ </p>
-<p>Using new rule declarations, the preceding example, involving the calculation, could be
-expressed this way:</p>
+ <p>In this package, the <a
+ href="../xref/chapter3/newRule/NewRuleCalculator.html">
+ <code>NewRuleCalculator</code></a> class contains the same setup as
+ we have seen so far, but for one line:</p>
+
+ <p class="source">ruleStore.addRule(new
+ Pattern("/computation/new-rule"), new NewRuleAction());</p>
+
+ <p>By adding this line, we ask Joran to allow new rules to be learnt
+ at parsing time. It works pretty much like the other rules: it has a
+ <code>begin()</code> and <code>end()</code> method, and is called each time
+ the parser finds a <em>new-rule</em> element.</p>
+
+ <p>When called, the <code>begin()</code> method looks for a
+ <em>pattern</em> and a <em>actionClass</em> attribute. The action
+ class is then instanciated and added to the <code>RuleStore</code>,
+ along with its corresponding pattern.</p>
+
+ <p>Here is how new rules can be declared in an xml file:</p>
+
+<div class="source"><pre><new-rule pattern="*/computation/literal"
+actionClass="chapter3.calculator.LiteralAction"/></pre></div>
+
+ <p>Using new rule declarations, the preceding example, involving the
+ calculation, could be expressed this way:</p>
+
+ <em>Example 3.<span class="autoEx"/>: Configuration file using new
+ rules on the fly
+ (logback-examples/src/main/java/chapter3/newrule/new-rule.xml)</em>
-<em>Example 3.21: Configuration file using new rules on the fly (logback-examples/src/main/java/chapter3/newrule/new-rule.xml)</em>
<div class="source"><pre><computation name="toto">
<new-rule pattern="*/computation/literal"
actionClass="chapter3.calculator.LiteralAction"/>
@@ -1390,88 +1504,96 @@
<multiply/>
</computation></pre></div>
-<a name="implicit"></a>
-<h3>Implicit actions </h3>
-<p>The rules defined thus far are called explicit rules because they
-require an explicit pattern, hence fixing the tag name of the elements
-for which they apply.
-</p>
+ <a name="implicit"></a>
+ <h3>Implicit actions </h3>
-<p>In highly extensible systems, the number and type of components to
-handle are innumerable so that it would become very tedious or even
-impossible to list all the applicable patterns by name.
-</p>
-
-<p>At the same time, even in highly extensible systems one can observe
-well-defined patterns linking the various parts together. Implicit
-rules come in very handy when processing components composed of
-sub-components unknown ahead of time. For example, Apache Ant is
-capable of handling tasks which contain tags unknown at compile time
-by looking at methods whose names start with <em>add</em>, as in
-<code>addFile</code>, or <code>addClassPath</code>.
-When Ant encounters an embedded tag within a task, it
-simply instantiates an object that matches the signature of the task
-class' add method and attaches the resulting object to the parent.
-</p>
-
-<p>Joran includes similar capability in the form of implicit
-actions. Joran keeps a list of implicit actions which can be applied
-if no explicit pattern matches the current XML element. However,
-applying an implicit action may not be always appropriate. Before
-executing the implicit action, Joran asks an implicit action whether
-it is appropriate in the current context. Only if the action replies
-affirmatively does Joran interpreter invoke the (implicit)
-action. This extra step makes it possible to support multiple implicit
-actions or obviously none, if no implicit action is appropriate for a
-given situation.
-</p>
-
-<p>For example, the <a href="../xref/ch/qos/logback/core/joran/action/NestedComponentIA.html">
-<code>NestedComponentIA</code></a> extending
-<a href="../xref/ch/qos/logback/core/joran/action/ImplicitAction.html">
-<code>ImplicitAction</code></a> , will
-instantiate the class specified in a nested component and attach it
-to the parent component by using setter method of the parent
-component and the nested element's name. Under certain circumstances,
-a nested action needs to be applied to an element say <a> and also
-to another element <b> nested within <a>. The current
-implementation of <code>NestedComponentIA</code> is capable of
-handling multiply nested elements requiring intervention by the same
-implicit action.
-</p>
+ <p>The rules defined thus far are called explicit rules because they
+ require an explicit pattern, hence fixing the tag name of the
+ elements for which they apply.
+ </p>
-<p>Both <code>ImplicitAction</code> and <code>NestedComponentIA</code> are located in the
-<code>ch.qos.logback.core.joran.action</code> package.
-</p>
+ <p>In highly extensible systems, the number and type of components
+ to handle are innumerable so that it would become very tedious or
+ even impossible to list all the applicable patterns by name.
+ </p>
-<p>Refer to the <em>logback-examples/src/main/java/joran/implicit</em>
-directory for an example of an implicit action.
-</p>
+ <p>At the same time, even in highly extensible systems one can
+ observe well-defined patterns linking the various parts
+ together. Implicit rules come in very handy when processing
+ components composed of sub-components unknown ahead of time. For
+ example, Apache Ant is capable of handling tasks which contain tags
+ unknown at compile time by looking at methods whose names start with
+ <em>add</em>, as in <code>addFile</code>, or
+ <code>addClassPath</code>. When Ant encounters an embedded tag
+ within a task, it simply instantiates an object that matches the
+ signature of the task class' add method and attaches the resulting
+ object to the parent.
+ </p>
-<p>In that directory, you will find two actions classes, one xml file and one
-class containing the setup of Joran.</p>
+ <p>Joran includes similar capability in the form of implicit
+ actions. Joran keeps a list of implicit actions which can be applied
+ if no explicit pattern matches the current XML element. However,
+ applying an implicit action may not be always appropriate. Before
+ executing the implicit action, Joran asks an implicit action whether
+ it is appropriate in the current context. Only if the action replies
+ affirmatively does Joran interpreter invoke the (implicit)
+ action. This extra step makes it possible to support multiple
+ implicit actions or obviously none, if no implicit action is
+ appropriate for a given situation.
+ </p>
-<p>The <a href="../xref/chapter3/implicit/NOPAction.html">
-<code>NOPAction</code></a> class does nothing. It is used to set
-the context of the <em>foo</em> element, using this line:</p>
+ <p>For example, the <a
+ href="../xref/ch/qos/logback/core/joran/action/NestedComponentIA.html">
+ <code>NestedComponentIA</code></a> extending <a
+ href="../xref/ch/qos/logback/core/joran/action/ImplicitAction.html">
+ <code>ImplicitAction</code></a> , will instantiate the class
+ specified in a nested component and attach it to the parent
+ component by using setter method of the parent component and the
+ nested element's name. Under certain circumstances, a nested action
+ needs to be applied to an element say <a> and also to another
+ element <b> nested within <a>. The current implementation of
+ <code>NestedComponentIA</code> is capable of handling multiply
+ nested elements requiring intervention by the same implicit action.
+ </p>
-<source>ruleStore.addRule(new Pattern("*/foo"), new NOPAction());</source>
+ <p>Both <code>ImplicitAction</code> and
+ <code>NestedComponentIA</code> are located in the
+ <code>ch.qos.logback.core.joran.action</code> package.
+ </p>
-<p>After that, the implicit action, namely
-<a href="../xref/chapter3/implicit/PrintMeImplicitAction.html">
-<code>PrintMeImplicitAction</code></a>,
-is added to the <code>RuleStore</code>. This is done by simply adding a new
-instance of the action to the <code>Joran interpreter</code></p>
+ <p>Refer to the
+ <em>logback-examples/src/main/java/joran/implicit</em> directory for
+ an example of an implicit action.
+ </p>
-<source>ji.addImplicitAction(new PrintMeImplicitAction());</source>
+ <p>In that directory, you will find two actions classes, one xml
+ file and one class containing the setup of Joran.</p>
-<p>When called, the <code>isApplicable()</code> method of <code>PrintMeImplicitAction</code>
-checks the value of the <em>printme</em> attribute. If the value is <code>true</code>,
-the implicit action is applicable: its <code>begin()</code> method will be called.</p>
+ <p>The <a href="../xref/chapter3/implicit/NOPAction.html">
+ <code>NOPAction</code></a> class does nothing. It is used to set the
+ context of the <em>foo</em> element, using this line:</p>
+
+ <p class="source">ruleStore.addRule(new Pattern("*/foo"), new NOPAction());</p>
+
+ <p>After that, the implicit action, namely <a
+ href="../xref/chapter3/implicit/PrintMeImplicitAction.html">
+ <code>PrintMeImplicitAction</code></a>, is added to the
+ <code>RuleStore</code>. This is done by simply adding a new instance
+ of the action to the <code>Joran interpreter</code></p>
+
+ <p class="source">ji.addImplicitAction(new
+ PrintMeImplicitAction());</p>
+
+ <p>When called, the <code>isApplicable()</code> method of
+ <code>PrintMeImplicitAction</code> checks the value of the
+ <em>printme</em> attribute. If the value is <code>true</code>, the
+ implicit action is applicable: its <code>begin()</code> method will
+ be called.</p>
-<p>The <em>implicit1.xml</em> file contains the following lines:</p>
+ <p>The <em>implicit1.xml</em> file contains the following lines:</p>
-<em>Example 3.22: Usage of implicit rules (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
+ <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
+ (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
<div class="source"><pre><foo>
<xyz printme="true">
@@ -1484,31 +1606,33 @@
</foo></pre></div>
-<p>As one can see, the first element will be printed, since it has a <em>printme</em>
-attribute, which bears the value <code>true</code>.</p>
-
-<p>The second element will not be printed, because no <em>printme</em> attibute is present.</p>
+ <p>As you can see, the first element will be printed, since it has a
+ <em>printme</em> attribute, which bears the value
+ <code>true</code>.</p>
+
+ <p>The second element will not be printed, because no <em>printme</em> attibute is present.</p>
+
+ <p>The last element will not be printed, although the required
+ attribute is present. This is because implicit rules are called
+ only if no explicit rules are defined. Since we added a
+ <code>NOPAction</code> with the <em>*/foo</em> pattern, it will be
+ used instead of the <code>PrintMeImplicitAction</code>.</p>
-<p>The last element will not be printed, although the required attribute is present.
-This is because implicit rules are called only if no explicit rules are defined. Since
-we added a <code>NOPAction</code> with the <em>*/foo</em> pattern, it will be used instead
-of the <code>PrintMeImplicitAction</code>.</p>
-
-<p>Running the example yields the following output:</p>
+ <p>Running the example yields the following output:</p>
<div class="source"><pre>Element <xyz> asked to be printed.
Element <abc> asked to be printed.
ERROR in ch.qos.logback.core.joran.spi.ExecutionContext at 1c5c1 - no applicable action \
for <xyz>, current pattern is [/foo/xyz]</pre></div>
-<p>The last line was printed because of a call to <code>StatusPrinter</code> at the end
-of the main class.</p>
+ <p>The last line was printed because of a call to
+ <code>StatusPrinter</code> at the end of the main class.</p>
-<h3>Non goals</h3>
+ <h3>Non goals</h3>
-<p>The Joran API is not intended to be used to parse documents with
-thousands of elements.
-</p>
+ <p>The Joran API is not intended to be used to parse documents with
+ thousands of elements.
+ </p>
More information about the logback-dev
mailing list