KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > log4j > PropertyConfigurator


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17
18 // Contibutors: "Luke Blanshard" <Luke@quiq.com>
19
// "Mark DONSZELMANN" <Mark.Donszelmann@cern.ch>
20
// Anders Kristensen <akristensen@dynamicsoft.com>
21

22 package org.apache.log4j;
23
24 import org.apache.log4j.DefaultCategoryFactory;
25 import org.apache.log4j.config.PropertySetter;
26 //import org.apache.log4j.config.PropertySetterException;
27
import org.apache.log4j.spi.OptionHandler;
28 import org.apache.log4j.spi.Configurator;
29 import org.apache.log4j.spi.LoggerFactory;
30 import org.apache.log4j.spi.LoggerRepository;
31 import org.apache.log4j.spi.RendererSupport;
32 import org.apache.log4j.or.RendererMap;
33 import org.apache.log4j.helpers.LogLog;
34 import org.apache.log4j.helpers.OptionConverter;
35 import org.apache.log4j.helpers.FileWatchdog;
36
37 import java.util.Enumeration JavaDoc;
38 import java.util.Properties JavaDoc;
39 import java.io.FileInputStream JavaDoc;
40 import java.io.IOException JavaDoc;
41 import java.util.StringTokenizer JavaDoc;
42 import java.util.Hashtable JavaDoc;
43
44 /**
45    Allows the configuration of log4j from an external file. See
46    <b>{@link #doConfigure(String, LoggerRepository)}</b> for the
47    expected format.
48
49    <p>It is sometimes useful to see how log4j is reading configuration
50    files. You can enable log4j internal logging by defining the
51    <b>log4j.debug</b> variable.
52
53    <P>As of log4j version 0.8.5, at class initialization time class,
54    the file <b>log4j.properties</b> will be searched from the search
55    path used to load classes. If the file can be found, then it will
56    be fed to the {@link PropertyConfigurator#configure(java.net.URL)}
57    method.
58
59    <p>The <code>PropertyConfigurator</code> does not handle the
60    advanced configuration features supported by the {@link
61    org.apache.log4j.xml.DOMConfigurator DOMConfigurator} such as
62    support for {@link org.apache.log4j.spi.Filter Filters}, custom
63    {@link org.apache.log4j.spi.ErrorHandler ErrorHandlers}, nested
64    appenders such as the {@link org.apache.log4j.AsyncAppender
65    AsyncAppender}, etc.
66
67    <p>All option <em>values</em> admit variable substitution. The
68    syntax of variable substitution is similar to that of Unix
69    shells. The string between an opening <b>&quot;${&quot;</b> and
70    closing <b>&quot;}&quot;</b> is interpreted as a key. The value of
71    the substituted variable can be defined as a system property or in
72    the configuration file itself. The value of the key is first
73    searched in the system properties, and if not found there, it is
74    then searched in the configuration file being parsed. The
75    corresponding value replaces the ${variableName} sequence. For
76    example, if <code>java.home</code> system property is set to
77    <code>/home/xyz</code>, then every occurrence of the sequence
78    <code>${java.home}</code> will be interpreted as
79    <code>/home/xyz</code>.
80
81
82    @author Ceki G&uuml;lc&uuml;
83    @author Anders Kristensen
84    @since 0.8.1 */

