[logback-dev] svn commit: r2140 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic logback-classic/src/main/java/ch/qos/logback/classic/boolex logback-core/src/main/java/ch/qos/logback/core/joran/action logback-examples/src/main/java/chapter10/implicit logback-examples/src/main/java/chapter10/newRule logback-site/src/site/pages/manual
noreply.ceki at qos.ch
noreply.ceki at qos.ch
Wed Feb 4 17:26:57 CET 2009
Author: ceki
Date: Wed Feb 4 17:26:57 2009
New Revision: 2140
Modified:
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java
logback/trunk/logback-examples/src/main/java/chapter10/implicit/PrintMe.java
logback/trunk/logback-examples/src/main/java/chapter10/newRule/NewRuleCalculator.java
logback/trunk/logback-examples/src/main/java/chapter10/newRule/new-rule.xml
logback/trunk/logback-examples/src/main/java/chapter10/newRule/readme.txt
logback/trunk/logback-site/src/site/pages/manual/onJoran.html
Log:
- Ongoing improvements to Joran documentation in chapter10
in relation to LBSITE-25 and LBSITE-24.
- Cosmetic changes in code.
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java Wed Feb 4 17:26:57 2009
@@ -1,11 +1,11 @@
/**
- * LOGBack: the reliable, fast and flexible logging library for Java.
- *
- * Copyright (C) 1999-2006, QOS.ch
- *
- * This library is free software, you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation.
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
*/
package ch.qos.logback.classic;
Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java (original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/boolex/JaninoEventEvaluator.java Wed Feb 4 17:26:57 2009
@@ -1,7 +1,7 @@
/**
* Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 2000-2008, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.java Wed Feb 4 17:26:57 2009
@@ -1,7 +1,7 @@
/**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
@@ -41,17 +41,16 @@
Stack<IADataForComplexProperty> actionDataStack = new Stack<IADataForComplexProperty>();
public boolean isApplicable(Pattern pattern, Attributes attributes,
- InterpretationContext ec) {
- // System.out.println("in NestedComplexPropertyIA.isApplicable [" + pattern
- // + "]");
+ InterpretationContext ic) {
+
String nestedElementTagName = pattern.peekLast();
- // calling ec.peekObject with an empty stack will throw an exception
- if (ec.isEmpty()) {
+ // calling ic.peekObject with an empty stack will throw an exception
+ if (ic.isEmpty()) {
return false;
}
- Object o = ec.peekObject();
+ Object o = ic.peekObject();
PropertySetter parentBean = new PropertySetter(o);
parentBean.setContext(context);
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/NewRuleAction.java Wed Feb 4 17:26:57 2009
@@ -1,7 +1,7 @@
/**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
Modified: logback/trunk/logback-examples/src/main/java/chapter10/implicit/PrintMe.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter10/implicit/PrintMe.java (original)
+++ logback/trunk/logback-examples/src/main/java/chapter10/implicit/PrintMe.java Wed Feb 4 17:26:57 2009
@@ -50,10 +50,8 @@
// link the configurator with its context
simpleConfigurator.setContext(context);
- try {
simpleConfigurator.doConfigure(args[0]);
- } catch (Exception e) {
- StatusPrinter.print(context);
- }
+ StatusPrinter.printInCaseOfErrorsOrWarnings(context);
+
}
}
Modified: logback/trunk/logback-examples/src/main/java/chapter10/newRule/NewRuleCalculator.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter10/newRule/NewRuleCalculator.java (original)
+++ logback/trunk/logback-examples/src/main/java/chapter10/newRule/NewRuleCalculator.java Wed Feb 4 17:26:57 2009
@@ -1,13 +1,12 @@
/**
- * Logback: the reliable, fast and flexible logging library for Java.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
-
package chapter10.newRule;
import java.util.HashMap;
@@ -17,49 +16,44 @@
import ch.qos.logback.core.ContextBase;
import ch.qos.logback.core.joran.action.Action;
import ch.qos.logback.core.joran.action.NewRuleAction;
-import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.joran.spi.Pattern;
import ch.qos.logback.core.util.StatusPrinter;
import chapter10.SimpleConfigurator;
-import chapter10.calculator.ComputationAction2;
-
+import chapter10.calculator.ComputationAction1;
/**
* This example illustrates the usage of NewRuleAction which allows the Joran
- * interpreter to learn new rules on the fly from the XML file being
- * interpreted.
- *
- * This example relies heavily on the code from the joran.calculator package.
- *
+ * interpreter to learn new rules on the fly.
+ *
+ * <p>This example relies heavily on the code from the joran.calculator
+ * package.
+ *
* @author Ceki Güulcü
*/
public class NewRuleCalculator {
public static void main(String[] args) throws Exception {
-
+
Context context = new ContextBase();
-
-
+
Map<Pattern, Action> ruleMap = new HashMap<Pattern, Action>();
// we start with the rule for the top-most (root) element
- ruleMap.put(new Pattern("*/computation"), new ComputationAction2());
+ ruleMap.put(new Pattern("*/computation"), new ComputationAction1());
- // Associate "/new-rule" pattern with NewRuleAction from the
+ // Associate "/new-rule" pattern with NewRuleAction from the
// org.apache.joran.action package.
//
- // We will let the XML file to teach the Joran interpreter about new rules
- ruleMap.put(
- new Pattern("/computation/new-rule"), new NewRuleAction());
+ // We will let the XML file to teach the Joran interpreter about new rules
+ ruleMap.put(new Pattern("/computation/new-rule"), new NewRuleAction());
SimpleConfigurator simpleConfigurator = new SimpleConfigurator(ruleMap);
// link the configurator with its context
simpleConfigurator.setContext(context);
- try {
- simpleConfigurator.doConfigure(args[0]);
- } catch (JoranException e) {
- // Print any errors that might have occured.
- StatusPrinter.print(context);
- }
- }
+ simpleConfigurator.doConfigure(args[0]);
+
+ // Print any errors that might have occured.
+ StatusPrinter.printInCaseOfErrorsOrWarnings(context);
+ }
+
}
Modified: logback/trunk/logback-examples/src/main/java/chapter10/newRule/new-rule.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter10/newRule/new-rule.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter10/newRule/new-rule.xml Wed Feb 4 17:26:57 2009
@@ -1,20 +1,16 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE computation>
-
-<!-- This file is intended to be executed by NewRuleCalculator.
- Note that the rules for adding and multiplying are learned on the fly, while parsing
- this file.
- -->
-
-
+<!--
+ This file is intended to be executed by NewRuleCalculator.
+ Note that the rules for adding and multiplying are learned on
+ the fly, while parsingthis file.
+-->
<computation name="toto">
<new-rule pattern="*/computation/literal"
- actionClass="chapter3.calculator.LiteralAction"/>
+ actionClass="chapter10.calculator.LiteralAction"/>
<new-rule pattern="*/computation/add"
- actionClass="chapter3.calculator.AddAction"/>
+ actionClass="chapter10.calculator.AddAction"/>
<new-rule pattern="*/computation/multiply"
- actionClass="chapter3.calculator.MultiplyAction"/>
+ actionClass="chapter10.calculator.MultiplyAction"/>
<computation>
<literal value="7"/>
Modified: logback/trunk/logback-examples/src/main/java/chapter10/newRule/readme.txt
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter10/newRule/readme.txt (original)
+++ logback/trunk/logback-examples/src/main/java/chapter10/newRule/readme.txt Wed Feb 4 17:26:57 2009
@@ -1,17 +1,8 @@
-+------------------------------+
-| |
-| Joran Examples |
-| |
-| New rule |
-| |
-+------------------------------+
-This directory contains an example using the new rule action.
+This directory contains an example showing how Joran can
+learn new parsing rules on the fly.
-It shows how Joran can learn new rules on the fly, while interpreting
-the xml file.
+For further documentation please see
-For more in-depth informations about this example, please visit:
-
-http://logback.qos.ch/manual/joran.html#newRule
+ http://logback.qos.ch/manual/onJoran.html#newRule
Modified: logback/trunk/logback-site/src/site/pages/manual/onJoran.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/onJoran.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/onJoran.html Wed Feb 4 17:26:57 2009
@@ -379,7 +379,7 @@
<p>The next example, <em>calculator2.xml</em> file is a bit more
complex, but also more interesting.</p>
- <em>Example 3.<span class="autoEx"/>: Calculator configuration
+ <em>Example 10.<span class="autoEx"/>: Calculator configuration
file
(logback-examples/src/main/java/chapter10/calculator/calculator2.xml)</em>
<div class="source"><pre><computation name="toto">
@@ -427,8 +427,8 @@
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>
+ <em>Example 10.<span class="autoEx"/>: Calculator configuration file
+ (logback-examples/src/main/java/chapter10/calculator/calculator3.xml)</em>
<div class="source"><pre><computation name="toto">
<computation>
@@ -444,7 +444,7 @@
<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">
+ href="../xref/chapter10/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
@@ -493,7 +493,7 @@
<p>The <a
href="../xref/chapter10/implicit/PrintMe.html"><code>PrintMe</code></a>
application associates an <a
- href="../xref/chapter3/implicit/NOPAction.html">
+ href="../xref/chapter10/implicit/NOPAction.html">
<code>NOPAction</code></a> instance with the pattern "*/foo", that
is any element named as "foo". As its name indicates, the
<code>begin</code>() and <code>end</code>() methods of
@@ -503,8 +503,8 @@
in its list of implicit actions. The
<code>PrintMeImplicitAction</code> is applicable for any element
which has a <span class="attr">printme</span> attribute set to
- true. See the isApplicable method in
- <code>PrintMeImplicitAction</code>. The <code>begin</code>() method
+ true. See the <code>isApplicable()</code> method in
+ <code>PrintMeImplicitAction</code>. The <code>begin()</code>() method
of <code>PrintMeImplicitAction</code> prints the name of the current
element on the console.
</p>
@@ -512,7 +512,7 @@
<p>The XML document <em>implicit1.xml</em> is designed to illustrate
how implicit actions come into play.</p>
- <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
+ <em>Example 10.<span class="autoEx"/>: Usage of implicit rules
(logback-examples/src/main/java/chapter10/implicit/implicit1.xml)</em>
<p class="source"><foo>
<xyz printme="true">
@@ -531,18 +531,25 @@
<p>yields:</p>
<p class="console">Element [xyz] asked to be printed.
-Element [abc] asked to be printed.</p>
+Element [abc] asked to be printed.
+20:33:43,750 |-ERROR in c.q.l.c.joran.spi.Interpreter@<b>10:9</b> - no applicable action for [xyz], current pattern is [[foo][xyz]]</p>
<p>Given that <code>NOPAction</code> instance is explicitly
- associated with the "*/foo" pattern, the
- <code>PrintMeImplicitAction</code> is never triggered for any of the
- <foo> elements. For other elements, the
- <code>isApplicable</code> method of
+ associated with the "*/foo" pattern, <code>NOPActgion</code>'s
+ <code>begin()</code> and <code>end()</code> methods are invoked on
+ <foo> elements. <code>PrintMeImplicitAction</code> is never
+ triggered for any of the <foo> elements. For other elements,
+ since there are no matching explicit actions, the
+ <code>isApplicable()</code> method of
<code>PrintMeImplicitAction</code> is invoked. It will return true
only for elements having a <span class="attr">printme</span>
attribute set to true, namely the first <xyz> element (but not
- the second) and the <abc> element. This explains the output shown
- above (previous paragraph).
+ the second) and the <abc> element. The second <xyz> element on
+ line 10, there are no applicable actions, an internal error message
+ is generated. This message is printed by the
+ <code>StatusPrinter.print</code> invocation, the last statement in
+ the <code>PrintMe</code> application. This explains the output shown
+ above (see previous paragraph).
</p>
<h3><a name="iaPractice" href="#iaPractice">Implicit actions in
@@ -556,86 +563,128 @@
<code>NestedComplexPropertyIA</code></a>.
</p>
- <p>
- <code>NestedBasicPropertyIA</code> is applicable for any property
+ <p><code>NestedBasicPropertyIA</code> is applicable for any property
whose type, is a primitive type, or equivalent object type in the
<code>java.lang</code> package, an enumeration type, or any type
adhering to the "valueOf" convention. A class is said to adhere to
the "valueOf" convention if it contains a static method named
<code>valueOf</code>() taking a <code>java.lang.String</code> as
- parameter and returning an instance of the type in question.
+ parameter and returning an instance of the type in question.
</p>
- <p> <code>NestedComplexPropertyIA</code> action is applicable in the
+ <p><code>NestedComplexPropertyIA</code> action is applicable, in the
remaining cases where <code>NestedBasicPropertyIA</code> is not
- applicable. In other words, <code>NestedComplexPropertyIA</code> is
- a last resort, catch-all, implicit action. It will
- </p>
-
- <p>For example, the <a
+ applicable <em>and</em> if the object at the top of the object stack
+ has a setter or adder method for a property name equal to the
+ current element name. This strategy allows <a
href="../xref/ch/qos/logback/core/joran/action/NestedComplexPropertyIA.html">
- <code>NestedComplexPropertyIA</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.
+ <code>NestedComplexPropertyIA</code></a> to instantiate the
+ appropriate class for the nested component and attach it to the
+ parent component (at the top of the object stack) by using the
+ setter/adder method of the parent component and the nested element's
+ name. The class to instantiate is specified by the <span
+ class="attr">class</span> attribute of the nested element. However,
+ the class name can be deduced implicitly, if any of the following is
+ true:
+ </p>
+
+ <ol>
+ <li>there is an internal rule associating the parent object's
+ property with a designated class,
+ </li>
+ <li>the setter method contains a @DefaultClass attribute
+ designating a given class,</li>
+
+ <li>the parameter type of the setter method is a contcrete class
+ possessing a public constructor,
+ </li>
+ </ol>
+
+ <p>In logback-classic, there are just two rules mapping (parent
+ class/property name) couples to a default class.</p>
+
+ <table class="bodyTable">
+ <tr>
+ <th>Parent class </th>
+ <th>property name </th>
+ <th>default nested class</th>
+ </tr>
+ <tr >
+ <td>ch.qos.logback.core.AppenderBase</td>
+ <td>layout</td>
+ <td>ch.qos.logback.classic.PatternLayout</td>
+ </tr>
+ <tr class="alt">
+ <td>ch.qos.logback.core.filter.EvaluatorFilter</td>
+ <td>evaluator</td>
+ <td>ch.qos.logback.classic.boolex.JaninoEventEvaluator</td>
+ </tr>
+ </table>
+
+ <p>This list may change in future releases. Please see
+ logback-classic <a
+ href="../xref/ch/qos/logback/classic/joran/JoranConfigurator.html">JoranConfigurator</a>'s
+ <code>addDefaultNestedComponentRegistryRules</code> method for the
+ latest rules.
+ </p>
+
+ <p>In logback-access, the rules are very similar. In the default
+ class for the nested component, the ch.qos.logback.classic package
+ is replaced by ch.qos.logback.access. See logback-access <a
+ href="../xref/ch/qos/logback/access/joran/JoranConfigurator.html">JoranConfigurator</a>'s
+ <code>addDefaultNestedComponentRegistryRules</code> method for the
+ latest rules.
</p>
-
-
- <a name="newRule"></a>
-
- <h3>New-rule action</h3>
+ <h3><a name="newRule" href="#newRule">New rules on the fly</a></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>
-
- <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>
+ learn new rules on the fly, that is while interpreting an XML
+ document. See the
+ <em>logback-examples/src/main/java/chapter10/newRule/</em> directory
+ for sample code. In this package, the <a
+ href="../xref/chapter10/newRule/NewRuleCalculator.html">
+ <code>NewRuleCalculator</code></a> application sets up just two
+ rules, one rule to process the top-most element, and a second rule
+ to learn new rules. Here is the relevant code from
+ <code>NewRuleCalculator</code>.
+ </p>
+
+ <p class="source">ruleMap.put(new Pattern("*/computation"), new ComputationAction1());
+<b>ruleStore.addRule(new Pattern("/computation/new-rule"), new NewRuleAction());</b></p>
+
+ <p><a
+ href="../xref/ch/qos/logback/core/joran/action/NewRuleAction.html"><code>NewRuleAction</code></a>,
+ part of logback-core, works pretty much like the other actions. 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. When
+ invoked, the <code>begin()</code> method looks for <em>pattern</em>
+ and <em>actionClass</em> attributes. It then instantiates the
+ corresponding action class and adds the pattern/action association
+ as a new rule in Joran's rule store.</p>
+
<p>Here is how new rules can be declared in an xml file:</p>
<p class="source"><new-rule pattern="*/computation/literal"
-actionClass="chapter10.calculator.LiteralAction"/></p>
+ actionClass="chapter10.calculator.LiteralAction"/></p>
- <p>Using new rule declarations, the preceding example, involving the
+ <p>Using such new-rule declarations, we can transform
+ <code>NewRuleCalculator</code> to behave like the
+ <code>Calculator1</code> application we saw earlier. involving the
calculation, could be expressed this way:</p>
- <em>Example 3.<span class="autoEx"/>: Configuration file using new
+ <em>Example 10..<span class="autoEx"/>: Configuration file using new
rules on the fly
- (logback-examples/src/main/java/chapter3/newrule/new-rule.xml)</em>
+ (logback-examples/src/main/java/chapter10/newrule/new-rule.xml)</em>
-<div class="source"><pre><computation name="toto">
+ <p class="source"><computation name="toto">
<new-rule pattern="*/computation/literal"
- actionClass="chapter3.calculator.LiteralAction"/>
+ actionClass="chapter10.calculator.LiteralAction"/>
<new-rule pattern="*/computation/add"
- actionClass="chapter3.calculator.AddAction"/>
+ actionClass="chapter10.calculator.AddAction"/>
<new-rule pattern="*/computation/multiply"
- actionClass="chapter3.calculator.MultiplyAction"/>
+ actionClass="chapter10.calculator.MultiplyAction"/>
<computation>
<literal value="7"/>
@@ -645,7 +694,18 @@
<literal value="3"/>
<multiply/>
-</computation></pre></div>
+</computation></p>
+
+
+ <p class="command">java java chapter10.newRule.NewRuleCalculator src/main/java/chapter10/newRule/new-rule.xml</p>
+
+ <p>yields</p>
+
+ <p class="console">The computation named [toto] resulted in the value 30</p>
+
+ <p>which is identical to the output of the <a
+ href="#calculator">original calculator example</a>.</p>
+
<script src="templates/footer.js" type="text/javascript"></script>
</div>
More information about the logback-dev
mailing list