[logback-dev] svn commit: r1769 - in logback/trunk: logback-classic/src/main/java/ch/qos/logback/classic/joran/action logback-classic/src/test/input/joran logback-core/src/main/java/ch/qos/logback/core/joran/action logback-examples/src/main/java/chapter3 logback-site/src/site/pages logback-site/src/site/pages/ghighlighter/Styles logback-site/src/site/pages/ghighlighter/js logback-site/src/site/pages/manual logback-site/src/site/pages/templates

noreply.ceki at qos.ch noreply.ceki at qos.ch
Thu Aug 21 19:18:28 CEST 2008


Author: ceki
Date: Thu Aug 21 19:18:27 2008
New Revision: 1769

Modified:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java
   logback/trunk/logback-classic/src/test/input/joran/simple2.xml
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java
   logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java
   logback/trunk/logback-examples/src/main/java/chapter3/sample0.xml
   logback/trunk/logback-examples/src/main/java/chapter3/sample1.xml
   logback/trunk/logback-examples/src/main/java/chapter3/sample2.xml
   logback/trunk/logback-examples/src/main/java/chapter3/sample3.xml
   logback/trunk/logback-examples/src/main/java/chapter3/sample4.xml
   logback/trunk/logback-site/src/site/pages/ghighlighter/Styles/SyntaxHighlighter.css
   logback/trunk/logback-site/src/site/pages/ghighlighter/js/shBrushJava.js
   logback/trunk/logback-site/src/site/pages/ghighlighter/js/shCore.js
   logback/trunk/logback-site/src/site/pages/manual/joran.html
   logback/trunk/logback-site/src/site/pages/news.html
   logback/trunk/logback-site/src/site/pages/templates/right.js

Log:
- simplified the syntax for setting the level of a logger in config files.
  The previous syntax is still honored but it will no longer be documented.

