diff --git a/impl/pom.xml b/impl/pom.xml index 813a193..c151708 100755 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -24,13 +24,13 @@ org.eclipse.ee4j project - 1.0.6 + 1.0.7 org.glassfish.web jakarta.servlet.jsp.jstl - 3.0.0-SNAPSHOT + 3.0.1-SNAPSHOT jar Jakarta Standard Tag Library Implementation @@ -106,12 +106,20 @@ jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api - 3.0.0-SNAPSHOT + 3.0.0 + provided xalan xalan 2.7.2 + compile + + + xml-apis + xml-apis + + org.junit.jupiter @@ -172,7 +180,7 @@ - + maven-compiler-plugin @@ -183,13 +191,6 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M6 - - org.apache.felix @@ -223,17 +224,15 @@ org.glassfish.jstl.integration - !org.apache.xpath, - !org.apache.xpath.objects, - !org.apache.xpath.jaxp, + !org.apache.bcel, + !org.apache.regexp, !org.apache.xml, !org.apache.xml.dtm, !org.apache.xml.utils, - !org.apache.xalan, - !org.apache.xalan.res, + !org.apache.xpath, + !org.apache.xpath.jaxp, + !org.apache.xpath.objects, !org.apache.xpath.res, - !org.apache.regexp, - !org.apache.bcel, !java_cup.runtime, !trax, org.xml.sax.ext, @@ -251,7 +250,7 @@ - + org.apache.maven.plugins @@ -272,7 +271,7 @@ - + org.apache.maven.plugins @@ -333,12 +332,9 @@ - - + - org.apache.maven.plugins maven-source-plugin - 3.2.1 true @@ -346,15 +342,12 @@ attach-sources - jar-no-fork + jar-no-fork - - + org.codehaus.mojo build-helper-maven-plugin @@ -375,7 +368,6 @@ - org.apache.maven.plugins maven-javadoc-plugin 3.3.1 @@ -414,76 +406,74 @@ Copyright © 2019, ${current.year} Eclipse Foundation. All rights reserved. - - - - - tlddocs - - - - - org.codehaus.mojo - exec-maven-plugin - 3.0.0 - - - generateTldDoc - prepare-package - - java - - - true - false - com.sun.tlddoc.TLDDoc - - -doctitle - Jakarta Tags doc - -windowtitle - Jakarta Tags Doc - -d - ${project.build.directory}/tlddoc - ${project.basedir}/src/main/resources/META-INF/sql.tld - ${project.basedir}/src/main/resources/META-INF/x.tld - ${project.basedir}/src/main/resources/META-INF/fmt.tld - ${project.basedir}/src/main/resources/META-INF/c.tld - ${project.basedir}/src/main/resources/META-INF/fn.tld - - - - - - - org.glassfish.web - tagsdoc - 1.0-SNAPSHOT - - - - - - - + + + + tlddocs + + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + generateTldDoc + prepare-package + + java + + + true + false + com.sun.tlddoc.TLDDoc + + -doctitle + Jakarta Tags doc + -windowtitle + Jakarta Tags Doc + -d + ${project.build.directory}/tlddoc + ${project.basedir}/src/main/resources/META-INF/sql.tld + ${project.basedir}/src/main/resources/META-INF/x.tld + ${project.basedir}/src/main/resources/META-INF/fmt.tld + ${project.basedir}/src/main/resources/META-INF/c.tld + ${project.basedir}/src/main/resources/META-INF/fn.tld + + + + + + + org.glassfish.web + tagsdoc + 1.0-SNAPSHOT + + + + + + + diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/DocumentBuilderProvider.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/DocumentBuilderProvider.java new file mode 100644 index 0000000..f7ae781 --- /dev/null +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/DocumentBuilderProvider.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 Eclipse Foundation and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.apache.taglibs.standard.tag.common.xml; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * Provides preconfigured {@link DocumentBuilder} instances. + * + * @author David Matejcek + */ +public class DocumentBuilderProvider { + + private static final DocumentBuilderFactory DBF; + private static final DocumentBuilderFactory DBF_SECURE; + static { + DBF = DocumentBuilderFactory.newInstance(); + DBF.setNamespaceAware(true); + DBF.setValidating(false); + + DBF_SECURE = DocumentBuilderFactory.newInstance(); + DBF_SECURE.setNamespaceAware(true); + DBF_SECURE.setValidating(false); + try { + DBF_SECURE.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + throw new Error("Parser does not support secure processing"); + } + } + + /** + * Creates a namespace-aware {@link DocumentBuilder} with disabled validation. + *

+ * Note that {@link DocumentBuilder} instances are not thread-safe and their implementation can + * be chosen as described in {@link DocumentBuilderFactory} documentation. + * + * @return new {@link DocumentBuilder} instance. + */ + public static DocumentBuilder createDocumentBuilder() { + try { + return DBF.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new Error("Could not initialize the DocumentBuilder!", e); + } + } + + + /** + * Creates a namespace-aware {@link DocumentBuilder} with disabled validation and enabled + * {@link XMLConstants#FEATURE_SECURE_PROCESSING}. + *

+ * Note that {@link DocumentBuilder} instances are not thread-safe and their implementation can + * be chosen as described in {@link DocumentBuilderFactory} documentation. + * + * @return new {@link DocumentBuilder} instance. + */ + public static DocumentBuilder createSecureDocumentBuilder() { + try { + return DBF_SECURE.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new Error("Could not initialize the DocumentBuilder!", e); + } + } +} diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLNodeList.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLNodeList.java new file mode 100644 index 0000000..f6312ed --- /dev/null +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLNodeList.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 Eclipse Foundation and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.apache.taglibs.standard.tag.common.xml; + +import java.util.Vector; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +class JSTLNodeList extends Vector implements NodeList { + + private static final long serialVersionUID = -1217630367839271134L; + + Vector nodeVector; + + JSTLNodeList(Vector nodeVector) { + this.nodeVector = nodeVector; + } + + + JSTLNodeList(NodeList nl) { + nodeVector = new Vector<>(); + // p("[JSTLNodeList] nodelist details"); + for (int i = 0; i < nl.getLength(); i++) { + Node currNode = nl.item(i); + // XPathUtil.printDetails ( currNode ); + nodeVector.add(i, currNode); + } + } + + + JSTLNodeList(Node n) { + nodeVector = new Vector<>(); + nodeVector.addElement(n); + } + + + JSTLNodeList(Object o) { + nodeVector = new Vector<>(); + + if (o instanceof NodeList) { + NodeList nl = (NodeList) o; + for (int i = 0; i < nl.getLength(); i++) { + Node currNode = nl.item(i); + // XPathUtil.printDetails ( currNode ); + nodeVector.add(i, currNode); + } + } else { + nodeVector.addElement(o); + } + } + + + @Override + public Node item(int index) { + return (Node) nodeVector.elementAt(index); + } + + + @Override + public Object elementAt(int index) { + return nodeVector.elementAt(index); + } + + + @Override + public Object get(int index) { + return nodeVector.get(index); + } + + + @Override + public int getLength() { + return nodeVector.size(); + } + + + @Override + public int size() { + return nodeVector.size(); + } + + // Can implement other Vector methods to redirect those methods to + // the vector in the variable param. As we are not using them as part + // of this implementation we are not doing that here. If this changes + // then we need to override those methods accordingly +} \ No newline at end of file diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathFactory.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathFactory.java index 8b41af9..0db4ba5 100644 --- a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathFactory.java +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathFactory.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,18 +18,21 @@ package org.apache.taglibs.standard.tag.common.xml; +import javax.xml.xpath.XPath; + import org.apache.xpath.jaxp.XPathFactoryImpl; /** * This factory class is added to provide access to our own implementation * of XPath, so that we can support a generic Object type in return type - * arguement for XPath's evaluate instance method. - * + * arguement for XPath's evaluate instance method. + * * @author dhirup */ public class JSTLXPathFactory extends XPathFactoryImpl { - - public javax.xml.xpath.XPath newXPath() { - return new org.apache.taglibs.standard.tag.common.xml.JSTLXPathImpl(null, null); - } + + @Override + public XPath newXPath() { + return new JSTLXPathImpl(null, null); + } } diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathImpl.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathImpl.java index 2a00917..624ea1f 100644 --- a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathImpl.java +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathImpl.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,541 +18,298 @@ package org.apache.taglibs.standard.tag.common.xml; +import java.io.IOException; -import javax.xml.namespace.QName; import javax.xml.namespace.NamespaceContext; -import javax.xml.xpath.XPathExpressionException; +import javax.xml.namespace.QName; +import javax.xml.transform.TransformerException; import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFunctionException; import javax.xml.xpath.XPathFunctionResolver; import javax.xml.xpath.XPathVariableResolver; -import javax.xml.xpath.XPathExpression; import org.apache.xml.dtm.DTM; -import org.apache.xpath.*; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.apache.xpath.jaxp.JAXPExtensionsProvider; +import org.apache.xpath.jaxp.JAXPPrefixResolver; +import org.apache.xpath.jaxp.JAXPVariableStack; +import org.apache.xpath.objects.XNodeSet; import org.apache.xpath.objects.XObject; import org.apache.xpath.res.XPATHErrorResources; -import org.apache.xalan.res.XSLMessages; - -import org.w3c.dom.Node; -import org.w3c.dom.DOMImplementation; +import org.apache.xpath.res.XPATHMessages; import org.w3c.dom.Document; +import org.w3c.dom.Node; import org.w3c.dom.traversal.NodeIterator; - import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import javax.xml.parsers.*; - -import java.io.IOException; - /** * The JSTLXPathImpl class provides implementation for the methods defined in * javax.xml.xpath.XPath interface. This provide simple access to the results - * of an XPath expression. - * - * This class provides our own implementation of XPath, so that we can support - * a generic Object type in returnType arguement for XPath's evaluate instance + * of an XPath expression. + * + * This class provides our own implementation of XPath, so that we can support + * a generic Object type in returnType arguement for XPath's evaluate instance * method. * - * Most of the implementation is exactly similar to what is already provided in + * Most of the implementation is exactly similar to what is already provided in * com.sun.org.apache.xpath.internal.jaxp.XPathImpl.java */ -public class JSTLXPathImpl implements javax.xml.xpath.XPath { +class JSTLXPathImpl implements javax.xml.xpath.XPath { + + private final XPathVariableResolver origVariableResolver; + private final XPathFunctionResolver origFunctionResolver; - // Private variables private XPathVariableResolver variableResolver; private XPathFunctionResolver functionResolver; - private XPathVariableResolver origVariableResolver; - private XPathFunctionResolver origFunctionResolver; - private NamespaceContext namespaceContext=null; - private org.apache.xpath.jaxp.JAXPPrefixResolver prefixResolver; - // By default Extension Functions are allowed in XPath Expressions. If + private NamespaceContext namespaceContext; + private JAXPPrefixResolver prefixResolver; + + // By default Extension Functions are allowed in XPath Expressions. If // Secure Processing Feature is set on XPathFactory then the invocation of // extensions function need to throw XPathFunctionException - private boolean featureSecureProcessing = false; + private boolean featureSecureProcessing; - JSTLXPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) { + JSTLXPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; } - JSTLXPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr, - boolean featureSecureProcessing ) { + + JSTLXPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; this.featureSecureProcessing = featureSecureProcessing; } - /** - *

Establishes a variable resolver.

- * - * @param resolver Variable Resolver - */ + + @Override + public void reset() { + this.variableResolver = this.origVariableResolver; + this.functionResolver = this.origFunctionResolver; + this.namespaceContext = null; + } + + + @Override public void setXPathVariableResolver(XPathVariableResolver resolver) { - if ( resolver == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPathVariableResolver"} ); - throw new NullPointerException( fmsg ); + if (resolver == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"XPathVariableResolver"}); + throw new NullPointerException(fmsg); } this.variableResolver = resolver; } - /** - *

Returns the current variable resolver.

- * - * @return Current variable resolver - */ + + @Override public XPathVariableResolver getXPathVariableResolver() { return variableResolver; } - /** - *

Establishes a function resolver.

- * - * @param resolver XPath function resolver - */ + + @Override public void setXPathFunctionResolver(XPathFunctionResolver resolver) { - if ( resolver == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPathFunctionResolver"} ); - throw new NullPointerException( fmsg ); + if (resolver == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"XPathFunctionResolver"}); + throw new NullPointerException(fmsg); } this.functionResolver = resolver; } - /** - *

Returns the current function resolver.

- * - * @return Current function resolver - */ + + @Override public XPathFunctionResolver getXPathFunctionResolver() { return functionResolver; } - /** - *

Establishes a namespace context.

- * - * @param nsContext Namespace context to use - */ + + @Override public void setNamespaceContext(NamespaceContext nsContext) { - if ( nsContext == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"NamespaceContext"} ); - throw new NullPointerException( fmsg ); + if (nsContext == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"NamespaceContext"}); + throw new NullPointerException(fmsg); } this.namespaceContext = nsContext; - this.prefixResolver = new org.apache.xpath.jaxp.JAXPPrefixResolver ( nsContext ); + this.prefixResolver = new JAXPPrefixResolver(nsContext); } - /** - *

Returns the current namespace context.

- * - * @return Current Namespace context - */ + + @Override public NamespaceContext getNamespaceContext() { return namespaceContext; } - private static Document d = null; - - private static DocumentBuilder getParser() { - try { - // we'd really like to cache those DocumentBuilders, but we can't because: - // 1. thread safety. parsers are not thread-safe, so at least - // we need one instance per a thread. - // 2. parsers are non-reentrant, so now we are looking at having a - // pool of parsers. - // 3. then the class loading issue. The look-up procedure of - // DocumentBuilderFactory.newInstance() depends on context class loader - // and system properties, which may change during the execution of JVM. - // - // so we really have to create a fresh DocumentBuilder every time we need one - // - KK - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware( true ); - dbf.setValidating( false ); - return dbf.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - // this should never happen with a well-behaving JAXP implementation. - throw new Error(e); - } - } - private static Document getDummyDocument( ) { - // we don't need synchronization here; even if two threads - // enter this code at the same time, we just waste a little time - if(d==null) { - DOMImplementation dim = getParser().getDOMImplementation(); - d = dim.createDocument("http://java.sun.com/jaxp/xpath", - "dummyroot", null); + @Override + public XPathExpression compile(String expression) + throws XPathExpressionException { + // This is never used in JSTL + if (expression == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"XPath expression"}); + throw new NullPointerException(fmsg); } - return d; + return null; } - - private XObject eval(String expression, Object contextItem) - throws javax.xml.transform.TransformerException { - org.apache.xpath.XPath xpath = new org.apache.xpath.XPath( expression, - null, prefixResolver, org.apache.xpath.XPath.SELECT ); - org.apache.xpath.XPathContext xpathSupport = null; - if ( functionResolver != null ) { - org.apache.xpath.jaxp.JAXPExtensionsProvider jep = - new org.apache.xpath.jaxp.JAXPExtensionsProvider( - functionResolver, featureSecureProcessing ); - xpathSupport = new org.apache.xpath.XPathContext( jep ); - } else { - xpathSupport = new org.apache.xpath.XPathContext(); - } - XObject xobj = null; - - xpathSupport.setVarStack(new org.apache.xpath.jaxp.JAXPVariableStack(variableResolver)); - - // If item is null, then we will create a a Dummy contextNode - if ( contextItem instanceof Node ) { - xobj = xpath.execute (xpathSupport, (Node)contextItem, - prefixResolver ); - } else { - xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver ); - } - - return xobj; - } - - /** - *

Evaluate an XPath expression in the specified context and return the result as the specified type.

- * - *

See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.

- * - *

If returnType is not one of the types defined in {@link XPathConstants} ( - * {@link XPathConstants#NUMBER NUMBER}, - * {@link XPathConstants#STRING STRING}, - * {@link XPathConstants#BOOLEAN BOOLEAN}, - * {@link XPathConstants#NODE NODE} or - * {@link XPathConstants#NODESET NODESET}) - * then an IllegalArgumentException is thrown.

- * - *

If a null value is provided for - * item, an empty document will be used for the - * context. - * If expression or returnType is null, then a - * NullPointerException is thrown.

- * - * @param expression The XPath expression. - * @param item The starting context (node or node list, for example). - * @param returnType The desired return type. - * - * @return Result of evaluating an XPath expression as an Object of returnType. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws IllegalArgumentException If returnType is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If expression or returnType is null. - */ - public Object evaluate(String expression, Object item, QName returnType) - throws XPathExpressionException { - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); + @Override + public Object evaluate(String expression, Object item, QName returnType) throws XPathExpressionException { + if (expression == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"XPath expression"}); + throw new NullPointerException(fmsg); } - if ( returnType == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"returnType"} ); - throw new NullPointerException ( fmsg ); + if (returnType == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"returnType"}); + throw new NullPointerException(fmsg); } // Checking if requested returnType is supported. returnType need to // be defined in XPathConstants or JSTLXPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); + if (!isSupported(returnType)) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] {returnType.toString()}); + throw new IllegalArgumentException(fmsg); } try { - - XObject resultObject = eval( expression, item ); - return getResultAsType( resultObject, returnType ); - } catch ( java.lang.NullPointerException npe ) { - // If VariableResolver returns null Or if we get + XObject resultObject = eval(expression, item); + return getResultAsType(resultObject, returnType); + } catch (NullPointerException npe) { + // If VariableResolver returns null Or if we get // NullPointerException at this stage for some other reason - // then we have to reurn XPathException - throw new XPathExpressionException ( npe ); - } catch ( javax.xml.transform.TransformerException te ) { + // then we have to reurn XPathException + throw new XPathExpressionException(npe); + } catch (TransformerException te) { Throwable nestedException = te.getException(); - if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { - throw (javax.xml.xpath.XPathFunctionException)nestedException; - } else { - // For any other exceptions we need to throw - // XPathExpressionException ( as per spec ) - throw new XPathExpressionException ( te ); + if (nestedException instanceof XPathFunctionException) { + throw (XPathFunctionException) nestedException; } - } - + // For any other exceptions we need to throw + // XPathExpressionException ( as per spec ) + throw new XPathExpressionException(te); + } } - private boolean isSupported( QName returnType ) { - if ( ( returnType.equals( XPathConstants.STRING ) ) || - ( returnType.equals( XPathConstants.NUMBER ) ) || - ( returnType.equals( XPathConstants.BOOLEAN ) ) || - ( returnType.equals( XPathConstants.NODE ) ) || - ( returnType.equals( XPathConstants.NODESET ) ) || - ( returnType.equals( JSTLXPathConstants.OBJECT ) ) ) { - - return true; - } - return false; - } - private Object getResultAsType( XObject resultObject, QName returnType ) - throws javax.xml.transform.TransformerException { - // XPathConstants.STRING - if ( returnType.equals( XPathConstants.STRING ) ) { - return resultObject.str(); - } - // XPathConstants.NUMBER - if ( returnType.equals( XPathConstants.NUMBER ) ) { - return new Double ( resultObject.num()); + @Override + public String evaluate(String expression, Object item) throws XPathExpressionException { + return (String) this.evaluate(expression, item, XPathConstants.STRING); + } + + + @Override + public Object evaluate(String expression, InputSource source, QName returnType) throws XPathExpressionException { + // Checking validity of different parameters + if (source == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"source"}); + throw new NullPointerException(fmsg); } - // XPathConstants.BOOLEAN - if ( returnType.equals( XPathConstants.BOOLEAN ) ) { - return Boolean.valueOf( resultObject.bool()); + if (expression == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"XPath expression"}); + throw new NullPointerException(fmsg); } - // XPathConstants.NODESET ---ORdered, UNOrdered??? - if ( returnType.equals( XPathConstants.NODESET ) ) { - return resultObject.nodelist(); + if (returnType == null) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {"returnType"}); + throw new NullPointerException(fmsg); } - // XPathConstants.NODE - if ( returnType.equals( XPathConstants.NODE ) ) { - NodeIterator ni = resultObject.nodeset(); - //Return the first node, or null - return ni.nextNode(); + + // Checking if requested returnType is supported. + // returnType need to be defined in XPathConstants + if (!isSupported(returnType)) { + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] {returnType.toString()}); + throw new IllegalArgumentException(fmsg); } - // JSTLXPathConstants.OBJECT - if ( returnType.equals( JSTLXPathConstants.OBJECT ) ) { - if (resultObject instanceof org.apache.xpath.objects.XNodeSet) - return resultObject.nodelist(); - else - return resultObject.object(); + + try { + Document document = DocumentBuilderProvider.createDocumentBuilder().parse(source); + XObject resultObject = eval(expression, document); + return getResultAsType(resultObject, returnType); + } catch (SAXException e) { + throw new XPathExpressionException(e); + } catch (IOException e) { + throw new XPathExpressionException(e); + } catch (TransformerException te) { + Throwable nestedException = te.getException(); + if (nestedException instanceof XPathFunctionException) { + throw (XPathFunctionException) nestedException; + } + throw new XPathExpressionException(te); } - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString()}); - throw new IllegalArgumentException( fmsg ); } - - - - /** - *

Evaluate an XPath expression in the specified context and return the result as a String.

- * - *

This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a returnType of - * {@link XPathConstants#STRING}.

- * - *

See "Evaluation of XPath Expressions" of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.

- * - *

If a null value is provided for - * item, an empty document will be used for the - * context. - * If expression is null, then a NullPointerException is thrown.

- * - * @param expression The XPath expression. - * @param item The starting context (node or node list, for example). - * - * @return The String that is the result of evaluating the expression and - * converting the result to a String. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws NullPointerException If expression is null. - */ - public String evaluate(String expression, Object item) - throws XPathExpressionException { - return (String)this.evaluate( expression, item, XPathConstants.STRING ); + + + @Override + public String evaluate(String expression, InputSource source) throws XPathExpressionException { + return (String) this.evaluate(expression, source, XPathConstants.STRING); } - /** - *

Compile an XPath expression for later evaluation.

- * - *

If expression contains any {@link javax.xml.xpath.XPathFunction}s, - * they must be available via the {@link XPathFunctionResolver}. - * An {@link XPathExpressionException} will be thrown if the XPathFunction - * cannot be resovled with the XPathFunctionResolver.

- * - *

If expression is null, a NullPointerException is thrown.

- * - * @param expression The XPath expression. - * - * @return Compiled XPath expression. - - * @throws XPathExpressionException If expression cannot be compiled. - * @throws NullPointerException If expression is null. - */ - public XPathExpression compile(String expression) - throws XPathExpressionException { - // This is never used in JSTL - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); + + private XObject eval(String expression, Object contextItem) throws TransformerException { + XPath xpath = new XPath(expression, null, prefixResolver, XPath.SELECT); + final XPathContext xpathSupport; + if (functionResolver != null) { + JAXPExtensionsProvider jep = new JAXPExtensionsProvider(functionResolver, featureSecureProcessing); + xpathSupport = new XPathContext(jep); + } else { + xpathSupport = new XPathContext(); } - return null; - /* - try { - com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null, - prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); - // Can have errorListener - com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl ximpl = - new com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl (xpath, - prefixResolver, functionResolver, variableResolver, - featureSecureProcessing ); - return ximpl; - } catch ( javax.xml.transform.TransformerException te ) { - throw new XPathExpressionException ( te ) ; + + xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); + + // If item is null, then we will create a a Dummy contextNode + if (contextItem instanceof Node) { + return xpath.execute(xpathSupport, (Node) contextItem, prefixResolver); } - **/ + return xpath.execute(xpathSupport, DTM.NULL, prefixResolver); } - /** - *

Evaluate an XPath expression in the context of the specified InputSource - * and return the result as the specified type.

- * - *

This method builds a data model for the {@link InputSource} and calls - * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.

- * - *

See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.

- * - *

If returnType is not one of the types defined in {@link XPathConstants}, - * then an IllegalArgumentException is thrown.

- * - *

If expression, source or returnType is null, - * then a NullPointerException is thrown.

- * - * @param expression The XPath expression. - * @param source The input source of the document to evaluate over. - * @param returnType The desired return type. - * - * @return The Object that encapsulates the result of evaluating the expression. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws IllegalArgumentException If returnType is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If expression, source or returnType - * is null. - */ - public Object evaluate(String expression, InputSource source, - QName returnType) throws XPathExpressionException { - // Checking validity of different parameters - if( source== null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"source"} ); - throw new NullPointerException ( fmsg ); + private boolean isSupported(QName returnType) { + return returnType.equals(XPathConstants.STRING) || returnType.equals(XPathConstants.NUMBER) + || returnType.equals(XPathConstants.BOOLEAN) || returnType.equals(XPathConstants.NODE) + || returnType.equals(XPathConstants.NODESET) || returnType.equals(JSTLXPathConstants.OBJECT); + } + + + private Object getResultAsType(XObject resultObject, QName returnType) throws TransformerException { + if (returnType.equals(XPathConstants.STRING)) { + return resultObject.str(); } - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); + if (returnType.equals(XPathConstants.NUMBER)) { + return Double.valueOf(resultObject.num()); } - if ( returnType == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"returnType"} ); - throw new NullPointerException ( fmsg ); + if (returnType.equals(XPathConstants.BOOLEAN)) { + return Boolean.valueOf(resultObject.bool()); } - - //Checking if requested returnType is supported. - //returnType need to be defined in XPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); + // XPathConstants.NODESET ---ORdered, UNOrdered??? + if (returnType.equals(XPathConstants.NODESET)) { + return resultObject.nodelist(); } - - try { - - Document document = getParser().parse( source ); - - XObject resultObject = eval( expression, document ); - return getResultAsType( resultObject, returnType ); - } catch ( SAXException e ) { - throw new XPathExpressionException ( e ); - } catch( IOException e ) { - throw new XPathExpressionException ( e ); - } catch ( javax.xml.transform.TransformerException te ) { - Throwable nestedException = te.getException(); - if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { - throw (javax.xml.xpath.XPathFunctionException)nestedException; - } else { - throw new XPathExpressionException ( te ); + if (returnType.equals(XPathConstants.NODE)) { + NodeIterator ni = resultObject.nodeset(); + // Return the first node, or null + return ni.nextNode(); + } + if (returnType.equals(JSTLXPathConstants.OBJECT)) { + if (resultObject instanceof XNodeSet) { + return resultObject.nodelist(); } + return resultObject.object(); } - - } - - - - - /** - *

Evaluate an XPath expression in the context of the specified InputSource - * and return the result as a String.

- * - *

This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a - * returnType of {@link XPathConstants#STRING}.

- * - *

See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.

- * - *

If expression or source is null, - * then a NullPointerException is thrown.

- * - * @param expression The XPath expression. - * @param source The InputSource of the document to evaluate over. - * - * @return The String that is the result of evaluating the expression and - * converting the result to a String. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws NullPointerException If expression or source is null. - */ - public String evaluate(String expression, InputSource source) - throws XPathExpressionException { - return (String)this.evaluate( expression, source, XPathConstants.STRING ); - } - - /** - *

Reset this XPath to its original configuration.

- * - *

XPath is reset to the same state as when it was created with - * {@link javax.xml.xpath.XPathFactory#newXPath()}. - * reset() is designed to allow the reuse of existing XPaths - * thus saving resources associated with the creation of new XPaths.

- * - *

The reset XPath is not guaranteed to have the same - * {@link XPathFunctionResolver}, {@link XPathVariableResolver} - * or {@link NamespaceContext} Objects, e.g. {@link Object#equals(Object obj)}. - * It is guaranteed to have a functionally equal XPathFunctionResolver, - * XPathVariableResolver - * and NamespaceContext.

- */ - public void reset() { - this.variableResolver = this.origVariableResolver; - this.functionResolver = this.origFunctionResolver; - this.namespaceContext = null; + String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] {returnType.toString()}); + throw new IllegalArgumentException(fmsg); } - } diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java index 025c505..ed1c15e 100644 --- a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997-2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,21 +18,20 @@ package org.apache.taglibs.standard.tag.common.xml; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.jsp.JspException; -import jakarta.servlet.jsp.JspTagException; -import jakarta.servlet.jsp.PageContext; -import jakarta.servlet.jsp.tagext.BodyTagSupport; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; @@ -72,7 +72,6 @@ public abstract class ParseSupport extends BodyTagSupport { private int scopeDom; // processed 'scopeDom' attr // state in support of XML parsing... - private DocumentBuilderFactory dbf; private DocumentBuilder db; private TransformerFactory tf; private TransformerHandler th; @@ -91,7 +90,6 @@ private void init() { xml = null; systemId = null; filter = null; - dbf = null; db = null; tf = null; th = null; @@ -107,18 +105,7 @@ private void init() { public int doEndTag() throws JspException { try { - // set up our DocumentBuilder - if (dbf == null) { - dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - try { - dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } catch (ParserConfigurationException e) { - throw new AssertionError("Parser does not support secure processing"); - } - } - db = dbf.newDocumentBuilder(); + db = DocumentBuilderProvider.createSecureDocumentBuilder(); // if we've gotten a filter, set up a transformer to support it if (filter != null) { @@ -167,8 +154,6 @@ else if (xmlText instanceof Reader) 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); } diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java index 7fb7c1e..aca5059 100644 --- a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997-2020 Oracle and/or its affiliates. All rights reserved. * Copyright 2004 The Apache Software Foundation * @@ -17,6 +18,12 @@ package org.apache.taglibs.standard.tag.common.xml; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + import java.io.IOException; import java.io.InputStream; import java.io.Reader; @@ -24,14 +31,8 @@ import java.io.Writer; import java.util.List; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.jsp.JspException; -import jakarta.servlet.jsp.JspTagException; -import jakarta.servlet.jsp.PageContext; -import jakarta.servlet.jsp.tagext.BodyTagSupport; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Source; @@ -81,7 +82,6 @@ public abstract class TransformSupport extends BodyTagSupport { private Transformer t; // actual Transformer private TransformerFactory tf; // reusable factory private DocumentBuilder db; // reusable factory - private DocumentBuilderFactory dbf; // reusable factory //********************************************************************* @@ -115,21 +115,9 @@ public int doStartTag() throws JspException { //************************************ // Initialize - - // set up our DocumentBuilderFactory if necessary - if (dbf == null) { - dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - dbf.setValidating(false); - try { - dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - } catch (ParserConfigurationException e) { - throw new AssertionError("Parser does not support secure processing"); - } - } - if (db == null) - db = dbf.newDocumentBuilder(); - + if (db == null) { + db = DocumentBuilderProvider.createSecureDocumentBuilder(); + } // set up the TransformerFactory if necessary if (tf == null) { tf = TransformerFactory.newInstance(); diff --git a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java index fbb2b9f..60d0238 100644 --- a/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java +++ b/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java @@ -1,7 +1,8 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997-2020 Oracle and/or its affiliates. All rights reserved. - * Copyright 2004 The Apache Software Foundation * Copyright (c) 2020 Payara Services Ltd. + * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,341 +20,155 @@ package org.apache.taglibs.standard.tag.common.xml; import java.util.List; -import java.util.Vector; -import java.security.AccessController; -import java.security.PrivilegedAction; import jakarta.servlet.jsp.JspTagException; import jakarta.servlet.jsp.PageContext; import jakarta.servlet.jsp.tagext.Tag; import jakarta.servlet.jsp.tagext.TagSupport; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathVariableResolver; -import javax.xml.xpath.XPathFactoryConfigurationException; - import org.apache.taglibs.standard.resources.Resources; import org.w3c.dom.Document; import org.w3c.dom.Node; -import org.w3c.dom.NodeList; /** - *

Support for tag handlers that evaluate XPath expressions.

+ * Support for tag handlers that evaluate XPath expressions. * * @author Shawn Bayern * @author Ramesh Mandava ( ramesh.mandava@sun.com ) * @author Pierre Delisle ( pierre.delisle@sun.com ) * @author Dongbin Nie + * @author David Matejcek */ -// would ideally be a base class, but some of our user handlers already -// have their own parents public class XPathUtil { - - //********************************************************************* - // Constructor - + + private static final String PAGE_NS_URL = "http://java.sun.com/jstl/xpath/page"; + private static final String REQUEST_NS_URL = "http://java.sun.com/jstl/xpath/request"; + private static final String SESSION_NS_URL = "http://java.sun.com/jstl/xpath/session"; + private static final String APP_NS_URL = "http://java.sun.com/jstl/xpath/app"; + private static final String PARAM_NS_URL = "http://java.sun.com/jstl/xpath/param"; + private static final String INITPARAM_NS_URL = "http://java.sun.com/jstl/xpath/initParam"; + private static final String COOKIE_NS_URL = "http://java.sun.com/jstl/xpath/cookie"; + private static final String HEADER_NS_URL = "http://java.sun.com/jstl/xpath/header"; + + private static final XPathFactory XPATH_FACTORY = new JSTLXPathFactory(); + private static final JSTLXPathNamespaceContext JSTL_XPATH_NS_CTX = initXPathNamespaceContext(); + + private final PageContext pageContext; + /** * Constructs a new XPathUtil object associated with the given * PageContext. */ public XPathUtil(PageContext pc) { pageContext = pc; - } - - //********************************************************************* - // Support for JSTL variable resolution - - // The URLs - private static final String PAGE_NS_URL - = "http://java.sun.com/jstl/xpath/page"; - private static final String REQUEST_NS_URL - = "http://java.sun.com/jstl/xpath/request"; - private static final String SESSION_NS_URL - = "http://java.sun.com/jstl/xpath/session"; - private static final String APP_NS_URL - = "http://java.sun.com/jstl/xpath/app"; - private static final String PARAM_NS_URL - = "http://java.sun.com/jstl/xpath/param"; - private static final String INITPARAM_NS_URL - = "http://java.sun.com/jstl/xpath/initParam"; - private static final String COOKIE_NS_URL - = "http://java.sun.com/jstl/xpath/cookie"; - private static final String HEADER_NS_URL - = "http://java.sun.com/jstl/xpath/header"; - - //********************************************************************* - // Support for XPath evaluation - - private PageContext pageContext; - - private static final String XPATH_FACTORY_CLASS_NAME = - "org.apache.taglibs.standard.tag.common.xml.JSTLXPathFactory"; - private static XPathFactory XPATH_FACTORY; - - private static JSTLXPathNamespaceContext jstlXPathNamespaceContext = null; - - private static DocumentBuilderFactory dbf = null; - - static { - initXPathFactory(); - initXPathNamespaceContext(); - initDocumentBuilderFactory(); } - private static void initXPathFactory() { - // If the system property DEFAULT_PROPERTY_NAME + ":uri" is present, - // where uri is the parameter to this method, then its value is read - // as a class name. The method will try to create a new instance of - // this class by using the class loader, and returns it if it is - // successfully created. - if (System.getSecurityManager() != null) { - AccessController.doPrivileged(new PrivilegedAction(){ - public Object run(){ - System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + - ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI, - XPATH_FACTORY_CLASS_NAME); - return null; - } - }); - } else { - System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + - ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI, - XPATH_FACTORY_CLASS_NAME); - } - try { - XPATH_FACTORY = XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI); - } catch (XPathFactoryConfigurationException xpce) { - xpce.printStackTrace(); - } - } - - /** Initialize globally useful data. */ - private static void initXPathNamespaceContext() { - // register supported namespaces - jstlXPathNamespaceContext = new JSTLXPathNamespaceContext(); - jstlXPathNamespaceContext.addNamespace("pageScope", PAGE_NS_URL); - jstlXPathNamespaceContext.addNamespace("requestScope", REQUEST_NS_URL); - jstlXPathNamespaceContext.addNamespace("sessionScope", SESSION_NS_URL); - jstlXPathNamespaceContext.addNamespace("applicationScope", APP_NS_URL); - jstlXPathNamespaceContext.addNamespace("param", PARAM_NS_URL); - jstlXPathNamespaceContext.addNamespace("initParam", INITPARAM_NS_URL); - jstlXPathNamespaceContext.addNamespace("header", HEADER_NS_URL); - jstlXPathNamespaceContext.addNamespace("cookie", COOKIE_NS_URL); - } - - private static void initDocumentBuilderFactory() { - dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware( true ); - dbf.setValidating( false ); - } - - /** - * Create a new empty document. - * - * This method always allocates a new document as its root node might be - * exposed to other tags and potentially be mutated. - * - * @return a new empty document - */ - private static Document newEmptyDocument() { - try { - DocumentBuilder db = dbf.newDocumentBuilder(); - return db.newDocument(); - } catch (ParserConfigurationException e) { - throw new AssertionError(); - } - } - + /** - * Evaluate an XPath expression to a String value. + * Evaluate an XPath expression to a String value. */ - public String valueOf(Node contextNode, String xpathString) - throws JspTagException { - // p("******** valueOf(" + n + ", " + xpathString + ")"); - XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext); - + public String valueOf(Node contextNode, String xpathString) throws JspTagException { XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setNamespaceContext(jstlXPathNamespaceContext); - xpath.setXPathVariableResolver(jxvr); + xpath.setNamespaceContext(JSTL_XPATH_NS_CTX); + xpath.setXPathVariableResolver(new JSTLXPathVariableResolver(pageContext)); try { return xpath.evaluate(xpathString, contextNode); } catch (XPathExpressionException ex) { throw new JspTagException(ex.toString(), ex); } } - - - /** - * Evaluate an XPath expression to a boolean value. + + + /** + * Evaluate an XPath expression to a boolean value. */ - public boolean booleanValueOf(Node contextNode, String xpathString) - throws JspTagException { - XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext); - + public boolean booleanValueOf(Node contextNode, String xpathString) throws JspTagException { XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setNamespaceContext(jstlXPathNamespaceContext); - xpath.setXPathVariableResolver(jxvr); + xpath.setNamespaceContext(JSTL_XPATH_NS_CTX); + xpath.setXPathVariableResolver(new JSTLXPathVariableResolver(pageContext)); try { - return ((Boolean) xpath.evaluate( - xpathString, contextNode, XPathConstants.BOOLEAN)).booleanValue(); + return ((Boolean) xpath.evaluate(xpathString, contextNode, XPathConstants.BOOLEAN)).booleanValue(); } catch (XPathExpressionException ex) { - throw new JspTagException( - Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex); + throw new JspTagException(Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex); } } - - /** - * Evaluate an XPath expression to a List of nodes. + + + /** + * Evaluate an XPath expression to a List of nodes. */ - public List selectNodes(Node contextNode, String xpathString) - throws JspTagException { - XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext); - + public List selectNodes(Node contextNode, String xpathString) throws JspTagException { try { XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setNamespaceContext(jstlXPathNamespaceContext); - xpath.setXPathVariableResolver(jxvr); - Object nl = xpath.evaluate( - xpathString, contextNode, JSTLXPathConstants.OBJECT); - return new JSTLNodeList( nl ); - } catch (XPathExpressionException ex ) { + xpath.setNamespaceContext(JSTL_XPATH_NS_CTX); + xpath.setXPathVariableResolver(new JSTLXPathVariableResolver(pageContext)); + Object nl = xpath.evaluate(xpathString, contextNode, JSTLXPathConstants.OBJECT); + return new JSTLNodeList(nl); + } catch (XPathExpressionException ex) { throw new JspTagException(ex.toString(), ex); } } - - /** - * Evaluate an XPath expression to a single node. + + + /** + * Evaluate an XPath expression to a single node. */ - public Node selectSingleNode(Node contextNode, String xpathString) - throws JspTagException { - //p("selectSingleNode of XPathUtil = passed node:" + - // "xpathString => " + n + " : " + xpathString ); + public Node selectSingleNode(Node contextNode, String xpathString) throws JspTagException { XPathVariableResolver jxvr = new JSTLXPathVariableResolver(pageContext); - try { XPath xpath = XPATH_FACTORY.newXPath(); - xpath.setNamespaceContext(jstlXPathNamespaceContext); + xpath.setNamespaceContext(JSTL_XPATH_NS_CTX); xpath.setXPathVariableResolver(jxvr); - return (Node) xpath.evaluate( - xpathString, contextNode, XPathConstants.NODE); + return (Node) xpath.evaluate(xpathString, contextNode, XPathConstants.NODE); } catch (XPathExpressionException ex) { - throw new JspTagException(ex.toString(), ex); - } - } - - //********************************************************************* - // Static support for context retrieval from parent tag - - public static Node getContext(Tag t) throws JspTagException { - ForEachTag xt = - (ForEachTag) TagSupport.findAncestorWithClass( - t, ForEachTag.class); - if (xt == null) - return newEmptyDocument(); - else - return (xt.getContext()); - } - - //********************************************************************* - // Utility methods - - private static void p(String s) { - System.out.println("[XPathUtil] " + s); - } - - public static void printDetails(Node n) { - p("\n\nDetails of Node = > " + n ) ; - p("Name:Type:Node Value = > " + n.getNodeName() + - ":" + n.getNodeType() + ":" + n.getNodeValue() ) ; - p("Namespace URI : Prefix : localName = > " + - n.getNamespaceURI() + ":" +n.getPrefix() + ":" + n.getLocalName()); - p("\n Node has children => " + n.hasChildNodes() ); - if ( n.hasChildNodes() ) { - NodeList nl = n.getChildNodes(); - p("Number of Children => " + nl.getLength() ); - for ( int i=0; i implements NodeList { - - Vector nodeVector; - - public JSTLNodeList ( Vector nodeVector ) { - this.nodeVector = nodeVector; - } - - public JSTLNodeList ( NodeList nl ) { - nodeVector = new Vector<>(); - //p("[JSTLNodeList] nodelist details"); - for ( int i=0; i(); - nodeVector.addElement( n ); - } - public JSTLNodeList (Object o) { - nodeVector = new Vector<>(); - - if (o instanceof NodeList) { - NodeList nl = (NodeList)o; - for ( int i=0; i " + nodeVector.size() ); - return nodeVector.size( ); + /** + * Create a new empty document. + * + * This method always allocates a new document as its root node might be + * exposed to other tags and potentially be mutated. + * + * @return a new empty document + */ + private static Document newEmptyDocument() { + return DocumentBuilderProvider.createDocumentBuilder().newDocument(); } - - // Can implement other Vector methods to redirect those methods to - // the vector in the variable param. As we are not using them as part - // of this implementation we are not doing that here. If this changes - // then we need to override those methods accordingly - } - +