[logback-dev] svn commit: r1775 - in logback/trunk: logback-examples/src/main/java/chapter3 logback-site/src/site/pages logback-site/src/site/pages/manual

noreply.ceki at qos.ch noreply.ceki at qos.ch
Sun Aug 24 00:25:55 CEST 2008


Author: ceki
Date: Sun Aug 24 00:25:55 2008
New Revision: 1775

Added:
   logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml
      - copied, changed from r1772, /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml
   logback/trunk/logback-site/src/site/pages/joran.html
Removed:
   logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml
Modified:
   logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml
   logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml
   logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml
   logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml
   logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml
   logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties
   logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties
   logback/trunk/logback-site/src/site/pages/documentation.html
   logback/trunk/logback-site/src/site/pages/manual/joran.html

Log:
- ongoing work on the documentation
  Chapter3 has been split into two parts, the fist part on logback configuration and a second part on Joran as a standalone framework

Copied: logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml (from r1772, /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml)
==============================================================================
--- /logback/trunk/logback-examples/src/main/java/chapter3/redirectConfig.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/containingConfig.xml	Sun Aug 24 00:25:55 2008
@@ -2,6 +2,11 @@
 
 <configuration>
 
-  <include file="path/to/configuration/file" />
+  <include file="src/main/java/chapter3/includedConfig.xml" />
+
+  <root level="DEBUG">
+    <appender-ref ref="includedConsole" />
+  </root>
+
 
 </configuration>

Modified: logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/includedConfig.xml	Sun Aug 24 00:25:55 2008
@@ -2,16 +2,10 @@
 
 <included>
 
-  <appender name="redirectConsole"
-    class="ch.qos.logback.core.ConsoleAppender">
+  <appender name="includedConsole"  class="ch.qos.logback.core.ConsoleAppender">
     <layout class="ch.qos.logback.classic.PatternLayout">
       <param name="Pattern" value="%d - %m%n" />
     </layout>
   </appender>
 
-  <root>
-    <level value="DEBUG" />
-    <appender-ref ref="redirectConsole" />
-  </root>
-
 </included>
\ No newline at end of file

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution1.xml	Sun Aug 24 00:25:55 2008
@@ -1,9 +1,9 @@
 <configuration>
 
-	<substitutionProperty name="user.home.dir" value="/home/sebastien" />
+	<substitutionProperty name="USER_HOME" value="/home/sebastien" />
 
 	<appender name="FILE" class="ch.qos.logback.core.FileAppender">
-		<file>${user.home.dir}/myApp.log</file>
+		<file>${USER_HOME}/myApp.log</file>
 		<layout class="ch.qos.logback.classic.PatternLayout">
 			<Pattern>%msg%n</Pattern>
 		</layout>

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution2.xml	Sun Aug 24 00:25:55 2008
@@ -1,18 +1,9 @@
 <configuration>
 
-	<appender name="FILE"
-		class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${user.home.dir}/myApp.log</file>
-		<rollingPolicy
-			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-			<FileNamePattern>
-				myApp-%d{yyyy-MM-dd-HH}.log
-			</FileNamePattern>
-		</rollingPolicy>
+	<appender name="FILE" class="ch.qos.logback.core.FileAppender">
+		<file>${USER_HOME}/myApp.log</file>
 		<layout class="ch.qos.logback.classic.PatternLayout">
-			<Pattern>
-				%date %level [%thread] %logger{10} [%file : %line] %msg%n
-			</Pattern>
+			<Pattern>%msg%n</Pattern>
 		</layout>
 	</appender>
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution3.xml	Sun Aug 24 00:25:55 2008
@@ -2,19 +2,10 @@
 
 	<substitutionProperty file="variables1.properties" />
 
-	<appender name="FILE"
-		class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${user.home.dir}/myApp.log</file>
-		<rollingPolicy
-			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-			<FileNamePattern>
-				myApp-%d{yyyy-MM-dd-HH}.log
-			</FileNamePattern>
-		</rollingPolicy>
+	<appender name="FILE" class="ch.qos.logback.core.FileAppender">
+		<file>${USER_HOME}/myApp.log</file>
 		<layout class="ch.qos.logback.classic.PatternLayout">
