You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2003/10/20 10:15:27 UTC

cvs commit: cocoon-2.2/src/java/org/apache/cocoon/environment EnvironmentStack.java EnvironmentHelper.java

cziegeler    2003/10/20 01:15:27

  Modified:    src/java/org/apache/cocoon/servlet CocoonServlet.java
               src/java/org/apache/cocoon Constants.java Cocoon.java
               src/java/org/apache/cocoon/components/treeprocessor
                        TreeProcessor.java
               src/java/org/apache/cocoon/components/treeprocessor/sitemap
                        MountNode.java
               src/java/org/apache/cocoon/environment
                        EnvironmentHelper.java
  Added:       src/java/org/apache/cocoon/environment EnvironmentStack.java
  Log:
  Starting cleaner environment handling
  Removing deprecated code
  
  Revision  Changes    Path
  1.18      +8 -6      cocoon-2.2/src/java/org/apache/cocoon/servlet/CocoonServlet.java
  
  Index: CocoonServlet.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/servlet/CocoonServlet.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- CocoonServlet.java	19 Oct 2003 17:20:23 -0000	1.17
  +++ CocoonServlet.java	20 Oct 2003 08:15:27 -0000	1.18
  @@ -86,6 +86,7 @@
   import org.apache.avalon.framework.component.ComponentManager;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
  +import org.apache.avalon.framework.container.ContainerUtil;
   import org.apache.avalon.framework.context.Contextualizable;
   import org.apache.avalon.framework.context.DefaultContext;
   import org.apache.avalon.framework.logger.LogEnabled;
  @@ -1349,14 +1350,15 @@
                   getLogger().info("Reloading from: " + configFile.toExternalForm());
               }
               Cocoon c = (Cocoon) ClassUtils.newInstance("org.apache.cocoon.Cocoon");
  -            c.enableLogging( getCocoonLogger() );
  +            ContainerUtil.enableLogging(c, this.getCocoonLogger());
               c.setLoggerManager( getLoggerManager() );
  -            c.contextualize(this.appContext);
  -            c.compose(getParentComponentManager());
  +            ContainerUtil.contextualize(c, this.appContext);
  +            ContainerUtil.compose(c, getParentComponentManager());
  +            ContainerUtil.service(c, this.getParentComponentManager());
               if (this.enableInstrumentation) {
                   c.setInstrumentManager(getInstrumentManager());
               }
  -            c.initialize();
  +            ContainerUtil.initialize(c);
               this.creationTime = System.currentTimeMillis();
   
               disposeCocoon();
  @@ -1486,7 +1488,7 @@
       private final void disposeCocoon()
       {
           if (this.cocoon != null) {
  -            this.cocoon.dispose();
  +            ContainerUtil.dispose(this.cocoon);
               this.cocoon = null;
           }
       }
  
  
  
  1.11      +1 -5      cocoon-2.2/src/java/org/apache/cocoon/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/Constants.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- Constants.java	19 Oct 2003 17:20:23 -0000	1.10
  +++ Constants.java	20 Oct 2003 08:15:27 -0000	1.11
  @@ -141,10 +141,6 @@
       /** The name of the class for the default XML parser to use */
       public static final String DEFAULT_PARSER  = "org.apache.excalibur.xml.impl.JaxpParser";
   
  -    /** The name of the property holding the class for a XML parser
  -     *  @deprecated This will be removed in future release */
  -    public static final String DEPRECATED_PARSER_PROPERTY = "org.apache.cocoon.components.parser.Parser";
  -
       /** The namespace for the XSP core logicsheet. */
       public static final String XSP_URI = "http://apache.org/xsp";
   
  
  
  
  1.25      +3 -1      cocoon-2.2/src/java/org/apache/cocoon/Cocoon.java
  
  Index: Cocoon.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/Cocoon.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- Cocoon.java	19 Oct 2003 17:43:17 -0000	1.24
  +++ Cocoon.java	20 Oct 2003 08:15:27 -0000	1.25
  @@ -371,6 +371,7 @@
           CocoonComponentManager.enterEnvironment(environment,
                                                   this.serviceManager,
                                                   this);              */
  +        EnvironmentHelper.enterProcessor(this);
           try {
               boolean result;
               if (this.getLogger().isDebugEnabled()) {
  @@ -395,6 +396,7 @@
               environment.tryResetResponse();
               throw any;
           } finally {
  +            EnvironmentHelper.leaveProcessor();
   //            CocoonComponentManager.leaveEnvironment();
   //            CocoonComponentManager.endProcessing(environment, key);
               if (this.getLogger().isDebugEnabled()) {
  
  
  
  1.19      +9 -7      cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
  
  Index: TreeProcessor.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- TreeProcessor.java	19 Oct 2003 17:43:17 -0000	1.18
  +++ TreeProcessor.java	20 Oct 2003 08:15:27 -0000	1.19
  @@ -209,11 +209,11 @@
        * @param language the language to be used by the child processor.
        * @return a new child processor.
        */
  -    public TreeProcessor createChildProcessor(
  -        ServiceManager manager,
  -        String language,
  -        Source source)
  -      throws Exception {
  +    public TreeProcessor createChildProcessor(ServiceManager manager,
  +                                                String language,
  +                                                Source source,
  +                                                String prefix)
  +    throws Exception {
   
           // Note: lifecycle methods aren't called, since this constructors copies all
           // that can be copied from the parent (see above)
  @@ -364,7 +364,8 @@
           }
   
           // and now process
  -        CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this);
  +        //CocoonComponentManager.enterEnvironment(environment, this.sitemapComponentManager, this);
  +        EnvironmentHelper.enterProcessor(this);
           try {
               boolean success = this.rootNode.invoke(environment, context);
               
  @@ -386,6 +387,7 @@
               }
   
           } finally {
  +            EnvironmentHelper.leaveProcessor();
               CocoonComponentManager.leaveEnvironment();
           }
       }
  
  
  
  1.8       +16 -11    cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java
  
  Index: MountNode.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/components/treeprocessor/sitemap/MountNode.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- MountNode.java	6 Oct 2003 16:42:39 -0000	1.7
  +++ MountNode.java	20 Oct 2003 08:15:27 -0000	1.8
  @@ -54,9 +54,9 @@
   import java.util.Iterator;
   import java.util.Map;
   
  -import org.apache.avalon.framework.component.ComponentException;
  -import org.apache.avalon.framework.component.ComponentManager;
  -import org.apache.avalon.framework.component.Composable;
  +import org.apache.avalon.framework.service.ServiceException;
  +import org.apache.avalon.framework.service.ServiceManager;
  +import org.apache.avalon.framework.service.Serviceable;
   import org.apache.cocoon.components.pipeline.ProcessingPipeline;
   import org.apache.cocoon.components.treeprocessor.AbstractProcessingNode;
   import org.apache.cocoon.components.treeprocessor.InvokeContext;
  @@ -72,7 +72,7 @@
    * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
    * @version CVS $Id$
    */
  -public class MountNode extends AbstractProcessingNode implements Composable {
  +public class MountNode extends AbstractProcessingNode implements Serviceable {
   
       /** The 'uri-prefix' attribute */
       private VariableResolver prefix;
  @@ -90,7 +90,7 @@
       private String language;
   
       /** The component manager to be used by the mounted processor */
  -    private ComponentManager manager;
  +    private ServiceManager manager;
   
       public MountNode(VariableResolver prefix, VariableResolver source, String language, TreeProcessor parentProcessor) {        this.prefix = prefix;
           this.source = source;
  @@ -98,7 +98,7 @@
           this.parentProcessor = parentProcessor;
       }
   
  -    public void compose(ComponentManager manager) throws ComponentException {
  +    public void service(ServiceManager manager) throws ServiceException {
           this.manager = manager;
       }
   
  @@ -108,10 +108,10 @@
           Map objectModel = env.getObjectModel();
   
           String resolvedSource = this.source.resolve(context, objectModel);
  -        TreeProcessor processor = getProcessor(resolvedSource);
  -
           String resolvedPrefix = this.prefix.resolve(context, objectModel);
   
  +        TreeProcessor processor = getProcessor(resolvedSource, resolvedPrefix);
  +
           String oldPrefix = env.getURIPrefix();
           String oldURI    = env.getURI();
           String oldContext   = env.getContext();
  @@ -140,7 +140,12 @@
           }
       }
   
  -    private synchronized TreeProcessor getProcessor(String source) throws Exception {
  +    /**
  +     * Get the processor for the sub sitemap
  +     * FIXME Better synchronization strategy
  +     */
  +    private synchronized TreeProcessor getProcessor(String source, String prefix) 
  +    throws Exception {
   
           TreeProcessor processor = (TreeProcessor)processors.get(source);
   
  @@ -156,7 +161,7 @@
               SourceResolver resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
               Source src = resolver.resolveURI(actualSource);
               try {
  -                processor = this.parentProcessor.createChildProcessor(this.manager, this.language, src);
  +                processor = this.parentProcessor.createChildProcessor(this.manager, this.language, src, prefix);
               } finally {
                   resolver.release(src);
                   this.manager.release(resolver);
  
  
  
  1.3       +90 -15    cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentHelper.java
  
  Index: EnvironmentHelper.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentHelper.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- EnvironmentHelper.java	19 Oct 2003 17:27:32 -0000	1.2
  +++ EnvironmentHelper.java	20 Oct 2003 08:15:27 -0000	1.3
  @@ -59,7 +59,10 @@
   import org.apache.avalon.framework.service.ServiceException;
   import org.apache.avalon.framework.service.ServiceManager;
   import org.apache.avalon.framework.service.Serviceable;
  +import org.apache.cocoon.ProcessingException;
  +import org.apache.cocoon.Processor;
   import org.apache.cocoon.components.source.SourceUtil;
  +import org.apache.cocoon.xml.XMLConsumer;
   import org.apache.excalibur.source.Source;
   
   /**
  @@ -80,9 +83,8 @@
       /** The service manager */
       protected ServiceManager manager;
       
  -    /** The current prefix to strip off from the request uri 
  -     *  TODO (CZ) Convert this to a String */
  -    protected StringBuffer prefix = new StringBuffer();
  +    /** The current prefix to strip off from the request uri */
  +    protected String prefix;
   
        /** The Context path */
       protected String context;
  @@ -90,6 +92,9 @@
       /** The root context path */
       protected String rootContext;
   
  +    /** The environment information */
  +    private static InheritableThreadLocal environmentStack = new CloningInheritableThreadLocal();
  +
       /**
        * Constructor
        *
  @@ -162,40 +167,47 @@
           return this.resolveURI(location, null, null);
       }
   
  -    public void changeContext(Environment env) {
  +    public void changeContext(Environment env) 
  +    throws ProcessingException {
           String uris = env.getURI();
  -        final int l = this.prefix.length();
  -        if ( l >= 1 ) {
  -            if (!uris.startsWith(this.prefix.toString())) {
  +        if ( this.prefix != null ) {
  +            if (!uris.startsWith(this.prefix)) {
                   String message = "The current URI (" + uris +
                                    ") doesn't start with given prefix (" + prefix + ")";
                   getLogger().error(message);
  -                throw new RuntimeException(message);
  +                throw new ProcessingException(message);
               }      
               // we don't need to check for slash at the beginning
               // of uris - the prefix always ends with a slash!
  +            final int l = this.prefix.length();
               uris = uris.substring(l);
               // TODO (CZ) Implement this in the environment
               // env.setURI(uris);
           }
       }
  +    
       /**
        * Adds an prefix to the overall stripped off prefix from the request uri
        */
  -    public void changeContext(String prefix, String newContext)
  +    public void changeContext(String newPrefix, String newContext)
       throws IOException {
           if (getLogger().isDebugEnabled()) {
               getLogger().debug("Changing Cocoon context");
               getLogger().debug("  from context(" + this.context + ") and prefix(" + this.prefix + ")");
  -            getLogger().debug("  to context(" + newContext + ") and prefix(" + prefix + ")");
  +            getLogger().debug("  to context(" + newContext + ") and prefix(" + newPrefix + ")");
           }
  -        int l = prefix.length();
  +        int l = newPrefix.length();
           if (l >= 1) {
  -            this.prefix.append(prefix);
  +            if ( this.prefix == null ) {
  +                this.prefix = "";
  +            }
  +            final StringBuffer buffer = new StringBuffer(this.prefix);
  +            buffer.append(newPrefix);
               // check for a slash at the beginning to avoid problems with subsitemaps
  -            if ( !this.prefix.toString().endsWith("/") ) {
  -                this.prefix.append('/');
  +            if ( buffer.charAt(buffer.length()-1) != '/') {
  +                buffer.append('/');
               }
  +            this.prefix = buffer.toString();
           }
   
           if (SourceUtil.getScheme(this.context).equals("zip")) {
  @@ -246,4 +258,67 @@
           }
       }
       
  +    /**
  +     * This hook must be called by the sitemap each time a sitemap is entered
  +     * This method should never raise an exception, except when the
  +     * parameters are not set!
  +     */
  +    public static void enterProcessor(Processor processor) {
  +        if ( null == processor) {
  +            throw new IllegalArgumentException("Processor is not set.");
  +        }
  +
  +        EnvironmentStack stack = (EnvironmentStack)environmentStack.get();
  +        if (stack == null) {
  +            stack = new EnvironmentStack();
  +            environmentStack.set(stack);
  +        }
  +        stack.push(new Object[] {processor, new Integer(stack.getOffset())});
  +        stack.setOffset(stack.size()-1);
  +    }
  +
  +    /**
  +     * This hook must be called by the sitemap each time a sitemap is left.
  +     * It's the counterpart to {@link #enterProcessor(Processor)}.
  +     */
  +    public static void leaveProcessor() {
  +        final EnvironmentStack stack = (EnvironmentStack)environmentStack.get();
  +        final Object[] objs = (Object[])stack.pop();
  +        stack.setOffset(((Integer)objs[1]).intValue());
  +    }
  +
  +    /**
  +     * Create an environment aware xml consumer for the cocoon
  +     * protocol
  +     */
  +    public static XMLConsumer createEnvironmentAwareConsumer(XMLConsumer consumer) {
  +        final EnvironmentStack stack = (EnvironmentStack)environmentStack.get();
  +        final Object[] objs = (Object[])stack.getCurrent();
  +        return stack.getEnvironmentAwareConsumerWrapper(consumer, ((Integer)objs[1]).intValue());
  +    }
   }
  +
  +final class CloningInheritableThreadLocal
  +    extends InheritableThreadLocal {
  +
  +    /**
  +     * Computes the child's initial value for this InheritableThreadLocal
  +     * as a function of the parent's value at the time the child Thread is
  +     * created.  This method is called from within the parent thread before
  +     * the child is started.
  +     * <p>
  +     * This method merely returns its input argument, and should be overridden
  +     * if a different behavior is desired.
  +     *
  +     * @param parentValue the parent thread's value
  +     * @return the child thread's initial value
  +     */
  +    protected Object childValue(Object parentValue) {
  +        if ( null != parentValue) {
  +            return ((EnvironmentStack)parentValue).clone();
  +        } else {
  +            return null;
  +        }
  +    }
  +}
  +
  
  
  
  1.1                  cocoon-2.2/src/java/org/apache/cocoon/environment/EnvironmentStack.java
  
  Index: EnvironmentStack.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <st...@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.environment;
  
  import org.apache.cocoon.xml.XMLConsumer;
  import org.apache.commons.collections.ArrayStack;
  import org.xml.sax.Attributes;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  
  /**
   * The stack for the processing environment.
   * This is a special implementation of a stack for the handling of the
   * cocoon protocol and the sitemap source resolving.
   *
   * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
   * @version CVS $Id: EnvironmentStack.java,v 1.1 2003/10/20 08:15:27 cziegeler Exp $
   */
  final class EnvironmentStack 
      extends ArrayStack 
      implements Cloneable {
      
      int offset;
      
      Object getCurrent() {
          return this.get(offset);
          //return this.peek(this.offset);
      }
      
      int getOffset() {
          return this.offset;
      }
    
      void setOffset(int value) {
          this.offset = value;  
      }
      
      public Object clone() {
          EnvironmentStack old = (EnvironmentStack) super.clone();
          old.offset = offset;
          return old;
      }
      
      XMLConsumer getEnvironmentAwareConsumerWrapper(XMLConsumer consumer, 
                                                     int oldOffset) {
          return new EnvironmentChanger(consumer, this, oldOffset, this.offset);
      }
  }
  
  /**
   * This class is an {@link XMLConsumer} that changes the current environment.
   * When a pipeline calls an internal pipeline, two environments are
   * established: one for the calling pipeline and one for the internal pipeline.
   * Now, if SAX events are send from the internal pipeline, they are
   * received by some component of the calling pipeline, so inbetween we
   * have to change the environment forth and back.
   */
  final class EnvironmentChanger
  implements XMLConsumer {
  
      final XMLConsumer consumer;
      final EnvironmentStack stack;
      final int oldOffset;
      final int newOffset;
      
      EnvironmentChanger(XMLConsumer consumer, EnvironmentStack es,
                         int oldOffset, int newOffset) {
          this.consumer = consumer;
          this.stack = es;
          this.oldOffset = oldOffset;
          this.newOffset = newOffset;
      }
      
      public void setDocumentLocator(Locator locator) {
          this.stack.setOffset(this.oldOffset);
          this.consumer.setDocumentLocator(locator);
          this.stack.setOffset(this.newOffset);
      }
  
      public void startDocument()
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startDocument();
          this.stack.setOffset(this.newOffset);
      }
  
      public void endDocument()
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endDocument();
          this.stack.setOffset(this.newOffset);
      }
  
      public void startPrefixMapping(String prefix, String uri)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startPrefixMapping(prefix, uri);
          this.stack.setOffset(this.newOffset);
      }
  
      public void endPrefixMapping(String prefix)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endPrefixMapping(prefix);
          this.stack.setOffset(this.newOffset);
      }
  
      public void startElement(String uri, String loc, String raw, Attributes a)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startElement(uri, loc, raw, a);
          this.stack.setOffset(this.newOffset);
      }
  
  
      public void endElement(String uri, String loc, String raw)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endElement(uri, loc, raw);
          this.stack.setOffset(this.newOffset);
      }
      
      public void characters(char c[], int start, int len)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.characters(c, start, len);
          this.stack.setOffset(this.newOffset);
      }
  
      public void ignorableWhitespace(char c[], int start, int len)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.ignorableWhitespace(c, start, len);
          this.stack.setOffset(this.newOffset);
      }
  
      public void processingInstruction(String target, String data)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.processingInstruction(target, data);
          this.stack.setOffset(this.newOffset);
      }
  
      public void skippedEntity(String name)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.skippedEntity(name);
          this.stack.setOffset(this.newOffset);
      }
  
      public void startDTD(String name, String publicId, String systemId)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startDTD(name, publicId, systemId);
          this.stack.setOffset(this.newOffset);
      }
  
      public void endDTD()
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endDTD();
          this.stack.setOffset(this.newOffset);
      }
  
      public void startEntity(String name)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startEntity(name);
          this.stack.setOffset(this.newOffset);
      }
  
      public void endEntity(String name)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endEntity(name);
          this.stack.setOffset(this.newOffset);
      }
  
      public void startCDATA()
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.startCDATA();
          this.stack.setOffset(this.newOffset);
      }
  
      public void endCDATA()
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.endCDATA();
          this.stack.setOffset(this.newOffset);
      }
  
      public void comment(char ch[], int start, int len)
      throws SAXException {
          this.stack.setOffset(this.oldOffset);
          this.consumer.comment(ch, start, len);
          this.stack.setOffset(this.newOffset);
      }
  }