85 public class PropertyConfigurator implements Configurator {
86
87   /**
88      Used internally to keep track of configured appenders.
89    */

90   protected Hashtable JavaDoc registry = new Hashtable JavaDoc(11);
91   protected LoggerFactory loggerFactory = new DefaultCategoryFactory();
92
93   static final String JavaDoc CATEGORY_PREFIX = "log4j.category.";
94   static final String JavaDoc LOGGER_PREFIX = "log4j.logger.";
95   static final String JavaDoc FACTORY_PREFIX = "log4j.factory";
96   static final String JavaDoc ADDITIVITY_PREFIX = "log4j.additivity.";
97   static final String JavaDoc ROOT_CATEGORY_PREFIX = "log4j.rootCategory";
98   static final String JavaDoc ROOT_LOGGER_PREFIX = "log4j.rootLogger";
99   static final String JavaDoc APPENDER_PREFIX = "log4j.appender.";
100   static final String JavaDoc RENDERER_PREFIX = "log4j.renderer.";
101   static final String JavaDoc THRESHOLD_PREFIX = "log4j.threshold";
102
103   /** Key for specifying the {@link org.apache.log4j.spi.LoggerFactory
104       LoggerFactory}. Currently set to "<code>log4j.loggerFactory</code>". */

105   public static final String JavaDoc LOGGER_FACTORY_KEY = "log4j.loggerFactory";
106
107   static final private String JavaDoc INTERNAL_ROOT_NAME = "root";
108
109   /**
110     Read configuration from a file. <b>The existing configuration is
111     not cleared nor reset.</b> If you require a different behavior,
112     then call {@link LogManager#resetConfiguration
113     resetConfiguration} method before calling
114     <code>doConfigure</code>.
115
116     <p>The configuration file consists of statements in the format
117     <code>key=value</code>. The syntax of different configuration
118     elements are discussed below.
119
120     <h3>Repository-wide threshold</h3>
121
122     <p>The repository-wide threshold filters logging requests by level
123     regardless of logger. The syntax is:
124
125     <pre>
126     log4j.threshold=[level]
127     </pre>
128
129     <p>The level value can consist of the string values OFF, FATAL,
130     ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
131     custom level value can be specified in the form
132     level#classname. By default the repository-wide threshold is set
133     to the lowest possible value, namely the level <code>ALL</code>.
134     </p>
135
136
137     <h3>Appender configuration</h3>
138
139     <p>Appender configuration syntax is:
140     <pre>
141     # For appender named <i>appenderName</i>, set its class.
142     # Note: The appender name can contain dots.
143     log4j.appender.appenderName=fully.qualified.name.of.appender.class
144
145     # Set appender specific options.
146     log4j.appender.appenderName.option1=value1
147     ...
148     log4j.appender.appenderName.optionN=valueN
149     </pre>
150
151     For each named appender you can configure its {@link Layout}. The
152     syntax for configuring an appender's layout is:
153     <pre>
154     log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
155     log4j.appender.appenderName.layout.option1=value1
156     ....
157     log4j.appender.appenderName.layout.optionN=valueN
158     </pre>
159
160     <h3>Configuring loggers</h3>
161
162     <p>The syntax for configuring the root logger is:
163     <pre>
164       log4j.rootLogger=[level], appenderName, appenderName, ...
165     </pre>
166
167     <p>This syntax means that an optional <em>level</em> can be
168     supplied followed by appender names separated by commas.
169
170     <p>The level value can consist of the string values OFF, FATAL,
171     ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
172     custom level value can be specified in the form
173     <code>level#classname</code>.
174
175     <p>If a level value is specified, then the root level is set
176     to the corresponding level. If no level value is specified,
177     then the root level remains untouched.
178
179     <p>The root logger can be assigned multiple appenders.
180
181     <p>Each <i>appenderName</i> (separated by commas) will be added to
182     the root logger. The named appender is defined using the
183     appender syntax defined above.
184
185     <p>For non-root categories the syntax is almost the same:
186     <pre>
187     log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
188     </pre>
189
190     <p>The meaning of the optional level value is discussed above
191     in relation to the root logger. In addition however, the value
192     INHERITED can be specified meaning that the named logger should
193     inherit its level from the logger hierarchy.
194
195     <p>If no level value is supplied, then the level of the
196     named logger remains untouched.
197
198     <p>By default categories inherit their level from the
199     hierarchy. However, if you set the level of a logger and later
200     decide that that logger should inherit its level, then you should
201     specify INHERITED as the value for the level value. NULL is a
202     synonym for INHERITED.
203
204     <p>Similar to the root logger syntax, each <i>appenderName</i>
205     (separated by commas) will be attached to the named logger.
206
207     <p>See the <a HREF="../../../../manual.html#additivity">appender
208     additivity rule</a> in the user manual for the meaning of the
209     <code>additivity</code> flag.
210
211     <h3>ObjectRenderers</h3>
212
213     You can customize the way message objects of a given type are
214     converted to String before being logged. This is done by
215     specifying an {@link org.apache.log4j.or.ObjectRenderer ObjectRenderer}
216     for the object type would like to customize.
217
218     <p>The syntax is:
219
220     <pre>
221     log4j.renderer.fully.qualified.name.of.rendered.class=fully.qualified.name.of.rendering.class
222     </pre>
223
224     As in,
225     <pre>
226     log4j.renderer.my.Fruit=my.FruitRenderer
227     </pre>
228
229     <h3>Logger Factories</h3>
230
231     The usage of custom logger factories is discouraged and no longer
232     documented.
233
234     <h3>Example</h3>
235
236     <p>An example configuration is given below. Other configuration
237     file examples are given in the <code>examples</code> folder.
238
239     <pre>
240
241     # Set options for appender named "A1".
242     # Appender "A1" will be a SyslogAppender
243     log4j.appender.A1=org.apache.log4j.net.SyslogAppender
244
245     # The syslog daemon resides on www.abc.net
246     log4j.appender.A1.SyslogHost=www.abc.net
247
248     # A1's layout is a PatternLayout, using the conversion pattern
249     # <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. Thus, the log output will
250     # include # the relative time since the start of the application in
251     # milliseconds, followed by the level of the log request,
252     # followed by the two rightmost components of the logger name,
253     # followed by the callers method name, followed by the line number,
254     # the nested disgnostic context and finally the message itself.
255     # Refer to the documentation of {@link PatternLayout} for further information
256     # on the syntax of the ConversionPattern key.
257     log4j.appender.A1.layout=org.apache.log4j.PatternLayout
258     log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
259
260     # Set options for appender named "A2"
261     # A2 should be a RollingFileAppender, with maximum file size of 10 MB
262     # using at most one backup file. A2's layout is TTCC, using the
263     # ISO8061 date format with context printing enabled.
264     log4j.appender.A2=org.apache.log4j.RollingFileAppender
265     log4j.appender.A2.MaxFileSize=10MB
266     log4j.appender.A2.MaxBackupIndex=1
267     log4j.appender.A2.layout=org.apache.log4j.TTCCLayout
268     log4j.appender.A2.layout.ContextPrinting=enabled
269     log4j.appender.A2.layout.DateFormat=ISO8601
270
271     # Root logger set to DEBUG using the A2 appender defined above.
272     log4j.rootLogger=DEBUG, A2
273
274     # Logger definitions:
275     # The SECURITY logger inherits is level from root. However, it's output
276     # will go to A1 appender defined above. It's additivity is non-cumulative.
277     log4j.logger.SECURITY=INHERIT, A1
278     log4j.additivity.SECURITY=false
279
280     # Only warnings or above will be logged for the logger "SECURITY.access".
281     # Output will go to A1.
282     log4j.logger.SECURITY.access=WARN
283
284
285     # The logger "class.of.the.day" inherits its level from the
286     # logger hierarchy. Output will go to the appender's of the root
287     # logger, A2 in this case.
288     log4j.logger.class.of.the.day=INHERIT
289     </pre>
290
291     <p>Refer to the <b>setOption</b> method in each Appender and
292     Layout for class specific options.
293
294     <p>Use the <code>#</code> or <code>!</code> characters at the
295     beginning of a line for comments.
296
297    <p>
298    @param configFileName The name of the configuration file where the
299    configuration information is stored.
300
301   */

302   public
303   void doConfigure(String JavaDoc configFileName, LoggerRepository hierarchy) {
304     Properties JavaDoc props = new Properties JavaDoc();
305     try {
306       FileInputStream JavaDoc istream = new FileInputStream JavaDoc(configFileName);
307       props.load(istream);
308       istream.close();
309     }
310     catch (IOException JavaDoc e) {
311       LogLog.error("Could not read configuration file ["+configFileName+"].", e);
312       LogLog.error("Ignoring configuration file [" + configFileName+"].");
313       return;
314     }
315     // If we reach here, then the config file is alright.
316
doConfigure(props, hierarchy);
317   }
318
319   /**
320    */

321   static
322   public
323   void configure(String JavaDoc configFilename) {
324     new PropertyConfigurator().doConfigure(configFilename,
325                        LogManager.getLoggerRepository());
326   }
327
328   /**
329      Read configuration options from url <code>configURL</code>.
330
331      @since 0.8.2
332    */

333   public
334   static
335   void configure(java.net.URL JavaDoc configURL) {
336     new PropertyConfigurator().doConfigure(configURL,
337                        LogManager.getLoggerRepository());
338   }
339
340
341   /**
342      Read configuration options from <code>properties</code>.
343
344      See {@link #doConfigure(String, LoggerRepository)} for the expected format.
345   */

346   static
347   public
348   void configure(Properties JavaDoc properties) {
349     new PropertyConfigurator().doConfigure(properties,
350                        LogManager.getLoggerRepository());
351   }
352
353   /**
354      Like {@link #configureAndWatch(String, long)} except that the
355      default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is
356      used.
357
358      @param configFilename A file in key=value format.
359
360   */

361   static
362   public
363   void configureAndWatch(String JavaDoc configFilename) {
364     configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
365   }
366
367
368   /**
369      Read the configuration file <code>configFilename</code> if it
370      exists. Moreover, a thread will be created that will periodically
371      check if <code>configFilename</code> has been created or
372      modified. The period is determined by the <code>delay</code>
373      argument. If a change or file creation is detected, then
374      <code>configFilename</code> is read to configure log4j.
375
376       @param configFilename A file in key=value format.
377       @param delay The delay in milliseconds to wait between each check.
378   */

379   static
380   public
381   void configureAndWatch(String JavaDoc configFilename, long delay) {
382     PropertyWatchdog pdog = new PropertyWatchdog(configFilename);
383     pdog.setDelay(delay);
384     pdog.start();
385   }
386
387
388   /**
389      Read configuration options from <code>properties</code>.
390
391      See {@link #doConfigure(String, LoggerRepository)} for the expected format.
392   */

393   public
394   void doConfigure(Properties JavaDoc properties, LoggerRepository hierarchy) {
395
396     String JavaDoc value = properties.getProperty(LogLog.DEBUG_KEY);
397     if(value == null) {
398       value = properties.getProperty(LogLog.CONFIG_DEBUG_KEY);
399       if(value != null)
400     LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
401     }
402
403     if(value != null) {
404       LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
405     }
406
407     String JavaDoc thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX,
408                                properties);
409     if(thresholdStr != null) {
410       hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr,
411                              (Level) Level.ALL));
412       LogLog.debug("Hierarchy threshold set to ["+hierarchy.getThreshold()+"].");
413     }
414
415     configureRootCategory(properties, hierarchy);
416     configureLoggerFactory(properties);
417     parseCatsAndRenderers(properties, hierarchy);
418
419     LogLog.debug("Finished configuring.");
420     // We don't want to hold references to appenders preventing their
421
// garbage collection.
422
registry.clear();
423   }
424
425   /**
426      Read configuration options from url <code>configURL</code>.
427    */

