[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>©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,'<');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(/</g,'<').replace(/>/g,'>').replace(/&/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*\/?>|<br\s*\/?>/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,' ');str=str.replace(/</g,'<');str=str.replace(/\n/gm,' <br>');if(css!=null)
-{if((/br/gi).test(str))
-{var lines=str.split(' <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+='·';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]+' ';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>©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, '<');
+ 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(/</g,'<')
+ .replace(/>/g,'>')
+ .replace(/&/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*\/?>|<br\s*\/?>/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, '&');
+ str = str.replace(/ /g, ' ');
+ str = str.replace(/</g, '<');
+// str = str.replace(/</g, '<');
+// str = str.replace(/>/g, '>');
+ str = str.replace(/\n/gm, ' <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(' <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 += '·';
+ 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] + ' ';
+
+ 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><configuration>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
+<div class="source"><pre><configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
- <root>
- <level value="debug" />
+ <root level="debug">
<appender-ref ref="STDOUT" />
</root>
-</configuration></pre></div>
+</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><configuration <b>debug="true"</b>>
- <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>
+<configuration <b>debug="true"</b>>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
- <root>
- <level value="debug" />
+ <root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration></pre></div>
<p>Setting the <code>debug</code> attribute within the
<configuration> 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><configuration>
-
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
- </layout>
- </appender>
- <root>
- <level value="debug" />
- <appender-ref ref="STDOUT" />
- </root>
-</configuration></pre></div>
+
+ <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,
+ <configuration> element, followed by zero or more <appender>
+ elements, followed by by zero or more <logger> elements, followed
+ by at most one <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><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><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>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
- <layout class="ch.qos.logback.classic.PatternLayout">
- <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
- </layout>
- </appender>
+ <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 <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>
- <root>
- <level value="debug" />
- <appender-ref ref="STDOUT" />
- </root>
-</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><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 <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 <root> element admits zero or more <appender-ref>
+ elements. Similar to the <logger element, declaring a <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><configuration>
- <appender name="STDOUT"
- class="ch.qos.logback.core.ConsoleAppender">
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
- <b><logger name="chapter3">
- <level value="INFO" />
- </logger></b>
+ <b class="red"><logger name="chapter3" level="INFO"/></b>
+
<root>
<!-- 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