- ongoing work on the docs

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LevelAction.java	Thu Aug 21 19:18:27 2008
@@ -1,13 +1,12 @@
 /**
- * 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-2008, 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.joran.action;
 
 import org.xml.sax.Attributes;
@@ -15,18 +14,19 @@
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.action.ActionConst;
 import ch.qos.logback.core.joran.spi.InterpretationContext;
 
-
+/**
+ * Action to handle the <level> element nested within <logger> element. 
+ * 
+ * <p>This action is <b>deprecated</b>. Use the level attribute within the logger
+ * element.
+ * 
+ * @author Ceki Gulcu
+ */
 public class LevelAction extends Action {
 
-  static final String VALUE_ATTR = "value";
-  static final String CLASS_ATTR = "class";
-  static final String INHERITED = "INHERITED";
-  static final String NULL = "NULL";
-  static final String EMPTY_STR = "";
-  static final Class[] ONE_STRING_PARAM = new Class[] {String.class};
-
   boolean inError = false;
 
   public void begin(InterpretationContext ec, String name, Attributes attributes) {
@@ -42,11 +42,11 @@
 
     String loggerName = l.getName();
 
-    String levelStr = attributes.getValue(VALUE_ATTR);
+    String levelStr = attributes.getValue(ActionConst.VALUE_ATTR);
     //addInfo("Encapsulating logger name is [" + loggerName
     //    + "], level value is  [" + levelStr + "].");
 
-    if (INHERITED.equalsIgnoreCase(levelStr) || NULL.equalsIgnoreCase(levelStr)) {
+    if (ActionConst.INHERITED.equalsIgnoreCase(levelStr) || ActionConst.NULL.equalsIgnoreCase(levelStr)) {
       l.setLevel(null);
     } else {
       l.setLevel(Level.toLevel(levelStr, Level.DEBUG));

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/LoggerAction.java	Thu Aug 21 19:18:27 2008
@@ -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-2008, 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
@@ -10,9 +10,9 @@
 
 package ch.qos.logback.classic.joran.action;
 
-
 import org.xml.sax.Attributes;
 
+import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.core.joran.action.Action;
@@ -20,51 +20,69 @@
 import ch.qos.logback.core.joran.spi.InterpretationContext;
 import ch.qos.logback.core.util.OptionHelper;
 
-
-
+/**
+ * Action which handles <logger> elements in configuration files.
+ * 
+ * @author Ceki Gulcu
+ */
 public class LoggerAction extends Action {
+  public static final String LEVEL_ATTRIBUTE = "level";
+
   boolean inError = false;
-  
+  Logger logger;
   public void begin(InterpretationContext ec, String name, Attributes attributes) {
     // Let us forget about previous errors (in this object)
     inError = false;
-
+    logger = null;
+    
     LoggerContext loggerContext = (LoggerContext) this.context;
 
-    // Create a new org.apache.log4j.Category object from the <category> element.
     String loggerName = attributes.getValue(NAME_ATTRIBUTE);
 
     if (OptionHelper.isEmpty(loggerName)) {
       inError = true;
-
-      String line =
-        ", around line " + getLineNumber(ec) + " column "
-        + getColumnNumber(ec);
-
+      String line = ", around line " + getLineNumber(ec) + " column "
+          + getColumnNumber(ec);
       String errorMsg = "No 'name' attribute in element " + name + line;
       addError(errorMsg);
-
       return;
     }
 
-    //getLogger().debug("Logger name is [" + loggerName + "].");
-
-    Logger l = loggerContext.getLogger(loggerName);
-    
+    logger = loggerContext.getLogger(loggerName);
 
-    boolean additive =
-      OptionHelper.toBoolean(
-        attributes.getValue(ActionConst.ADDITIVITY_ATTRIBUTE), true);
-    //getLogger().debug(
-    //  "Setting [" + l.getName() + "] additivity to [" + additivity + "].");
-    l.setAdditive(additive);
+    String levelStr = attributes.getValue(LEVEL_ATTRIBUTE);
+    if (!OptionHelper.isEmpty(levelStr)) {
+      if (ActionConst.INHERITED.equalsIgnoreCase(levelStr)
+          || ActionConst.NULL.equalsIgnoreCase(levelStr)) {
+        addInfo("Setting level of logger [" + loggerName
+            + "] to null, i.e. INHERITED");
+        logger.setLevel(null);
+      } else {
+        Level level = Level.toLevel(levelStr);
+        addInfo("Setting level of logger [" + loggerName + "] to " + level);
+        logger.setLevel(level);
+      }
+    }
 
-    //getLogger().debug("Pushing logger named [" + loggerName + "].");
-    ec.pushObject(l);
+    if (!OptionHelper.isEmpty(ActionConst.ADDITIVITY_ATTRIBUTE)) {
+      boolean additive = OptionHelper.toBoolean(attributes
+          .getValue(ActionConst.ADDITIVITY_ATTRIBUTE), true);
+      addInfo("Setting additivity of logger [" + loggerName + "] to "
+          + additive);
+      logger.setAdditive(additive);
+    }
+    ec.pushObject(logger);
   }
 
   public void end(InterpretationContext ec, String e) {
-    if (!inError) {
+    if (inError) {
+      return;
+    }
+    Object o = ec.peekObject();
+    if (o != logger) {
+      addWarn("The object on the top the of the stack is not "+logger+" pushed earlier");
+      addWarn("It is: " + o);
+    } else {
       ec.popObject();
     }
   }

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/RootLoggerAction.java	Thu Aug 21 19:18:27 2008
@@ -9,50 +9,46 @@
  */
 package ch.qos.logback.classic.joran.action;
 
-
 import org.xml.sax.Attributes;
 
+import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.action.ActionConst;
 import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.util.OptionHelper;
 
 public class RootLoggerAction extends Action {
-  static final String NAME_ATTR = "name";
-  static final String CLASS_ATTR = "class";
-  static final String ADDITIVITY_ATTR = "additivity";
-  static final String EMPTY_STR = "";
-  static final Class[] ONE_STRING_PARAM = new Class[] { String.class };
  
   Logger root;
   boolean inError = false;
-  
+
   public void begin(InterpretationContext ec, String name, Attributes attributes) {
     inError = false;
-    //logger.debug("In begin method");
 
     LoggerContext loggerContext = (LoggerContext) this.context;
     root = loggerContext.getLogger(LoggerContext.ROOT_NAME);
 
-    //getLogger().debug("Pushing root logger on stack");
+    String levelStr = attributes.getValue(ActionConst.LEVEL_ATTRIBUTE);
+    if (!OptionHelper.isEmpty(levelStr)) {
+      Level level = Level.toLevel(levelStr);
+      addInfo("Setting level of ROOT logger to " + level);
+      root.setLevel(level);
+    }
+
     ec.pushObject(root);
   }
 
   public void end(InterpretationContext ec, String name) {
-    //logger.debug("end() called.");
-
     if (inError) {
       return;
     }
-
     Object o = ec.peekObject();
-
     if (o != root) {
-      addWarn(
-        "The object on the top the of the stack is not the root logger");
-      addWarn("It is: "+o);
+      addWarn("The object on the top the of the stack is not the root logger");
+      addWarn("It is: " + o);
     } else {
-      //getLogger().debug("Removing root logger from top of stack.");
       ec.popObject();
     }
   }

Modified: logback/trunk/logback-classic/src/test/input/joran/simple2.xml
==============================================================================
--- logback/trunk/logback-classic/src/test/input/joran/simple2.xml	(original)
+++ logback/trunk/logback-classic/src/test/input/joran/simple2.xml	Thu Aug 21 19:18:27 2008
@@ -9,8 +9,7 @@
     </layout>
   </appender>
     
-  <root>
-    <level value="DEBUG" />
+  <root level="DEBUG">
     <appender-ref ref="CONSOLE" />
   </root>
   

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java	Thu Aug 21 19:18:27 2008
@@ -25,9 +25,9 @@
  *
  * Most of the work for configuring log4j is done by Actions.
  *
- * Methods of an Action are invoked while an XML file is parsed through.
+ * <p>Methods of an Action are invoked while an XML file is parsed through.
  *
- * This class is largely copied from the relevant class in the commons-digester
+ * <p>This class is largely inspired from the relevant class in the commons-digester
  * project of the Apache Software Foundation.
  *
  * @author Craig McClanahan
@@ -42,6 +42,7 @@
   public static final String FILE_ATTRIBUTE = "file";
   public static final String CLASS_ATTRIBUTE = "class";
   public static final String PATTERN_ATTRIBUTE = "pattern";
+  
   public static final String ACTION_CLASS_ATTRIBUTE = "actionClass";
 
   /**

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ActionConst.java	Thu Aug 21 19:18:27 2008
@@ -21,13 +21,15 @@
   public static final String APPENDER_TAG = "appender";
   public static final String REF_ATTRIBUTE = "ref";
   public static final String ADDITIVITY_ATTRIBUTE = "additivity";
+  public static final String LEVEL_ATTRIBUTE = "level";
   public static final String CONVERTER_CLASS_ATTRIBUTE = "converterClass";
   public static final String CONVERSION_WORD_ATTRIBUTE = "conversionWord";
   public static final String PATTERN_ATTRIBUTE = "pattern";
+  public static final String VALUE_ATTR = "value";
   public static final String ACTION_CLASS_ATTRIBUTE = "actionClass";
 
-  static final String INHERITED = "INHERITED";
-  static final String NULL = "NULL";
+  public static final String INHERITED = "INHERITED";
+  public static final String NULL = "NULL";
   static final Class[] ONE_STRING_PARAM = new Class[] { String.class };
 
   public static final String APPENDER_BAG = "APPENDER_BAG";

Modified: logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/MyApp3.java	Thu Aug 21 19:18:27 2008
@@ -32,11 +32,14 @@
     try {
       JoranConfigurator configurator = new JoranConfigurator();
       configurator.setContext(lc);
+      // the context was probably already configured by default configuration
+      // rules
       lc.shutdownAndReset();
       configurator.doConfigure(args[0]);
     } catch (JoranException je) {
-      StatusPrinter.print(lc);
+      je.printStackTrace();
     }
+    StatusPrinter.printIfErrorsOccured(lc);
 
     logger.info("Entering application.");
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/sample0.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/sample0.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/sample0.xml	Thu Aug 21 19:18:27 2008
@@ -8,8 +8,7 @@
     </layout>
   </appender>
 
-  <root>
-    <level value="debug" />
+  <root level="debug">
     <appender-ref ref="STDOUT" />
   </root>
 </configuration>

Modified: logback/trunk/logback-examples/src/main/java/chapter3/sample1.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/sample1.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/sample1.xml	Thu Aug 21 19:18:27 2008
@@ -8,8 +8,7 @@
     </layout>
   </appender>
 
-  <root>
-    <level value="debug" />
+  <root level="debug">
     <appender-ref ref="STDOUT" />
   </root>
 </configuration>

Modified: logback/trunk/logback-examples/src/main/java/chapter3/sample2.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/sample2.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/sample2.xml	Thu Aug 21 19:18:27 2008
@@ -10,14 +10,11 @@
 		</layout>
 	</appender>
 
-	<logger name="chapter3">
-		<level value="INFO" />
-	</logger>
+	<logger name="chapter3" level="INFO" />
 
-	<root>
-		<!-- The following level element is not necessary since the -->
-		<!-- level of the root level is set to DEBUG by default.    -->
-		<level value="DEBUG" />
+	<!-- Strictly speaking, the level attribute is not necessary since -->
+	<!-- the level of the root level is set to DEBUG by default.       -->
+	<root level="DEBUG">
 		<appender-ref ref="STDOUT" />
 	</root>
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/sample3.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/sample3.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/sample3.xml	Thu Aug 21 19:18:27 2008
@@ -10,18 +10,11 @@
 		</layout>
 	</appender>
 
-	<logger name="chapter3">
-		<level value="INFO" />
-	</logger>
+	<logger name="chapter3" level="INFO" />
 
-	<logger name="chapter3.Foo">
-		<level value="DEBUG" />
-	</logger>
+	<logger name="chapter3.Foo" level="DEBUG" />
 
-	<root>
-		<!-- The following level element is not necessary since the -->
-		<!-- level of the root level is set to DEBUG by default.    -->
-		<level value="DEBUG" />
+	<root level="DEBUG">
 		<appender-ref ref="STDOUT" />
 	</root>
 

Modified: logback/trunk/logback-examples/src/main/java/chapter3/sample4.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter3/sample4.xml	(original)
+++ logback/trunk/logback-examples/src/main/java/chapter3/sample4.xml	Thu Aug 21 19:18:27 2008
@@ -10,12 +10,9 @@
 		</layout>
 	</appender>
 
-	<logger name="chapter3">
-		<level value="INFO" />
-	</logger>
+	<logger name="chapter3" level="INFO" />
 
-	<root>
-		<level value="OFF" />
+	<root level="OFF">
 		<appender-ref ref="STDOUT" />
 	</root>
 

Modified: logback/trunk/logback-site/src/site/pages/ghighlighter/Styles/SyntaxHighlighter.css
==============================================================================
--- logback/trunk/logback-site/src/site/pages/ghighlighter/Styles/SyntaxHighlighter.css	(original)
+++ logback/trunk/logback-site/src/site/pages/ghighlighter/Styles/SyntaxHighlighter.css	Thu Aug 21 19:18:27 2008
@@ -182,4 +182,6 @@
 .dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; }
 .dp-highlighter .string { color: blue; background-color: inherit; }
 .dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; }
+.dp-highlighter .more { font-weight: bolder;  }
+.dp-highlighter .less { font-weight: lighter; }
 .dp-highlighter .preprocessor { color: gray; background-color: inherit; }

Modified: logback/trunk/logback-site/src/site/pages/ghighlighter/js/shBrushJava.js
==============================================================================
--- logback/trunk/logback-site/src/site/pages/ghighlighter/js/shBrushJava.js	(original)
+++ logback/trunk/logback-site/src/site/pages/ghighlighter/js/shBrushJava.js	Thu Aug 21 19:18:27 2008
@@ -1,10 +1,30 @@
-/*
- * JsMin
- * Javascript Compressor
- * http://www.crockford.com/
- * http://www.smallsharptools.com/
-*/
+dp.sh.Brushes.Java = function()
+{
+	var keywords =	'abstract assert boolean break byte case catch char class const ' +
+			'continue default do double else enum extends ' +
+			'false final finally float for goto if implements import ' +
+			'instanceof int interface long native new null ' +
+			'package private protected public return ' +
+			'short static strictfp super switch synchronized this throw throws true ' +
+			'transient try void volatile while';
 
-dp.sh.Brushes.Java=function()
-{var keywords='abstract assert boolean break byte case catch char class const '+'continue default do double else enum extends '+'false final finally float for goto if implements import '+'instanceof int interface long native new null '+'package private protected public return '+'short static strictfp super switch synchronized this throw throws true '+'transient try void volatile while';this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:'comment'},{regex:dp.sh.RegexLib.MultiLineCComments,css:'comment'},{regex:dp.sh.RegexLib.DoubleQuotedString,css:'string'},{regex:dp.sh.RegexLib.SingleQuotedString,css:'string'},{regex:new RegExp('\\b([\\d]+(\\.[\\d]+)?|0x[a-f0-9]+)\\b','gi'),css:'number'},{regex:new RegExp('(?!\\@interface\\b)\\@[\\$\\w]+\\b','g'),css:'annotation'},{regex:new RegExp('\\@interface\\b','g'),css:'keyword'},{regex:new RegExp(this.GetKeywords(keywords),'gm'),css:'keyword'}];this.CssClass='dp-j';this.Style='.dp-j .annotation { color: #646464; }'+'.dp-j .n
 umber { color: #C00000; }';}
-dp.sh.Brushes.Java.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Java.Aliases=['java'];
+	this.regexList = [
+		{ regex: dp.sh.RegexLib.SingleLineCComments,							css: 'comment' },		// one line comments
+		{ regex: dp.sh.RegexLib.MultiLineCComments,								css: 'comment' },		// multiline comments
+		{ regex: dp.sh.RegexLib.DoubleQuotedString,								css: 'string' },		// strings
+		{ regex: dp.sh.RegexLib.SingleQuotedString,								css: 'string' },		// strings
+		{ regex: new RegExp('\\b([\\d]+(\\.[\\d]+)?|0x[a-f0-9]+)\\b', 'gi'),	css: 'number' },		// numbers
+		{ regex: new RegExp('(?!\\@interface\\b)\\@[\\$\\w]+\\b', 'g'),			css: 'annotation' },	// annotation @anno
+		{ regex: new RegExp('\\@interface\\b', 'g'),							css: 'keyword' },		// @interface keyword
+		{ regex: new RegExp('<b>.*</b>', 'g'),							css: 'more' },		// @interface keyword
+  
+		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),					css: 'keyword' }		// java keyword
+		];
+
+	this.CssClass = 'dp-j';
+	this.Style =	'.dp-j .annotation { color: #646464; }' +
+					'.dp-j .number { color: #C00000; }';
+}
+
+dp.sh.Brushes.Java.prototype	= new dp.sh.Highlighter();
+dp.sh.Brushes.Java.Aliases	= ['java'];

Modified: logback/trunk/logback-site/src/site/pages/ghighlighter/js/shCore.js
==============================================================================
--- logback/trunk/logback-site/src/site/pages/ghighlighter/js/shCore.js	(original)
+++ logback/trunk/logback-site/src/site/pages/ghighlighter/js/shCore.js	Thu Aug 21 19:18:27 2008
@@ -1,161 +1,705 @@
-/*
- * JsMin
- * Javascript Compressor
- * http://www.crockford.com/
- * http://www.smallsharptools.com/
-*/
-
-var dp={sh:{Toolbar:{},Utils:{},RegexLib:{},Brushes:{},Strings:{AboutDialog:'<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/syntaxhighlighter</a></p>&copy;2004-2007 Alex Gorbatchev.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>'},ClipboardSwf:null,Version:'1.5.1'}};dp.SyntaxHighlighter=dp.sh;dp.sh.Toolbar.Commands={ExpandSource:{label:'+ expand source',check:function(highlighter){return highlighter.collapse;},func:function(sender,highlighter)
-{sender.parentNode.removeChild(sender);highlighter.div.className=highlighter.div.className.replace('collapsed','');}},ViewSource:{label:'view plain',func:function(sender,highlighter)
-{var code=dp.sh.Utils.FixForBlogger(highlighter.originalCode).replace(/</g,'&lt;');var wnd=window.open('','_blank','width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=0');wnd.document.write('<textarea style="width:99%;height:99%">'+code+'</textarea>');wnd.document.close();}},CopyToClipboard:{label:'copy to clipboard',check:function(){return window.clipboardData!=null||dp.sh.ClipboardSwf!=null;},func:function(sender,highlighter)
-{var code=dp.sh.Utils.FixForBlogger(highlighter.originalCode).replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');if(window.clipboardData)
-{window.clipboardData.setData('text',code);}
-else if(dp.sh.ClipboardSwf!=null)
-{var flashcopier=highlighter.flashCopier;if(flashcopier==null)
-{flashcopier=document.createElement('div');highlighter.flashCopier=flashcopier;highlighter.div.appendChild(flashcopier);}
-flashcopier.innerHTML='<embed src="'+dp.sh.ClipboardSwf+'" FlashVars="clipboard='+encodeURIComponent(code)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';}
-alert('The code is in your clipboard now');}},PrintSource:{label:'print',func:function(sender,highlighter)
-{var iframe=document.createElement('IFRAME');var doc=null;iframe.style.cssText='position:absolute;width:0px;height:0px;left:-500px;top:-500px;';document.body.appendChild(iframe);doc=iframe.contentWindow.document;dp.sh.Utils.CopyStyles(doc,window.document);doc.write('<div class="'+highlighter.div.className.replace('collapsed','')+' printing">'+highlighter.div.innerHTML+'</div>');doc.close();iframe.contentWindow.focus();iframe.contentWindow.print();alert('Printing...');document.body.removeChild(iframe);}},About:{label:'?',func:function(highlighter)
-{var wnd=window.open('','_blank','dialog,width=300,height=150,scrollbars=0');var doc=wnd.document;dp.sh.Utils.CopyStyles(doc,window.document);doc.write(dp.sh.Strings.AboutDialog.replace('{V}',dp.sh.Version));doc.close();wnd.focus();}}};dp.sh.Toolbar.Create=function(highlighter)
-{var div=document.createElement('DIV');div.className='tools';for(var name in dp.sh.Toolbar.Commands)
-{var cmd=dp.sh.Toolbar.Commands[name];if(cmd.check!=null&&!cmd.check(highlighter))
-continue;div.innerHTML+='<a href="#" onclick="dp.sh.Toolbar.Command(\''+name+'\',this);return false;">'+cmd.label+'</a>';}
-return div;}
-dp.sh.Toolbar.Command=function(name,sender)
-{var n=sender;while(n!=null&&n.className.indexOf('dp-highlighter')==-1)
-n=n.parentNode;if(n!=null)
-dp.sh.Toolbar.Commands[name].func(sender,n.highlighter);}
-dp.sh.Utils.CopyStyles=function(destDoc,sourceDoc)
-{var links=sourceDoc.getElementsByTagName('link');for(var i=0;i<links.length;i++)
-if(links[i].rel.toLowerCase()=='stylesheet')
-destDoc.write('<link type="text/css" rel="stylesheet" href="'+links[i].href+'"></link>');}
-dp.sh.Utils.FixForBlogger=function(str)
-{return(dp.sh.isBloggerMode==true)?str.replace(/<br\s*\/?>|&lt;br\s*\/?&gt;/gi,'\n'):str;}
-dp.sh.RegexLib={MultiLineCComments:new RegExp('/\\*[\\s\\S]*?\\*/','gm'),SingleLineCComments:new RegExp('//.*$','gm'),SingleLinePerlComments:new RegExp('#.*$','gm'),DoubleQuotedString:new RegExp('"(?:\\.|(\\\\\\")|[^\\""\\n])*"','g'),SingleQuotedString:new RegExp("'(?:\\.|(\\\\\\')|[^\\''\\n])*'",'g')};dp.sh.Match=function(value,index,css)
-{this.value=value;this.index=index;this.length=value.length;this.css=css;}
-dp.sh.Highlighter=function()
-{this.noGutter=false;this.addControls=true;this.collapse=false;this.tabsToSpaces=true;this.wrapColumn=80;this.showColumns=true;}
-dp.sh.Highlighter.SortCallback=function(m1,m2)
-{if(m1.index<m2.index)
-return-1;else if(m1.index>m2.index)
-return 1;else
-{if(m1.length<m2.length)
-return-1;else if(m1.length>m2.length)
-return 1;}
-return 0;}
-dp.sh.Highlighter.prototype.CreateElement=function(name)
-{var result=document.createElement(name);result.highlighter=this;return result;}
-dp.sh.Highlighter.prototype.GetMatches=function(regex,css)
-{var index=0;var match=null;while((match=regex.exec(this.code))!=null)
-this.matches[this.matches.length]=new dp.sh.Match(match[0],match.index,css);}
-dp.sh.Highlighter.prototype.AddBit=function(str,css)
-{if(str==null||str.length==0)
-return;var span=this.CreateElement('SPAN');str=str.replace(/ /g,'&nbsp;');str=str.replace(/</g,'&lt;');str=str.replace(/\n/gm,'&nbsp;<br>');if(css!=null)
-{if((/br/gi).test(str))
-{var lines=str.split('&nbsp;<br>');for(var i=0;i<lines.length;i++)
-{span=this.CreateElement('SPAN');span.className=css;span.innerHTML=lines[i];this.div.appendChild(span);if(i+1<lines.length)
-this.div.appendChild(this.CreateElement('BR'));}}
-else
-{span.className=css;span.innerHTML=str;this.div.appendChild(span);}}
-else
-{span.innerHTML=str;this.div.appendChild(span);}}
-dp.sh.Highlighter.prototype.IsInside=function(match)
-{if(match==null||match.length==0)
-return false;for(var i=0;i<this.matches.length;i++)
-{var c=this.matches[i];if(c==null)
-continue;if((match.index>c.index)&&(match.index<c.index+c.length))
-return true;}
-return false;}
-dp.sh.Highlighter.prototype.ProcessRegexList=function()
-{for(var i=0;i<this.regexList.length;i++)
-this.GetMatches(this.regexList[i].regex,this.regexList[i].css);}
-dp.sh.Highlighter.prototype.ProcessSmartTabs=function(code)
-{var lines=code.split('\n');var result='';var tabSize=4;var tab='\t';function InsertSpaces(line,pos,count)
-{var left=line.substr(0,pos);var right=line.substr(pos+1,line.length);var spaces='';for(var i=0;i<count;i++)
-spaces+=' ';return left+spaces+right;}
-function ProcessLine(line,tabSize)
-{if(line.indexOf(tab)==-1)
-return line;var pos=0;while((pos=line.indexOf(tab))!=-1)
-{var spaces=tabSize-pos%tabSize;line=InsertSpaces(line,pos,spaces);}
-return line;}
-for(var i=0;i<lines.length;i++)
-result+=ProcessLine(lines[i],tabSize)+'\n';return result;}
-dp.sh.Highlighter.prototype.SwitchToList=function()
-{var html=this.div.innerHTML.replace(/<(br)\/?>/gi,'\n');var lines=html.split('\n');if(this.addControls==true)
-this.bar.appendChild(dp.sh.Toolbar.Create(this));if(this.showColumns)
-{var div=this.CreateElement('div');var columns=this.CreateElement('div');var showEvery=10;var i=1;while(i<=150)
-{if(i%showEvery==0)
-{div.innerHTML+=i;i+=(i+'').length;}
-else
-{div.innerHTML+='&middot;';i++;}}
-columns.className='columns';columns.appendChild(div);this.bar.appendChild(columns);}
-for(var i=0,lineIndex=this.firstLine;i<lines.length-1;i++,lineIndex++)
-{var li=this.CreateElement('LI');var span=this.CreateElement('SPAN');li.className=(i%2==0)?'alt':'';span.innerHTML=lines[i]+'&nbsp;';li.appendChild(span);this.ol.appendChild(li);}
-this.div.innerHTML='';}
-dp.sh.Highlighter.prototype.Highlight=function(code)
-{function Trim(str)
-{return str.replace(/^\s*(.*?)[\s\n]*$/g,'$1');}
-function Chop(str)
-{return str.replace(/\n*$/,'').replace(/^\n*/,'');}
-function Unindent(str)
-{var lines=dp.sh.Utils.FixForBlogger(str).split('\n');var indents=new Array();var regex=new RegExp('^\\s*','g');var min=1000;for(var i=0;i<lines.length&&min>0;i++)
-{if(Trim(lines[i]).length==0)
-continue;var matches=regex.exec(lines[i]);if(matches!=null&&matches.length>0)
-min=Math.min(matches[0].length,min);}
-if(min>0)
-for(var i=0;i<lines.length;i++)
-lines[i]=lines[i].substr(min);return lines.join('\n');}
-function Copy(string,pos1,pos2)
-{return string.substr(pos1,pos2-pos1);}
-var pos=0;if(code==null)
-code='';this.originalCode=code;this.code=Chop(Unindent(code));this.div=this.CreateElement('DIV');this.bar=this.CreateElement('DIV');this.ol=this.CreateElement('OL');this.matches=new Array();this.div.className='dp-highlighter';this.div.highlighter=this;this.bar.className='bar';this.ol.start=this.firstLine;if(this.CssClass!=null)
-this.ol.className=this.CssClass;if(this.collapse)
-this.div.className+=' collapsed';if(this.noGutter)
-this.div.className+=' nogutter';if(this.tabsToSpaces==true)
-this.code=this.ProcessSmartTabs(this.code);this.ProcessRegexList();if(this.matches.length==0)
-{this.AddBit(this.code,null);this.SwitchToList();this.div.appendChild(this.bar);this.div.appendChild(this.ol);return;}
-this.matches=this.matches.sort(dp.sh.Highlighter.SortCallback);for(var i=0;i<this.matches.length;i++)
-if(this.IsInside(this.matches[i]))
-this.matches[i]=null;for(var i=0;i<this.matches.length;i++)
-{var match=this.matches[i];if(match==null||match.length==0)
-continue;this.AddBit(Copy(this.code,pos,match.index),null);this.AddBit(match.value,match.css);pos=match.index+match.length;}
-this.AddBit(this.code.substr(pos),null);this.SwitchToList();this.div.appendChild(this.bar);this.div.appendChild(this.ol);}
-dp.sh.Highlighter.prototype.GetKeywords=function(str)
-{return'\\b'+str.replace(/ /g,'\\b|\\b')+'\\b';}
-dp.sh.BloggerMode=function()
-{dp.sh.isBloggerMode=true;}
-dp.sh.HighlightAll=function(name,showGutter,showControls,collapseAll,firstLine,showColumns)
-{function FindValue()
-{var a=arguments;for(var i=0;i<a.length;i++)
-{if(a[i]==null)
-continue;if(typeof(a[i])=='string'&&a[i]!='')
-return a[i]+'';if(typeof(a[i])=='object'&&a[i].value!='')
-return a[i].value+'';}
-return null;}
-function IsOptionSet(value,list)
-{for(var i=0;i<list.length;i++)
-if(list[i]==value)
-return true;return false;}
-function GetOptionValue(name,list,defaultValue)
-{var regex=new RegExp('^'+name+'\\[(\\w+)\\]$','gi');var matches=null;for(var i=0;i<list.length;i++)
-if((matches=regex.exec(list[i]))!=null)
-return matches[1];return defaultValue;}
-function FindTagsByName(list,name,tagName)
-{var tags=document.getElementsByTagName(tagName);for(var i=0;i<tags.length;i++)
-if(tags[i].getAttribute('name')==name)
-list.push(tags[i]);}
-var elements=[];var highlighter=null;var registered={};var propertyName='innerHTML';FindTagsByName(elements,name,'pre');FindTagsByName(elements,name,'textarea');if(elements.length==0)
-return;for(var brush in dp.sh.Brushes)
-{var aliases=dp.sh.Brushes[brush].Aliases;if(aliases==null)
-continue;for(var i=0;i<aliases.length;i++)
-registered[aliases[i]]=brush;}
-for(var i=0;i<elements.length;i++)
-{var element=elements[i];var options=FindValue(element.attributes['class'],element.className,element.attributes['language'],element.language);var language='';if(options==null)
-continue;options=options.split(':');language=options[0].toLowerCase();if(registered[language]==null)
-continue;highlighter=new dp.sh.Brushes[registered[language]]();element.style.display='none';highlighter.noGutter=(showGutter==null)?IsOptionSet('nogutter',options):!showGutter;highlighter.addControls=(showControls==null)?!IsOptionSet('nocontrols',options):showControls;highlighter.collapse=(collapseAll==null)?IsOptionSet('collapse',options):collapseAll;highlighter.showColumns=(showColumns==null)?IsOptionSet('showcolumns',options):showColumns;var headNode=document.getElementsByTagName('head')[0];if(highlighter.Style&&headNode)
-{var styleNode=document.createElement('style');styleNode.setAttribute('type','text/css');if(styleNode.styleSheet)
-{styleNode.styleSheet.cssText=highlighter.Style;}
-else
-{var textNode=document.createTextNode(highlighter.Style);styleNode.appendChild(textNode);}
-headNode.appendChild(styleNode);}
-highlighter.firstLine=(firstLine==null)?parseInt(GetOptionValue('firstline',options,1)):firstLine;highlighter.Highlight(element[propertyName]);highlighter.source=element;element.parentNode.insertBefore(highlighter.div,element);}}
+/**
+ * Code Syntax Highlighter.
+ * Version 1.5.1
+ * Copyright (C) 2004-2007 Alex Gorbatchev.
+ * http://www.dreamprojections.com/syntaxhighlighter/
+ * 
+ * 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; either version 2.1 of the License, or (at your option) 
+ * any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+//
+// create namespaces
+//
+var dp = {
+	sh :
+	{
+		Toolbar : {},
+		Utils	: {},
+		RegexLib: {},
+		Brushes	: {},
+		Strings : {
+			AboutDialog : '<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/syntaxhighlighter</a></p>&copy;2004-2007 Alex Gorbatchev.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>'
+		},
+		ClipboardSwf : null,
+		Version : '1.5.1'
+	}
+};
+
+// make an alias
+dp.SyntaxHighlighter = dp.sh;
+
+//
+// Toolbar functions
+//
+
+dp.sh.Toolbar.Commands = {
+	ExpandSource: {
+		label: '+ expand source',
+		check: function(highlighter) { return highlighter.collapse; },
+		func: function(sender, highlighter)
+		{
+			sender.parentNode.removeChild(sender);
+			highlighter.div.className = highlighter.div.className.replace('collapsed', '');
+		}
+	},
+	
+	// opens a new windows and puts the original unformatted source code inside.
+	ViewSource: {
+		label: 'view plain',
+		func: function(sender, highlighter)
+		{
+			var code = dp.sh.Utils.FixForBlogger(highlighter.originalCode).replace(/</g, '&lt;');
+			var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=0');
+			wnd.document.write('<textarea style="width:99%;height:99%">' + code + '</textarea>');
+			wnd.document.close();
+		}
+	},
+	
+	// Copies the original source code in to the clipboard. Uses either IE only method or Flash object if ClipboardSwf is set
+	CopyToClipboard: {
+		label: 'copy to clipboard',
+		check: function() { return window.clipboardData != null || dp.sh.ClipboardSwf != null; },
+		func: function(sender, highlighter)
+		{
+			var code = dp.sh.Utils.FixForBlogger(highlighter.originalCode)
+				.replace(/&lt;/g,'<')
+				.replace(/&gt;/g,'>')
+				.replace(/&amp;/g,'&')
+			;
+			
+			if(window.clipboardData)
+			{
+				window.clipboardData.setData('text', code);
+			}
+			else if(dp.sh.ClipboardSwf != null)
+			{
+				var flashcopier = highlighter.flashCopier;
+				
+				if(flashcopier == null)
+				{
+					flashcopier = document.createElement('div');
+					highlighter.flashCopier = flashcopier;
+					highlighter.div.appendChild(flashcopier);
+				}
+				
+				flashcopier.innerHTML = '<embed src="' + dp.sh.ClipboardSwf + '" FlashVars="clipboard='+encodeURIComponent(code)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
+			}
+			
+			alert('The code is in your clipboard now');
+		}
+	},
+	
+	// creates an invisible iframe, puts the original source code inside and prints it
+	PrintSource: {
+		label: 'print',
+		func: function(sender, highlighter)
+		{
+			var iframe = document.createElement('IFRAME');
+			var doc = null;
+
+			// this hides the iframe
+			iframe.style.cssText = 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;';
+			
+			document.body.appendChild(iframe);
+			doc = iframe.contentWindow.document;
+
+			dp.sh.Utils.CopyStyles(doc, window.document);
+			doc.write('<div class="' + highlighter.div.className.replace('collapsed', '') + ' printing">' + highlighter.div.innerHTML + '</div>');
+			doc.close();
+
+			iframe.contentWindow.focus();
+			iframe.contentWindow.print();
+			
+			alert('Printing...');
+			
+			document.body.removeChild(iframe);
+		}
+	},
+	
+	About: {
+		label: '?',
+		func: function(highlighter)
+		{
+			var wnd	= window.open('', '_blank', 'dialog,width=300,height=150,scrollbars=0');
+			var doc	= wnd.document;
+
+			dp.sh.Utils.CopyStyles(doc, window.document);
+			
+			doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
+			doc.close();
+			wnd.focus();
+		}
+	}
+};
+
+// creates a <div /> with all toolbar links
+dp.sh.Toolbar.Create = function(highlighter)
+{
+	var div = document.createElement('DIV');
+	
+	div.className = 'tools';
+	
+	for(var name in dp.sh.Toolbar.Commands)
+	{
+		var cmd = dp.sh.Toolbar.Commands[name];
+		
+		if(cmd.check != null && !cmd.check(highlighter))
+			continue;
+		
+		div.innerHTML += '<a href="#" onclick="dp.sh.Toolbar.Command(\'' + name + '\',this);return false;">' + cmd.label + '</a>';
+	}
+	
+	return div;
+}
+
+// executes toolbar command by name
+dp.sh.Toolbar.Command = function(name, sender)
+{
+	var n = sender;
+	
+	while(n != null && n.className.indexOf('dp-highlighter') == -1)
+		n = n.parentNode;
+	
+	if(n != null)
+		dp.sh.Toolbar.Commands[name].func(sender, n.highlighter);
+}
+
+// copies all <link rel="stylesheet" /> from 'target' window to 'dest'
+dp.sh.Utils.CopyStyles = function(destDoc, sourceDoc)
+{
+	var links = sourceDoc.getElementsByTagName('link');
+
+	for(var i = 0; i < links.length; i++)
+		if(links[i].rel.toLowerCase() == 'stylesheet')
+			destDoc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
+}
+
+dp.sh.Utils.FixForBlogger = function(str)
+{
+	return (dp.sh.isBloggerMode == true) ? str.replace(/<br\s*\/?>|&lt;br\s*\/?&gt;/gi, '\n') : str;
+}
+
+//
+// Common reusable regular expressions
+//
+dp.sh.RegexLib = {
+	MultiLineCComments : new RegExp('/\\*[\\s\\S]*?\\*/', 'gm'),
+	SingleLineCComments : new RegExp('//.*$', 'gm'),
+	SingleLinePerlComments : new RegExp('#.*$', 'gm'),
+	DoubleQuotedString : new RegExp('"(?:\\.|(\\\\\\")|[^\\""\\n])*"','g'),
+	SingleQuotedString : new RegExp("'(?:\\.|(\\\\\\')|[^\\''\\n])*'", 'g')
+};
+
+//
+// Match object
+//
+dp.sh.Match = function(value, index, css)
+{
+	this.value = value;
+	this.index = index;
+	this.length = value.length;
+	this.css = css;
+}
+
+//
+// Highlighter object
+//
+dp.sh.Highlighter = function()
+{
+	this.noGutter = false;
+	this.addControls = true;
+	this.collapse = false;
+	this.tabsToSpaces = true;
+	this.wrapColumn = 80;
+	this.showColumns = true;
+}
+
+// static callback for the match sorting
+dp.sh.Highlighter.SortCallback = function(m1, m2)
+{
+	// sort matches by index first
+	if(m1.index < m2.index)
+		return -1;
+	else if(m1.index > m2.index)
+		return 1;
+	else
+	{
+		// if index is the same, sort by length
+		if(m1.length < m2.length)
+			return -1;
+		else if(m1.length > m2.length)
+			return 1;
+	}
+	return 0;
+}
+
+dp.sh.Highlighter.prototype.CreateElement = function(name)
+{
+	var result = document.createElement(name);
+	result.highlighter = this;
+	return result;
+}
+
+// gets a list of all matches for a given regular expression
+dp.sh.Highlighter.prototype.GetMatches = function(regex, css)
+{
+	var index = 0;
+	var match = null;
+
+	while((match = regex.exec(this.code)) != null)
+		this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css);
+}
+
+dp.sh.Highlighter.prototype.AddBit = function(str, css)
+{
+	if(str == null || str.length == 0)
+		return;
+
+	var span = this.CreateElement('SPAN');
+	
+//	str = str.replace(/&/g, '&amp;');
+	str = str.replace(/ /g, '&nbsp;');
+	str = str.replace(/</g, '&lt;');
+//	str = str.replace(/&lt;/g, '<');
+//	str = str.replace(/>/g, '&gt;');
+	str = str.replace(/\n/gm, '&nbsp;<br>');
+
+	// when adding a piece of code, check to see if it has line breaks in it 
+	// and if it does, wrap individual line breaks with span tags
+	if(css != null)
+	{
+		if((/br/gi).test(str))
+		{
+			var lines = str.split('&nbsp;<br>');
+			
+			for(var i = 0; i < lines.length; i++)
+			{
+				span = this.CreateElement('SPAN');
+				span.className = css;
+				span.innerHTML = lines[i];
+				
+				this.div.appendChild(span);
+				
+				// don't add a <BR> for the last line
+				if(i + 1 < lines.length)
+					this.div.appendChild(this.CreateElement('BR'));
+			}
+		}
+		else
+		{
+			span.className = css;
+			span.innerHTML = str;
+			this.div.appendChild(span);
+		}
+	}
+	else
+	{
+		span.innerHTML = str;
+		this.div.appendChild(span);
+	}
+}
+
+// checks if one match is inside any other match
+dp.sh.Highlighter.prototype.IsInside = function(match)
+{
+	if(match == null || match.length == 0)
+		return false;
+	
+	for(var i = 0; i < this.matches.length; i++)
+	{
+		var c = this.matches[i];
+		
+		if(c == null)
+			continue;
+
+		if((match.index > c.index) && (match.index < c.index + c.length))
+			return true;
+	}
+	
+	return false;
+}
+
+dp.sh.Highlighter.prototype.ProcessRegexList = function()
+{
+	for(var i = 0; i < this.regexList.length; i++)
+		this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
+}
+
+dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code)
+{
+	var lines	= code.split('\n');
+	var result	= '';
+	var tabSize	= 4;
+	var tab		= '\t';
+
+	// This function inserts specified amount of spaces in the string
+	// where a tab is while removing that given tab. 
+	function InsertSpaces(line, pos, count)
+	{
+		var left	= line.substr(0, pos);
+		var right	= line.substr(pos + 1, line.length);	// pos + 1 will get rid of the tab
+		var spaces	= '';
+		
+		for(var i = 0; i < count; i++)
+			spaces += ' ';
+		
+		return left + spaces + right;
+	}
+
+	// This function process one line for 'smart tabs'
+	function ProcessLine(line, tabSize)
+	{
+		if(line.indexOf(tab) == -1)
+			return line;
+
+		var pos = 0;
+
+		while((pos = line.indexOf(tab)) != -1)
+		{
+			// This is pretty much all there is to the 'smart tabs' logic.
+			// Based on the position within the line and size of a tab, 
+			// calculate the amount of spaces we need to insert.
+			var spaces = tabSize - pos % tabSize;
+			
+			line = InsertSpaces(line, pos, spaces);
+		}
+		
+		return line;
+	}
+
+	// Go through all the lines and do the 'smart tabs' magic.
+	for(var i = 0; i < lines.length; i++)
+		result += ProcessLine(lines[i], tabSize) + '\n';
+	
+	return result;
+}
+
+dp.sh.Highlighter.prototype.SwitchToList = function()
+{
+	// thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
+	var html = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n');
+	var lines = html.split('\n');
+	
+	if(this.addControls == true)
+		this.bar.appendChild(dp.sh.Toolbar.Create(this));
+
+	// add columns ruler
+	if(this.showColumns)
+	{
+		var div = this.CreateElement('div');
+		var columns = this.CreateElement('div');
+		var showEvery = 10;
+		var i = 1;
+		
+		while(i <= 150)
+		{
+			if(i % showEvery == 0)
+			{
+				div.innerHTML += i;
+				i += (i + '').length;
+			}
+			else
+			{
+				div.innerHTML += '&middot;';
+				i++;
+			}
+		}
+		
+		columns.className = 'columns';
+		columns.appendChild(div);
+		this.bar.appendChild(columns);
+	}
+
+	for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++)
+	{
+		var li = this.CreateElement('LI');
+		var span = this.CreateElement('SPAN');
+		
+		// uses .line1 and .line2 css styles for alternating lines
+		li.className = (i % 2 == 0) ? 'alt' : '';
+		span.innerHTML = lines[i] + '&nbsp;';
+
+		li.appendChild(span);
+		this.ol.appendChild(li);
+	}
+	
+	this.div.innerHTML	= '';
+}
+
+dp.sh.Highlighter.prototype.Highlight = function(code)
+{
+	function Trim(str)
+	{
+		return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
+	}
+	
+	function Chop(str)
+	{
+		return str.replace(/\n*$/, '').replace(/^\n*/, '');
+	}
+
+	function Unindent(str)
+	{
+		var lines = dp.sh.Utils.FixForBlogger(str).split('\n');
+		var indents = new Array();
+		var regex = new RegExp('^\\s*', 'g');
+		var min = 1000;
+
+		// go through every line and check for common number of indents
+		for(var i = 0; i < lines.length && min > 0; i++)
+		{
+			if(Trim(lines[i]).length == 0)
+				continue;
+				
+			var matches = regex.exec(lines[i]);
+
+			if(matches != null && matches.length > 0)
+				min = Math.min(matches[0].length, min);
+		}
+
+		// trim minimum common number of white space from the begining of every line
+		if(min > 0)
+			for(var i = 0; i < lines.length; i++)
+				lines[i] = lines[i].substr(min);
+
+		return lines.join('\n');
+	}
+	
+	// This function returns a portions of the string from pos1 to pos2 inclusive
+	function Copy(string, pos1, pos2)
+	{
+		return string.substr(pos1, pos2 - pos1);
+	}
+
+	var pos	= 0;
+	
+	if(code == null)
+		code = '';
+	
+	this.originalCode = code;
+	this.code = Chop(Unindent(code));
+	this.div = this.CreateElement('DIV');
+	this.bar = this.CreateElement('DIV');
+	this.ol = this.CreateElement('OL');
+	this.matches = new Array();
+
+	this.div.className = 'dp-highlighter';
+	this.div.highlighter = this;
+	
+	this.bar.className = 'bar';
+	
+	// set the first line
+	this.ol.start = this.firstLine;
+
+	if(this.CssClass != null)
+		this.ol.className = this.CssClass;
+
+	if(this.collapse)
+		this.div.className += ' collapsed';
+	
+	if(this.noGutter)
+		this.div.className += ' nogutter';
+
+	// replace tabs with spaces
+	if(this.tabsToSpaces == true)
+		this.code = this.ProcessSmartTabs(this.code);
+
+	this.ProcessRegexList();	
+
+	// if no matches found, add entire code as plain text
+	if(this.matches.length == 0)
+	{
+		this.AddBit(this.code, null);
+		this.SwitchToList();
+		this.div.appendChild(this.bar);
+		this.div.appendChild(this.ol);
+		return;
+	}
+
+	// sort the matches
+	this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback);
+
+	// The following loop checks to see if any of the matches are inside
+	// of other matches. This process would get rid of highligted strings
+	// inside comments, keywords inside strings and so on.
+	for(var i = 0; i < this.matches.length; i++)
+		if(this.IsInside(this.matches[i]))
+			this.matches[i] = null;
+
+	// Finally, go through the final list of matches and pull the all
+	// together adding everything in between that isn't a match.
+	for(var i = 0; i < this.matches.length; i++)
+	{
+		var match = this.matches[i];
+
+		if(match == null || match.length == 0)
+			continue;
+
+		this.AddBit(Copy(this.code, pos, match.index), null);
+		this.AddBit(match.value, match.css);
+
+		pos = match.index + match.length;
+	}
+	
+	this.AddBit(this.code.substr(pos), null);
+
+	this.SwitchToList();
+	this.div.appendChild(this.bar);
+	this.div.appendChild(this.ol);
+}
+
+dp.sh.Highlighter.prototype.GetKeywords = function(str) 
+{
+	return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
+}
+
+dp.sh.BloggerMode = function()
+{
+	dp.sh.isBloggerMode = true;
+}
+
+// highlightes all elements identified by name and gets source code from specified property
+dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */, showColumns /* optional */)
+{
+	function FindValue()
+	{
+		var a = arguments;
+		
+		for(var i = 0; i < a.length; i++)
+		{
+			if(a[i] == null)
+				continue;
+				
+			if(typeof(a[i]) == 'string' && a[i] != '')
+				return a[i] + '';
+		
+			if(typeof(a[i]) == 'object' && a[i].value != '')
+				return a[i].value + '';
+		}
+		
+		return null;
+	}
+	
+	function IsOptionSet(value, list)
+	{
+		for(var i = 0; i < list.length; i++)
+			if(list[i] == value)
+				return true;
+		
+		return false;
+	}
+	
+	function GetOptionValue(name, list, defaultValue)
+	{
+		var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
+		var matches = null;
+
+		for(var i = 0; i < list.length; i++)
+			if((matches = regex.exec(list[i])) != null)
+				return matches[1];
+		
+		return defaultValue;
+	}
+	
+	function FindTagsByName(list, name, tagName)
+	{
+		var tags = document.getElementsByTagName(tagName);
+
+		for(var i = 0; i < tags.length; i++)
+			if(tags[i].getAttribute('name') == name)
+				list.push(tags[i]);
+	}
+
+	var elements = [];
+	var highlighter = null;
+	var registered = {};
+	var propertyName = 'innerHTML';
+
+	// for some reason IE doesn't find <pre/> by name, however it does see them just fine by tag name... 
+	FindTagsByName(elements, name, 'pre');
+	FindTagsByName(elements, name, 'textarea');
+
+	if(elements.length == 0)
+		return;
+
+	// register all brushes
+	for(var brush in dp.sh.Brushes)
+	{
+		var aliases = dp.sh.Brushes[brush].Aliases;
+
+		if(aliases == null)
+			continue;
+		
+		for(var i = 0; i < aliases.length; i++)
+			registered[aliases[i]] = brush;
+	}
+
+	for(var i = 0; i < elements.length; i++)
+	{
+		var element = elements[i];
+		var options = FindValue(
+				element.attributes['class'], element.className, 
+				element.attributes['language'], element.language
+				);
+		var language = '';
+		
+		if(options == null)
+			continue;
+		
+		options = options.split(':');
+		
+		language = options[0].toLowerCase();
+
+		if(registered[language] == null)
+			continue;
+		
+		// instantiate a brush
+		highlighter = new dp.sh.Brushes[registered[language]]();
+		
+		// hide the original element
+		element.style.display = 'none';
+
+		highlighter.noGutter = (showGutter == null) ? IsOptionSet('nogutter', options) : !showGutter;
+		highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
+		highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
+		highlighter.showColumns = (showColumns == null) ? IsOptionSet('showcolumns', options) : showColumns;
+
+		// write out custom brush style
+		var headNode = document.getElementsByTagName('head')[0];
+		if(highlighter.Style && headNode)
+		{
+			var styleNode = document.createElement('style');
+			styleNode.setAttribute('type', 'text/css');
+
+			if(styleNode.styleSheet) // for IE
+			{
+				styleNode.styleSheet.cssText = highlighter.Style;
+			}
+			else // for everyone else
+			{
+				var textNode = document.createTextNode(highlighter.Style);
+				styleNode.appendChild(textNode);
+			}
+
+			headNode.appendChild(styleNode);
+		}
+		
+		// first line idea comes from Andrew Collington, thanks!
+		highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;
+
+		highlighter.Highlight(element[propertyName]);
+		
+		highlighter.source = element;
+
+		element.parentNode.insertBefore(highlighter.div, element);
+	}	
+}

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 21 19:18:27 2008
@@ -11,15 +11,6 @@
 <body>
   <script type="text/javascript">prefix='../'</script>
   <script type="text/javascript" src="../templates/header.js"></script>
