You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2004/09/02 22:31:16 UTC
svn commit: rev 37419 - in cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon: taglib transformation
Author: vgritsenko
Date: Thu Sep 2 13:31:16 2004
New Revision: 37419
Modified:
cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/TagSupport.java
cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/XMLProducerTagSupport.java
cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/transformation/TagTransformer.java
Log:
Allow tags extending from TagSupport to throw IOException in setup() method.
Set consumer for XML producing tags before setup method.
Refactor some code into methods.
Exception handling: do not ignore tag setup() exceptions.
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/TagSupport.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/TagSupport.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/TagSupport.java Thu Sep 2 13:31:16 2004
@@ -1,12 +1,12 @@
/*
* 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.
@@ -16,6 +16,7 @@
package org.apache.cocoon.taglib;
import java.util.Map;
+import java.io.IOException;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
@@ -31,12 +32,11 @@
/**
* Abstract implementation for all Tags
- *
+ *
* @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
- * @version CVS $Id: TagSupport.java,v 1.3 2004/03/05 13:02:24 bdelacretaz Exp $
+ * @version CVS $Id$
*/
public abstract class TagSupport extends AbstractLogEnabled implements Tag, Recyclable {
- protected String var;
protected Tag parent;
protected SourceResolver resolver;
protected Map objectModel;
@@ -82,7 +82,8 @@
* @return EVAL_PAGE.
* @throws SAXException
*/
- public int doEndTag(String namespaceURI, String localName, String qName) throws SAXException {
+ public int doEndTag(String namespaceURI, String localName, String qName)
+ throws SAXException {
return EVAL_PAGE;
}
@@ -96,7 +97,8 @@
*
* @return EVAL_BODY or SKIP_BODY.
*/
- public int doStartTag(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+ public int doStartTag(String namespaceURI, String localName, String qName, Attributes atts)
+ throws SAXException {
return EVAL_BODY;
}
@@ -135,7 +137,6 @@
public void recycle() {
getLogger().debug("recycle");
- this.var = null;
this.parent = null;
this.resolver = null;
this.objectModel = null;
@@ -160,7 +161,8 @@
* Set the <code>SourceResolver</code>, objectModel <code>Map</code>
* and sitemap <code>Parameters</code> used to process the request.
*/
- public void setup(SourceResolver resolver, Map objectModel, Parameters parameters) {
+ public void setup(SourceResolver resolver, Map objectModel, Parameters parameters)
+ throws SAXException, IOException {
this.resolver = resolver;
this.objectModel = objectModel;
this.parameters = parameters;
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/XMLProducerTagSupport.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/XMLProducerTagSupport.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/taglib/XMLProducerTagSupport.java Thu Sep 2 13:31:16 2004
@@ -1,12 +1,12 @@
/*
* 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.
@@ -19,10 +19,10 @@
/**
* @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
- * @version CVS $Id: XMLProducerTagSupport.java,v 1.3 2004/03/05 13:02:24 bdelacretaz Exp $
+ * @version CVS $Id$
*/
public abstract class XMLProducerTagSupport extends TagSupport implements XMLProducerTag {
-
+
protected XMLConsumer xmlConsumer;
/*
@@ -31,12 +31,12 @@
public void setConsumer(XMLConsumer xmlConsumer) {
this.xmlConsumer = xmlConsumer;
}
-
+
/*
* @see Recyclable#recycle()
*/
public void recycle() {
- xmlConsumer = null;
+ this.xmlConsumer = null;
super.recycle();
}
}
Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/transformation/TagTransformer.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/transformation/TagTransformer.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/taglib/java/org/apache/cocoon/transformation/TagTransformer.java Thu Sep 2 13:31:16 2004
@@ -1,12 +1,12 @@
/*
* 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.
@@ -15,17 +15,6 @@
*/
package org.apache.cocoon.transformation;
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.collections.ArrayStack;
-import org.apache.commons.collections.map.StaticBucketMap;
import org.apache.avalon.excalibur.pool.Recyclable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentSelector;
@@ -37,6 +26,7 @@
import org.apache.avalon.framework.service.ServiceManager;
import org.apache.avalon.framework.service.ServiceSelector;
import org.apache.avalon.framework.service.Serviceable;
+
import org.apache.cocoon.components.sax.XMLDeserializer;
import org.apache.cocoon.components.sax.XMLSerializer;
import org.apache.cocoon.environment.SourceResolver;
@@ -46,31 +36,49 @@
import org.apache.cocoon.xml.XMLConsumer;
import org.apache.cocoon.xml.XMLProducer;
+import org.apache.commons.collections.ArrayStack;
+import org.apache.commons.collections.map.StaticBucketMap;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
/**
- * Transformer which implements the dynamic Tag functionalty.
+ * Transformer which implements the taglib functionalty.
+ *
+ * <p>Transformer processes incoming SAX events and for each element it tries to
+ * find {@link Tag} component with matching namespace and tag name.
*
* @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
* @version CVS $Id$
*/
public class TagTransformer
- extends AbstractXMLProducer
- implements Transformer, Serviceable, Configurable, Disposable, Recyclable {
+ extends AbstractXMLProducer
+ implements Transformer, Serviceable, Configurable, Disposable, Recyclable {
+
+ private int recordingLevel;
+ private int skipLevel;
- private int recordingLevel = 0;
- private int skipLevel = 0;
private String transformerHint;
+ private ServiceSelector transformerSelector;
+
+ private final ArrayStack tagStack = new ArrayStack();
+ private final ArrayStack tagSelectorStack = new ArrayStack();
+ private final ArrayStack tagTransformerStack = new ArrayStack();
- private ArrayStack tagStack = new ArrayStack();
- private ArrayStack tagSelectorStack = new ArrayStack();
- private ArrayStack tagTransformerStack = new ArrayStack();
private ServiceSelector tagNamespaceSelector;
- private ServiceSelector transformerSelector;
private Tag currentTag;
+
/** current SAX Event Consumer */
private XMLConsumer currentConsumer;
+
/** backup of currentConsumer while recording */
private XMLConsumer currentConsumerBackup;
@@ -78,39 +86,26 @@
/** The SourceResolver for this request */
private SourceResolver resolver;
+
/** The current objectModel of the environment */
private Map objectModel;
+
/** The parameters specified in the sitemap */
private Parameters parameters;
+
/** The Avalon ServiceManager */
private ServiceManager manager;
- /** Array for dynamic calling of Tag set property methods */
- private String[] paramArray = new String[1];
- /** Map for caching Tag Introspection */
- private static Map writeMethodMap = new StaticBucketMap();
-
- /**
- * SAX Event handling
- */
- public void characters(char[] ch, int start, int length) throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
- currentConsumer.characters(ch, start, length);
- }
+ /** Array for dynamic calling of Tag set property methods */
+ private final String[] paramArray = new String[1];
- /**
- * SAX Event handling
- */
- public void comment(char[] ch, int start, int length) throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
+ /** Map for caching Tag Introspection */
+ private static Map TAG_PROPERTIES_MAP = new StaticBucketMap();
- currentConsumer.comment(ch, start, length);
- }
+ //
+ // Component Lifecycle Methods
+ //
/**
* Avalon Serviceable Interface
@@ -118,77 +113,267 @@
*/
public void service(ServiceManager manager) throws ServiceException {
this.manager = manager;
- tagNamespaceSelector = (ServiceSelector) manager.lookup(Tag.ROLE + "Selector");
+ this.tagNamespaceSelector = (ServiceSelector) manager.lookup(Tag.ROLE + "Selector");
}
/**
* Avalon Configurable Interface
*/
public void configure(Configuration conf) throws ConfigurationException {
- transformerHint = conf.getChild("transformer-hint").getValue(null);
- if (transformerHint != null) {
+ this.transformerHint = conf.getChild("transformer-hint").getValue(null);
+ if (this.transformerHint != null) {
try {
- transformerSelector = (ServiceSelector) manager.lookup(Transformer.ROLE + "Selector");
+ this.transformerSelector = (ServiceSelector) manager.lookup(Transformer.ROLE + "Selector");
} catch (ServiceException e) {
- String message = "can't lookup transformer";
- getLogger().error(message, e);
+ String message = "Can't lookup transformer selector";
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug(message, e);
+ }
throw new ConfigurationException(message, e);
}
}
}
/**
- * SAX Event handling
+ * Set the <code>EntityResolver</code>, objectModel <code>Map</code>,
+ * the source and sitemap <code>Parameters</code> used to process the request.
*/
- public void endCDATA() throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
-
- currentConsumer.endCDATA();
+ public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters)
+ throws IOException, SAXException {
+ this.resolver = resolver;
+ this.objectModel = objectModel;
+ this.parameters = parameters;
}
/**
- * SAX Event handling
+ * Recycle this component.
*/
- public void endDocument() throws SAXException {
- currentConsumer.endDocument();
- getLogger().debug("endDocument");
+ public void recycle() {
+ this.recordingLevel = 0;
+ this.skipLevel = 0;
+ this.resolver = null;
+ this.objectModel = null;
+ this.parameters = null;
+ this.currentTag = null;
+ this.currentConsumer = null;
+ this.currentConsumerBackup = null;
+
+ // can happen if there was a error in the pipeline
+ if (xmlSerializer != null) {
+ manager.release(xmlSerializer);
+ xmlSerializer = null;
+ }
+
+ while (!tagStack.isEmpty()) {
+ Tag tag = (Tag) tagStack.pop();
+ if (tag == null)
+ continue;
+ ComponentSelector tagSelector = (ComponentSelector)tagSelectorStack.pop();
+ tagSelector.release(tag);
+
+ tagNamespaceSelector.release(tagSelector);
+ }
+
+ while (!tagTransformerStack.isEmpty()) {
+ Transformer transformer = (Transformer) tagTransformerStack.pop();
+ transformerSelector.release(transformer);
+ }
+
+ if (!tagSelectorStack.isEmpty()) {
+ getLogger().fatalError("recycle: internal Error, tagSelectorStack not empty");
+ tagSelectorStack.clear();
+ }
+
+ super.recycle();
}
/**
- * SAX Event handling
+ * Dispose this component.
+ */
+ public void dispose() {
+ this.manager.release(tagNamespaceSelector);
+ tagNamespaceSelector = null;
+ if (transformerSelector != null) {
+ this.manager.release(transformerSelector);
+ transformerSelector = null;
+ }
+ }
+
+ /*
+ * @see XMLProducer#setConsumer(XMLConsumer)
*/
+ public void setConsumer(XMLConsumer consumer) {
+ this.currentConsumer = consumer;
+ super.setConsumer(consumer);
+ }
+
+
+ //
+ // SAX Events Methods
+ //
+
+ public void setDocumentLocator(org.xml.sax.Locator locator) {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.setDocumentLocator(locator);
+ }
+
+ public void startDocument() throws SAXException {
+ this.currentConsumer.startDocument();
+ }
+
+ public void endDocument() throws SAXException {
+ this.currentConsumer.endDocument();
+ }
+
+ public void processingInstruction(String target, String data) throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.processingInstruction(target, data);
+ }
+
+ public void startDTD(String name, String publicId, String systemId) throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.startDTD(name, publicId, systemId);
+ }
+
public void endDTD() throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.endDTD();
+ this.currentConsumer.endDTD();
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.startPrefixMapping(prefix, uri);
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.endPrefixMapping(prefix);
+ }
+
+ public void startCDATA() throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.startCDATA();
+ }
+
+ public void endCDATA() throws SAXException {
+ // If we are skipping the body of a tag, ignore this...
+ if (this.skipLevel > 0) {
+ return;
+ }
+
+ this.currentConsumer.endCDATA();
+ }
+
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
+ throws SAXException {
+ // Are we recording for iteration ?
+ if (this.recordingLevel > 0) {
+ this.recordingLevel ++;
+ this.currentConsumer.startElement(namespaceURI, localName, qName, atts);
+ return;
+ }
+
+ // If we are skipping the body of a Tag
+ if (this.skipLevel > 0) {
+ // Remember to skip one more end element
+ this.skipLevel ++;
+ // and ignore this start element
+ return;
+ }
+
+ Tag tag = null;
+ if (namespaceURI != null && namespaceURI.length() > 0) {
+ // Try to find Tag corresponding to this element
+ ComponentSelector tagSelector = null;
+ try {
+ tagSelector = (ComponentSelector) tagNamespaceSelector.select(namespaceURI);
+ tagSelectorStack.push(tagSelector);
+
+ // namespace matches tag library, lookup tag now.
+ tag = (Tag) tagSelector.select(localName);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("startElement: Got tag " + qName);
+ }
+
+ setupTag(tag, qName, atts);
+ } catch (SAXException e) {
+ throw e;
+ } catch (Exception ignore) {
+ // No namespace or tag found, process it as normal element (tag == null)
+ }
+ }
+
+ tagStack.push(tag);
+ if (tag == null) {
+ currentConsumer.startElement(namespaceURI, localName, qName, atts);
+ return;
+ }
+
+ // Execute Tag
+ int eval = tag.doStartTag(namespaceURI, localName, qName, atts);
+ switch (eval) {
+ case Tag.EVAL_BODY :
+ skipLevel = 0;
+ if (tag instanceof IterationTag) {
+ // start recording for IterationTag
+ startRecording();
+ }
+ break;
+
+ case Tag.SKIP_BODY :
+ skipLevel = 1;
+ break;
+
+ default :
+ String tagName = tag.getClass().getName();
+ getLogger().warn("Bad return value from doStartTag(" + tagName + "): " + eval);
+ break;
+ }
}
- /**
- * SAX Event handling
- */
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
Object saxFragment = null;
- // recording for iteration ?
+
+ // Are we recording?
if (recordingLevel > 0) {
if (--recordingLevel > 0) {
currentConsumer.endElement(namespaceURI, localName, qName);
return;
}
- //recording finished
- currentConsumer = currentConsumerBackup;
- saxFragment = xmlSerializer.getSAXFragment();
- manager.release(xmlSerializer);
- xmlSerializer = null;
+ // Recording finished
+ saxFragment = endRecording();
}
if (skipLevel > 0) {
- --skipLevel;
-
- if (skipLevel > 0) {
+ if (--skipLevel > 0) {
return;
}
}
@@ -198,7 +383,7 @@
ComponentSelector tagSelector = (ComponentSelector)tagSelectorStack.pop();
try {
if (saxFragment != null) {
- //start Iteration
+ // Start Iteration
IterationTag iterTag = (IterationTag) tag;
XMLDeserializer xmlDeserializer = null;
try {
@@ -207,350 +392,217 @@
do {
xmlDeserializer.deserialize(saxFragment);
} while (iterTag.doAfterBody() != Tag.SKIP_BODY);
-
} catch (ServiceException e) {
- throw new SAXException("lookup XMLDeserializer failed", e);
- }
- finally {
- if (xmlDeserializer != null)
+ throw new SAXException("Can't obtain XMLDeserializer", e);
+ } finally {
+ if (xmlDeserializer != null) {
manager.release(xmlDeserializer);
+ }
}
}
tag.doEndTag(namespaceURI, localName, qName);
currentTag = tag.getParent();
- if (tag == currentConsumer) {
- // search next XMLConsumer
- Tag loop = currentTag;
- for (; loop != null; loop = loop.getParent()) {
- if (loop instanceof XMLConsumer)
- break;
- }
- if (loop != null) {
- currentConsumer = (XMLConsumer) loop;
- } else {
- currentConsumer = this.xmlConsumer;
- }
+ if (tag == this.currentConsumer) {
+ popConsumer();
}
} finally {
- getLogger().debug("endElement: release Tag");
- tagSelector.release(tag);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("endElement: Release tag " + qName);
+ }
+ tagSelector.release(tag);
tagNamespaceSelector.release(tagSelector);
if (transformerSelector != null && tag instanceof XMLProducer) {
- getLogger().debug("endElement: release transformer");
+ getLogger().debug("endElement: Release transformer");
Transformer transformer = (Transformer) tagTransformerStack.pop();
transformerSelector.release(transformer);
}
}
} else {
- currentConsumer.endElement(namespaceURI, localName, qName);
+ this.currentConsumer.endElement(namespaceURI, localName, qName);
}
}
- /**
- * SAX Event handling
- */
- public void endEntity(String name) throws SAXException {
+ public void startEntity(String name) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.endEntity(name);
+ this.currentConsumer.startEntity(name);
}
- /**
- * SAX Event handling
- */
- public void endPrefixMapping(String prefix) throws SAXException {
+ public void endEntity(String name) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.endPrefixMapping(prefix);
+ this.currentConsumer.endEntity(name);
}
- /**
- * SAX Event handling
- */
- public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ public void skippedEntity(String name) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.ignorableWhitespace(ch, start, length);
+ this.currentConsumer.skippedEntity(name);
}
- /**
- * SAX Event handling
- */
- public void processingInstruction(String target, String data) throws SAXException {
+ public void characters(char[] ch, int start, int length) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
-
- currentConsumer.processingInstruction(target, data);
- }
-
- /**
- * Recycle this component.
- */
- public void recycle() {
- recordingLevel = 0;
- skipLevel = 0;
- resolver = null;
- objectModel = null;
- parameters = null;
- currentTag = null;
- currentConsumer = null;
- currentConsumerBackup = null;
-
- // can happen if there was a error in the pipeline
- if (xmlSerializer != null) {
- manager.release(xmlSerializer);
- xmlSerializer = null;
- }
-
- while (!tagStack.isEmpty()) {
- Tag tag = (Tag) tagStack.pop();
- if (tag == null)
- continue;
- ComponentSelector tagSelector = (ComponentSelector)tagSelectorStack.pop();
- tagSelector.release(tag);
-
- tagNamespaceSelector.release(tagSelector);
}
- while (!tagTransformerStack.isEmpty()) {
- Transformer transformer = (Transformer) tagTransformerStack.pop();
- transformerSelector.release(transformer);
- }
-
- if (!tagSelectorStack.isEmpty()) {
- getLogger().fatalError("recycle: internal Error, tagSelectorStack not empty");
- tagSelectorStack.clear();
- }
-
- super.recycle();
+ this.currentConsumer.characters(ch, start, length);
}
- /*
- * @see XMLProducer#setConsumer(XMLConsumer)
- */
- public void setConsumer(XMLConsumer consumer) {
- this.currentConsumer = consumer;
- super.setConsumer(consumer);
- }
-
- /**
- * SAX Event handling
- */
- public void setDocumentLocator(org.xml.sax.Locator locator) {
+ public void comment(char[] ch, int start, int length) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.setDocumentLocator(locator);
- }
-
- /**
- * Set the <code>EntityResolver</code>, objectModel <code>Map</code>,
- * the source and sitemap <code>Parameters</code> used to process the request.
- */
- public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters)
- throws IOException, SAXException {
- this.resolver = resolver;
- this.objectModel = objectModel;
- this.parameters = parameters;
+ this.currentConsumer.comment(ch, start, length);
}
- /**
- * SAX Event handling
- */
- public void skippedEntity(String name) throws SAXException {
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
// If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
+ if (this.skipLevel > 0) {
return;
+ }
- currentConsumer.skippedEntity(name);
+ this.currentConsumer.ignorableWhitespace(ch, start, length);
}
- /**
- * SAX Event handling
- */
- public void startCDATA() throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
- currentConsumer.startCDATA();
- }
+ //
+ // Internal Implementation Methods
+ //
- /**
- * SAX Event handling
- */
- public void startDocument() throws SAXException {
- currentConsumer.startDocument();
- }
+ private void setupTag(Tag tag, String name, Attributes atts) throws SAXException {
+ // Set Tag Parent
+ tag.setParent(this.currentTag);
- /**
- * SAX Event handling
- */
- public void startDTD(String name, String publicId, String systemId) throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
+ // Set Tag XML Consumer
+ if (tag instanceof XMLProducer) {
+ XMLConsumer tagConsumer;
+ if (transformerSelector != null) {
+ Transformer tagTransformer = null;
+ try {
+ // Add additional (Tag)Transformer to the output of the Tag
+ tagTransformer = (Transformer) transformerSelector.select(transformerHint);
+ tagTransformerStack.push(tagTransformer);
+ tagTransformer.setConsumer(currentConsumer);
+ tagTransformer.setup(this.resolver, this.objectModel, null, this.parameters);
+ } catch (SAXException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SAXException("Failed to setup tag transformer " + transformerHint, e);
+ }
+ tagConsumer = tagTransformer;
+ } else {
+ tagConsumer = this.currentConsumer;
+ }
- currentConsumer.startDTD(name, publicId, systemId);
- }
+ ((XMLProducer) tag).setConsumer(tagConsumer);
+ }
- /**
- * SAX Event handling
- */
- public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
- // recording for iteration ?
- if (recordingLevel > 0) {
- ++recordingLevel;
- currentConsumer.startElement(namespaceURI, localName, qName, atts);
- return;
+ // Setup Tag
+ try {
+ tag.setup(this.resolver, this.objectModel, this.parameters);
+ } catch (IOException e) {
+ throw new SAXException("Could not set up tag " + name, e);
}
- // If we are skipping the body of a Tag
- if (skipLevel > 0) {
- // Remember to skip one more end element
- skipLevel++;
- // and ignore this start element
- return;
+
+ if (tag instanceof XMLConsumer) {
+ this.currentConsumer = (XMLConsumer) tag;
}
+ this.currentTag = tag;
- Tag tag = null;
- if (namespaceURI != null && namespaceURI.length() > 0) {
- ComponentSelector tagSelector = null;
- Transformer tagTransformer = null;
+ // Set Tag-Attributes, Attributes are mapped to the coresponding Tag method
+ for (int i = 0; i < atts.getLength(); i++) {
+ String attributeName = atts.getLocalName(i);
+ String attributeValue = atts.getValue(i);
+ this.paramArray[0] = attributeValue;
try {
- tagSelector = (ComponentSelector) tagNamespaceSelector.select(namespaceURI);
- tagSelectorStack.push(tagSelector);
-
- // namespace matches tag library, lookup tag now.
- tag = (Tag) tagSelector.select(localName);
-
- // tag found, setup Tag and connect it to pipeline
- tag.setParent(currentTag);
- tag.setup(this.resolver, this.objectModel, this.parameters);
-
- if (tag instanceof XMLProducer) {
- if (transformerSelector != null) {
- // add additional (Tag)Transformer to the output of the Tag
- tagTransformer = (Transformer) transformerSelector.select(transformerHint);
- tagTransformerStack.push(tagTransformer);
- tagTransformer.setup(this.resolver, this.objectModel, null, this.parameters);
- ((XMLProducer) tag).setConsumer(tagTransformer);
- tagTransformer.setConsumer(currentConsumer);
- }
- }
- if (tag instanceof XMLConsumer) {
- currentConsumer = (XMLConsumer) tag;
- }
-
- currentTag = tag;
-
- // Set Tag-Attributes, Attributes are mapped to the coresponding Tag method
- for (int i = 0; i < atts.getLength(); i++) {
- String attributeName = atts.getLocalName(i);
- String attributeValue = atts.getValue(i);
- paramArray[0] = attributeValue;
- try {
- Method method = getWriteMethod(tag.getClass(), attributeName);
- method.invoke(tag, paramArray);
- } catch (Throwable e) {
- if (getLogger().isInfoEnabled())
- getLogger().info("startElement(" + localName + "): Attribute " + attributeName + " not set", e);
- }
+ Method method = getWriteMethod(tag.getClass(), attributeName);
+ method.invoke(tag, this.paramArray);
+ } catch (Throwable e) {
+ if (getLogger().isInfoEnabled()) {
+ getLogger().info("Tag " + name + " attribute " + attributeName + " not set", e);
}
- } catch (Exception ignore) {
- // No namespace or tag found, process it as normal element (tag == null)
- }
- }
-
- tagStack.push(tag);
- if (tag == null) {
- currentConsumer.startElement(namespaceURI, localName, qName, atts);
- } else {
- int eval = tag.doStartTag(namespaceURI, localName, qName, atts);
- switch (eval) {
- case Tag.EVAL_BODY :
- skipLevel = 0;
- if (tag instanceof IterationTag) {
- // start recording for IterationTag
- try {
- xmlSerializer = (XMLSerializer) manager.lookup(XMLSerializer.ROLE);
- currentConsumerBackup = currentConsumer;
- currentConsumer = xmlSerializer;
- recordingLevel = 1;
- } catch (ServiceException e) {
- throw new SAXException("lookup XMLSerializer failed", e);
- }
- }
- break;
-
- case Tag.SKIP_BODY :
- skipLevel = 1;
- break;
-
- default :
- String tagName = tag.getClass().getName();
- getLogger().warn("Bad return value from doStartTag(" + tagName + "): " + eval);
- break;
}
}
}
/**
- * SAX Event handling
+ * Start recording for the iterator tag.
*/
- public void startEntity(String name) throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
+ private void startRecording() throws SAXException {
+ try {
+ this.xmlSerializer = (XMLSerializer) manager.lookup(XMLSerializer.ROLE);
+ } catch (ServiceException e) {
+ throw new SAXException("Can't lookup XMLSerializer", e);
+ }
- currentConsumer.startEntity(name);
+ this.currentConsumerBackup = this.currentConsumer;
+ this.currentConsumer = this.xmlSerializer;
+ this.recordingLevel = 1;
}
/**
- * SAX Event handling
+ * End recording for the iterator tag and returns recorded XML fragment.
*/
- public void startPrefixMapping(String prefix, String uri) throws SAXException {
- // If we are skipping the body of a tag, ignore this...
- if (skipLevel > 0)
- return;
+ private Object endRecording() {
+ // Restore XML Consumer
+ this.currentConsumer = this.currentConsumerBackup;
+ this.currentConsumerBackup = null;
- currentConsumer.startPrefixMapping(prefix, uri);
+ // Get XML Fragment
+ Object saxFragment = this.xmlSerializer.getSAXFragment();
+
+ // Release Serializer
+ this.manager.release(this.xmlSerializer);
+ this.xmlSerializer = null;
+
+ return saxFragment;
}
/**
- * Dispose this component.
+ * Find previous XML consumer when processing of current consumer
+ * is complete.
*/
- public void dispose() {
- this.manager.release(tagNamespaceSelector);
- tagNamespaceSelector = null;
- if (transformerSelector != null) {
- this.manager.release(transformerSelector);
- transformerSelector = null;
+ private void popConsumer() {
+ Tag loop = this.currentTag;
+ for (; loop != null; loop = loop.getParent()) {
+ if (loop instanceof XMLConsumer) {
+ this.currentConsumer = (XMLConsumer) loop;
+ return;
+ }
}
+
+ this.currentConsumer = this.xmlConsumer;
}
private static Method getWriteMethod(Class type, String propertyName) throws IntrospectionException {
Map map = getWriteMethodMap(type);
Method method = (Method) map.get(propertyName);
- if (method == null)
+ if (method == null) {
throw new IntrospectionException("No such property: " + propertyName);
+ }
return method;
}
private static Map getWriteMethodMap(Class beanClass) throws IntrospectionException {
- Map map = (Map) writeMethodMap.get(beanClass);
- if (map != null)
+ Map map = (Map) TAG_PROPERTIES_MAP.get(beanClass);
+ if (map != null) {
return map;
+ }
BeanInfo info = Introspector.getBeanInfo(beanClass);
if (info != null) {
@@ -566,7 +618,7 @@
map.put(name, method);
}
}
- writeMethodMap.put(beanClass, map);
+ TAG_PROPERTIES_MAP.put(beanClass, map);
return map;
}
}