Added: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/extras/DOMConfigurator.html URL: http://svn.apache.org/viewvc/logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/extras/DOMConfigurator.html?rev=569257&view=auto ============================================================================== --- logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/extras/DOMConfigurator.html (added) +++ logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/extras/DOMConfigurator.html Thu Aug 23 22:43:39 2007 @@ -0,0 +1,1059 @@ + + + +DOMConfigurator xref + + + +
View Javadoc
+
+1   /*
+2    * Licensed to the Apache Software Foundation (ASF) under one or more
+3    * contributor license agreements.  See the NOTICE file distributed with
+4    * this work for additional information regarding copyright ownership.
+5    * The ASF licenses this file to You under the Apache License, Version 2.0
+6    * (the "License"); you may not use this file except in compliance with
+7    * the License.  You may obtain a copy of the License at
+8    * 
+9    *      http://www.apache.org/licenses/LICENSE-2.0
+10   * 
+11   * Unless required by applicable law or agreed to in writing, software
+12   * distributed under the License is distributed on an "AS IS" BASIS,
+13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+14   * See the License for the specific language governing permissions and
+15   * limitations under the License.
+16   */
+17  
+18  package org.apache.log4j.extras;
+19  
+20  import org.apache.log4j.Appender;
+21  import org.apache.log4j.Layout;
+22  import org.apache.log4j.Level;
+23  import org.apache.log4j.LogManager;
+24  import org.apache.log4j.Logger;
+25  import org.apache.log4j.config.PropertySetter;
+26  import org.apache.log4j.helpers.FileWatchdog;
+27  import org.apache.log4j.helpers.Loader;
+28  import org.apache.log4j.helpers.LogLog;
+29  import org.apache.log4j.helpers.OptionConverter;
+30  import org.apache.log4j.or.RendererMap;
+31  import org.apache.log4j.spi.AppenderAttachable;
+32  import org.apache.log4j.spi.Configurator;
+33  import org.apache.log4j.spi.ErrorHandler;
+34  import org.apache.log4j.spi.Filter;
+35  import org.apache.log4j.spi.LoggerFactory;
+36  import org.apache.log4j.spi.LoggerRepository;
+37  import org.apache.log4j.spi.OptionHandler;
+38  import org.apache.log4j.spi.RendererSupport;
+39  import org.apache.log4j.xml.SAXErrorHandler;
+40  import org.apache.log4j.xml.UnrecognizedElementHandler;
+41  import org.w3c.dom.Document;
+42  import org.w3c.dom.Element;
+43  import org.w3c.dom.NamedNodeMap;
+44  import org.w3c.dom.Node;
+45  import org.w3c.dom.NodeList;
+46  import org.xml.sax.EntityResolver;
+47  import org.xml.sax.InputSource;
+48  import org.xml.sax.SAXException;
+49  
+50  import javax.xml.parsers.DocumentBuilder;
+51  import javax.xml.parsers.DocumentBuilderFactory;
+52  import javax.xml.parsers.FactoryConfigurationError;
+53  import java.io.ByteArrayInputStream;
+54  import java.io.File;
+55  import java.io.IOException;
+56  import java.io.InputStream;
+57  import java.io.Reader;
+58  import java.lang.reflect.Method;
+59  import java.net.URL;
+60  import java.util.Hashtable;
+61  import java.util.Properties;
+62  
+63  /***
+64   * This is a duplicate (with minor modifications)
+65   *  of the log4j 1.2.15 DOMConfigurator
+66   * renamed for use with earlier versions of log4j.
+67   *
+68  */
+69  public class DOMConfigurator implements Configurator {
+70  
+71    static final String CONFIGURATION_TAG = "log4j:configuration";
+72    static final String OLD_CONFIGURATION_TAG = "configuration";
+73    static final String RENDERER_TAG      = "renderer";
+74    static final String APPENDER_TAG 	= "appender";
+75    static final String APPENDER_REF_TAG 	= "appender-ref";  
+76    static final String PARAM_TAG    	= "param";
+77    static final String LAYOUT_TAG	= "layout";
+78    static final String CATEGORY		= "category";
+79    static final String LOGGER		= "logger";
+80    static final String LOGGER_REF	= "logger-ref";
+81    static final String CATEGORY_FACTORY_TAG  = "categoryFactory";
+82    static final String LOGGER_FACTORY_TAG  = "loggerFactory";
+83    static final String NAME_ATTR		= "name";
+84    static final String CLASS_ATTR        = "class";
+85    static final String VALUE_ATTR	= "value";
+86    static final String ROOT_TAG		= "root";
+87    static final String ROOT_REF		= "root-ref";
+88    static final String LEVEL_TAG	        = "level";
+89    static final String PRIORITY_TAG      = "priority";
+90    static final String FILTER_TAG	= "filter";
+91    static final String ERROR_HANDLER_TAG	= "errorHandler";
+92    static final String REF_ATTR		= "ref";
+93    static final String ADDITIVITY_ATTR    = "additivity";  
+94    static final String THRESHOLD_ATTR       = "threshold";
+95    static final String CONFIG_DEBUG_ATTR  = "configDebug";
+96    static final String INTERNAL_DEBUG_ATTR  = "debug";
+97    private static final String RESET_ATTR  = "reset";
+98    static final String RENDERING_CLASS_ATTR = "renderingClass";
+99    static final String RENDERED_CLASS_ATTR = "renderedClass";
+100 
+101   static final String EMPTY_STR = "";
+102   static final Class[] ONE_STRING_PARAM = new Class[] {String.class};
+103 
+104   final static String dbfKey = "javax.xml.parsers.DocumentBuilderFactory";
+105 
+106   
+107   // key: appenderName, value: appender
+108   private Hashtable appenderBag;
+109 
+110   private Properties props;
+111   private LoggerRepository repository;
+112 
+113   private LoggerFactory catFactory = null;
+114 
+115   /***
+116      No argument constructor.
+117   */
+118   public DOMConfigurator() {
+119     appenderBag = new Hashtable();
+120   }
+121 
+122   /***
+123      Used internally to parse appenders by IDREF name.
+124   */
+125   protected
+126   Appender findAppenderByName(Document doc, String appenderName)  {      
+127     Appender appender = (Appender) appenderBag.get(appenderName);
+128 
+129     if(appender != null) {
+130       return appender;
+131     } else {
+132       // Doesn't work on DOM Level 1 :
+133       // Element element = doc.getElementById(appenderName);
+134                         
+135       // Endre's hack:
+136       Element element = null;
+137       NodeList list = doc.getElementsByTagName("appender");
+138       for (int t=0; t < list.getLength(); t++) {
+139 	Node node = list.item(t);
+140 	NamedNodeMap map= node.getAttributes();
+141 	Node attrNode = map.getNamedItem("name");
+142 	if (appenderName.equals(attrNode.getNodeValue())) {
+143 	  element = (Element) node;
+144 	  break;
+145 	}
+146       }
+147       // Hack finished.
+148 
+149       if(element == null) {
+150 	LogLog.error("No appender named ["+appenderName+"] could be found."); 
+151 	return null;
+152       } else {
+153 	appender = parseAppender(element);
+154 	appenderBag.put(appenderName, appender);
+155 	return appender;
+156       }
+157     } 
+158   }
+159   /***
+160      Used internally to parse appenders by IDREF element.
+161    */
+162   protected
+163   Appender findAppenderByReference(Element appenderRef) {    
+164     String appenderName = subst(appenderRef.getAttribute(REF_ATTR));    
+165     Document doc = appenderRef.getOwnerDocument();
+166     return findAppenderByName(doc, appenderName);
+167   }
+168 
+169     /***
+170      * Delegates unrecognized content to created instance if
+171      * it supports UnrecognizedElementParser.
+172      * @since 1.2.15
+173      * @param instance instance, may be null.
+174      * @param element element, may not be null.
+175      * @param props properties
+176      * @throws IOException thrown if configuration of owner object
+177      * should be abandoned.
+178      */
+179   private static void parseUnrecognizedElement(final Object instance,
+180                                         final Element element,
+181                                         final Properties props) throws Exception {
+182       boolean recognized = false;
+183       if (instance instanceof UnrecognizedElementHandler) {
+184           recognized = ((UnrecognizedElementHandler) instance).parseUnrecognizedElement(
+185                   element, props);
+186       }
+187       if (!recognized) {
+188           LogLog.warn("Unrecognized element " + element.getNodeName());
+189       }
+190   }
+191 
+192     /***
+193       * Delegates unrecognized content to created instance if
+194       * it supports UnrecognizedElementParser and catches and
+195      *  logs any exception.
+196       * @since 1.2.15
+197       * @param instance instance, may be null.
+198       * @param element element, may not be null.
+199       * @param props properties
+200       */
+201    private static void quietParseUnrecognizedElement(final Object instance,
+202                                           final Element element,
+203                                           final Properties props) {
+204       try {
+205           parseUnrecognizedElement(instance, element, props);
+206       } catch (Exception ex) {
+207           LogLog.error("Error in extension content: ", ex);
+208       }
+209   }
+210 
+211   /***
+212      Used internally to parse an appender element.
+213    */
+214   protected
+215   Appender parseAppender (Element appenderElement) {
+216     String className = subst(appenderElement.getAttribute(CLASS_ATTR));
+217     LogLog.debug("Class name: [" + className+']');    
+218     try {
+219       Object instance 	= Loader.loadClass(className).newInstance();
+220       Appender appender	= (Appender)instance;
+221       PropertySetter propSetter = new PropertySetter(appender);
+222 
+223       appender.setName(subst(appenderElement.getAttribute(NAME_ATTR)));
+224       
+225       NodeList children	= appenderElement.getChildNodes();
+226       final int length 	= children.getLength();
+227 
+228       for (int loop = 0; loop < length; loop++) {
+229 	Node currentNode = children.item(loop);
+230 
+231 	/* We're only interested in Elements */
+232 	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+233 	  Element currentElement = (Element)currentNode;
+234 
+235 	  // Parse appender parameters 
+236 	  if (currentElement.getTagName().equals(PARAM_TAG)) {
+237             setParameter(currentElement, propSetter);
+238 	  }
+239 	  // Set appender layout
+240 	  else if (currentElement.getTagName().equals(LAYOUT_TAG)) {
+241 	    appender.setLayout(parseLayout(currentElement));
+242 	  }
+243 	  // Add filters
+244 	  else if (currentElement.getTagName().equals(FILTER_TAG)) {
+245 	    parseFilters(currentElement, appender);
+246 	  }
+247 	  else if (currentElement.getTagName().equals(ERROR_HANDLER_TAG)) {
+248 	    parseErrorHandler(currentElement, appender);
+249 	  }
+250 	  else if (currentElement.getTagName().equals(APPENDER_REF_TAG)) {
+251 	    String refName = subst(currentElement.getAttribute(REF_ATTR));
+252 	    if(appender instanceof AppenderAttachable) {
+253 	      AppenderAttachable aa = (AppenderAttachable) appender;
+254 	      LogLog.debug("Attaching appender named ["+ refName+
+255 			   "] to appender named ["+ appender.getName()+"].");
+256 	      aa.addAppender(findAppenderByReference(currentElement));
+257 	    } else {
+258 	      LogLog.error("Requesting attachment of appender named ["+
+259 			   refName+ "] to appender named ["+ appender.getName()+
+260                 "] which does not implement org.apache.log4j.spi.AppenderAttachable.");
+261 	    }
+262 	  } else {
+263           parseUnrecognizedElement(instance, currentElement, props);
+264       }
+265 	}
+266       }
+267       propSetter.activate();
+268       return appender;
+269     }
+270     /* Yes, it's ugly.  But all of these exceptions point to the same
+271        problem: we can't create an Appender */
+272     catch (Exception oops) {
+273       LogLog.error("Could not create an Appender. Reported error follows.",
+274 		   oops);
+275       return null;
+276     }
+277   }
+278 
+279   /***
+280      Used internally to parse an {@link ErrorHandler} element.
+281    */
+282   protected
+283   void parseErrorHandler(Element element, Appender appender) {
+284     ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByClassName(
+285                                        subst(element.getAttribute(CLASS_ATTR)),
+286                                        org.apache.log4j.spi.ErrorHandler.class, 
+287  				       null);
+288     
+289     if(eh != null) {
+290       eh.setAppender(appender);
+291 
+292       PropertySetter propSetter = new PropertySetter(eh);
+293       NodeList children = element.getChildNodes();
+294       final int length 	= children.getLength();
+295 
+296       for (int loop = 0; loop < length; loop++) {
+297 	Node currentNode = children.item(loop);
+298 	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+299 	  Element currentElement = (Element) currentNode;
+300 	  String tagName = currentElement.getTagName();
+301 	  if(tagName.equals(PARAM_TAG)) {
+302             setParameter(currentElement, propSetter);
+303 	  } else if(tagName.equals(APPENDER_REF_TAG)) {
+304 	    eh.setBackupAppender(findAppenderByReference(currentElement));
+305 	  } else if(tagName.equals(LOGGER_REF)) {
+306 	    String loggerName = currentElement.getAttribute(REF_ATTR);	    
+307 	    Logger logger = (catFactory == null) ? repository.getLogger(loggerName)
+308                 : repository.getLogger(loggerName, catFactory);
+309 	    eh.setLogger(logger);
+310 	  } else if(tagName.equals(ROOT_REF)) {
+311 	    Logger root = repository.getRootLogger();
+312 	    eh.setLogger(root);
+313 	  } else {
+314           quietParseUnrecognizedElement(eh, currentElement, props);
+315       }
+316 	}
+317       }
+318       propSetter.activate();
+319       appender.setErrorHandler(eh);
+320     }
+321   }
+322   
+323   /***
+324      Used internally to parse a filter element.
+325    */
+326   protected
+327   void parseFilters(Element element, Appender appender) {
+328     String clazz = subst(element.getAttribute(CLASS_ATTR));
+329     Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz,
+330                                                 Filter.class, null);
+331     
+332     if(filter != null) {
+333       PropertySetter propSetter = new PropertySetter(filter);
+334       NodeList children = element.getChildNodes();
+335       final int length 	= children.getLength();
+336 
+337       for (int loop = 0; loop < length; loop++) {
+338 	Node currentNode = children.item(loop);
+339 	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+340 	  Element currentElement = (Element) currentNode;
+341 	  String tagName = currentElement.getTagName();
+342 	  if(tagName.equals(PARAM_TAG)) {
+343             setParameter(currentElement, propSetter);
+344 	  } else {
+345             quietParseUnrecognizedElement(filter, currentElement, props);
+346       }
+347 	}
+348       }
+349       propSetter.activate();
+350       LogLog.debug("Adding filter of type ["+filter.getClass()
+351 		   +"] to appender named ["+appender.getName()+"].");
+352       appender.addFilter(filter);
+353     }    
+354   }
+355   
+356   /***
+357      Used internally to parse an category element.
+358   */
+359   protected
+360   void parseCategory (Element loggerElement) {
+361     // Create a new org.apache.log4j.Category object from the <category> element.
+362     String catName = subst(loggerElement.getAttribute(NAME_ATTR));
+363 
+364     Logger cat;    
+365 
+366     String className = subst(loggerElement.getAttribute(CLASS_ATTR));
+367 
+368 
+369     if(EMPTY_STR.equals(className)) {
+370       LogLog.debug("Retreiving an instance of org.apache.log4j.Logger.");
+371       cat = (catFactory == null) ? repository.getLogger(catName) : repository.getLogger(catName, catFactory);
+372     }
+373     else {
+374       LogLog.debug("Desired logger sub-class: ["+className+']');
+375        try {	 
+376 	 Class clazz = Loader.loadClass(className);
+377 	 Method getInstanceMethod = clazz.getMethod("getLogger", 
+378 						    ONE_STRING_PARAM);
+379 	 cat = (Logger) getInstanceMethod.invoke(null, new Object[] {catName});
+380        } catch (Exception oops) {
+381 	 LogLog.error("Could not retrieve category ["+catName+
+382 		      "]. Reported error follows.", oops);
+383 	 return;
+384        }
+385     }
+386 
+387     // Setting up a category needs to be an atomic operation, in order
+388     // to protect potential log operations while category
+389     // configuration is in progress.
+390     synchronized(cat) {
+391       boolean additivity = OptionConverter.toBoolean(
+392                            subst(loggerElement.getAttribute(ADDITIVITY_ATTR)),
+393 			   true);
+394     
+395       LogLog.debug("Setting ["+cat.getName()+"] additivity to ["+additivity+"].");
+396       cat.setAdditivity(additivity);
+397       parseChildrenOfLoggerElement(loggerElement, cat, false);
+398     }
+399   }
+400 
+401 
+402   /***
+403      Used internally to parse the category factory element.
+404   */
+405   protected
+406   void parseCategoryFactory(Element factoryElement) {
+407     String className = subst(factoryElement.getAttribute(CLASS_ATTR));
+408 
+409     if(EMPTY_STR.equals(className)) {
+410       LogLog.error("Category Factory tag " + CLASS_ATTR + " attribute not found.");
+411       LogLog.debug("No Category Factory configured.");
+412     }
+413     else {
+414       LogLog.debug("Desired category factory: ["+className+']');
+415       Object factory = OptionConverter.instantiateByClassName(className,
+416                                                                  LoggerFactory.class, 
+417                                                                  null);
+418       if (factory instanceof LoggerFactory) {
+419           catFactory = (LoggerFactory) factory;
+420       } else {
+421           LogLog.error("Category Factory class " + className + " does not implement org.apache.log4j.LoggerFactory");
+422       }
+423       PropertySetter propSetter = new PropertySetter(factory);
+424 
+425       Element  currentElement = null;
+426       Node     currentNode    = null;
+427       NodeList children       = factoryElement.getChildNodes();
+428       final int length        = children.getLength();
+429 
+430       for (int loop=0; loop < length; loop++) {
+431         currentNode = children.item(loop);
+432 	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+433 	  currentElement = (Element)currentNode;
+434 	  if (currentElement.getTagName().equals(PARAM_TAG)) {
+435 	    setParameter(currentElement, propSetter);
+436 	  } else {
+437            quietParseUnrecognizedElement(factory, currentElement, props);
+438       }
+439 	}
+440       }
+441     }
+442   }
+443 
+444 
+445   /***
+446      Used internally to parse the roor category element.
+447   */
+448   protected
+449   void parseRoot (Element rootElement) {
+450     Logger root = repository.getRootLogger();
+451     // category configuration needs to be atomic
+452     synchronized(root) {    
+453       parseChildrenOfLoggerElement(rootElement, root, true);
+454     }
+455   }
+456 
+457 
+458   /***
+459      Used internally to parse the children of a category element.
+460   */
+461   protected
+462   void parseChildrenOfLoggerElement(Element catElement,
+463 				      Logger cat, boolean isRoot) {
+464     
+465     PropertySetter propSetter = new PropertySetter(cat);
+466     
+467     // Remove all existing appenders from cat. They will be
+468     // reconstructed if need be.
+469     cat.removeAllAppenders();
+470 
+471 
+472     NodeList children 	= catElement.getChildNodes();
+473     final int length 	= children.getLength();
+474     
+475     for (int loop = 0; loop < length; loop++) {
+476       Node currentNode = children.item(loop);
+477 
+478       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+479 	Element currentElement = (Element) currentNode;
+480 	String tagName = currentElement.getTagName();
+481 	
+482 	if (tagName.equals(APPENDER_REF_TAG)) {
+483 	  Element appenderRef = (Element) currentNode;
+484 	  Appender appender = findAppenderByReference(appenderRef);
+485 	  String refName =  subst(appenderRef.getAttribute(REF_ATTR));
+486 	  if(appender != null)
+487 	    LogLog.debug("Adding appender named ["+ refName+ 
+488 			 "] to category ["+cat.getName()+"].");
+489 	  else 
+490 	    LogLog.debug("Appender named ["+ refName + "] not found.");
+491 	    
+492 	  cat.addAppender(appender);
+493 	  
+494 	} else if(tagName.equals(LEVEL_TAG)) {
+495 	  parseLevel(currentElement, cat, isRoot);	
+496 	} else if(tagName.equals(PRIORITY_TAG)) {
+497 	  parseLevel(currentElement, cat, isRoot);
+498 	} else if(tagName.equals(PARAM_TAG)) {
+499           setParameter(currentElement, propSetter);
+500 	} else {
+501         quietParseUnrecognizedElement(cat, currentElement, props);
+502     }
+503       }
+504     }
+505     propSetter.activate();
+506   }
+507 
+508   /***
+509      Used internally to parse a layout element.
+510   */  
+511   protected
+512   Layout parseLayout (Element layout_element) {
+513     String className = subst(layout_element.getAttribute(CLASS_ATTR));
+514     LogLog.debug("Parsing layout of class: \""+className+"\"");		 
+515     try {
+516       Object instance 	= Loader.loadClass(className).newInstance();
+517       Layout layout   	= (Layout)instance;
+518       PropertySetter propSetter = new PropertySetter(layout);
+519       
+520       NodeList params 	= layout_element.getChildNodes();
+521       final int length 	= params.getLength();
+522 
+523       for (int loop = 0; loop < length; loop++) {
+524 	Node currentNode = (Node)params.item(loop);
+525 	if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+526 	  Element currentElement = (Element) currentNode;
+527 	  String tagName = currentElement.getTagName();
+528 	  if(tagName.equals(PARAM_TAG)) {
+529             setParameter(currentElement, propSetter);
+530 	  } else {
+531           parseUnrecognizedElement(instance, currentElement, props);
+532       }
+533 	}
+534       }
+535       
+536       propSetter.activate();
+537       return layout;
+538     }
+539     catch (Exception oops) {
+540       LogLog.error("Could not create the Layout. Reported error follows.",
+541 		   oops);
+542       return null;
+543     }
+544   }
+545 
+546   protected 
+547   void parseRenderer(Element element) {
+548     String renderingClass = subst(element.getAttribute(RENDERING_CLASS_ATTR));
+549     String renderedClass = subst(element.getAttribute(RENDERED_CLASS_ATTR));
+550     if(repository instanceof RendererSupport) {
+551       RendererMap.addRenderer((RendererSupport) repository, renderedClass, 
+552 			      renderingClass);
+553     }
+554   }
+555 
+556   /***
+557      Used internally to parse a level  element.
+558   */
+559   protected
+560   void parseLevel(Element element, Logger logger, boolean isRoot) {
+561     String catName = logger.getName();
+562     if(isRoot) {
+563       catName = "root";
+564     }
+565 
+566     String priStr = subst(element.getAttribute(VALUE_ATTR));
+567     LogLog.debug("Level value for "+catName+" is  ["+priStr+"].");
+568     
+569     if(INHERITED.equalsIgnoreCase(priStr) || NULL.equalsIgnoreCase(priStr)) {
+570       if(isRoot) {
+571 	LogLog.error("Root level cannot be inherited. Ignoring directive.");
+572       } else {
+573 	logger.setLevel(null);
+574       }
+575     } else {
+576       String className = subst(element.getAttribute(CLASS_ATTR));      
+577       if(EMPTY_STR.equals(className)) {	
+578 	logger.setLevel(OptionConverter.toLevel(priStr, Level.DEBUG));
+579       } else {
+580 	LogLog.debug("Desired Level sub-class: ["+className+']');
+581 	try {	 
+582 	  Class clazz = Loader.loadClass(className);
+583 	  Method toLevelMethod = clazz.getMethod("toLevel", 
+584 						    ONE_STRING_PARAM);
+585 	  Level pri = (Level) toLevelMethod.invoke(null, 
+586 						    new Object[] {priStr});
+587 	  logger.setLevel(pri);
+588 	} catch (Exception oops) {
+589 	  LogLog.error("Could not create level ["+priStr+
+590 		       "]. Reported error follows.", oops);
+591 	  return;
+592 	}
+593       }
+594     }
+595     LogLog.debug(catName + " level set to " + logger.getLevel());    
+596   }
+597 
+598   protected
+599   void setParameter(Element elem, PropertySetter propSetter) {
+600       setParameter(elem, propSetter, props);
+601   }
+602 
+603 
+604   /***
+605      Configure log4j using a <code>configuration</code> element as
+606      defined in the log4j.dtd. 
+607 
+608   */
+609   static
+610   public
+611   void configure (Element element) {
+612     DOMConfigurator configurator = new DOMConfigurator();
+613     configurator.doConfigure(element,  LogManager.getLoggerRepository());
+614   }
+615 
+616  /***
+617      Like {@link #configureAndWatch(String, long)} except that the
+618      default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is
+619      used. 
+620 
+621      @param configFilename A log4j configuration file in XML format.
+622 
+623   */
+624   static
+625   public
+626   void configureAndWatch(String configFilename) {
+627     configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY);
+628   }
+629 
+630   /***
+631      Read the configuration file <code>configFilename</code> if it
+632      exists. Moreover, a thread will be created that will periodically
+633      check if <code>configFilename</code> has been created or
+634      modified. The period is determined by the <code>delay</code>
+635      argument. If a change or file creation is detected, then
+636      <code>configFilename</code> is read to configure log4j.  
+637 
+638       @param configFilename A log4j configuration file in XML format.
+639       @param delay The delay in milliseconds to wait between each check.
+640   */
+641   static
+642   public
+643   void configureAndWatch(String configFilename, long delay) {
+644     XMLWatchdog xdog = new XMLWatchdog(configFilename);
+645     xdog.setDelay(delay);
+646     xdog.start();
+647   }
+648   
+649   private interface ParseAction {
+650       Document parse(final DocumentBuilder parser) throws SAXException, IOException;
+651   }
+652 
+653 
+654   public
+655   void doConfigure(final String filename, LoggerRepository repository) {
+656     ParseAction action = new ParseAction() {
+657           public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
+658               return parser.parse(new File(filename));
+659           }
+660           public String toString() { 
+661               return "file [" + filename + "]"; 
+662           }
+663     };
+664     doConfigure(action, repository);
+665   }
+666   
+667 
+668   public
+669   void doConfigure(final URL url, LoggerRepository repository) {
+670       ParseAction action = new ParseAction() {
+671           public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
+672               return parser.parse(url.toString());
+673           }
+674           public String toString() { 
+675               return "url [" + url.toString() + "]"; 
+676           }
+677       };
+678       doConfigure(action, repository);
+679   }
+680 
+681   /***
+682      Configure log4j by reading in a log4j.dtd compliant XML
+683      configuration file.
+684 
+685   */
+686   public
+687   void doConfigure(final InputStream inputStream, LoggerRepository repository) 
+688                                           throws FactoryConfigurationError {
+689       ParseAction action = new ParseAction() {
+690           public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
+691               InputSource inputSource = new InputSource(inputStream);
+692               inputSource.setSystemId("dummy://log4j.dtd");
+693               return parser.parse(inputSource);
+694           }
+695           public String toString() { 
+696               return "input stream [" + inputStream.toString() + "]"; 
+697           }
+698       };
+699       doConfigure(action, repository);
+700   }
+701 
+702   /***
+703      Configure log4j by reading in a log4j.dtd compliant XML
+704      configuration file.
+705 
+706   */
+707   public
+708   void doConfigure(final Reader reader, LoggerRepository repository) 
+709                                           throws FactoryConfigurationError {
+710       ParseAction action = new ParseAction() {
+711           public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
+712               InputSource inputSource = new InputSource(reader);
+713               inputSource.setSystemId("dummy://log4j.dtd");
+714               return parser.parse(inputSource);
+715           }
+716           public String toString() { 
+717               return "reader [" + reader.toString() + "]"; 
+718           }
+719       };
+720     doConfigure(action, repository);
+721   }
+722 
+723   /***
+724      Configure log4j by reading in a log4j.dtd compliant XML
+725      configuration file.
+726 
+727   */
+728   protected
+729   void doConfigure(final InputSource inputSource, LoggerRepository repository) 
+730                                           throws FactoryConfigurationError {
+731       if (inputSource.getSystemId() == null) {
+732           inputSource.setSystemId("dummy://log4j.dtd");
+733       }
+734       ParseAction action = new ParseAction() {
+735           public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
+736               return parser.parse(inputSource);
+737           }
+738           public String toString() { 
+739               return "input source [" + inputSource.toString() + "]"; 
+740           }
+741       };
+742       doConfigure(action, repository);
+743     }
+744     
+745     
+746   private final void doConfigure(final ParseAction action, final LoggerRepository repository)
+747          throws FactoryConfigurationError {
+748     DocumentBuilderFactory dbf = null;
+749     this.repository = repository;
+750     try { 
+751       LogLog.debug("System property is :"+
+752   	                        OptionConverter.getSystemProperty(dbfKey, 
+753 								  null)); 
+754       dbf = DocumentBuilderFactory.newInstance();
+755       LogLog.debug("Standard DocumentBuilderFactory search succeded.");
+756       LogLog.debug("DocumentBuilderFactory is: "+dbf.getClass().getName());
+757     } catch(FactoryConfigurationError fce) {
+758       Exception e = fce.getException();
+759       LogLog.debug("Could not instantiate a DocumentBuilderFactory.", e);
+760       throw fce;
+761     }
+762       
+763     try {
+764       dbf.setValidating(true);
+765 
+766       DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+767 
+768       docBuilder.setErrorHandler(new SAXErrorHandler());      
+769       docBuilder.setEntityResolver(new Log4jEntityResolver());
+770          
+771       Document doc = action.parse(docBuilder);     
+772       parse(doc.getDocumentElement());
+773     } catch (Exception e) {
+774       // I know this is miserable...
+775       LogLog.error("Could not parse "+ action.toString() + ".", e);
+776     }
+777   }
+778 
+779   /***
+780      Configure by taking in an DOM element. 
+781   */
+782   public void doConfigure(Element element, LoggerRepository repository) {
+783     this.repository = repository;
+784     parse(element);
+785   }
+786 
+787   
+788   /***
+789      A static version of {@link #doConfigure(String, LoggerRepository)}.  */
+790   static
+791   public
+792   void configure(String filename) throws FactoryConfigurationError {
+793     new DOMConfigurator().doConfigure(filename,
+794 				      LogManager.getLoggerRepository());
+795   }
+796 
+797   /***
+798      A static version of {@link #doConfigure(URL, LoggerRepository)}.
+799    */
+800   static
+801   public
+802   void configure(URL url) throws FactoryConfigurationError {
+803     new DOMConfigurator().doConfigure(url, LogManager.getLoggerRepository());
+804   }
+805 
+806   /***
+807      Used internally to configure the log4j framework by parsing a DOM
+808      tree of XML elements based on <a
+809      href="doc-files/log4j.dtd">log4j.dtd</a>.
+810      
+811   */
+812   protected
+813   void parse(Element element) {
+814 
+815     String rootElementName = element.getTagName();
+816 
+817     if (!rootElementName.equals(CONFIGURATION_TAG)) {
+818       if(rootElementName.equals(OLD_CONFIGURATION_TAG)) {
+819 	LogLog.warn("The <"+OLD_CONFIGURATION_TAG+
+820 		     "> element has been deprecated.");
+821 	LogLog.warn("Use the <"+CONFIGURATION_TAG+"> element instead.");
+822       } else {
+823 	LogLog.error("DOM element is - not a <"+CONFIGURATION_TAG+"> element.");
+824 	return;
+825       }
+826     }
+827 
+828     String debugAttrib = subst(element.getAttribute(INTERNAL_DEBUG_ATTR));
+829       
+830     LogLog.debug("debug attribute= \"" + debugAttrib +"\".");
+831     // if the log4j.dtd is not specified in the XML file, then the
+832     // "debug" attribute is returned as the empty string.
+833     if(!debugAttrib.equals("") && !debugAttrib.equals("null")) {      
+834       LogLog.setInternalDebugging(OptionConverter.toBoolean(debugAttrib, true));
+835     } else {
+836       LogLog.debug("Ignoring " + INTERNAL_DEBUG_ATTR + " attribute.");
+837     }
+838 
+839       //
+840       //   reset repository before configuration if reset="true"
+841       //       on configuration element.
+842       //
+843     String resetAttrib = subst(element.getAttribute(RESET_ATTR));
+844     LogLog.debug("reset attribute= \"" + resetAttrib +"\".");
+845     if(!("".equals(resetAttrib))) {
+846          if (OptionConverter.toBoolean(resetAttrib, false)) {
+847              repository.resetConfiguration();
+848          }
+849     }
+850 
+851 
+852     String confDebug = subst(element.getAttribute(CONFIG_DEBUG_ATTR));
+853     if(!confDebug.equals("") && !confDebug.equals("null")) {      
+854       LogLog.warn("The \""+CONFIG_DEBUG_ATTR+"\" attribute is deprecated.");
+855       LogLog.warn("Use the \""+INTERNAL_DEBUG_ATTR+"\" attribute instead.");
+856       LogLog.setInternalDebugging(OptionConverter.toBoolean(confDebug, true));
+857     }
+858 
+859     String thresholdStr = subst(element.getAttribute(THRESHOLD_ATTR));
+860     LogLog.debug("Threshold =\"" + thresholdStr +"\".");
+861     if(!"".equals(thresholdStr) && !"null".equals(thresholdStr)) {
+862       repository.setThreshold(thresholdStr);
+863     }
+864 
+865     //Hashtable appenderBag = new Hashtable(11);
+866 
+867     /* Building Appender objects, placing them in a local namespace
+868        for future reference */
+869 
+870     // First configure each category factory under the root element.
+871     // Category factories need to be configured before any of
+872     // categories they support.
+873     //
+874     String   tagName = null;
+875     Element  currentElement = null;
+876     Node     currentNode = null;
+877     NodeList children = element.getChildNodes();
+878     final int length = children.getLength();
+879 
+880     for (int loop = 0; loop < length; loop++) {
+881       currentNode = children.item(loop);
+882       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+883 	currentElement = (Element) currentNode;
+884 	tagName = currentElement.getTagName();
+885 
+886 	if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
+887 	  parseCategoryFactory(currentElement);
+888 	}
+889       }
+890     }
+891     
+892     for (int loop = 0; loop < length; loop++) {
+893       currentNode = children.item(loop);
+894       if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+895 	currentElement = (Element) currentNode;
+896 	tagName = currentElement.getTagName();
+897 
+898 	if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
+899 	  parseCategory(currentElement);
+900 	} else if (tagName.equals(ROOT_TAG)) {
+901 	  parseRoot(currentElement);
+902 	} else if(tagName.equals(RENDERER_TAG)) {
+903 	  parseRenderer(currentElement);
+904 	} else if (!(tagName.equals(APPENDER_TAG)
+905             || tagName.equals(CATEGORY_FACTORY_TAG)
+906             || tagName.equals(LOGGER_FACTORY_TAG))) {
+907         quietParseUnrecognizedElement(repository, currentElement, props);
+908     }
+909       }
+910     }
+911   }
+912 
+913   
+914   protected
+915   String subst(final String value) {
+916       return subst(value, props);
+917   }
+918 
+919     /***
+920      * Substitutes property value for any references in expression.
+921      *
+922      * @param value value from configuration file, may contain
+923      *              literal text, property references or both
+924      * @param props properties.
+925      * @return evaluated expression, may still contain expressions
+926      *         if unable to expand.
+927      * @since 1.2.15
+928      */
+929     public static String subst(final String value, final Properties props) {
+930         try {
+931             return OptionConverter.substVars(value, props);
+932         } catch (IllegalArgumentException e) {
+933             LogLog.warn("Could not perform variable substitution.", e);
+934             return value;
+935         }
+936     }
+937 
+938 
+939     /***
+940      * Sets a parameter based from configuration file content.
+941      *
+942      * @param elem       param element, may not be null.
+943      * @param propSetter property setter, may not be null.
+944      * @param props      properties
+945      * @since 1.2.15
+946      */
+947     public static void setParameter(final Element elem,
+948                                     final PropertySetter propSetter,
+949                                     final Properties props) {
+950         String name = subst(elem.getAttribute("name"), props);
+951         String value = (elem.getAttribute("value"));
+952         value = subst(OptionConverter.convertSpecialChars(value), props);
+953         propSetter.setProperty(name, value);
+954     }
+955 
+956 
+957     /***
+958      * Creates an OptionHandler and processes any nested param elements
+959      * but does not call activateOptions.  If the class also supports
+960      * UnrecognizedElementParser, the parseUnrecognizedElement method
+961      * will be call for any child elements other than param.
+962      *
+963      * @param element       element, may not be null.
+964      * @param props         properties
+965      * @param expectedClass interface or class expected to be implemented
+966      *                      by created class
+967      * @return created class or null.
+968      * @throws Exception thrown if the contain object should be abandoned.
+969      * @since 1.2.15
+970      */
+971     public static OptionHandler parseElement(final Element element,
+972                                              final Properties props,
+973                                              final Class expectedClass) throws Exception {
+974         String clazz = subst(element.getAttribute("class"), props);
+975         Object instance = OptionConverter.instantiateByClassName(clazz,
+976                 expectedClass, null);
+977 
+978         if (instance instanceof OptionHandler) {
+979             OptionHandler optionHandler = (OptionHandler) instance;
+980             PropertySetter propSetter = new PropertySetter(optionHandler);
+981             NodeList children = element.getChildNodes();
+982             final int length = children.getLength();
+983 
+984             for (int loop = 0; loop < length; loop++) {
+985                 Node currentNode = children.item(loop);
+986                 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
+987                     Element currentElement = (Element) currentNode;
+988                     String tagName = currentElement.getTagName();
+989                     if (tagName.equals("param")) {
+990                         setParameter(currentElement, propSetter, props);
+991                     } else {
+992                          parseUnrecognizedElement(instance, currentElement, props);
+993                     }
+994                 }
+995             }
+996             return optionHandler;
+997         }
+998         return null;
+999     }
+1000 
+1001     private static class XMLWatchdog extends FileWatchdog {
+1002 
+1003         XMLWatchdog(String filename) {
+1004         super(filename);
+1005       }
+1006 
+1007       /***
+1008          Call {@link DOMConfigurator#configure(String)} with the
+1009          <code>filename</code> to reconfigure log4j. */
+1010       public
+1011       void doOnChange() {
+1012         new DOMConfigurator().doConfigure(filename,
+1013                           LogManager.getLoggerRepository());
+1014       }
+1015     }
+1016 
+1017 
+1018     /***
+1019      * An {@link EntityResolver} specifically designed to return
+1020      * <code>log4j.dtd</code> which is embedded within the log4j jar
+1021      * file.
+1022      *
+1023      * @author Paul Austin
+1024      * */
+1025     private static final class Log4jEntityResolver implements EntityResolver {
+1026 
+1027       public InputSource resolveEntity (String publicId, String systemId) {
+1028         if (systemId.endsWith("log4j.dtd")) {
+1029           InputStream in = Log4jEntityResolver.class.getResourceAsStream("log4j.dtd");
+1030           if (in == null) {
+1031             LogLog.warn("Could not find [log4j.dtd] using [" +
+1032                     Log4jEntityResolver.class.getClassLoader()
+1033                  + "] class loader, parsed without DTD.");
+1034             in = new ByteArrayInputStream(new byte[0]);
+1035           }
+1036           return new InputSource(in);
+1037         } else {
+1038           return null;
+1039         }
+1040       }
+1041     }
+1042 
+1043 
+1044 }
+1045 
+1046 
+
+
+ + Propchange: logging/site/trunk/docs/log4j/companions/extras/xref/org/apache/log4j/extras/DOMConfigurator.html ------------------------------------------------------------------------------ svn:mime-type = text/html