-  <script type="text/javascript" language="javascript" src="../ghighlighter/js/shCore.js"></script>
-  <script type="text/javascript" language="javascript" src="../ghighlighter/js/shBrushJava.js"></script>
-  <script type="text/javascript" language="javascript" src="../ghighlighter/js/shBrushXml.js"></script>
-  <script type="text/javascript" language="javascript">
-    window.onload = function () {
-    dp.SyntaxHighlighter.HighlightAll('code');
-    }
-  </script>
-
 <div id="left">
   <script type="text/javascript" src="../templates/left.js"></script>
 </div>
@@ -42,23 +33,6 @@
     </script>
 
 
-    <pre name="code" class="java">
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class MyApp1 {
-  final static Logger logger = LoggerFactory.getLogger(MyApp1.class);
-
-  public static void main(String[] args) {
-    logger.info("Entering application.");
-
-    Foo foo = new Foo();
-    foo.doIt();
-    logger.info("Exiting application.");
-  }
-}
-    </pre>
-
     <p>Joran stands for a cold north-west wind which, every now and
     then, blows forcefully on Lake Geneva. Located right in the middle
     of Europe, the Geneva lake happens to be the continent's largest
@@ -146,7 +120,7 @@
     <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;
+<div class="source"><pre>package chapter3;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -237,43 +211,45 @@
  <p><em>Example 3.<span class="autoEx"/>: Basic configuration file
   (logback-examples/src/main/java/chapter3/sample0.xml)</em></p>
 
