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]

Reply via email to