-			<Pattern>
-				%date %level [%thread] %logger{10} [%file : %line] %msg%n
-			</Pattern>
+			<Pattern>%msg%n</Pattern>
 		</layout>
 	</appender>
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variableSubstitution4.xml	Sun Aug 24 00:25:55 2008
@@ -2,19 +2,10 @@
 
 	<substitutionProperty file="variables2.properties" />
 
-	<appender name="FILE"
-		class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${destination}</file>
-		<rollingPolicy
-			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-			<FileNamePattern>
-				myApp-%d{yyyy-MM-dd-HH}.log
-			</FileNamePattern>
-		</rollingPolicy>
+	<appender name="FILE" class="ch.qos.logback.core.FileAppender">
+		<file>${destination}/myApp.log</file>
 		<layout class="ch.qos.logback.classic.PatternLayout">
-			<Pattern>
-				%date %level [%thread] %logger{10} [%file : %line] %msg%n
-			</Pattern>
+			<Pattern>%msg%n</Pattern>
 		</layout>
 	</appender>
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variables1.properties	Sun Aug 24 00:25:55 2008
@@ -1 +1 @@
-user.home.dir=/Users/seb
\ No newline at end of file
+USER_HOME=/home/sebastien
\ No newline at end of file

Modified: logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/variables2.properties	Sun Aug 24 00:25:55 2008
@@ -1,3 +1,3 @@
-user.home.dir=/Users/seb
+USER_HOME=/home/sebastien
 fileName=myApp.log
-destination=${user.home.dir}/${fileName}
\ No newline at end of file
+destination=${USER_HOME}/${fileName}
\ No newline at end of file

Modified: logback/trunk/logback-site/src/site/pages/documentation.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/documentation.html	(original)
+++ logback/trunk/logback-site/src/site/pages/documentation.html	Sun Aug 24 00:25:55 2008
@@ -38,7 +38,11 @@
       <li>
       	<a href="dependencies.html">Dependencies per module</a>
       </li>
-     
+          
+      <li>
+      	<a href="joran.html">Using Joran in your applications</a>
+      </li>
+
       <li>
       	<a href="jmxConfig.html">How to use the logback JMX Configurator</a>
       </li>