- <div class="source"><pre>&lt;configuration>
 
-  &lt;appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
+<div class="source"><pre>&lt;configuration>
+
+  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
       &lt;Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
-  &lt;root>
-    &lt;level value="debug" />
+  &lt;root level="debug">
     &lt;appender-ref ref="STDOUT" />
   &lt;/root>
-&lt;/configuration></pre></div>   
+&lt;/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>
+   <p>If and only if there are errors during the parsing of the
+   configuration file, logback will automatically print status data on
+   the console. In the absence of errors, if you still wish to inspect
+   logback's internal status, then you can instruct logback to print
+   status data by 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>
+  
+<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>
+    // print logback's internal status
+    <b>LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();</b>
+    <b>StatusPrinter.print(lc);</b>
     ...
   }</pre></div>
 
@@ -300,35 +276,39 @@
 
    <p>Instead of invoking <code>StatusPrinter</code> programmatically
    from your code, you can instruct the configuration file to dump
-   status data. To achieve this, you need to set the <span
-   class="attr">debug</span> attribute of the <em>configuration</em>
-   element, i.e. the top-most element in the configuration file, as
-   shown below. Please note that this <span class="attr">debug</span>
-   attribute relates only to the status data. It does <em>not</em>
-   affect logback's configuration otherwise, in particuler with
-   respect to logger levels. (Put differently, no, the root logger
-   will <em>not</em> be set to DEBUG.)
+   status data, even in the absence of errors. To achieve this, you
+   need to set the <span class="attr">debug</span> attribute of the
+   <em>configuration</em> element, i.e. the top-most element in the
+   configuration file, as shown below. Please note that this <span
+   class="attr">debug</span> attribute relates only to the status
+   data. It does <em>not</em> affect logback's configuration
+   otherwise, in particuler with respect to logger levels. (Put
+   differently, no, the root logger will <em>not</em> be set to
+   DEBUG.)
    </p>
 