428   public
429   void doConfigure(java.net.URL JavaDoc configURL, LoggerRepository hierarchy) {
430     Properties JavaDoc props = new Properties JavaDoc();
431     LogLog.debug("Reading configuration from URL " + configURL);
432     try {
433       props.load(configURL.openStream());
434     }
435     catch (java.io.IOException JavaDoc e) {
436       LogLog.error("Could not read configuration file from URL [" + configURL
437            + "].", e);
438       LogLog.error("Ignoring configuration file [" + configURL +"].");
439       return;
440     }
441     doConfigure(props, hierarchy);
442   }
443
444
445   // --------------------------------------------------------------------------
446
// Internal stuff
447
// --------------------------------------------------------------------------
448

449   /**
450      Check the provided <code>Properties</code> object for a
451      {@link org.apache.log4j.spi.LoggerFactory LoggerFactory}
452      entry specified by {@link #LOGGER_FACTORY_KEY}. If such an entry
453      exists, an attempt is made to create an instance using the default
454      constructor. This instance is used for subsequent Category creations
455      within this configurator.
456
457      @see #parseCatsAndRenderers
458    */

459   protected void configureLoggerFactory(Properties JavaDoc props) {
460     String JavaDoc factoryClassName = OptionConverter.findAndSubst(LOGGER_FACTORY_KEY,
461                                props);
462     if(factoryClassName != null) {
463       LogLog.debug("Setting category factory to ["+factoryClassName+"].");
464       loggerFactory = (LoggerFactory)
465               OptionConverter.instantiateByClassName(factoryClassName,
466                              LoggerFactory.class,
467                              loggerFactory);
468       PropertySetter.setProperties(loggerFactory, props, FACTORY_PREFIX + ".");
469     }
470   }
471
472   /*
473   void configureOptionHandler(OptionHandler oh, String prefix,
474                   Properties props) {
475     String[] options = oh.getOptionStrings();
476     if(options == null)
477       return;
478
479     String value;
480     for(int i = 0; i < options.length; i++) {
481       value = OptionConverter.findAndSubst(prefix + options[i], props);
482       LogLog.debug(
483          "Option " + options[i] + "=[" + (value == null? "N/A" : value)+"].");
484       // Some option handlers assume that null value are not passed to them.
485       // So don't remove this check
486       if(value != null) {
487     oh.setOption(options[i], value);
488       }
489     }
490     oh.activateOptions();
491   }
492   */

