You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by jb...@apache.org on 2010/10/03 21:46:55 UTC
svn commit: r1004032 - in /tomcat/taglibs/standard/trunk/impl: ./
src/main/java/org/apache/taglibs/standard/resources/
src/main/java/org/apache/taglibs/standard/tag/common/xml/
src/main/java/org/apache/taglibs/standard/tag/el/xml/
src/main/java/org/apa...
Author: jboynes
Date: Sun Oct 3 19:46:54 2010
New Revision: 1004032
URL: http://svn.apache.org/viewvc?rev=1004032&view=rev
Log:
refactor transform tag and add more parameter validation
Added:
tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/
tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java
Modified:
tomcat/taglibs/standard/trunk/impl/pom.xml
tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.properties
tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java
tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java
tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java
Modified: tomcat/taglibs/standard/trunk/impl/pom.xml
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/pom.xml?rev=1004032&r1=1004031&r2=1004032&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/pom.xml (original)
+++ tomcat/taglibs/standard/trunk/impl/pom.xml Sun Oct 3 19:46:54 2010
@@ -157,6 +157,7 @@
<include>org/apache/taglibs/standard/lang/jstl/test/StaticFunctionTests.java</include>
<include>org/apache/taglibs/standard/TestVersion.java</include>
<include>org/apache/taglibs/standard/tag/common/core/TestSetSupport.java</include>
+ <include>org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java</include>
</includes>
<excludes>
<!-- Old tests -->
Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.properties
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.properties?rev=1004032&r1=1004031&r2=1004032&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.properties (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.properties Sun Oct 3 19:46:54 2010
@@ -235,17 +235,35 @@ PARSE_NO_SAXTRANSFORMER=\
Filter supplied to <parse>, but default TransformerFactory \
does not support SAX.
-TRANSFORM_NO_TRANSFORMER=\
- <transform> was not passed an XSLT stylesheet
+TRANSFORM_XSLT_IS_NULL=\
+ <transform> 'xslt' attribute must not be null
-TRANSFORM_SOURCE_INVALID_LIST=\
- <transform> encountered an invalid java.util.List while processing 'xml' attribute. This error is typically caused if you pass a node-set with more than one node to <transform>'s 'xml' attribute.
+TRANSFORM_XSLT_IS_EMPTY=\
+ <transform> 'xslt' attribute must not be an empty String
-TRANSFORM_SOURCE_UNRECOGNIZED=\
- <transform> encountered an unknown type while processing 'xml' attribute
+TRANSFORM_XSLT_UNSUPPORTED_TYPE=\
+ <transform> 'xslt' attribute was of an unsupported type: {0}
-TRANSFORM_XSLT_UNRECOGNIZED=\
- <transform> encountered an unknown type while processing 'xslt' attribute
+TRANSFORM_XML_IS_NULL=\
+ <transform> 'xml' or 'doc' attribute must not be null
+
+TRANSFORM_XML_IS_EMPTY=\
+ <transform> 'xml' or 'doc' attribute must not be an empty String
+
+TRANSFORM_XML_LIST_SIZE=\
+ <transform> 'xml' or 'doc' attribute of List type may only contain 1 element
+
+TRANSFORM_XML_UNSUPPORTED_TYPE=\
+ <transform> 'xml' or 'doc' attribute was of an unsupported type: {0}
+
+TRANSFORM_BODY_IS_NULL=\
+ <transform> body content was null
+
+TRANSFORM_BODY_CONTENT_IS_NULL=\
+ <transform> body content value was null
+
+TRANSFORM_BODY_IS_EMPTY=\
+ <transform> body content evaluated to an empty String
UNABLE_TO_RESOLVE_ENTITY=\
Could not resolve entity reference: "{0}"
Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java?rev=1004032&r1=1004031&r2=1004032&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java Sun Oct 3 19:46:54 2010
@@ -66,6 +66,7 @@ public abstract class TransformSupport e
// Protected state
protected Object xml; // attribute
+ protected boolean xmlSpecified; // true if xml attribute was specified
protected String xmlSystemId; // attribute
protected Object xslt; // attribute
protected String xsltSystemId; // attribute
@@ -79,23 +80,32 @@ public abstract class TransformSupport e
private Transformer t; // actual Transformer
private TransformerFactory tf; // reusable factory
private DocumentBuilder db; // reusable factory
- private DocumentBuilderFactory dbf; // reusable factory
//*********************************************************************
// Constructor and initialization
public TransformSupport() {
- super();
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ db = dbf.newDocumentBuilder();
+ tf = TransformerFactory.newInstance();
+ } catch (ParserConfigurationException e) {
+ throw (AssertionError) new AssertionError("Unable to create DocumentBuilder").initCause(e);
+ }
+
init();
}
private void init() {
xml = xslt = null;
+ xmlSpecified = false;
xmlSystemId = xsltSystemId = null;
var = null;
result = null;
- tf = null;
+ tf.setURIResolver(null);
scope = PageContext.PAGE_SCOPE;
}
@@ -104,79 +114,15 @@ public abstract class TransformSupport e
// Tag logic
public int doStartTag() throws JspException {
- /*
- * We can set up our Transformer here, so we do so, and we let
- * it receive parameters directly from subtags (instead of
- * caching them.
- */
- try {
-
- //************************************
- // Initialize
-
- // set up our DocumentBuilderFactory if necessary
- if (dbf == null) {
- dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true);
- dbf.setValidating(false);
- }
- if (db == null)
- db = dbf.newDocumentBuilder();
-
- // set up the TransformerFactory if necessary
- if (tf == null)
- tf = TransformerFactory.newInstance();
-
- //************************************
- // Produce transformer
-
- Source s;
- if (xslt != null) {
- if (!(xslt instanceof String) && !(xslt instanceof Reader)
- && !(xslt instanceof javax.xml.transform.Source))
- throw new JspTagException(
- Resources.getMessage("TRANSFORM_XSLT_UNRECOGNIZED"));
- s = getSource(xslt, xsltSystemId);
- } else {
- throw new JspTagException(
- Resources.getMessage("TRANSFORM_NO_TRANSFORMER"));
- }
- tf.setURIResolver(new JstlUriResolver(pageContext));
- t = tf.newTransformer(s);
-
- return EVAL_BODY_BUFFERED;
-
- } catch (SAXException ex) {
- throw new JspException(ex);
- } catch (ParserConfigurationException ex) {
- throw new JspException(ex);
- } catch (IOException ex) {
- throw new JspException(ex);
- } catch (TransformerConfigurationException ex) {
- throw new JspException(ex);
- }
+ // set up transformer in the start tag so that nested <param> tags can set parameters directly
+ t = getTransformer(xslt, xsltSystemId);
+ return EVAL_BODY_BUFFERED;
}
- // parse 'xml' or body, transform via our Transformer,
- // and store as 'var' or through 'result'
-
public int doEndTag() throws JspException {
- try {
-
- //************************************
- // Determine source XML
-
- // if we haven't gotten a source, use the body (which may be empty)
- Object xml = this.xml;
- if (xml == null) // still equal
- if (bodyContent != null && bodyContent.getString() != null)
- xml = bodyContent.getString().trim();
- else
- xml = "";
-
- // let the Source be with you
- Source source = getSource(xml, xmlSystemId);
+ Source source = xmlSpecified ? getSourceFromXmlAttribute() : getDocumentFromBodyContent();
+ try {
//************************************
// Conduct the transformation
@@ -191,18 +137,10 @@ public abstract class TransformSupport e
t.transform(source, doc);
pageContext.setAttribute(var, d, scope);
} else {
- Result page =
- new StreamResult(new SafeWriter(pageContext.getOut()));
+ Result page = new StreamResult(new SafeWriter(pageContext.getOut()));
t.transform(source, page);
}
-
return EVAL_PAGE;
- } catch (SAXException ex) {
- throw new JspException(ex);
- } catch (ParserConfigurationException ex) {
- throw new JspException(ex);
- } catch (IOException ex) {
- throw new JspException(ex);
} catch (TransformerException ex) {
throw new JspException(ex);
}
@@ -211,9 +149,16 @@ public abstract class TransformSupport e
// Releases any resources we may have (or inherit)
public void release() {
+ super.release();
init();
}
+ @Override
+ public void setPageContext(PageContext pageContext) {
+ super.setPageContext(pageContext);
+ tf.setURIResolver(pageContext == null ? null : new JstlUriResolver(pageContext));
+ }
+
//*********************************************************************
// Public methods for subtags
@@ -244,46 +189,124 @@ public abstract class TransformSupport e
}
/**
- * Retrieves a Source from the given Object, whether it be a String,
- * Reader, Node, or other supported types (even a Source already).
- * If 'url' is true, then we must be passed a String and will interpret
- * it as a URL. A null input always results in a null output.
+ * Create a Transformer from the xslt attribute.
+ *
+ * @param xslt the xslt attribute
+ * @param systemId the systemId for the transform
+ * @return an XSLT transformer
+ * @throws JspException if there was a problem creating the transformer
*/
- private Source getSource(Object o, String systemId)
- throws SAXException, ParserConfigurationException, IOException {
- if (o == null)
- return null;
- else if (o instanceof Source) {
- return (Source) o;
- } else if (o instanceof String) {
- // if we've got a string, chain to Reader below
- return getSource(new StringReader((String) o), systemId);
- } else if (o instanceof Reader) {
+ Transformer getTransformer(Object xslt, String systemId) throws JspException {
+ if (xslt == null) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_IS_NULL"));
+ }
+ Source source;
+ if (xslt instanceof Source) {
+ source = (Source) xslt;
+ } else {
+ if (xslt instanceof String) {
+ String s = (String) xslt;
+ s = s.trim();
+ if (s.length() == 0) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_IS_EMPTY"));
+ }
+ xslt = new StringReader(s);
+ }
+ if (xslt instanceof Reader) {
+ source = getSource((Reader) xslt, systemId);
+ } else {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_UNSUPPORTED_TYPE", xslt.getClass()));
+ }
+ }
+ try {
+ return tf.newTransformer(source);
+ } catch (TransformerConfigurationException e) {
+ throw new JspTagException(e);
+ }
+ }
+
+ /**
+ * Return the Source for a document specified in the "doc" or "xml" attribute.
+ *
+ * @return the document Source
+ * @throws JspTagException if there is a problem with the attribute
+ */
+ Source getSourceFromXmlAttribute() throws JspTagException {
+ Object xml = this.xml;
+ if (xml == null) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XML_IS_NULL"));
+ }
+
+ // other JSTL XML tags may produce a list
+ if (xml instanceof List) {
+ List<?> list = (List<?>) xml;
+ if (list.size() != 1) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XML_LIST_SIZE"));
+ }
+ xml = list.get(0);
+ }
+
+ if (xml instanceof Source) {
+ return (Source) xml;
+ }
+ if (xml instanceof String) {
+ String s = (String) xml;
+ s = s.trim();
+ if (s.length() == 0) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XML_IS_EMPTY"));
+ }
+ return getSource(new StringReader(s), xmlSystemId);
+ }
+ if (xml instanceof Reader) {
+ return getSource((Reader) xml, xmlSystemId);
+ }
+ if (xml instanceof Node) {
+ return new DOMSource((Node) xml, xmlSystemId);
+ }
+ throw new JspTagException(Resources.getMessage("TRANSFORM_XML_UNSUPPORTED_TYPE", xml.getClass()));
+ }
+
+ /**
+ * Return the Source for a document specified as body content.
+ * @return the document Source
+ * @throws JspTagException if there is a problem with the body content
+ */
+ Source getDocumentFromBodyContent() throws JspTagException {
+ if (bodyContent == null) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_IS_NULL"));
+ }
+ String s = bodyContent.getString();
+ if (s == null) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_CONTENT_IS_NULL"));
+ }
+ s = s.trim();
+ if (s.length() == 0) {
+ throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_IS_EMPTY"));
+ }
+ return getSource(new StringReader(s), xmlSystemId);
+ }
+
+ /**
+ * Create a Source from a Reader
+ *
+ * @param reader the Reader to read
+ * @param systemId the systemId for the document
+ * @return a SAX Source
+ * @throws JspTagException if there is a problem creating the Source
+ */
+ Source getSource(Reader reader, String systemId) throws JspTagException {
+ try {
// explicitly go through SAX to maintain control
// over how relative external entities resolve
XMLReader xr = XMLReaderFactory.createXMLReader();
- xr.setEntityResolver(
- new ParseSupport.JstlEntityResolver(pageContext));
- InputSource s = new InputSource((Reader) o);
+ xr.setEntityResolver(new ParseSupport.JstlEntityResolver(pageContext));
+ InputSource s = new InputSource(reader);
s.setSystemId(wrapSystemId(systemId));
- Source result = new SAXSource(xr, s);
- result.setSystemId(wrapSystemId(systemId));
- return result;
- } else if (o instanceof Node) {
- return new DOMSource((Node) o);
- } else if (o instanceof List) {
- // support 1-item List because our XPath processor outputs them
- List l = (List) o;
- if (l.size() == 1) {
- return getSource(l.get(0), systemId); // unwrap List
- } else {
- throw new IllegalArgumentException(
- Resources.getMessage("TRANSFORM_SOURCE_INVALID_LIST"));
- }
- } else {
- throw new IllegalArgumentException(
- Resources.getMessage("TRANSFORM_SOURCE_UNRECOGNIZED")
- + o.getClass());
+ Source source = new SAXSource(xr, s);
+ source.setSystemId(wrapSystemId(systemId));
+ return source;
+ } catch (SAXException e) {
+ throw new JspTagException(e);
}
}
@@ -309,6 +332,7 @@ public abstract class TransformSupport e
* toilet in my office similarly...)
*/
private static class SafeWriter extends Writer {
+ // TODO: shouldn't we be delegating all methods?
private Writer w;
public SafeWriter(Writer w) {
Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java?rev=1004032&r1=1004031&r2=1004032&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java Sun Oct 3 19:46:54 2010
@@ -77,6 +77,7 @@ public class TransformTag extends Transf
// for EL-based attribute
public void setXml(String xml_) {
this.xml_ = xml_;
+ this.xmlSpecified = true;
}
// for EL-based attribute
Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java?rev=1004032&r1=1004031&r2=1004032&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java Sun Oct 3 19:46:54 2010
@@ -37,12 +37,13 @@ public class TransformTag extends Transf
// Deprecated as of JSTL 1.1
// for tag attribute
public void setXml(Object xml) throws JspTagException {
- this.xml = xml;
+ setDoc(xml);
}
// 'doc' replaces 'xml' as of JSTL 1.1
public void setDoc(Object xml) throws JspTagException {
this.xml = xml;
+ this.xmlSpecified = true;
}
// Deprecated as of JSTL 1.1
Added: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java?rev=1004032&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TestTransformSupport.java Sun Oct 3 19:46:54 2010
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.taglibs.standard.tag.common.xml;
+
+import javax.servlet.jsp.JspException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+/**
+ */
+public class TestTransformSupport {
+ private TransformSupport tag;
+
+ @Before
+ public void setup() {
+ tag = new TransformSupport() {
+ };
+ }
+
+ @Test
+ public void testNullTransform() {
+ tag.xslt = null;
+ try {
+ tag.doStartTag();
+ fail();
+ } catch (JspException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testEmptyTransform() {
+ tag.xslt = "";
+ try {
+ tag.doStartTag();
+ fail();
+ } catch (JspException e) {
+ // expected
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org