-<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>&lt;configuration <b>debug="true"</b>>
 
-  &lt;appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
+   <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>
+&lt;configuration <b>debug="true"</b>> 
+
+  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
       &lt;Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
-  &lt;root>
-    &lt;level value="debug" />
+  &lt;root level="debug">
     &lt;appender-ref ref="STDOUT" />
   &lt;/root>
 &lt;/configuration></pre></div>
   
    <p>Setting the <code>debug</code> attribute within the
    &lt;configuration&gt; element will output status information, under
-   the assumption that 
+   the assumption that
    </p>
    <ol>
      <li>the configuration file is found</li>
@@ -337,32 +317,31 @@
      
    <p>If any of these two conditions is not fulfilled, the Joran
    cannot interpret <code>debug</code> attribute since the
-   configuration file cannot be read. it follows that no status
-   information will be printed. If you would like to ensure that
-   status information is printed, then, as in <em>MyApp2</em>
-   application above, programmatically invoking
-   <code>StatusPrinter.print()</code> is your safest bet.
-   </p>
-
-   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
-   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
-   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
-   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
-   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
-
-   <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 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>.
+   configuration file cannot be read. If the configuration file is
+   found but is ill-formed, then logback will detect the error
+   condition and automatically print its internal status on the
+   console. However, if the configration file cannot be found, since
+   this is not necessarily an error condition, logback will not
+   automatically print its status data.  Programmatically invoking
+   <code>StatusPrinter.print()</code>, as as in <em>MyApp2</em>
+   application above, ensures that status information is always
+   printed.
    </p>
 