493
494
495   void configureRootCategory(Properties JavaDoc props, LoggerRepository hierarchy) {
496     String JavaDoc effectiveFrefix = ROOT_LOGGER_PREFIX;
497     String JavaDoc value = OptionConverter.findAndSubst(ROOT_LOGGER_PREFIX, props);
498
499     if(value == null) {
500       value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props);
501       effectiveFrefix = ROOT_CATEGORY_PREFIX;
502     }
503
504     if(value == null)
505       LogLog.debug("Could not find root logger information. Is this OK?");
506     else {
507       Logger root = hierarchy.getRootLogger();
508       synchronized(root) {
509     parseCategory(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value);
510       }
511     }
512   }
513
514
515   /**
516      Parse non-root elements, such non-root categories and renderers.
517   */

518   protected
519   void parseCatsAndRenderers(Properties JavaDoc props, LoggerRepository hierarchy) {
520     Enumeration JavaDoc enumeration = props.propertyNames();
521     while(enumeration.hasMoreElements()) {
522       String JavaDoc key = (String JavaDoc) enumeration.nextElement();
523       if(key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) {
524     String JavaDoc loggerName = null;
525     if(key.startsWith(CATEGORY_PREFIX)) {
526       loggerName = key.substring(CATEGORY_PREFIX.length());
527     } else if(key.startsWith(LOGGER_PREFIX)) {
528       loggerName = key.substring(LOGGER_PREFIX.length());
529     }
530     String JavaDoc value = OptionConverter.findAndSubst(key, props);
531     Logger logger = hierarchy.getLogger(loggerName, loggerFactory);
532     synchronized(logger) {
533       parseCategory(props, logger, key, loggerName, value);
534       parseAdditivityForLogger(props, logger, loggerName);
535     }
536       } else if(key.startsWith(RENDERER_PREFIX)) {
537     String JavaDoc renderedClass = key.substring(RENDERER_PREFIX.length());
538     String JavaDoc renderingClass = OptionConverter.findAndSubst(key, props);
539     if(hierarchy instanceof RendererSupport) {
540       RendererMap.addRenderer((RendererSupport) hierarchy, renderedClass,
541                   renderingClass);
542     }
543       }
544     }
545   }
546
547   /**
548      Parse the additivity option for a non-root category.
549    */

