Index: src/org/apache/taglibs/standard/extra/spath/SPathFilter.java =================================================================== --- src/org/apache/taglibs/standard/extra/spath/SPathFilter.java (revision 25424) +++ src/org/apache/taglibs/standard/extra/spath/SPathFilter.java (working copy) @@ -30,9 +30,9 @@ import java.util.Stack; /* -import org.apache.xalan.serialize.Serializer; -import org.apache.xalan.serialize.SerializerFactory; -import org.apache.xalan.templates.OutputProperties; +import com.sun.xalan.org.apache.xalan.serialize.Serializer; +import com.sun.xalan.org.apache.xalan.serialize.SerializerFactory; +import com.sun.xalan.org.apache.xalan.templates.OutputProperties; */ import org.xml.sax.Attributes; import org.xml.sax.InputSource; Index: src/org/apache/taglibs/standard/resources/Resources.properties =================================================================== --- src/org/apache/taglibs/standard/resources/Resources.properties (revision 25424) +++ src/org/apache/taglibs/standard/resources/Resources.properties (working copy) @@ -241,21 +241,42 @@ 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_XSLT_IS_EMPTY=\ + <transform> 'xslt' attribute must not be an empty String -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_UNSUPPORTED_TYPE=\ + <transform> 'xslt' attribute was of an unsupported type: {0} -TRANSFORM_SOURCE_UNRECOGNIZED=\ - <transform> encountered an unknown type while processing 'xml' attribute +TRANSFORM_XML_IS_NULL=\ + <transform> 'xml' or 'doc' attribute must not be null -TRANSFORM_XSLT_UNRECOGNIZED=\ - <transform> encountered an unknown type while processing 'xslt' attribute +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}" +XPATH_UNABLE_TO_RESOLVE_VARIABLE=\ + Could not resolve XPath variable: {0} + ######################################################################### # JSTL core TLV messages ######################################################################### @@ -305,9 +326,3 @@ SET_NO_SETTER_METHOD=No setter method in <set> for property "{0}" IMPORT_ABS_ERROR=Problem accessing the absolute URL "{0}". {1} - -XPATH_ERROR_EVALUATING_EXPR=Error evaluating XPath expression "{0}": {1} - -XPATH_ILLEGAL_ARG_EVALUATING_EXPR=Illegal argument evaluating XPath expression "{0}": {1} - -XPATH_ERROR_XOBJECT=Error accessing data in XObject: {0} Index: src/org/apache/taglibs/standard/tag/el/xml/TransformTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/el/xml/TransformTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/el/xml/TransformTag.java (working copy) @@ -1,35 +1,68 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. + * The Apache Software License, Version 1.1 * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. + * Copyright (c) 1999 The Apache Software Foundation. All rights + * reserved. * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. * - * Portions Copyright Apache Software Foundation. + * 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 acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Tomcat", 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 names without prior written + * permission of the Apache Group. + * + * 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 (INCLUDING, 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. For more + * information on the Apache Software Foundation, please see + * . + * */ package org.apache.taglibs.standard.tag.el.xml; -import javax.servlet.jsp.JspException; +import javax.servlet.jsp.*; +import javax.servlet.jsp.tagext.*; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; import javax.xml.transform.Result; - -import org.apache.taglibs.standard.tag.common.xml.TransformSupport; import org.apache.taglibs.standard.tag.el.core.ExpressionUtil; +import org.apache.taglibs.standard.tag.common.xml.*; +import org.apache.taglibs.standard.resources.Resources; /** *

A handler for <transform> that accepts attributes as Strings @@ -42,10 +75,9 @@ //********************************************************************* // 'Private' state (implementation details) - private String xml_; // stores EL-based property - private String xmlSystemId_; // stores EL-based property + private String source_; // stores EL-based property private String xslt_; // stores EL-based property - private String xsltSystemId_; // stores EL-based property + private String transformer_; // stores EL-based property private String result_; // stores EL-based property @@ -82,31 +114,41 @@ //********************************************************************* // Accessor methods - // for EL-based attribute - public void setXml(String xml_) { - this.xml_ = xml_; + public void setXml(Object xml) throws JspTagException { + setDoc(xml); } + // 'doc' replaces 'xml' as of JSTL 1.1 + public void setDoc(Object xml) throws JspTagException { + this.xml = xml; + this.xmlSpecified = true; + } + // for EL-based attribute public void setXmlSystemId(String xmlSystemId_) { - this.xmlSystemId_ = xmlSystemId_; + this.xmlSystemId = xmlSystemId_; } // for EL-based attribute + public void setSource(String source_) { + this.source_ = source_; + } + + // for EL-based attribute public void setXslt(String xslt_) { this.xslt_ = xslt_; } // for EL-based attribute public void setXsltSystemId(String xsltSystemId_) { - this.xsltSystemId_ = xsltSystemId_; + this.xsltSystemId = xsltSystemId_; } - /* Removed for RI 0.5 - // for EL-based attribute - public void setTransformer(String transformer_) { - this.transformer_ = transformer_; - } + /* Removed for RI 0.5 + // for EL-based attribute + public void setTransformer(String transformer_) { + this.transformer_ = transformer_; + } */ // for EL-based attribute @@ -121,7 +163,7 @@ // (re)initializes state (during release() or construction) private void init() { // null implies "no expression" - xml_ = xmlSystemId = xslt_ = xsltSystemId_ = result_ = null; + source_ = xslt_ = transformer_ = result_ = null; } /* Evaluates expressions as necessary */ @@ -134,19 +176,14 @@ * propagate up. */ - xml = ExpressionUtil.evalNotNull( - "transform", "xml", xml_, Object.class, this, pageContext); - xmlSystemId = (String) ExpressionUtil.evalNotNull( - "transform", "xmlSystemId", xmlSystemId_, String.class, - this, pageContext); - xslt= ExpressionUtil.evalNotNull( - "transform", "xslt", xslt_, Object.class, this, - pageContext); - xsltSystemId = (String) ExpressionUtil.evalNotNull( - "transform", "xsltSystemId", xsltSystemId_, String.class, - this, pageContext); + Source source = (Source)ExpressionUtil.evalNotNull( + "transform", "source", source_, Object.class, this, pageContext); + xslt = ExpressionUtil.evalNotNull( + "transform", "xslt", xslt_, Object.class, this, pageContext); + Transformer transformer = (Transformer) ExpressionUtil.evalNotNull( + "transform", "transformer", transformer_, Transformer.class, + this, pageContext); result = (Result) ExpressionUtil.evalNotNull( "transform", "result", result_, Result.class, this, pageContext); - } } Index: src/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java (working copy) @@ -1,27 +1,19 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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.rt.xml; @@ -44,39 +36,48 @@ // 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 // for tag attribute + public void setXmlSystemId(String xmlSystemId) throws JspTagException { this.xmlSystemId = xmlSystemId; } // 'docSystemId' replaces 'xmlSystemId' as of JSTL 1.1 + public void setDocSystemId(String xmlSystemId) throws JspTagException { this.xmlSystemId = xmlSystemId; } // for tag attribute + public void setXslt(Object xslt) throws JspTagException { this.xslt = xslt; } // for tag attribute + public void setXsltSystemId(String xsltSystemId) throws JspTagException { this.xsltSystemId = xsltSystemId; } // for tag attribute + public void setResult(Result result) throws JspTagException { this.result = result; } } + Index: src/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java (working copy) @@ -41,7 +41,7 @@ // for tag attribute public void setEscapeXml(boolean escapeXml) { - this.escapeXml = escapeXml; + this.escapeXml = escapeXml; } } Index: src/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (working copy) @@ -1,93 +1,102 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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 java.util.List; - +import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.jstl.core.LoopTagSupport; +import javax.xml.transform.TransformerException; -import org.apache.taglibs.standard.resources.Resources; +import com.sun.xalan.org.apache.xml.dtm.DTMIterator; +import com.sun.xalan.org.apache.xpath.XPath; +import com.sun.xalan.org.apache.xpath.XPathContext; +import com.sun.xalan.org.apache.xpath.objects.XObject; /** - *

Support for the XML library's <forEach> tag.

+ * Implementation of <x:forEach> tag using low-level Xalan API. * - * @see javax.servlet.jsp.jstl.core.LoopTagSupport * @author Shawn Bayern + * @see javax.servlet.jsp.jstl.core.LoopTagSupport */ public class ForEachTag extends LoopTagSupport { - //********************************************************************* - // Private state + private XPath select; + private XPathContext context; - private String select; // tag attribute - private List nodes; // XPath result - private int nodesIndex; // current index - private org.w3c.dom.Node current; // current node + @Override + public void release() { + super.release(); + select = null; + context = null; + } - //********************************************************************* - // Iteration control methods - - // (We inherit semantics and Javadoc from LoopTagSupport.) - + @Override protected void prepare() throws JspTagException { - nodesIndex = 0; - XPathUtil xu = new XPathUtil(pageContext); - nodes = xu.selectNodes(XPathUtil.getContext(this), select); + context = XalanUtil.getContext(this, pageContext); + try { + XObject nodes = select.execute(context, context.getCurrentNode(), null); + + // create an iterator over the returned nodes and push into the context + DTMIterator iterator = nodes.iter(); + context.pushContextNodeList(iterator); + } catch (TransformerException e) { + throw new JspTagException(e); + } } + @Override protected boolean hasNext() throws JspTagException { - return (nodesIndex < nodes.size()); + DTMIterator iterator = context.getContextNodeList(); + return iterator.getCurrentPos() < iterator.getLength(); } + @Override protected Object next() throws JspTagException { - Object o = nodes.get(nodesIndex++); - if (!(o instanceof org.w3c.dom.Node)) - throw new JspTagException( - Resources.getMessage("FOREACH_NOT_NODESET")); - current = (org.w3c.dom.Node) o; - return current; + DTMIterator iterator = context.getContextNodeList(); + int next = iterator.nextNode(); + context.pushCurrentNode(next); + return iterator.getDTM(next).getNode(next); } + @Override + public int doAfterBody() throws JspException { + // pop the context node after executing the body + context.popCurrentNode(); + return super.doAfterBody(); + } - //********************************************************************* - // Tag logic and lifecycle management - - // Releases any resources we may have (or inherit) - public void release() { - init(); - super.release(); + @Override + public void doFinally() { + // context might be null as prepare is not called if end < begin + if (context != null) { + // pop the list of nodes being iterated + context.popContextNodeList(); + context = null; + } + super.doFinally(); } - - //********************************************************************* - // Attribute accessors - public void setSelect(String select) { - this.select = select; + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } } public void setBegin(int begin) throws JspTagException { @@ -107,25 +116,15 @@ this.step = step; validateStep(); } - - //********************************************************************* - // Public methods for subtags - /* Retrieves the current context. */ - public org.w3c.dom.Node getContext() throws JspTagException { - // expose the current node as the context - return current; + /** + * Return the current XPath context to support expression evaluation in nested tags. + * + * @return the current XPath context + */ + XPathContext getContext() { + return context; } - - - //********************************************************************* - // Private utility methods - - private void init() { - select = null; - nodes = null; - nodesIndex = 0; - current = null; - } } + Index: src/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java (working copy) @@ -1,27 +1,19 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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; @@ -68,15 +60,15 @@ protected Object xml; // 'xml' attribute protected String systemId; // 'systemId' attribute - protected XMLFilter filter; // 'filter' attribute + protected XMLFilter filter; // 'filter' attribute //********************************************************************* // Private state private String var; // 'var' attribute - private String varDom; // 'varDom' attribute - private int scope; // processed 'scope' attr - private int scopeDom; // processed 'scopeDom' attr + private String varDom; // 'varDom' attribute + private int scope; // processed 'scope' attr + private int scopeDom; // processed 'scopeDom' attr // state in support of XML parsing... private DocumentBuilderFactory dbf; @@ -89,21 +81,21 @@ // Constructor and initialization public ParseSupport() { - super(); - init(); + super(); + init(); } private void init() { - var = varDom = null; - xml = null; - systemId = null; - filter = null; - dbf = null; - db = null; - tf = null; - th = null; - scope = PageContext.PAGE_SCOPE; - scopeDom = PageContext.PAGE_SCOPE; + var = varDom = null; + xml = null; + systemId = null; + filter = null; + dbf = null; + db = null; + tf = null; + th = null; + scope = PageContext.PAGE_SCOPE; + scopeDom = PageContext.PAGE_SCOPE; } @@ -111,85 +103,97 @@ // Tag logic // parse 'source' or body, storing result in 'var' + + @Override public int doEndTag() throws JspException { - try { - - // set up our DocumentBuilder - if (dbf == null) { - dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - } - db = dbf.newDocumentBuilder(); + try { - // if we've gotten a filter, set up a transformer to support it - if (filter != null) { - if (tf == null) - tf = TransformerFactory.newInstance(); - if (!tf.getFeature(SAXTransformerFactory.FEATURE)) + // set up our DocumentBuilder + if (dbf == null) { + dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + } + db = dbf.newDocumentBuilder(); + + // if we've gotten a filter, set up a transformer to support it + if (filter != null) { + if (tf == null) { + tf = TransformerFactory.newInstance(); + } + if (!tf.getFeature(SAXTransformerFactory.FEATURE)) { + throw new JspTagException( + Resources.getMessage("PARSE_NO_SAXTRANSFORMER")); + } + SAXTransformerFactory stf = (SAXTransformerFactory) tf; + th = stf.newTransformerHandler(); + } + + // produce a Document by parsing whatever the attributes tell us to use + Document d; + Object xmlText = this.xml; + if (xmlText == null) { + // if the attribute was specified, use the body as 'xml' + if (bodyContent != null && bodyContent.getString() != null) { + xmlText = bodyContent.getString().trim(); + } else { + xmlText = ""; + } + } + if (xmlText instanceof String) { + d = parseStringWithFilter((String) xmlText, filter); + } else if (xmlText instanceof Reader) { + d = parseReaderWithFilter((Reader) xmlText, filter); + } else { throw new JspTagException( - Resources.getMessage("PARSE_NO_SAXTRANSFORMER")); - SAXTransformerFactory stf = (SAXTransformerFactory) tf; - th = stf.newTransformerHandler(); - } + Resources.getMessage("PARSE_INVALID_SOURCE")); + } - // produce a Document by parsing whatever the attributes tell us to use - Document d; - Object xmlText = this.xml; - if (xmlText == null) { - // if the attribute was specified, use the body as 'xml' - if (bodyContent != null && bodyContent.getString() != null) - xmlText = bodyContent.getString().trim(); - else - xmlText = ""; - } - if (xmlText instanceof String) - d = parseStringWithFilter((String) xmlText, filter); - else if (xmlText instanceof Reader) - d = parseReaderWithFilter((Reader) xmlText, filter); - else - throw new JspTagException( - Resources.getMessage("PARSE_INVALID_SOURCE")); + // we've got a Document object; store it out as appropriate + // (let any exclusivity or other constraints be enforced by TEI/TLV) + if (var != null) { + pageContext.setAttribute(var, d, scope); + } + if (varDom != null) { + pageContext.setAttribute(varDom, d, scopeDom); + } - // we've got a Document object; store it out as appropriate - // (let any exclusivity or other constraints be enforced by TEI/TLV) - if (var != null) - pageContext.setAttribute(var, d, scope); - if (varDom != null) - pageContext.setAttribute(varDom, d, scopeDom); - - return EVAL_PAGE; - } catch (SAXException ex) { - throw new JspException(ex); - } catch (IOException ex) { - throw new JspException(ex); - } catch (ParserConfigurationException ex) { - throw new JspException(ex); - } catch (TransformerConfigurationException ex) { - throw new JspException(ex); - } + return EVAL_PAGE; + } catch (SAXException ex) { + throw new JspException(ex); + } catch (IOException ex) { + throw new JspException(ex); + } catch (ParserConfigurationException ex) { + throw new JspException(ex); + } catch (TransformerConfigurationException ex) { + throw new JspException(ex); + } } // Releases any resources we may have (or inherit) + + @Override public void release() { - init(); + init(); } //********************************************************************* // Private utility methods - /** Parses the given InputSource after, applying the given XMLFilter. */ + /** + * Parses the given InputSource after, applying the given XMLFilter. + */ private Document parseInputSourceWithFilter(InputSource s, XMLFilter f) throws SAXException, IOException { - if (f != null) { + if (f != null) { // prepare an output Document Document o = db.newDocument(); // use TrAX to adapt SAX events to a Document object th.setResult(new DOMResult(o)); XMLReader xr = XMLReaderFactory.createXMLReader(); - xr.setEntityResolver(new JstlEntityResolver(pageContext)); + xr.setEntityResolver(new JstlEntityResolver(pageContext)); // (note that we overwrite the filter's parent. this seems // to be expected usage. we could cache and reset the old // parent, but you can't setParent(null), so this wouldn't @@ -198,107 +202,132 @@ f.setContentHandler(th); f.parse(s); return o; - } else - return parseInputSource(s); + } else { + return parseInputSource(s); + } } - /** Parses the given Reader after applying the given XMLFilter. */ + /** + * Parses the given Reader after applying the given XMLFilter. + */ private Document parseReaderWithFilter(Reader r, XMLFilter f) throws SAXException, IOException { - return parseInputSourceWithFilter(new InputSource(r), f); + return parseInputSourceWithFilter(new InputSource(r), f); } - /** Parses the given String after applying the given XMLFilter. */ + /** + * Parses the given String after applying the given XMLFilter. + */ private Document parseStringWithFilter(String s, XMLFilter f) throws SAXException, IOException { StringReader r = new StringReader(s); return parseReaderWithFilter(r, f); } - /** Parses the given Reader after applying the given XMLFilter. */ + /** + * Parses the given Reader after applying the given XMLFilter. + */ private Document parseURLWithFilter(String url, XMLFilter f) throws SAXException, IOException { - return parseInputSourceWithFilter(new InputSource(url), f); + return parseInputSourceWithFilter(new InputSource(url), f); } - /** Parses the given InputSource into a Document. */ + /** + * Parses the given InputSource into a Document. + */ private Document parseInputSource(InputSource s) - throws SAXException, IOException { - db.setEntityResolver(new JstlEntityResolver(pageContext)); + throws SAXException, IOException { + db.setEntityResolver(new JstlEntityResolver(pageContext)); // normalize URIs so they can be processed consistently by resolver - if (systemId == null) + if (systemId == null) { s.setSystemId("jstl:"); - else if (ImportSupport.isAbsoluteUrl(systemId)) + } else if (ImportSupport.isAbsoluteUrl(systemId)) { s.setSystemId(systemId); - else + } else { s.setSystemId("jstl:" + systemId); - return db.parse(s); + } + return db.parse(s); } - /** Parses the given Reader into a Document. */ + /** + * Parses the given Reader into a Document. + */ private Document parseReader(Reader r) throws SAXException, IOException { return parseInputSource(new InputSource(r)); } - /** Parses the given String into a Document. */ + /** + * Parses the given String into a Document. + */ private Document parseString(String s) throws SAXException, IOException { StringReader r = new StringReader(s); return parseReader(r); } - /** Parses the URL (passed as a String) into a Document. */ + /** + * Parses the URL (passed as a String) into a Document. + */ private Document parseURL(String url) throws SAXException, IOException { - return parseInputSource(new InputSource(url)); + return parseInputSource(new InputSource(url)); } //********************************************************************* // JSTL-specific EntityResolver class - /** Lets us resolve relative external entities. */ + /** + * Lets us resolve relative external entities. + */ public static class JstlEntityResolver implements EntityResolver { - private final PageContext ctx; + private final PageContext ctx; + public JstlEntityResolver(PageContext ctx) { this.ctx = ctx; } + public InputSource resolveEntity(String publicId, String systemId) - throws FileNotFoundException { + throws FileNotFoundException { - // pass if we don't have a systemId - if (systemId == null) - return null; + // pass if we don't have a systemId + if (systemId == null) { + return null; + } - // strip leading "jstl:" off URL if applicable - if (systemId.startsWith("jstl:")) - systemId = systemId.substring(5); + // strip leading "jstl:" off URL if applicable + if (systemId.startsWith("jstl:")) { + systemId = systemId.substring(5); + } - // we're only concerned with relative URLs - if (ImportSupport.isAbsoluteUrl(systemId)) - return null; + // we're only concerned with relative URLs + if (ImportSupport.isAbsoluteUrl(systemId)) { + return null; + } - // for relative URLs, load and wrap the resource. - // don't bother checking for 'null' since we specifically want - // the parser to fail if the resource doesn't exist - InputStream s; - if (systemId.startsWith("/")) { - s = ctx.getServletContext().getResourceAsStream(systemId); - if (s == null) - throw new FileNotFoundException( - Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", - systemId)); - } else { - String pagePath = - ((HttpServletRequest) ctx.getRequest()).getServletPath(); - String basePath = - pagePath.substring(0, pagePath.lastIndexOf("/")); - s = ctx.getServletContext().getResourceAsStream( - basePath + "/" + systemId); - if (s == null) - throw new FileNotFoundException( - Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", - systemId)); - } - return new InputSource(s); + // for relative URLs, load and wrap the resource. + // don't bother checking for 'null' since we specifically want + // the parser to fail if the resource doesn't exist + InputStream s; + if (systemId.startsWith("/")) { + s = ctx.getServletContext().getResourceAsStream(systemId); + if (s == null) { + throw new FileNotFoundException( + Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", + systemId)); + } + } else { + String pagePath = + ((HttpServletRequest) ctx.getRequest()).getServletPath(); + String basePath = + pagePath.substring(0, pagePath.lastIndexOf("/")); + s = ctx.getServletContext().getResourceAsStream( + basePath + "/" + systemId); + if (s == null) { + throw new FileNotFoundException( + Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", + systemId)); + } + } + return new InputSource(s); } } @@ -306,18 +335,19 @@ // Tag attributes public void setVar(String var) { - this.var = var; + this.var = var; } public void setVarDom(String varDom) { - this.varDom = varDom; + this.varDom = varDom; } public void setScope(String scope) { - this.scope = Util.getScope(scope); + this.scope = Util.getScope(scope); } public void setScopeDom(String scopeDom) { - this.scopeDom = Util.getScope(scopeDom); + this.scopeDom = Util.getScope(scopeDom); } } + Index: src/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java (working copy) @@ -1,27 +1,19 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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; @@ -74,37 +66,47 @@ //********************************************************************* // Protected state - protected Object xml; // attribute - protected String xmlSystemId; // attribute - protected Object xslt; // attribute - protected String xsltSystemId; // attribute - protected Result result; // attribute + 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 + protected Result result; // attribute //********************************************************************* // Private state - private String var; // 'var' attribute - private int scope; // processed 'scope' attr - private Transformer t; // actual Transformer - private TransformerFactory tf; // reusable factory - private DocumentBuilder db; // reusable factory - private DocumentBuilderFactory dbf; // reusable factory + private String var; // 'var' attribute + private int scope; // processed 'scope' attr + private Transformer t; // actual Transformer + private TransformerFactory tf; // reusable factory + private DocumentBuilder db; // reusable factory //********************************************************************* // Constructor and initialization public TransformSupport() { - super(); - init(); + 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; - xmlSystemId = xsltSystemId = null; - var = null; - result = null; - tf = null; + xml = xslt = null; + xmlSpecified = false; + xmlSystemId = xsltSystemId = null; + var = null; + result = null; + tf.setURIResolver(null); scope = PageContext.PAGE_SCOPE; } @@ -112,122 +114,65 @@ //********************************************************************* // Tag logic + @Override 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 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' + @Override public int doEndTag() throws JspException { - try { + Source source = xmlSpecified ? getSourceFromXmlAttribute() : getDocumentFromBodyContent(); - //************************************ - // Determine source XML + try { + //************************************ + // Conduct the transformation - // 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); - - //************************************ - // Conduct the transformation - - // we can assume at most one of 'var' or 'result' is specified - if (result != null) - // we can write directly to the Result - t.transform(source, result); - else if (var != null) { - // we need a Document - Document d = db.newDocument(); - Result doc = new DOMResult(d); - t.transform(source, doc); - pageContext.setAttribute(var, d, scope); - } else { - 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); - } + // we can assume at most one of 'var' or 'result' is specified + if (result != null) + // we can write directly to the Result + { + t.transform(source, result); + } else if (var != null) { + // we need a Document + Document d = db.newDocument(); + Result doc = new DOMResult(d); + t.transform(source, doc); + pageContext.setAttribute(var, d, scope); + } else { + Result page = new StreamResult(new SafeWriter(pageContext.getOut())); + t.transform(source, page); + } + return EVAL_PAGE; + } catch (TransformerException ex) { + throw new JspException(ex); + } } // Releases any resources we may have (or inherit) + + @Override public void release() { - init(); + super.release(); + init(); } + @Override + public void setPageContext(PageContext pageContext) { + super.setPageContext(pageContext); + tf.setURIResolver(pageContext == null ? null : new JstlUriResolver(pageContext)); + } + //********************************************************************* // Public methods for subtags - /** Sets (adds) a transformation parameter on our transformer. */ + /** + * Sets (adds) a transformation parameter on our transformer. + */ public void addParameter(String name, Object value) { - t.setParameter(name, value); + t.setParameter(name, value); } @@ -240,56 +185,136 @@ * the current directory in the filesystem. */ private static String wrapSystemId(String systemId) { - if (systemId == null) - return "jstl:"; - else if (ImportSupport.isAbsoluteUrl(systemId)) - return systemId; - else - return ("jstl:" + systemId); + if (systemId == null) { + return "jstl:"; + } else if (ImportSupport.isAbsoluteUrl(systemId)) { + return systemId; + } else { + return ("jstl:" + systemId); + } } /** - * 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) { - // explicitly go through SAX to maintain control - // over how relative external entities resolve + 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); + } } @@ -297,7 +322,7 @@ // Tag attributes public void setVar(String var) { - this.var = var; + this.var = var; } public void setScope(String scope) { @@ -314,52 +339,71 @@ * toilet in my office similarly...) */ private static class SafeWriter extends Writer { - private Writer w; - public SafeWriter(Writer w) { this.w = w; } - public void close() { } - public void flush() { } - public void write(char[] cbuf, int off, int len) throws IOException { - w.write(cbuf, off, len); - } - } + // TODO: shouldn't we be delegating all methods? + private Writer w; + public SafeWriter(Writer w) { + this.w = w; + } + + @Override + public void close() { + } + + @Override + public void flush() { + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + w.write(cbuf, off, len); + } + } + //********************************************************************* // JSTL-specific URIResolver class - /** Lets us resolve relative external entities. */ + /** + * Lets us resolve relative external entities. + */ private static class JstlUriResolver implements URIResolver { private final PageContext ctx; + public JstlUriResolver(PageContext ctx) { this.ctx = ctx; } + public Source resolve(String href, String base) - throws TransformerException { + throws TransformerException { // pass if we don't have a systemId - if (href == null) + if (href == null) { return null; + } - // remove "jstl" marker from 'base' + // remove "jstl" marker from 'base' // NOTE: how 'base' is determined varies among different Xalan // xsltc implementations int index; if (base != null && (index = base.indexOf("jstl:")) != -1) { base = base.substring(index + 5); - } + } // we're only concerned with relative URLs if (ImportSupport.isAbsoluteUrl(href) - || (base != null && ImportSupport.isAbsoluteUrl(base))) + || (base != null && ImportSupport.isAbsoluteUrl(base))) { return null; + } - // base is relative; remove everything after trailing '/' - if (base == null || base.lastIndexOf("/") == -1) - base = ""; - else - base = base.substring(0, base.lastIndexOf("/") + 1); + // base is relative; remove everything after trailing '/' + if (base == null || base.lastIndexOf("/") == -1) { + base = ""; + } else { + base = base.substring(0, base.lastIndexOf("/") + 1); + } - // concatenate to produce the real URL we're interested in - String target = base + href; + // concatenate to produce the real URL we're interested in + String target = base + href; // for relative URLs, load and wrap the resource. // don't bother checking for 'null' since we specifically want @@ -367,24 +411,27 @@ InputStream s; if (target.startsWith("/")) { s = ctx.getServletContext().getResourceAsStream(target); - if (s == null) + if (s == null) { throw new TransformerException( - Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", - href)); + Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", + href)); + } } else { String pagePath = - ((HttpServletRequest) ctx.getRequest()).getServletPath(); + ((HttpServletRequest) ctx.getRequest()).getServletPath(); String basePath = - pagePath.substring(0, pagePath.lastIndexOf("/")); + pagePath.substring(0, pagePath.lastIndexOf("/")); s = ctx.getServletContext().getResourceAsStream( - basePath + "/" + target); - if (s == null) - throw new TransformerException( - Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", - href)); + basePath + "/" + target); + if (s == null) { + throw new TransformerException( + Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", + href)); + } } return new StreamSource(s); } } } + Index: src/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (working copy) @@ -1,95 +1,74 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. + * 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 * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. + * http://www.apache.org/licenses/LICENSE-2.0 * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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 java.io.IOException; + import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.tagext.TagSupport; +import javax.xml.transform.TransformerException; +import org.apache.taglibs.standard.util.EscapeXML; +import com.sun.xalan.org.apache.xpath.XPath; +import com.sun.xalan.org.apache.xpath.XPathContext; + /** - *

Tag handler for <expr> in JSTL's XML library.

+ * Tag handler for <out> in JSTL's XML library. + * TODO: should we rename this to OutSupport to match the tag name? * * @author Shawn Bayern */ - public abstract class ExprSupport extends TagSupport { - //********************************************************************* - // Internal state + private XPath select; + protected boolean escapeXml = true; // tag attribute - private String select; // tag attribute - protected boolean escapeXml; // tag attribute - - //********************************************************************* - // Construction and initialization - - /** - * Constructs a new handler. As with TagSupport, subclasses should - * not provide other constructors and are expected to call the - * superclass constructor. - */ - public ExprSupport() { - super(); - init(); + @Override + public void release() { + super.release(); + select = null; } - // resets local state - private void init() { - select = null; - escapeXml = true; - } - - //********************************************************************* // Tag logic // applies XPath expression from 'select' and prints the result + @Override public int doStartTag() throws JspException { try { - XPathUtil xu = new XPathUtil(pageContext); - String result = xu.valueOf(XPathUtil.getContext(this), select); - org.apache.taglibs.standard.tag.common.core.OutSupport.out( - pageContext, escapeXml, result); - return SKIP_BODY; - } catch (java.io.IOException ex) { - throw new JspTagException(ex.toString(), ex); + XPathContext context = XalanUtil.getContext(this, pageContext); + String result = select.execute(context, context.getCurrentNode(), null).str(); + EscapeXML.emit(result, escapeXml, pageContext.getOut()); + return SKIP_BODY; + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } catch (TransformerException e) { + throw new JspTagException(e); } } - // Releases any resources we may have (or inherit) - public void release() { - super.release(); - init(); - } - - - //********************************************************************* - // Attribute accessors - public void setSelect(String select) { - this.select = select; + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } } } + Index: src/org/apache/taglibs/standard/tag/common/xml/SetTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/SetTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/SetTag.java (working copy) @@ -1,37 +1,32 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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 java.util.List; - import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.TagSupport; +import javax.xml.transform.TransformerException; import org.apache.taglibs.standard.tag.common.core.Util; +import com.sun.xalan.org.apache.xpath.XPath; +import com.sun.xalan.org.apache.xpath.XPathContext; +import com.sun.xalan.org.apache.xpath.objects.XObject; /** *

Tag handler for <set> in JSTL's XML library.

@@ -40,77 +35,54 @@ */ public class SetTag extends TagSupport { - //********************************************************************* - // Internal state + private XPath select; + private String var; + private int scope = PageContext.PAGE_SCOPE; - private String select; // tag attribute - private String var; // tag attribute - private int scope; // processed tag attribute - //********************************************************************* // Construction and initialization - /** - * Constructs a new handler. As with TagSupport, subclasses should - * not provide other constructors and are expected to call the - * superclass constructor. - */ - public SetTag() { - super(); - init(); + @Override + public void release() { + super.release(); + select = null; + var = null; } - // resets local state - private void init() { - var = null; - select = null; - scope = PageContext.PAGE_SCOPE; - } - - //********************************************************************* // Tag logic // applies XPath expression from 'select' and stores the result in 'var' + + @Override public int doStartTag() throws JspException { - // process the query - XPathUtil xu = new XPathUtil(pageContext); - List result = - xu.selectNodes(XPathUtil.getContext(this), select); - Object ret = result; - - // unwrap primitive types if that's what we received - if (result.size() == 1) { - Object o = result.get(0); - if (o instanceof String || o instanceof Boolean - || o instanceof Number) - ret = o; + try { + XPathContext context = XalanUtil.getContext(this, pageContext); + XObject result = select.execute(context, context.getCurrentNode(), null); + pageContext.setAttribute(var, XalanUtil.coerceToJava(result), scope); + return SKIP_BODY; + } catch (TransformerException e) { + throw new JspTagException(e); } - - // expose the final result - pageContext.setAttribute(var, ret, scope); - return SKIP_BODY; } - // Releases any resources we may have (or inherit) - public void release() { - super.release(); - init(); - } - - //********************************************************************* // Attribute accessors public void setSelect(String select) { - this.select = select; + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } } public void setVar(String var) { - this.var = var; + this.var = var; } public void setScope(String scope) { - this.scope = Util.getScope(scope); + this.scope = Util.getScope(scope); } } + Index: src/org/apache/taglibs/standard/tag/common/xml/IfTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/IfTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/IfTag.java (working copy) @@ -1,33 +1,29 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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.JspTagException; import javax.servlet.jsp.jstl.core.ConditionalTagSupport; +import javax.xml.transform.TransformerException; +import com.sun.xalan.org.apache.xpath.XPath; +import com.sun.xalan.org.apache.xpath.XPathContext; + /** *

Tag handler for <if> in JSTL's XML library.

* @@ -36,50 +32,31 @@ public class IfTag extends ConditionalTagSupport { - //********************************************************************* - // Constructor and lifecycle management + private XPath select; - // initialize inherited and local state - public IfTag() { - super(); - init(); - } - // Releases any resources we may have (or inherit) + @Override public void release() { super.release(); - init(); + select = null; } - - //********************************************************************* - // Supplied conditional logic - + @Override protected boolean condition() throws JspTagException { - XPathUtil xu = new XPathUtil(pageContext); - return (xu.booleanValueOf(XPathUtil.getContext(this), select)); + XPathContext context = XalanUtil.getContext(this, pageContext); + try { + return select.bool(context, context.getCurrentNode(), null); + } catch (TransformerException e) { + throw new JspTagException(e); + } } - - //********************************************************************* - // Private state - - private String select; // the value of the 'test' attribute - - - //********************************************************************* - // Attribute accessors - public void setSelect(String select) { - this.select = select; + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } } - - - //********************************************************************* - // Private utility methods - - // resets internal state - private void init() { - select = null; - } } + Index: src/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java (working copy) @@ -1,27 +1,19 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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; @@ -36,8 +28,8 @@ *

Support for tag handlers for <param>, the XML parameter * subtag for <transformt<.

* - * @see TransformSupport * @author Shawn Bayern + * @see TransformSupport */ public abstract class ParamSupport extends BodyTagSupport { @@ -52,13 +44,13 @@ // Constructor and initialization public ParamSupport() { - super(); - init(); + super(); + init(); } private void init() { - name = null; - value = null; + name = null; + value = null; } @@ -66,26 +58,33 @@ // Tag logic // simply send our name and value to our parent tag + + @Override public int doEndTag() throws JspException { - Tag t = findAncestorWithClass(this, TransformSupport.class); - if (t == null) - throw new JspTagException( - Resources.getMessage("PARAM_OUTSIDE_TRANSFORM")); - TransformSupport parent = (TransformSupport) t; + Tag t = findAncestorWithClass(this, TransformSupport.class); + if (t == null) { + throw new JspTagException( + Resources.getMessage("PARAM_OUTSIDE_TRANSFORM")); + } + TransformSupport parent = (TransformSupport) t; - Object value = this.value; - if (value == null) { - if (bodyContent == null || bodyContent.getString() == null) + Object value = this.value; + if (value == null) { + if (bodyContent == null || bodyContent.getString() == null) { value = ""; - else + } else { value = bodyContent.getString().trim(); + } } - parent.addParameter(name, value); - return EVAL_PAGE; + parent.addParameter(name, value); + return EVAL_PAGE; } // Releases any resources we may have (or inherit) + + @Override public void release() { - init(); + init(); } } + Index: src/org/apache/taglibs/standard/tag/common/xml/WhenTag.java =================================================================== --- src/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (revision 25424) +++ src/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (working copy) @@ -1,33 +1,28 @@ /* - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * glassfish/bootstrap/legal/CDDLv1.0.txt or - * https://glassfish.dev.java.net/public/CDDLv1.0.html. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Portions Copyright Apache Software Foundation. - */ + * 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.JspTagException; +import javax.xml.transform.TransformerException; import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; +import com.sun.xalan.org.apache.xpath.XPath; +import com.sun.xalan.org.apache.xpath.XPathContext; /** *

Tag handler for <if> in JSTL's XML library.

@@ -37,49 +32,30 @@ public class WhenTag extends WhenTagSupport { - //********************************************************************* - // Constructor and lifecycle management + private XPath select; - // initialize inherited and local state - public WhenTag() { - super(); - init(); - } - - // Releases any resources we may have (or inherit) + @Override public void release() { super.release(); - init(); + select = null; } - - //********************************************************************* - // Supplied conditional logic - + @Override protected boolean condition() throws JspTagException { - XPathUtil xu = new XPathUtil(pageContext); - return (xu.booleanValueOf(XPathUtil.getContext(this), select)); + XPathContext context = XalanUtil.getContext(this, pageContext); + try { + return select.bool(context, context.getCurrentNode(), null); + } catch (TransformerException e) { + throw new JspTagException(e); + } } - //********************************************************************* - // Private state - - private String select; // the value of the 'test' attribute - - - //********************************************************************* - // Attribute accessors - public void setSelect(String select) { - this.select = select; + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } } - - - //********************************************************************* - // Private utility methods - - // resets internal state - private void init() { - select = null; - } } + Index: build.xml =================================================================== --- build.xml (revision 25424) +++ build.xml (working copy) @@ -132,7 +132,7 @@