ceki 2004/12/10 11:08:37 Modified: src/java/org/apache/log4j/joran JoranConfigurator.java Added: src/java/org/apache/log4j/joran/util JoranDocument.java Log: - Joran now replays events instead of two-passes. - Contributed by Curt Arnold, http://issues.eu.apache.org/bugzilla/show_bug.cgi?id=32478 Revision Changes Path 1.1 logging-log4j/src/java/org/apache/log4j/joran/util/JoranDocument.java Index: JoranDocument.java =================================================================== /* * Copyright 1999,2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.log4j.joran.util; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.helpers.Constants; import org.apache.log4j.spi.ErrorItem; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.LocatorImpl; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Collects all configuration significant elements from * an XML parse. * */ public final class JoranDocument extends DefaultHandler { public static final String LOG4J_NS = "http://jakarta.apache.org/log4j/"; public static final String LS_NS = "http://logging.apache.org/"; private final List errorList; private final List events = new ArrayList(20); private SAXParseException fatalError; private Locator location; public JoranDocument(final List errorList) { this.errorList = errorList; } public void error(final SAXParseException spe) { errorReport(spe); } public void fatalError(final SAXParseException spe) { if (fatalError == null) { fatalError = spe; } errorReport(spe); } public void warning(final SAXParseException spe) { errorReport(spe); } private void errorReport(final SAXParseException spe) { int line = spe.getLineNumber(); ErrorItem errorItem = new ErrorItem("Parsing warning", spe); errorItem.setLineNumber(line); errorItem.setColNumber(spe.getColumnNumber()); errorList.add(errorItem); } public void startElement( final String namespaceURI, final String localName, final String qName, final Attributes attributes) { if ( (namespaceURI == null) || (namespaceURI.length() == 0) || namespaceURI.equals(LOG4J_NS) || namespaceURI.equals(LS_NS)) { events.add(new StartElementEvent(localName, location, attributes)); } } public void endElement( final String namespaceURI, final String localName, final String qName) { if ( (namespaceURI == null) || (namespaceURI.length() == 0) || namespaceURI.equals(LOG4J_NS)) { events.add(new EndElementEvent(localName, location)); } } public void replay(final ContentHandler handler) throws SAXException { if (fatalError != null) { throw fatalError; } LocatorImpl replayLocation = new LocatorImpl(); handler.setDocumentLocator(replayLocation); for (Iterator iter = events.iterator(); iter.hasNext();) { ElementEvent event = (ElementEvent) iter.next(); event.replay(handler, replayLocation); } } public InputSource resolveEntity( final String publicId, final String systemId) throws SAXException { // // if log4j.dtd is requested then // return an empty input source. // We aren't validating and do not need anything from // the dtd and do not want a failure if it isn't present. if ((systemId != null) && systemId.endsWith("log4j.dtd")) { Logger logger = LogManager.getLogger(this.getClass().getName()); logger.warn("The 'log4j.dtd' is no longer used nor needed."); logger.warn("See {}#log4j_dtd for more details.", Constants.CODES_HREF); return new InputSource(new ByteArrayInputStream(new byte[0])); } return super.resolveEntity(publicId, systemId); } public void setDocumentLocator(Locator location) { this.location = location; } private abstract static class ElementEvent { private String localName; private Locator location; ElementEvent(final String localName, final Locator location) { this.localName = localName; if (location != null) { this.location = new LocatorImpl(location); } } public final String getLocalName() { return localName; } public void replay( final ContentHandler handler, final LocatorImpl replayLocation) throws SAXException { if (location != null) { replayLocation.setPublicId(location.getPublicId()); replayLocation.setColumnNumber(location.getColumnNumber()); replayLocation.setLineNumber(location.getLineNumber()); replayLocation.setSystemId(location.getSystemId()); } } } private static class EndElementEvent extends ElementEvent { public EndElementEvent(final String localName, final Locator location) { super(localName, location); } public void replay( final ContentHandler handler, final LocatorImpl replayLocation) throws SAXException { super.replay(handler, replayLocation); handler.endElement( JoranDocument.LOG4J_NS, getLocalName(), getLocalName()); } } private static class StartElementEvent extends ElementEvent { private Attributes attributes; public StartElementEvent( final String localName, final Locator location, final Attributes attributes) { super(localName, location); this.attributes = new AttributesImpl(attributes); } public void replay( final ContentHandler handler, final LocatorImpl replayLocation) throws SAXException { super.replay(handler, replayLocation); handler.startElement( JoranDocument.LOG4J_NS, getLocalName(), getLocalName(), attributes); } } } 1.26 +105 -116 logging-log4j/src/java/org/apache/log4j/joran/JoranConfigurator.java Index: JoranConfigurator.java =================================================================== RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/joran/JoranConfigurator.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- JoranConfigurator.java 6 Dec 2004 21:07:56 -0000 1.25 +++ JoranConfigurator.java 10 Dec 2004 19:08:37 -0000 1.26 @@ -40,14 +40,15 @@ import org.apache.log4j.joran.action.RepositoryPropertyAction; import org.apache.log4j.joran.action.RootLoggerAction; import org.apache.log4j.joran.action.SubstitutionPropertyAction; -import org.apache.log4j.joran.util.XMLUtil; +import org.apache.log4j.joran.util.JoranDocument; import org.apache.log4j.spi.ErrorItem; import org.apache.log4j.spi.LoggerRepository; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; -import java.io.FileInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -56,7 +57,6 @@ import java.util.HashMap; import java.util.List; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -76,165 +76,154 @@ public JoranConfigurator() { selfInitialize(); } - - public void doConfigure(URL url, LoggerRepository repository) { + + protected interface ParseAction { + void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException; + } + + final public void doConfigure(final URL url, final LoggerRepository repository) { + ParseAction action = new ParseAction() { + public void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException { + parser.parse(url.toString(), handler); + } + }; + doConfigure(action, repository); + } + + final public void doConfigure(final String filename, final LoggerRepository repository) { + ParseAction action = new ParseAction() { + public void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException { + parser.parse(new File(filename), handler); + } + }; + doConfigure(action, repository); + } + + final public void doConfigure(final File file, final LoggerRepository repository) { + ParseAction action = new ParseAction() { + public void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException { + parser.parse(file, handler); + } + }; + doConfigure(action, repository); + } + + final public void doConfigure(final InputSource source, final LoggerRepository repository) { + ParseAction action = new ParseAction() { + public void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException { + parser.parse(source, handler); + } + }; + doConfigure(action, repository); + } + + final public void doConfigure(final InputStream stream, final LoggerRepository repository) { + ParseAction action = new ParseAction() { + public void parse(final SAXParser parser, final DefaultHandler handler) throws SAXException, IOException { + parser.parse(stream, handler); + } + }; + doConfigure(action, repository); + } + + protected void doConfigure(final ParseAction action, final LoggerRepository repository) { // This line is needed here because there is logging from inside this method. this.repository = repository; ExecutionContext ec = joranInterpreter.getExecutionContext(); List errorList = ec.getErrorList(); - int result = XMLUtil.checkIfWellFormed(url, errorList); - switch (result) { - case XMLUtil.ILL_FORMED: - case XMLUtil.UNRECOVERABLE_ERROR: - errorList.add( - new ErrorItem( - "Problem parsing XML document. See previously reported errors. Abandoning all further processing.")); + SAXParser saxParser = null; + try { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setValidating(false); + spf.setNamespaceAware(true); + saxParser = spf.newSAXParser(); + } catch (Exception pce) { + final String errMsg = "Parser configuration error occured"; + getLogger(repository).error(errMsg, pce); + ec.addError(new ErrorItem(errMsg, pce)); return; } - - String errMsg; + + JoranDocument document = new JoranDocument(errorList); + try { - InputStream in = url.openStream(); - doConfigure(in, repository); - in.close(); - } catch (IOException ioe) { - errMsg = "Could not open [" + url + "]."; - getLogger(repository).error(errMsg, ioe); - ec.addError(new ErrorItem(errMsg, ioe)); - } - } - - public List getErrorList() { - return getExecutionContext().getErrorList(); - } - - /** - * Configure a repository from a configuration file passed as parameter. - */ - public void doConfigure(String filename, LoggerRepository repository) { - // This line is needed here because there is logging from inside this method. - this.repository = repository; - getLogger(repository).info( - "in JoranConfigurator doConfigure {}", filename); - - ExecutionContext ec = joranInterpreter.getExecutionContext(); - List errorList = ec.getErrorList(); - - int result = XMLUtil.checkIfWellFormed(filename, errorList); - switch (result) { - case XMLUtil.ILL_FORMED: - case XMLUtil.UNRECOVERABLE_ERROR: + action.parse(saxParser, document); + } catch(IOException ie) { + final String errMsg = "I/O error occured while parsing xml file"; + getLogger(repository).error(errMsg, ie); + ec.addError(new ErrorItem(errMsg, ie)); + } catch (Exception ex) { + final String errMsg = "Problem parsing XML document. See previously reported errors. Abandoning all further processing."; + getLogger(repository).error(errMsg, ex); errorList.add( - new ErrorItem( - "Problem parsing XML document. See previously reported errors. Abandoning all furhter processing.")); + new ErrorItem(errMsg)); return; } - - FileInputStream fis = null; - try { - fis = new FileInputStream(filename); - doConfigure(fis, repository); - } catch (IOException ioe) { - String errMsg = "Could not open [" + filename + "]."; - getLogger(repository).error(errMsg, ioe); - ec.addError(new ErrorItem(errMsg, ioe)); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (java.io.IOException e) { - getLogger(repository).error( - "Could not close [" + filename + "].", e); - } - } - } - } - - /** - * Configure a repository from the input stream passed as parameter - */ - public void doConfigure(InputStream in, LoggerRepository repository) { - doConfigure(new InputSource(in), repository); - } - - /** - * All doConfigure methods evenually call this form. - * */ - public void doConfigure( - InputSource inputSource, LoggerRepository repository) { - this.repository = repository; - ExecutionContext ec = joranInterpreter.getExecutionContext(); + ec.pushObject(repository); String errMsg; try { attachListAppender(repository); - - getLogger(repository).debug("Starting to parse input source."); - SAXParserFactory spf = SAXParserFactory.newInstance(); - - // we want non-validating parsers - spf.setValidating(false); - SAXParser saxParser = spf.newSAXParser(); - saxParser.parse(inputSource, joranInterpreter); + document.replay(joranInterpreter); + getLogger(repository).debug("Finished parsing."); } catch (SAXException e) { // all exceptions should have been recorded already. - } catch (ParserConfigurationException pce) { - errMsg = "Parser configuration error occured"; - getLogger(repository).error(errMsg, pce); - ec.addError(new ErrorItem(errMsg, pce)); - } catch (IOException ie) { - errMsg = "I/O error occured while parsing xml file"; - ec.addError(new ErrorItem("Parser configuration error occured", ie)); } finally { detachListAppender(repository); } + + + } + + public List getErrorList() { + return getExecutionContext().getErrorList(); } + protected void selfInitialize() { RuleStore rs = new SimpleRuleStore(); - rs.addRule(new Pattern("log4j:configuration"), new ConfigurationAction()); + rs.addRule(new Pattern("configuration"), new ConfigurationAction()); rs.addRule( - new Pattern("log4j:configuration/substitutionProperty"), + new Pattern("configuration/substitutionProperty"), new SubstitutionPropertyAction()); rs.addRule( - new Pattern("log4j:configuration/repositoryProperty"), + new Pattern("configuration/repositoryProperty"), new RepositoryPropertyAction()); - rs.addRule(new Pattern("log4j:configuration/plugin"), new PluginAction()); - rs.addRule(new Pattern("log4j:configuration/logger"), new LoggerAction()); + rs.addRule(new Pattern("configuration/plugin"), new PluginAction()); + rs.addRule(new Pattern("configuration/logger"), new LoggerAction()); rs.addRule( - new Pattern("log4j:configuration/logger/level"), new LevelAction()); + new Pattern("configuration/logger/level"), new LevelAction()); rs.addRule( - new Pattern("log4j:configuration/logger/priority"), new PriorityAction()); + new Pattern("configuration/logger/priority"), new PriorityAction()); rs.addRule( - new Pattern("log4j:configuration/root"), new RootLoggerAction()); + new Pattern("configuration/root"), new RootLoggerAction()); rs.addRule( - new Pattern("log4j:configuration/root/level"), new LevelAction()); + new Pattern("configuration/root/level"), new LevelAction()); rs.addRule( - new Pattern("log4j:configuration/root/priority"), new PriorityAction()); + new Pattern("configuration/root/priority"), new PriorityAction()); rs.addRule( - new Pattern("log4j:configuration/logger/appender-ref"), + new Pattern("configuration/logger/appender-ref"), new AppenderRefAction()); rs.addRule( - new Pattern("log4j:configuration/root/appender-ref"), + new Pattern("configuration/root/appender-ref"), new AppenderRefAction()); rs.addRule( - new Pattern("log4j:configuration/appender"), new AppenderAction()); + new Pattern("configuration/appender"), new AppenderAction()); rs.addRule( - new Pattern("log4j:configuration/appender/layout"), new LayoutAction()); + new Pattern("configuration/appender/layout"), new LayoutAction()); rs.addRule( - new Pattern("log4j:configuration/appender/layout/conversionRule"), + new Pattern("configuration/appender/layout/conversionRule"), new ConversionRuleAction()); + rs.addRule( + new Pattern("log4j:configuration/jndiSubstitutionProperty"), + new JndiSubstitutionPropertyAction()); rs.addRule( - new Pattern("log4j:configuration/jndiSubstitutionProperty"), - new JndiSubstitutionPropertyAction()); - rs.addRule( - new Pattern("log4j:configuration/newRule"), new NewRuleAction()); + new Pattern("configuration/newRule"), new NewRuleAction()); rs.addRule(new Pattern("*/param"), new ParamAction()); - joranInterpreter = new Interpreter(rs);
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]