+   <h3>Invoking <code>JoranConfigurator</code> directly</h3>
 
-   <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>
+   <p>Logback relies on a configuration library called Joran which is
+   part of logback-core. Logback's default configuration mechanism
+   invokes JoranConfigurator on the default configuration files it
+   finds on the claspath. For whatever reason if you wish to override
+   logback's default configuration meachanism, you can do so by
+   invoking JoranConfigurator directly. The next application,
+   <em>MyApp3</em>, invokes JoranConfirator on a configuration file
+   passed as parameter.</p>
+   
+   <p><em>Example 3.<span class="autoEx"/>: Invoking
+   <code>JoranConfigurator</code> directly <a
+   href="../xref/chapter3/MyApp3.html">(logback-examples/src/main/java/chapter3/MyApp3.java)</a></em></p>
 
 <div class="source"><pre>package chapter3;
 
@@ -384,11 +363,14 @@
     <b>try {
       JoranConfigurator configurator = new JoranConfigurator();
       configurator.setContext(lc);
-      lc.shutdownAndReset();
+      // the context was probably already configured by default configuration 
+      // rules
+      lc.shutdownAndReset(); 
       configurator.doConfigure(args[0]);
     } catch (JoranException je) {
-      StatusPrinter.print(lc);
-    }</b>
+       je.printStackTrace();
+    }
+    StatusPrinter.printIfErrorsOccured(lc);</b>
 
     logger.info("Entering application.");
 