Added: logback/trunk/logback-site/src/site/pages/joran.html
==============================================================================
--- (empty file)
+++ logback/trunk/logback-site/src/site/pages/joran.html	Sun Aug 24 00:25:55 2008
@@ -0,0 +1,512 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+<title>Using Joran</title>
+<link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />
+<link rel="stylesheet" type="text/css" media="print" href="css/print.css" />
+ 
+</head>
+<body>
+  <script type="text/javascript">prefix='./'</script>
+  <script type="text/javascript" src="templates/header.js"></script>
+<div id="left">
+  <script type="text/javascript" src="templates/left.js"></script>
+</div>
+<div id="right"><script type="text/javascript" src="templates/right.js"></script></div>
+<div id="content">
+
+  <h2>Using Joran in your own applications</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>
+
+  <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 class="red" style="text-decoration: line-through;">The examples
+  for this chapter can be found under
+  <em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
+  </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>
+  
+  <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>In log4j, logback's predecessor, <code>DOMConfigurator</code>
+  which shipped with log4j version 1.2.x could also 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>&lt;b></code> element nested within an <code>&lt;a></code>
+  element but not a <code>&lt;c></code> element, even if nested within
+  a <code>&lt;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>&lt;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>
+
+  <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>Joran was first implemented in DOM. However, the author migrated
+  to SAX in order to benefit location information, available only with
+  the SAX API. Location information allows Joran to display the exact
+  line and column number where an error occured, which comes in quite
+  handy when hunting down problems.
+  </p>
+
+
+  <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>
+
+
+<div class="source"><pre>package ch.qos.logback.core.joran.action;
+
+import org.xml.sax.Attributes;
+import ch.qos.logback.core.joran.spi.ExecutionContext;
+
+public abstract class Action {
+  
+
+ /**
+  * Called when the parser first encounters an element.
+  */
+  public abstract void begin(ExecutionContext ec, 
+                             String name, 
+                             Attributes attributes);
+
+ /**
+  * Called when the parser encounters the element end. At 
+  * this stage, we can assume that child elements, if any,
+  * have been processed. 
+  */
+  public abstract void end(ExecutionContext ec, String name);
+}</pre></div>
+
+  <p>Thus, every action must implement the begin and end methods.</p>
+
+
+  <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>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>
+
+  <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 &lt;hello-world&gt;
+  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>
+
+  <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>
+
+  <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>
+
+  <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>&lt;computation name="toto"&gt;
+  &lt;literal value="7"/&gt;
+  &lt;literal value="3"/&gt;
+  &lt;add/&gt;
+  &lt;literal value="3"/&gt;
+  &lt;multiply/&gt;
+&lt;/computation&gt;</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.<span class="autoEx"/>: Calculator configuration file
+  (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
+
+<div class="source"><pre>&lt;computation name="toto"&gt;
+  &lt;computation&gt;
+    &lt;literal value="7"/&gt;
+    &lt;literal value="3"/&gt;
+    &lt;add/&gt;
+  &lt;/computation&gt;   
+ 
+  &lt;literal value="3"/&gt;
+  &lt;multiply/&gt;
+&lt;/computation&gt;</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>
+
+  <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>&lt;new-rule pattern="*/computation/literal"
+actionClass="chapter3.calculator.LiteralAction"/&gt;</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>
+
+<div class="source"><pre>&lt;computation name="toto"&gt;
+  &lt;new-rule pattern="*/computation/literal" 
+            actionClass="chapter3.calculator.LiteralAction"/&gt;
+  &lt;new-rule pattern="*/computation/add" 
+            actionClass="chapter3.calculator.AddAction"/&gt;
+  &lt;new-rule pattern="*/computation/multiply" 
+            actionClass="chapter3.calculator.MultiplyAction"/&gt;
+
+  &lt;computation&gt;
+    &lt;literal value="7"/&gt;
+    &lt;literal value="3"/&gt;
+    &lt;add/&gt;
+  &lt;/computation&gt;   
+ 
+  &lt;literal value="3"/&gt;
+  &lt;multiply/&gt;
+&lt;/computation&gt;</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>
+
+  <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 &lt;a> and also to another
+  element &lt;b> nested within &lt;a>. The current implementation of
+  <code>NestedComponentIA</code> is capable of handling multiply
+  nested elements requiring intervention by the same implicit action.
+  </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>Refer to the
+  <em>logback-examples/src/main/java/joran/implicit</em> directory for
+  an example of an implicit action.
+  </p>
+
+  <p>In that directory, you will find two actions classes, one xml
+  file and one class containing the setup of Joran.</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>
+
+  <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
+  (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
+<div class="source"><pre>&lt;foo&gt;
+
+  &lt;xyz printme="true"&gt;
+    &lt;abc printme="true"/&gt;
+  &lt;/xyz&gt;
+
+  &lt;xyz/&gt;
+
+  &lt;foo printme="true"/&gt;
+
+&lt;/foo&gt;</pre></div>
+
+  <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>Running the example yields the following output:</p>
+
+<div class="source"><pre>Element &lt;xyz> asked to be printed.
+Element &lt;abc> asked to be printed.
+ERROR in ch.qos.logback.core.joran.spi.ExecutionContext at 1c5c1 - no applicable action \
+for &lt;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>
+
+  <h3>Non goals</h3>
+
+  <p>The Joran API is not intended to be used to parse documents with
+  thousands of elements.
+  </p>
+
+
+<script src="templates/footer.js"></script>
+</div>
+</body>
+</html>

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	Sun Aug 24 00:25:55 2008
@@ -5,7 +5,7 @@
 <title>Chapter3: Logback configuration &amp; Joran</title>
 <link rel="stylesheet" type="text/css" media="screen" href="../css/site.css" />
 <link rel="stylesheet" type="text/css" media="print" href="../css/print.css" />
-<link type="text/css" rel="stylesheet" href="../ghighlighter/Styles/SyntaxHighlighter.css"></link>
+
  
 </head>
 <body>
@@ -881,24 +881,22 @@
 
   <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>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>In principle, variable substitution can occur at any point where
+  a value can be specified. 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 in the
+  configuration file itself, in an external properties file or as a
+  system property.  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 next example shows a variable, a.k.a. a substitution
+  property, declared the beginning of the configuration file. It is
+  then used further down the file to specify the location of the
+  output file.
   </p>
 
   <em>Example 3.<span class="autoEx"/>: Simple Variable substitution
@@ -907,21 +905,13 @@
 
   <div class="source"><pre>&lt;configuration>
 
-  <b>&lt;substitutionProperty name="user.home.dir" value="/Users/seb" /></b>
+  <b>&lt;substitutionProperty name="USER_HOME" value="/home/sebastien" /></b>
 
   &lt;appender name="FILE"
-    class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <b>&lt;file>${user.home.dir}/myApp.log&lt;/file></b>
-    &lt;rollingPolicy
-      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      &lt;FileNamePattern>
-        myApp-%d{yyyy-MM-dd-HH}.log
-      &lt;/FileNamePattern>
-    &lt;/rollingPolicy>
+    class="ch.qos.logback.core.FileAppender">
+    <b>&lt;file>${USER_HOME}/myApp.log&lt;/file></b>
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>
-        %date %level [%thread] %logger{10} [%file : %line] %msg%n
-      &lt;/Pattern>
+      &lt;Pattern>%msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
@@ -932,9 +922,13 @@
 &lt;/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>The next example shows the use of a System property to achieve
+  the same result. The property is not declared in the configuration
+  file, thus logback will look for it in the System properties. Java
+  system properties can be set on the command line.
   </p>
+  
+  <p class="source">java -DUSER_HOME="/home/sebastien" MyApp2</p>
 
   <em>Example 3.<span class="autoEx"/>: System Variable substitution
   (logback-examples/src/main/java/chapter3/variableSubstitution2.xml)
@@ -943,18 +937,10 @@
   <div class="source"><pre>&lt;configuration>
 
   &lt;appender name="FILE"
-    class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <b>&lt;file>${user.home.dir}/myApp.log&lt;/file></b>
-    &lt;rollingPolicy
-      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      &lt;FileNamePattern>
-        myApp-%d{yyyy-MM-dd-HH}.log
-      &lt;/FileNamePattern>
-    &lt;/rollingPolicy>
+    class="ch.qos.logback.core.FileAppender">
+    <b>&lt;file>${USER_HOME}/myApp.log&lt;/file></b>
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>
-        %date %level [%thread] %logger{10} [%file : %line] %msg%n
-      &lt;/Pattern>
+      &lt;Pattern>%msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
@@ -964,7 +950,8 @@
   &lt;/root>
 &lt;/configuration></pre></div>
 
-  <p>When many variables are used, it is often more convenient to
+  
+  <p>When multiple variables are needed, it may be more convenient to
   create a separate file that will contain all the variables. Here is
   how one can do such a setup.
   </p>
@@ -978,19 +965,11 @@
 
   <b>&lt;substitutionProperty file="variables1.properties" /></b>
 
-  &lt;appender name="FILE"
-    class="ch.qos.logback.core.rolling.RollingFileAppender">
-    <b>&lt;file>${user.home.dir}/myApp.log&lt;/file></b>
-    &lt;rollingPolicy
-      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      &lt;FileNamePattern>
-        myApp-%d{yyyy-MM-dd-HH}.log
-      &lt;/FileNamePattern>
-    &lt;/rollingPolicy>
+ &lt;appender name="FILE"
+    class="ch.qos.logback.core.FileAppender">
+    <b>&lt;file>${USER_HOME}/myApp.log&lt;/file></b>
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>
-        %date %level [%thread] %logger{10} [%file : %line] %msg%n
-      &lt;/Pattern>
+      &lt;Pattern>%msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
@@ -1000,56 +979,53 @@
   &lt;/root>
 &lt;/configuration></pre></div>
 
-<p>
-This configuration file contains a link to another file called <em>variables1.properties</em>.
-The variables contained in that other file will be read and will thus be available to the 
-logback configuration file. Here is what the <em>variable.properties</em> file looks like.
-</p>
-
-<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>
-Nothing more is needed to declare the variable.
-</p>
-
-<p>
-Recursive subsitution is also available. If the user wants to use variables to
-specify not only the destination directory but also the file name, here is what she
-would write in her <em>variables1.properties</em> file.
-</p>
-
-
-<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
+   <p>This configuration file contains a reference to a file named
+   <em>variables1.properties</em>.  The variables contained in that
+   file will be read defined within the context of the logback
+   configuration file. Here is what the <em>variable.properties</em>
+   file might look like.
+   </p>
+
+   <em>Example 3.<span class="autoEx"/>: Variable file
+   (logback-examples/src/main/java/chapter3/variables1.properties)</em>
+
+   <div class="source"><pre>USER_HOME=/home/sebastien</pre></div>
+
+   <p>Nested variabled subsitution is also supported. By nested, we
+   mean that the value definition of a variable contains referenced to
+   other variables. Here is an example. Suppose you wish to use
+   variables to specify not only the destination directory but also
+   the file name, and combine those variable in a third variable
+   called "destination". The properties file shown below gives an
+   example.
+   </p>
+
+
+   <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=/home/sebastien
 fileName=myApp.log
-destination=${user.home.dir}/${fileName}</pre></div>
+<b>destination=${USER_HOME}/${fileName}</b></pre></div>
 
-    <p>In the configuration file, only the last variable,
-    <em>${destination}</em> will be used, as shown below:
+    <p>Note that in the properties file above, "destination" is
+    composed out of two other variables, namely "USER_HOME" and
+    "fileName".
     </p>
-
-    <em>Example 3.<span class="autoEx"/>: Variable substitution using a separate file
+    
+    <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>&lt;configuration>
 
-  &lt;substitutionProperty file="variables1.properties" />
+  &lt;substitutionProperty file="variables2.properties" />
 
   &lt;appender name="FILE"
-    class="ch.qos.logback.core.rolling.RollingFileAppender">
+    class="ch.qos.logback.core.FileAppender">
     <b>&lt;file>${destination}&lt;/file></b>
-    &lt;rollingPolicy
-      class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-      &lt;FileNamePattern>
-        myApp-%d{yyyy-MM-dd-HH}.log
-      &lt;/FileNamePattern>
-    &lt;/rollingPolicy>
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>
-        %date %level [%thread] %logger{10} [%file : %line] %msg%n
-      &lt;/Pattern>
+      &lt;Pattern>%msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
@@ -1059,546 +1035,62 @@
   &lt;/root>
 &lt;/configuration></pre></div>
 
+  <h3>Default substitution values for variables</h3>
+
+  <p>Under certain circumstances, it may be desirable for a variable
+  to have a default value in case it is not declared or its value is
+  null. As in the <a
+  href="http://tldp.org/LDP/abs/html/parameter-substitution.html">Bash
+  shell</a>, default values can be specified using the <b>":-"</b>
+  operator. For example, assuming <em>aKey</em> is not defined,
+  <code>"${aKey<b>:-golden</b>}"</code> will be interpreted as
+  "golden".</p>
+  
+
   <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>Joran supports including parts of a configuration file from
+  another file. This is done by declaring a <code>&lt;include></code>
+  element, as shown below:
   </p>
 
   <em>Example 3.<span class="autoEx"/>: File include
-  (logback-examples/src/main/java/chapter3/redirectConfig.xml)</em>
+  (logback-examples/src/main/java/chapter3/containingConfig.xml)</em>
 
   <div class="source"><pre>&lt;configuration>
-  <b>&lt;include file="path/to/configuration/file"/></b>
-  &lt;/configuration></pre></div>
+  <b>&lt;include file="src/main/java/chapter3/includedConfig.xml"/></b>
 
-  <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:
+  &lt;root level="DEBUG">
+    &lt;appender-ref ref="includedConsole" />
+  &lt;/root>
+
+&lt;/configuration></pre></div>
+
+  <p>The target file MUST have its elements nested inside an
+  <code>&lt;included></code> element. For example, a
+  <code>ConsoleAppender</code> could be declared as:
   </p>
 
   <em>Example 3.<span class="autoEx"/>: File include
   (logback-examples/src/main/java/chapter3/includedConfig.xml)</em>
 
-  <div class="source"><pre>&lt;included>
-
-  &lt;appender name="redirectConsole"
-    class="ch.qos.logback.core.ConsoleAppender">
+  <div class="source"><pre><b class="green">&lt;included></b>
+  &lt;appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;param name="Pattern" value="%d - %m%n" />
+      &lt;Pattern>"%d - %m%n"&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
+<b class="green">&lt;/included></b></pre></div>
 
-  &lt;root>
-    &lt;level value="DEBUG" />
-    &lt;appender-ref ref="redirectConsole" />
-  &lt;/root>
-
-&lt;/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>
-
-
-  <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>
-
-  <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>The examples for this chapter can be found under
-  <em>LOGBACK_HOME/logback-examples/src/main/java/chapter3</em>.
-  </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>
-  
-  <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>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>&lt;b></code> element nested within an <code>&lt;a></code>
-  element but not a <code>&lt;c></code> element, even if nested within
-  a <code>&lt;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>&lt;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>
-
-  <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>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>
-
-  <p>Actions extend the
-  <code>ch.qos.logback.core.joran.action.Action</code> class which
-  consists of the following abstract methods.
+  <p>The file to be included can be referenced as a file, as a URL or
+  as a resource. To reference a file use the <span
+  class="attr">file</span> attribute. To reference a URL use the <span
+  class="attr">url</span> attribute. To reference a resource, use the
+  <span class="attr">resource</span> attribute.
   </p>
 
 
-<div class="source"><pre>package ch.qos.logback.core.joran.action;
-
-import org.xml.sax.Attributes;
-import ch.qos.logback.core.joran.spi.ExecutionContext;
-
-public abstract class Action {
-  
-
- /**
-  * Called when the parser first encounters an element.
-  */
-  public abstract void begin(ExecutionContext ec, 
-                             String name, 
-                             Attributes attributes);
-
- /**
-  * Called when the parser encounters the element end. At 
-  * this stage, we can assume that child elements, if any,
-  * have been processed. 
-  */
-  public abstract void end(ExecutionContext ec, String name);
-}</pre></div>
-
-  <p>Thus, every action must implement the begin and end methods.</p>
-
-
-  <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>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>
-
-  <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 &lt;hello-world&gt;
-  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>
-
-  <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>
-
-  <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>
-
-  <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>&lt;computation name="toto"&gt;
-  &lt;literal value="7"/&gt;
-  &lt;literal value="3"/&gt;
-  &lt;add/&gt;
-  &lt;literal value="3"/&gt;
-  &lt;multiply/&gt;
-&lt;/computation&gt;</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.<span class="autoEx"/>: Calculator configuration file
-  (logback-examples/src/main/java/chapter3/calculator/calculator3.xml)</em>
-
-<div class="source"><pre>&lt;computation name="toto"&gt;
-  &lt;computation&gt;
-    &lt;literal value="7"/&gt;
-    &lt;literal value="3"/&gt;
-    &lt;add/&gt;
-  &lt;/computation&gt;   
- 
-  &lt;literal value="3"/&gt;
-  &lt;multiply/&gt;
-&lt;/computation&gt;</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>
-
-  <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>&lt;new-rule pattern="*/computation/literal"
-actionClass="chapter3.calculator.LiteralAction"/&gt;</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>
-
-<div class="source"><pre>&lt;computation name="toto"&gt;
-  &lt;new-rule pattern="*/computation/literal" 
-            actionClass="chapter3.calculator.LiteralAction"/&gt;
-  &lt;new-rule pattern="*/computation/add" 
-            actionClass="chapter3.calculator.AddAction"/&gt;
-  &lt;new-rule pattern="*/computation/multiply" 
-            actionClass="chapter3.calculator.MultiplyAction"/&gt;
-
-  &lt;computation&gt;
-    &lt;literal value="7"/&gt;
-    &lt;literal value="3"/&gt;
-    &lt;add/&gt;
-  &lt;/computation&gt;   
- 
-  &lt;literal value="3"/&gt;
-  &lt;multiply/&gt;
-&lt;/computation&gt;</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>
-
-  <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 &lt;a> and also to another
-  element &lt;b> nested within &lt;a>. The current implementation of
-  <code>NestedComponentIA</code> is capable of handling multiply
-  nested elements requiring intervention by the same implicit action.
-  </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>Refer to the
-  <em>logback-examples/src/main/java/joran/implicit</em> directory for
-  an example of an implicit action.
-  </p>
-
-  <p>In that directory, you will find two actions classes, one xml
-  file and one class containing the setup of Joran.</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>
-
-  <em>Example 3.<span class="autoEx"/>: Usage of implicit rules
-  (logback-examples/src/main/java/chapter3/implicit/implicit1.xml)</em>
-<div class="source"><pre>&lt;foo&gt;
-
-  &lt;xyz printme="true"&gt;
-    &lt;abc printme="true"/&gt;
-  &lt;/xyz&gt;
-
-  &lt;xyz/&gt;
-
-  &lt;foo printme="true"/&gt;
-
-&lt;/foo&gt;</pre></div>
-
-  <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>Running the example yields the following output:</p>
-
-<div class="source"><pre>Element &lt;xyz> asked to be printed.
-Element &lt;abc> asked to be printed.
-ERROR in ch.qos.logback.core.joran.spi.ExecutionContext at 1c5c1 - no applicable action \
-for &lt;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>
-
-  <h3>Non goals</h3>
-
-  <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