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

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>')
participants (1)
-
noreply.ceki@qos.ch