@@ -398,189 +380,128 @@
   }
 }</pre></div>
 
-  <p><code>MyApp2</code> fetches the <code>LoggerContext</code>
-  currently in effect, creates a new <code>JoranConfigurator</code>,
-  gives it the context and finally asks that the configurator parses a
-  configuration file. A basic configuration file that creates the same
-  logging environment as would the default configuration is listed
-  below:
+  <p>This application fetches the <code>LoggerContext</code> currently
+  in effect, creates a new <code>JoranConfigurator</code>, sets the
+  context on which it will operate, resets the logger context, and
+  then finally asks the configurator to configure the context using
+  configuration file passed as parameter to the application. Internal
+  status data is printed in case errors occur.
   </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>&lt;configuration>
-
-  &lt;appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern>
-    &lt;/layout>
-  &lt;/appender>
 
-  &lt;root>
-    &lt;level value="debug" />
-    &lt;appender-ref ref="STDOUT" />
-  &lt;/root>
-&lt;/configuration></pre></div>
+   
 
+  <h2>
+    <a name="syntax" href="#syntax">Configuration file Syntax</a>
+  </h2>
 
-	<p>The above configuration file directs logback to create an
-	<code>ConsoleAppender</code> named <em>STDOUT</em> whose output is
-	format is managed by a <code>PatternLayout</code>. The root logger
-	is configued by setting its level to DEBUG and attaching it the
-	previously created <code>ConsoleAppender</code>.
+	<p>To obtain these different logging behaviors we do not need to
+	recompile code.  You can easily configure logback so as to disable
+	logging for certain parts of your application, or direct output to a
+	UNIX Syslog daemon, to a database, to a log visualizer, or forward
+	logging events to a remote logback server, which would log according
+	to local server policy, for example by forwarding the log event to a
+	second logback server.
   </p>