550   void parseAdditivityForLogger(Properties JavaDoc props, Logger cat,
551                   String JavaDoc loggerName) {
552     String JavaDoc value = OptionConverter.findAndSubst(ADDITIVITY_PREFIX + loggerName,
553                          props);
554     LogLog.debug("Handling "+ADDITIVITY_PREFIX + loggerName+"=["+value+"]");
555     // touch additivity only if necessary
556
if((value != null) && (!value.equals(""))) {
557       boolean additivity = OptionConverter.toBoolean(value, true);
558       LogLog.debug("Setting additivity for \""+loggerName+"\" to "+
559            additivity);
560       cat.setAdditivity(additivity);
561     }
562   }
563
564   /**
565      This method must work for the root category as well.
566    */

567   void parseCategory(Properties JavaDoc props, Logger logger, String JavaDoc optionKey,
568              String JavaDoc loggerName, String JavaDoc value) {
569
570     LogLog.debug("Parsing for [" +loggerName +"] with value=[" + value+"].");
571     // We must skip over ',' but not white space
572
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(value, ",");
573
574     // If value is not in the form ", appender.." or "", then we should set
575
// the level of the loggeregory.
576

577     if(!(value.startsWith(",") || value.equals(""))) {
578
579       // just to be on the safe side...
580
if(!st.hasMoreTokens())
581     return;
582
583       String JavaDoc levelStr = st.nextToken();
584       LogLog.debug("Level token is [" + levelStr + "].");
585
586       // If the level value is inherited, set category level value to
587
// null. We also check that the user has not specified inherited for the
588
// root category.
589
if(INHERITED.equalsIgnoreCase(levelStr) ||
590                                       NULL.equalsIgnoreCase(levelStr)) {
591     if(loggerName.equals(INTERNAL_ROOT_NAME)) {
592       LogLog.warn("The root logger cannot be set to null.");
593     } else {
594       logger.setLevel(null);
595     }
596       } else {
597     logger.setLevel(OptionConverter.toLevel(levelStr, (Level) Level.DEBUG));
598       }
599       LogLog.debug("Category " + loggerName + " set to " + logger.getLevel());
600     }
601
602     // Begin by removing all existing appenders.
603
logger.removeAllAppenders();
604
605     Appender appender;
606     String JavaDoc appenderName;
607     while(st.hasMoreTokens()) {
608       appenderName = st.nextToken().trim();
609       if(appenderName == null || appenderName.equals(","))
610     continue;
611       LogLog.debug("Parsing appender named \"" + appenderName +"\".");
612       appender = parseAppender(props, appenderName);
613       if(appender != null) {
614     logger.addAppender(appender);
615       }
616     }
617   }
618
619   Appender parseAppender(Properties JavaDoc props, String JavaDoc appenderName) {
620     Appender appender = registryGet(appenderName);
621     if((appender != null)) {
622       LogLog.debug("Appender \"" + appenderName + "\" was already parsed.");
623       return appender;
624     }
625     // Appender was not previously initialized.
626
String JavaDoc prefix = APPENDER_PREFIX + appenderName;
627     String JavaDoc layoutPrefix = prefix + ".layout";
628
629     appender = (Appender) OptionConverter.instantiateByKey(props, prefix,
630                           org.apache.log4j.Appender.class,
631                           null);
632     if(appender == null) {
633       LogLog.error(
634               "Could not instantiate appender named \"" + appenderName+"\".");
635       return null;
636     }
637     appender.setName(appenderName);
638
639     if(appender instanceof OptionHandler) {
640       if(appender.requiresLayout()) {
641     Layout layout = (Layout) OptionConverter.instantiateByKey(props,
642                                   layoutPrefix,
643                                   Layout.class,
644                                   null);
645     if(layout != null) {
646       appender.setLayout(layout);
647       LogLog.debug("Parsing layout options for \"" + appenderName +"\".");
648       //configureOptionHandler(layout, layoutPrefix + ".", props);
649
PropertySetter.setProperties(layout, props, layoutPrefix + ".");
650       LogLog.debug("End of parsing for \"" + appenderName +"\".");
651     }
652       }
653       //configureOptionHandler((OptionHandler) appender, prefix + ".", props);
654
PropertySetter.setProperties(appender, props, prefix + ".");
655       LogLog.debug("Parsed \"" + appenderName +"\" options.");
656     }
657     registryPut(appender);
658     return appender;
659   }
660
661
662   void registryPut(Appender appender) {
663     registry.put(appender.getName(), appender);
664   }
665
666   Appender registryGet(String JavaDoc name) {
667     return (Appender) registry.get(name);
668   }
669 }
670
671 class PropertyWatchdog extends FileWatchdog {
672
673   PropertyWatchdog(String JavaDoc filename) {
674     super(filename);
675   }
676
677   /**
678      Call {@link PropertyConfigurator#configure(String)} with the
679      <code>filename</code> to reconfigure log4j. */

680   public
681   void doOnChange() {
682     new PropertyConfigurator().doConfigure(filename,
683                        LogManager.getLoggerRepository());
684   }
685 }
686
Popular Tags