sylvain 01/12/03 07:05:09
Modified: src/org/apache/cocoon/generation Tag: cocoon_20_branch
ServerPagesGenerator.java
Log:
Refactored document completion :
- it is now optional (disabled by default),
- if enabled, made faster by the use of a single ArrayStack instead of a LinkedList
of new objects.
Revision Changes Path
No revision
No revision
1.7.2.11 +344 -394
xml-cocoon2/src/org/apache/cocoon/generation/ServerPagesGenerator.java
Index: ServerPagesGenerator.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/org/apache/cocoon/generation/ServerPagesGenerator.java,v
retrieving revision 1.7.2.10
retrieving revision 1.7.2.11
diff -u -r1.7.2.10 -r1.7.2.11
--- ServerPagesGenerator.java 2001/10/10 09:25:14 1.7.2.10
+++ ServerPagesGenerator.java 2001/12/03 15:05:08 1.7.2.11
@@ -7,457 +7,239 @@
*****************************************************************************/
package org.apache.cocoon.generation;
+import org.apache.avalon.excalibur.collections.ArrayStack;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.activity.Disposable;
-
import org.apache.avalon.framework.component.Component;
-
import org.apache.avalon.framework.component.ComponentException;
-
import org.apache.avalon.framework.component.ComponentManager;
-
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
-
import org.apache.cocoon.ResourceNotFoundException;
-
import org.apache.cocoon.caching.CacheValidity;
-
import org.apache.cocoon.caching.Cacheable;
-
import org.apache.cocoon.caching.CompositeCacheValidity;
-
import org.apache.cocoon.caching.ParametersCacheValidity;
-
import org.apache.cocoon.components.language.generator.ProgramGenerator;
-
import org.apache.cocoon.components.language.markup.xsp.XSPGenerator;
-
import org.apache.cocoon.environment.Source;
-
import org.apache.cocoon.environment.SourceResolver;
-
import org.apache.cocoon.util.HashUtil;
-
-import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.AbstractXMLPipe;
import org.xml.sax.Attributes;
-
import org.xml.sax.Locator;
-
import org.xml.sax.SAXException;
-
-
import java.io.IOException;
import java.util.HashMap;
-
import java.util.LinkedList;
-
import java.util.Map;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
/**
* This class acts as a proxy to a dynamically loaded<code>Generator</code>
* delegating actual SAX event generation.
+ * <p>
+ * It has a single configuration item :
+ *
<code><autocomplete-documents>true|false<autocomplete-documents></code>
+ * (default is <code>false</code>).
+ * <p>
+ * This tells the generator to automatically close all elements that weren't
properly closed
+ * by the XSP, such as when a <code>return</code> statement is used to prematurely
end
+ * processing. Activating this feature <em>sensibly increases CPU-usage</em> and
should
+ * therefore be used only if really needed (it's better to have clean XSP pages
that don't
+ * break abruptly generation flow).
*
* @author <a href="mailto:[EMAIL PROTECTED]">Ricardo Rocha</a>
- * @version CVS $Revision: 1.7.2.10 $ $Date: 2001/10/10 09:25:14 $
+ * @author <a href="mailto:[EMAIL PROTECTED]">Sylvain Wallez</a>
+ * @version CVS $Revision: 1.7.2.11 $ $Date: 2001/12/03 15:05:08 $
*/
-public class ServerPagesGenerator
- extends ServletGenerator
- implements Recyclable, Disposable, Cacheable, XMLConsumer
+public class ServerPagesGenerator extends ServletGenerator
+ implements Recyclable, Disposable, Cacheable, Configurable
{
- /**
- * The sitemap-defined server pages program generator
- */
- protected static ProgramGenerator programGenerator = null;
-
- protected XSPGenerator generator = null;
-
- /** The source */
- private Source inputSource;
-
- /**
- * Set the global component manager. This method sets the sitemap-defined
- * program generator
- *
- * @param manager The global component manager
- */
- public void compose(ComponentManager manager) throws ComponentException {
- super.compose(manager);
-
- if (programGenerator == null) {
- getLogger().debug("Looking up " + ProgramGenerator.ROLE);
- try {
- this.programGenerator = (ProgramGenerator)
- manager.lookup(ProgramGenerator.ROLE);
- } catch (Exception e) {
- getLogger().error("Could not find ProgramGenerator", e);
- }
- }
- }
-
- /**
- * Generates the unique key.
- * This key must be unique inside the space of this component.
- * Users may override this method to take
- * advantage of SAX event cacheing
- *
- * @return A long representing the cache key (defaults to not cachable)
- */
- public long generateKey() {
- return HashUtil.hash(this.inputSource.getSystemId() + generator.generateKey());
- }
-
- /**
- * Generate the validity object.
- *
- * @return The generated validity object or <code>null</code> if the
- * component is currently not cachable.
- */
- public CacheValidity generateValidity() {
- CacheValidity genValidity = generator.generateValidity();
- if (genValidity != null) {
- HashMap map = new HashMap (1);
- map.put("source", this.inputSource.getSystemId());
- ParametersCacheValidity pcv = new ParametersCacheValidity(map);
- return new CompositeCacheValidity(genValidity, pcv);
- }
- return null;
- }
-
- /**
- * The loaded generator's <code>MarkupLanguage</code>
- */
- protected String markupLanguage;
-
- /**
- * The loaded generator's <code>ProgrammingLanguage</code>
- */
- protected String programmingLanguage;
-
- /**
- * The default <code>MarkupLanguage</code>
- */
- public final static String DEFAULT_MARKUP_LANGUAGE = "xsp";
-
- /**
- * The default <code>ProgrammingLanguage</code>
- */
- public final static String DEFAULT_PROGRAMMING_LANGUAGE = "java";
-
- public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par)
- throws ProcessingException, SAXException, IOException {
-
- super.setup(resolver, objectModel, src, par);
-
- this.inputSource = this.resolver.resolve(super.source);
-
- if (this.markupLanguage == null) {
- this.markupLanguage = this.parameters.getParameter(
- "markup-language", DEFAULT_MARKUP_LANGUAGE
- );
- this.programmingLanguage = this.parameters.getParameter(
- "programming-language", DEFAULT_PROGRAMMING_LANGUAGE
- );
- }
-
- try {
- generator = (XSPGenerator)
- programGenerator.load(this.manager, super.source, this.markupLanguage,
this.programmingLanguage, this.resolver);
- } catch (ProcessingException e) {
- throw e;
- } catch (Exception e) {
- getLogger().warn("ServerPagesGenerator.generate()", e);
- throw new ResourceNotFoundException(e.getMessage(), e);
- } catch (NoClassDefFoundError e) {
- getLogger().warn("Failed to load class: " + e);
- throw new ResourceNotFoundException(e.getMessage());
- }
- generator.setup(this.resolver, this.objectModel, super.source, this.parameters);
- }
-
- /**
- * Generate XML data. This method loads a server pages generator associated
- * with its (file) input source and delegates SAX event generator to it
- * taking care of "closing" any event left open by the loaded generator as a
- * result of its possible "premature" return (a common situation in server
- * pages)
- *
- * @exception IOException IO Error
- * @exception SAXException SAX event generation error
- * @exception ProcessingException Error during load/execution
- */
- public void generate() throws IOException, SAXException, ProcessingException {
-
- generator.setConsumer(this);
-
- // log exception and ensure that generator is released.
- try {
- generator.generate();
- } catch (IOException e){
- getLogger().error("IOException in ServerPagesGenerator.generate()", e);
- throw e;
- } catch (SAXException e){
- getLogger().error("SAXException in ServerPagesGenerator.generate()", e);
- throw e;
- } catch (ProcessingException e){
- getLogger().error("ProcessingException in ServerPagesGenerator.generate()",
e);
- throw e;
- } catch (Exception e){
- getLogger().error("Exception in ServerPagesGenerator.generate()", e);
- throw new ProcessingException("Exception in
ServerPagesGenerator.generate()", e);
- } finally {
- if(generator != null)
- programGenerator.release(generator);
- generator = null;
- }
-
- // End any started events in case of premature return
- while (this.eventStack.size()!=0) {
- EventData eventData = (EventData) this.eventStack.removeFirst();
-
- switch (eventData.eventType) {
- case DOCUMENT:
- this.contentHandler.endDocument();
- break;
- case ELEMENT:
- this.contentHandler.endElement(
- eventData.getNamespaceURI(),
- eventData.getLocalName(),
- eventData.getRawName()
- );
- break;
- case PREFIX_MAPPING:
- this.contentHandler.endPrefixMapping(eventData.getPrefix());
- break;
- case CDATA:
- this.lexicalHandler.endCDATA();
- break;
- case DTD:
- this.lexicalHandler.endDTD();
- break;
- case ENTITY:
- this.lexicalHandler.endEntity(eventData.getName());
- break;
- }
- }
- }
-
- /* Handlers */
-
- /**
- * The SAX event stack. Used for "completing" pendind SAX events left "open"
- * by prematurely returning server pages generators
- */
- protected LinkedList eventStack = new LinkedList();
-
/**
- * Receive notification of character data.
+ * The sitemap-defined server pages program generator
*/
- public void characters(char[] ch, int start, int length) throws SAXException {
- this.contentHandler.characters(ch, start, length);
- }
-
- /**
- * Receive notification of the end of a document.
- */
- public void endDocument() throws SAXException {
- this.eventStack.removeFirst();
- this.contentHandler.endDocument();
- }
-
- /**
- * Receive notification of the end of an element.
- */
- public void endElement(String namespaceURI, String localName, String rawName)
- throws SAXException
- {
- this.eventStack.removeFirst();
- this.contentHandler.endElement(namespaceURI, localName, rawName);
- }
-
- /**
- * End the scope of a prefix-URI mapping.
- */
- public void endPrefixMapping(String prefix) throws SAXException {
- this.eventStack.removeFirst();
- this.contentHandler.endPrefixMapping(prefix);
- }
+ protected static ProgramGenerator programGenerator = null;
+
+ protected XSPGenerator generator = null;
+
+ /** The source */
+ private Source inputSource;
+
+ private CompletionPipe completionPipe;
+
+ /**
+ * Set the global component manager. This method sets the sitemap-defined
+ * program generator
+ *
+ * @param manager The global component manager
+ */
+ public void compose(ComponentManager manager) throws ComponentException {
+ super.compose(manager);
+
+ if (programGenerator == null) {
+ getLogger().debug("Looking up " + ProgramGenerator.ROLE);
+ try {
+ this.programGenerator = (ProgramGenerator)
+ manager.lookup(ProgramGenerator.ROLE);
+ } catch (Exception e) {
+ getLogger().error("Could not find ProgramGenerator", e);
+ }
+ }
+ }
- /**
- * Receive notification of ignorable whitespace in element content.
- */
- public void ignorableWhitespace(char[] ch, int start, int length)
- throws SAXException
- {
- this.contentHandler.ignorableWhitespace(ch, start, length);
- }
+ public void configure(Configuration config) throws ConfigurationException {
+ boolean autoComplete =
config.getChild("autocomplete-documents").getValueAsBoolean(false);
+ if (autoComplete) {
+ this.completionPipe = new CompletionPipe();
+ this.completionPipe.setLogger(getLogger());
+ }
+ }
+
/**
- * Receive notification of a processing instruction.
- */
- public void processingInstruction(String target, String data)
- throws SAXException
- {
- this.contentHandler.processingInstruction(target, data);
- }
+ * Generates the unique key.
+ * This key must be unique inside the space of this component.
+ * Users may override this method to take
+ * advantage of SAX event cacheing
+ *
+ * @return A long representing the cache key (defaults to not cachable)
+ */
+ public long generateKey() {
+ return HashUtil.hash(this.inputSource.getSystemId() +
generator.generateKey());
+ }
/**
- * Receive an object for locating the origin of SAX document events.
- */
- public void setDocumentLocator(Locator locator) {
- this.contentHandler.setDocumentLocator(locator);
- }
+ * Generate the validity object.
+ *
+ * @return The generated validity object or <code>null</code> if the
+ * component is currently not cachable.
+ */
+ public CacheValidity generateValidity() {
+ CacheValidity genValidity = generator.generateValidity();
+ if (genValidity != null) {
+ HashMap map = new HashMap (1);
+ map.put("source", this.inputSource.getSystemId());
+ ParametersCacheValidity pcv = new ParametersCacheValidity(map);
+ return new CompositeCacheValidity(genValidity, pcv);
+ }
+ return null;
+ }
/**
- * Receive notification of a skipped entity.
+ * The loaded generator's <code>MarkupLanguage</code>
*/
- public void skippedEntity(String name)
- throws SAXException
- {
- this.contentHandler.skippedEntity(name);
- }
-
+ protected String markupLanguage;
+
/**
- * Receive notification of the beginning of a document.
+ * The loaded generator's <code>ProgrammingLanguage</code>
*/
- public void startDocument() throws SAXException {
- this.contentHandler.startDocument();
- this.eventStack.addFirst(new EventData(DOCUMENT));
- }
-
+ protected String programmingLanguage;
+
/**
- * Receive notification of the beginning of an element.
+ * The default <code>MarkupLanguage</code>
*/
- public void startElement(
- String namespaceURI, String localName, String rawName, Attributes atts
- )
- throws SAXException
- {
- this.contentHandler.startElement(namespaceURI, localName, rawName, atts);
- this.eventStack.addFirst(new EventData(ELEMENT, namespaceURI, localName,
rawName));
- }
-
+ public final static String DEFAULT_MARKUP_LANGUAGE = "xsp";
+
/**
- * Begin the scope of a prefix-URI Namespace mapping.
+ * The default <code>ProgrammingLanguage</code>
*/
- public void startPrefixMapping(String prefix, String uri) throws SAXException
- {
- this.contentHandler.startPrefixMapping(prefix, uri);
- this.eventStack.addFirst(new EventData(PREFIX_MAPPING, prefix, uri));
- }
-
- public void comment(char[] ch, int start, int length) throws SAXException {
- this.lexicalHandler.comment(ch, start, length);
- }
-
- public void endCDATA() throws SAXException {
- this.lexicalHandler.endCDATA();
- this.eventStack.removeFirst();
- }
-
- public void endDTD() throws SAXException {
- this.lexicalHandler.endDTD();
- this.eventStack.removeFirst();
- }
-
- public void endEntity(String name) throws SAXException {
- this.lexicalHandler.endEntity(name);
- this.eventStack.removeFirst();
- }
-
- public void startCDATA() throws SAXException {
- this.lexicalHandler.startCDATA();
- this.eventStack.addFirst(new EventData(CDATA));
- }
-
- public void startDTD(String name, String publicId, String systemId)
- throws SAXException
- {
- this.lexicalHandler.startDTD(name, publicId, systemId);
- this.eventStack.addFirst(new EventData(DTD, name, publicId, systemId));
- }
-
- public void startEntity(String name) throws SAXException {
- this.lexicalHandler.startEntity(name);
- this.eventStack.addFirst(new EventData(ENTITY, name));
- }
-
- protected final static int DOCUMENT = 0;
- protected final static int ELEMENT = 1;
- protected final static int PREFIX_MAPPING = 2;
- protected final static int CDATA = 3;
- protected final static int DTD = 4;
- protected final static int ENTITY = 5;
-
- protected class EventData {
- protected int eventType;
- protected String namespaceURI;
- protected String localName;
- protected String rawName;
- protected String prefix;
- protected String publicId;
- protected String systemId;
- protected String name;
-
- protected EventData(int eventType) {
- this.eventType = eventType; // DOCUMENT | CDATA
- }
-
- protected EventData(
- int eventType, String data1, String data2, String data3
- )
- {
- this.eventType = eventType;
- switch (this.eventType) {
- case ELEMENT:
- this.namespaceURI = data1;
- this.localName = data2;
- this.rawName = data3;
- break;
- case DTD:
- this.name = data1;
- this.publicId = data2;
- this.systemId = data3;
- break;
- }
- }
+ public final static String DEFAULT_PROGRAMMING_LANGUAGE = "java";
+
+ public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par)
+ throws ProcessingException, SAXException, IOException {
- protected EventData(
- int eventType, String data1, String data2
- )
- {
- this.eventType = eventType;
- switch (this.eventType) {
- case PREFIX_MAPPING:
- this.prefix = data1;
- this.namespaceURI = data2;
- break;
- }
+ super.setup(resolver, objectModel, src, par);
+
+ this.inputSource = this.resolver.resolve(super.source);
+
+ if (this.markupLanguage == null) {
+ this.markupLanguage = this.parameters.getParameter(
+ "markup-language", DEFAULT_MARKUP_LANGUAGE
+ );
+ this.programmingLanguage = this.parameters.getParameter(
+ "programming-language", DEFAULT_PROGRAMMING_LANGUAGE
+ );
+ }
+
+ try {
+ generator = (XSPGenerator)
+ programGenerator.load(this.manager, super.source,
this.markupLanguage, this.programmingLanguage, this.resolver);
+ } catch (ProcessingException e) {
+ throw e;
+ } catch (Exception e) {
+ getLogger().warn("ServerPagesGenerator.generate()", e);
+ throw new ResourceNotFoundException(e.getMessage(), e);
+ } catch (NoClassDefFoundError e) {
+ getLogger().warn("Failed to load class: " + e);
+ throw new ResourceNotFoundException(e.getMessage());
+ }
+ generator.setup(this.resolver, this.objectModel, super.source,
this.parameters);
}
- protected EventData(int eventType, String data) {
- this.eventType = eventType;
- switch (this.eventType) {
- case ENTITY:
- this.name = data;
- break;
- }
+ /**
+ * Generate XML data. This method loads a server pages generator associated
+ * with its (file) input source and delegates SAX event generator to it
+ * taking care of "closing" any event left open by the loaded generator as a
+ * result of its possible "premature" return (a common situation in server
+ * pages)
+ *
+ * @exception IOException IO Error
+ * @exception SAXException SAX event generation error
+ * @exception ProcessingException Error during load/execution
+ */
+ public void generate() throws IOException, SAXException, ProcessingException {
+
+ if (this.completionPipe != null) {
+ generator.setConsumer(this.completionPipe);
+ if (this.xmlConsumer != null) {
+ this.completionPipe.setConsumer(this.xmlConsumer);
+ } else {
+ this.completionPipe.setContentHandler(this.contentHandler);
+ this.completionPipe.setLexicalHandler(this.lexicalHandler);
+ }
+ } else {
+ if (this.xmlConsumer != null) {
+ generator.setConsumer(this.xmlConsumer);
+ } else {
+ generator.setContentHandler(this.contentHandler);
+ generator.setLexicalHandler(this.lexicalHandler);
+ }
+ }
+
+ // log exception and ensure that generator is released.
+ try {
+ generator.generate();
+ } catch (IOException e){
+ getLogger().error("IOException in ServerPagesGenerator.generate()", e);
+ throw e;
+ } catch (SAXException e){
+ getLogger().error("SAXException in ServerPagesGenerator.generate()", e);
+ throw e;
+ } catch (ProcessingException e){
+ getLogger().error("ProcessingException in
ServerPagesGenerator.generate()", e);
+ throw e;
+ } catch (Exception e){
+ getLogger().error("Exception in ServerPagesGenerator.generate()", e);
+ throw new ProcessingException("Exception in
ServerPagesGenerator.generate()", e);
+ } finally {
+ if(generator != null)
+ programGenerator.release(generator);
+ generator = null;
+ }
+
+ if (this.completionPipe != null) {
+ this.completionPipe.flushEvents();
+ }
}
- protected String getNamespaceURI() { return this.namespaceURI; }
- protected String getLocalName() { return this.localName; }
- protected String getRawName() { return this.rawName; }
- protected String getPrefix() { return this.prefix; }
- protected String getPublicId() { return this.publicId; }
- protected String getSystemId() { return this.systemId; }
- protected String getName() { return this.name; }
- }
-
/**
* Recycle the generator by removing references
*/
@@ -470,7 +252,9 @@
this.inputSource.recycle();
this.inputSource = null;
}
- this.eventStack.clear();
+ if (this.completionPipe != null) {
+ this.completionPipe.recycle();
+ }
}
/**
@@ -478,5 +262,171 @@
*/
public void dispose() {
if(this.programGenerator != null)
manager.release((Component)this.programGenerator);
+ }
+
+ /* Completion pipe */
+
+ // int values for event types
+ private final static int DOCUMENT = 0;
+ private final static int ELEMENT = 1;
+ private final static int PREFIX_MAPPING = 2;
+ private final static int CDATA = 3;
+ private final static int DTD = 4;
+ private final static int ENTITY = 5;
+
+ // Integer equivalents to push on the stack
+ private final static Integer DOCUMENT_OBJ = new Integer(DOCUMENT);
+ private final static Integer ELEMENT_OBJ = new Integer(ELEMENT);
+ private final static Integer PREFIX_MAPPING_OBJ = new Integer(PREFIX_MAPPING);
+ private final static Integer CDATA_OBJ = new Integer(CDATA);
+ private final static Integer DTD_OBJ = new Integer(DTD);
+ private final static Integer ENTITY_OBJ = new Integer(ENTITY);
+
+ public class CompletionPipe extends AbstractXMLPipe {
+
+ /**
+ * The SAX event stack. Used for "completing" pendind SAX events left "open"
+ * by prematurely returning server pages generators
+ */
+ protected ArrayStack eventStack = new ArrayStack();
+
+ /**
+ * Receive notification of the beginning of a document.
+ */
+ public void startDocument() throws SAXException {
+ super.startDocument();
+ this.eventStack.push(DOCUMENT_OBJ);
+ }
+
+ /**
+ * Receive notification of the end of a document.
+ */
+ public void endDocument() throws SAXException {
+ this.eventStack.pop();
+ super.endDocument();
+ }
+
+ /**
+ * Receive notification of the beginning of an element.
+ */
+ public void startElement(String namespaceURI, String localName, String
rawName, Attributes atts)
+ throws SAXException {
+ super.startElement(namespaceURI, localName, rawName, atts);
+ this.eventStack.push(rawName);
+ this.eventStack.push(localName);
+ this.eventStack.push(namespaceURI);
+ this.eventStack.push(ELEMENT_OBJ);
+ }
+
+ /**
+ * Receive notification of the end of an element.
+ */
+ public void endElement(String namespaceURI, String localName, String
rawName)
+ throws SAXException {
+ this.eventStack.pop(); // ELEMENT_OBJ
+ this.eventStack.pop(); // namespaceURI
+ this.eventStack.pop(); // localName
+ this.eventStack.pop(); // rawName
+ super.endElement(namespaceURI, localName, rawName);
+ }
+
+ /**
+ * Begin the scope of a prefix-URI Namespace mapping.
+ */
+ public void startPrefixMapping(String prefix, String uri) throws
SAXException {
+ super.startPrefixMapping(prefix, uri);
+ this.eventStack.push(prefix);
+ this.eventStack.push(PREFIX_MAPPING_OBJ);
+ }
+
+ /**
+ * End the scope of a prefix-URI mapping.
+ */
+ public void endPrefixMapping(String prefix) throws SAXException {
+ this.eventStack.pop(); // PREFIX_MAPPING_OBJ
+ this.eventStack.pop(); // prefix
+ super.endPrefixMapping(prefix);
+ }
+
+ public void startCDATA() throws SAXException {
+ super.startCDATA();
+ this.eventStack.push(CDATA_OBJ);
+ }
+
+ public void endCDATA() throws SAXException {
+ this.eventStack.pop();
+ super.endCDATA();
+ }
+
+ public void startDTD(String name, String publicId, String systemId)
+ throws SAXException
+ {
+ super.startDTD(name, publicId, systemId);
+ this.eventStack.push(DTD_OBJ);
+ }
+
+ public void endDTD() throws SAXException {
+ this.eventStack.pop();
+ super.endDTD();
+ }
+
+ public void startEntity(String name) throws SAXException {
+ super.startEntity(name);
+ this.eventStack.push(name);
+ this.eventStack.push(ENTITY_OBJ);
+ }
+
+ public void endEntity(String name) throws SAXException {
+ this.eventStack.pop(); // ENTITY_OBJ
+ this.eventStack.pop(); // name
+ super.endEntity(name);
+ }
+
+ public void flushEvents() throws SAXException {
+
+ if (getLogger().isWarnEnabled()) {
+ if (this.eventStack.size() > 0) {
+ getLogger().warn("Premature end of document generated by " +
inputSource.getSystemId());
+ }
+ }
+
+ // End any started events in case of premature return
+ while (this.eventStack.size() != 0) {
+ int event = ((Integer)eventStack.pop()).intValue();
+
+ switch(event) {
+ case DOCUMENT :
+ super.endDocument();
+ break;
+
+ case ELEMENT :
+ String namespaceURI = (String)eventStack.pop();
+ String localName = (String)eventStack.pop();
+ String rawName = (String)eventStack.pop();
+ super.endElement(namespaceURI, localName, rawName);
+ break;
+
+ case PREFIX_MAPPING :
+ super.endPrefixMapping((String)eventStack.pop());
+ break;
+
+ case CDATA:
+ super.endCDATA();
+ break;
+
+ case DTD:
+ super.endDTD();
+ break;
+
+ case ENTITY:
+ super.endEntity((String)eventStack.pop());
+ break;
+ }
+ }
+ }
+
+ public void recycle() {
+ this.eventStack.clear();
+ }
}
}
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]