-
-	<p>Note we could have omitted setting the level of the root logger
-	to DEBUG because that is its default value.
+	
+  <p>The remainder of this section presents the syntax of
+  configuration files. 
   </p>
 
+  <p>As shall become clear, the syntax of logback configuration files
+  is extremely flexible. As such, it is not possible specify the
+  allowed syntax with a DTD file or an XML Schema. Nevertheles, the
+  very basic structure of configration can be desribed as,
+  &lt;configuration> element, followed by zero or more &lt;appender>
+  elements, followed by by zero or more &lt;logger> elements, followed
+  by at most one &lt;root> element. The following diagram illustrates
+  this basic structure.</p>
 
-  <p>Assuming the current directory is <em>logback-examples</em>, try
-  running the <code>MyApp2</code> class by issuing the following
-  command:
+  
+  <p align="left">
+    <img src="images/chapter3/basicSyntax.png" 
+       alt="basic Syntax" title="Basic configuration file structure"/>
   </p>
 
-  <div class="source"><pre>java chapter3.MyApp2 src/main/java/chapter3/sample0.xml</pre>
-  </div>
+   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
+   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
+   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
+   <!-- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -->
 
-  <p>
-    The ouput of this command is very similar to the output of the
-    previous example, except that <code>MyApp2</code> retrieves a
-    logger called <em>chapter3.MyApp2</em> instead of
-    <code>chapter3.MyApp1</code>. The output will reflect the
-    difference.
-  </p>
 
-  <div class="source"><pre>16:09:00.593 [main] INFO  chapter3.MyApp2 - Entering application.
-16:09:00.593 [main] DEBUG chapter3.Foo - Did it again!
-16:09:00.593 [main] INFO  chapter3.MyApp2 - Exiting application.</pre></div>
+  <h4>Configuring Loggers, or the <code>&lt;logger></code> element</h4>
 
-   <p>It is often very useful to define the logback debug
-   configuration property in order to instruct logback to output
-   internal configuration messages on the console. To achieve this,
-   one only needs to add an attribute to the main
-   <em>configuration</em> element in the configuration file, as shown
-   above:
-   </p>
-
-<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>&lt;configuration <b>debug="true"</b>>
+  <p>A logger is configured using the <code>logger</code> element. A
+  <em>logger</em> element takes exactly one mandatory <span
+  class="attr">name</span> atttribute, an optional <span
+  class="attr">level</span> attribute, and an optional <span
+  class="attr">aditivity</span> attribute, which admits the values
+  <em>true</em> or <em>false</em>. The value of the <span
+  class="attr">level</span> attribute can be one of the
+  case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or
+  OFF. 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. This comes in handy in
+  case you set the level of a logger and later decide that it should
+  inherit its level.
+  </p>
 
-  &lt;appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
-    &lt;layout class="ch.qos.logback.classic.PatternLayout">
-      &lt;Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern>
-    &lt;/layout>
-  &lt;/appender>
+  <p>The <em>logger</em> element may 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 &lt;logger 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>
 
-  &lt;root>
-    &lt;level value="debug" />
-    &lt;appender-ref ref="STDOUT" />
-  &lt;/root>
-&lt;/configuration></pre></div>
 
-  <p>This should cause logback to print internal configuration
-  messages in addition to the actual logs. Relaunching the
-  <code>MyApp2</code> application with this new configuration file
-  will ouput the following lines:
-  </p>
-
-<div class="source"><pre>|-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch. \
-qos.logback.core.ConsoleAppender]
-|-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
-|-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the \
-object stack
-|-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG
-|-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to \
-Logger[root]
-|-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
-16:18:23.687 [main] INFO  chapter3.MyApp2 - Entering application.
-16:18:23.687 [main] DEBUG chapter3.Foo - Did it again!
-16:18:23.687 [main] INFO  chapter3.MyApp2 - Exiting application.</pre></div>
 
+  <h4>Configuring the roor logger, or the <code>&lt;root></code>
+  element</h4>
 
-  <h2>
-    <a name="xml_syntax" href="#xml_syntax">XML Syntax</a>
-  </h2>
-	<p>To obtain these different logging behaviors we do not need to
-	recompile code.  You can easily configure logging so that output is
-	directed to a UNIX Syslog daemon, or to a log visualizer, or forward
-	logging events to a remote logback server, which would log according
-	to local server policy, for example by forwarding the log event to a
-	second logback server.</p>
-	
-  <p>The remainder of this chapter presents the syntax of the
-  directives allowing all these variations.
-  </p>
 
 
-<h4>Configuring Loggers</h4>
+  <p>The &lt;root> element configures the root logger. It admits a
+  single attribute, namely the <span class="attr">level</span>
+  attribute. It does not admit any other attributes because the
+  additivity flag does not apply to the root logger.  Moreover, since
+  the root logger is already named, it does not admit a name attribute
+  either. The value of the level attribute can be set to one of the
+  case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or
+  OFF. Note that the level of the root logger cannot be inherited.
+  </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 &lt;root> element admits zero or more &lt;appender-ref>
+  elements.  Similar to the &lt;logger element, declaring a &lt;root
+  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>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>
+  <h4>Example</h4>
 
-  <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>Setting the level of a logger or root 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 DEBUG
+  level logs from any component belonging to the chapter3 package. The
+  following configuration file shows how to achieve that.
   </p>
 
 <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>&lt;configuration>
 
-  &lt;appender name="STDOUT"
-    class="ch.qos.logback.core.ConsoleAppender">
+  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     &lt;layout class="ch.qos.logback.classic.PatternLayout">
       &lt;Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern>
     &lt;/layout>
   &lt;/appender>
 
-  <b>&lt;logger name="chapter3">
-    &lt;level value="INFO" />
-  &lt;/logger></b>
+  <b class="red">&lt;logger name="chapter3" level="INFO"/></b>
+
   
   &lt;root>		
     &lt;!-- The following level element is not necessary since the -->

Modified: logback/trunk/logback-site/src/site/pages/news.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/news.html	(original)
+++ logback/trunk/logback-site/src/site/pages/news.html	Thu Aug 21 19:18:27 2008
@@ -31,6 +31,10 @@
 
   <h3>XXth of XXX 2008 - Release of version 0.9.10</h3>
 
+  <p>Logback-classic now prints its internal status in case of
+  errors. This has been a frequently requested feature.
+  </p>
+
   <p>The LogbackValve in logback-access (ensuring integration with
   Tomcat), will now systematically print its internal status upon
   initialization, unless told to be quiet. This greatly helps

Modified: logback/trunk/logback-site/src/site/pages/templates/right.js
==============================================================================
--- logback/trunk/logback-site/src/site/pages/templates/right.js	(original)
+++ logback/trunk/logback-site/src/site/pages/templates/right.js	Thu Aug 21 19:18:27 2008
@@ -6,6 +6,9 @@
 
 document.write('<p class="menu"><a href="http://wimpi.coalevo.net/2008/04/logger-name-based-filtering-in-logback.html">Filtering by logger name</a>')
 
+document.write('<p class="menu"><a href="http://out-println.blogspot.com/2007/09/slf4j-and-logback.html">SLF4J and Logback</a>')
+
+
 document.write('<p class="menu"><a href="http://wizardforge.org/pc?action=showVersion&id=72">Configuration Wizard</a>')
 
 document.write('<p class="menu"><a href="http://xhab.blogspot.com/2007/03/new-logging-experience.html">A new logging experience!</a>')


More information about the logback-dev mailing list