ASF Bugzilla – Attachment 26445 Details for
Bug 27717
<x:forEach> very slow in JSTL 1.1
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch to use JAXP XPath support
taglibs-jaxp.patch (text/plain), 93.37 KB, created by
Jeremy Boynes
on 2010-12-23 15:11:18 UTC
(
hide
)
Description:
Patch to use JAXP XPath support
Filename:
MIME Type:
Creator:
Jeremy Boynes
Created:
2010-12-23 15:11:18 UTC
Size:
93.37 KB
patch
obsolete
>Index: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathExpression.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathExpression.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathExpression.java (revision 0) >@@ -0,0 +1,33 @@ >+/* >+ * 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.xpath; >+ >+import javax.servlet.jsp.JspTagException; >+import javax.servlet.jsp.PageContext; >+ >+/** >+ */ >+public interface JSTLXPathExpression { >+ >+ boolean evaluateBoolean(JSTLXPathContext context, PageContext pageContext) throws JspTagException; >+ >+ String evaluateString(JSTLXPathContext context, PageContext pageContext) throws JspTagException; >+ >+ Object evaluateObject(JSTLXPathContext context, PageContext pageContext) throws JspTagException; >+ >+ JSTLXPathContext iterate(JSTLXPathContext context, PageContext pageContext) throws JspTagException; >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathFactory.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathFactory.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathFactory.java (revision 0) >@@ -0,0 +1,42 @@ >+/* >+ * 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.xpath.jaxp; >+ >+import javax.xml.xpath.XPath; >+import javax.xml.xpath.XPathFactory; >+ >+import org.apache.taglibs.standard.xpath.JSTLVariableResolver; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; >+ >+/** >+ */ >+public class JAXPXPathFactory extends JSTLXPathFactory { >+ private static final XPathFactory xpf = XPathFactory.newInstance(); >+ >+ @Override >+ public JSTLXPathCompiler newCompiler() { >+ XPath xpath; >+ synchronized (xpf) { >+ xpath = xpf.newXPath(); >+ } >+ JSTLVariableResolver resolver = new JSTLVariableResolver(); >+ xpath.setXPathVariableResolver(resolver); >+ xpath.setNamespaceContext(resolver); >+ return new JAXPXPathCompiler(xpath); >+ } >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathCompiler.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathCompiler.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathCompiler.java (revision 0) >@@ -0,0 +1,44 @@ >+/* >+ * 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.xpath.jaxp; >+ >+import javax.xml.xpath.XPath; >+import javax.xml.xpath.XPathExpressionException; >+ >+import org.apache.taglibs.standard.xpath.InvalidXPathException; >+import org.apache.taglibs.standard.xpath.JSTLVariableResolver; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+ >+/** >+ */ >+public class JAXPXPathCompiler implements JSTLXPathCompiler { >+ private final XPath xpath; >+ >+ public JAXPXPathCompiler(XPath xpath) { >+ this.xpath = xpath; >+ } >+ >+ public JSTLXPathExpression compile(String select) { >+ try { >+ JSTLVariableResolver resolver = (JSTLVariableResolver) xpath.getXPathVariableResolver(); >+ return new JAXPXPathExpression(xpath.compile(select), resolver); >+ } catch (XPathExpressionException e) { >+ throw new InvalidXPathException(e); >+ } >+ } >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathExpression.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathExpression.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathExpression.java (revision 0) >@@ -0,0 +1,69 @@ >+/* >+ * 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.xpath.jaxp; >+ >+import javax.servlet.jsp.JspTagException; >+import javax.servlet.jsp.PageContext; >+import javax.xml.namespace.QName; >+import javax.xml.xpath.XPathConstants; >+import javax.xml.xpath.XPathExpression; >+import javax.xml.xpath.XPathExpressionException; >+ >+import org.apache.taglibs.standard.xpath.JSTLVariableResolver; >+import org.apache.taglibs.standard.xpath.JSTLXPathContext; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.w3c.dom.Node; >+import org.w3c.dom.NodeList; >+ >+/** >+ */ >+public class JAXPXPathExpression implements JSTLXPathExpression { >+ private final XPathExpression expr; >+ private final JSTLVariableResolver resolver; >+ >+ public JAXPXPathExpression(XPathExpression expr, JSTLVariableResolver resolver) { >+ this.expr = expr; >+ this.resolver = resolver; >+ } >+ >+ public boolean evaluateBoolean(JSTLXPathContext context, PageContext pageContext) throws JspTagException { >+ return (Boolean) evaluate(context, pageContext, XPathConstants.BOOLEAN); >+ } >+ >+ public String evaluateString(JSTLXPathContext context, PageContext pageContext) throws JspTagException { >+ return (String) evaluate(context, pageContext, XPathConstants.STRING); >+ } >+ >+ public Object evaluateObject(JSTLXPathContext context, PageContext pageContext) throws JspTagException { >+ return evaluate(context, pageContext, XPathConstants.NODE); >+ } >+ >+ public JSTLXPathContext iterate(JSTLXPathContext context, PageContext pageContext) throws JspTagException { >+ NodeList nodes = (NodeList) evaluate(context, pageContext, XPathConstants.NODESET); >+ return new JAXPXPathContext(nodes); >+ } >+ >+ private Object evaluate(JSTLXPathContext context, PageContext pageContext, QName resultType) throws JspTagException { >+ resolver.setPageContext(pageContext); >+ Node contextNode = (context == null) ? null : ((JAXPXPathContext) context).current(); >+ try { >+ return expr.evaluate(contextNode, resultType); >+ } catch (XPathExpressionException e) { >+ throw new JspTagException(e); >+ } >+ } >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathContext.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathContext.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathContext.java (revision 0) >@@ -0,0 +1,44 @@ >+/* >+ * 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.xpath.jaxp; >+ >+import org.apache.taglibs.standard.xpath.JSTLXPathContext; >+import org.w3c.dom.Node; >+import org.w3c.dom.NodeList; >+ >+/** >+ */ >+public class JAXPXPathContext implements JSTLXPathContext { >+ private final NodeList nodes; >+ private int index; >+ >+ public JAXPXPathContext(NodeList nodes) { >+ this.nodes = nodes; >+ } >+ >+ public boolean hasNext() { >+ return index < nodes.getLength(); >+ } >+ >+ public Object next() { >+ return nodes.item(index++); >+ } >+ >+ Node current() { >+ return nodes.item(index); >+ } >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java (revision 0) >@@ -0,0 +1,163 @@ >+/* >+ * 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.xpath; >+ >+import javax.servlet.http.Cookie; >+import javax.servlet.http.HttpServletRequest; >+import javax.servlet.jsp.PageContext; >+import javax.xml.XMLConstants; >+import javax.xml.namespace.NamespaceContext; >+import javax.xml.namespace.QName; >+import javax.xml.xpath.XPathVariableResolver; >+import java.util.HashMap; >+import java.util.Iterator; >+import java.util.Map; >+ >+/** >+ */ >+public class JSTLVariableResolver implements XPathVariableResolver, NamespaceContext { >+ >+ private static enum Scope { >+ JSP, >+ PARAM, >+ HEADER, >+ COOKIE, >+ INITPARAM, >+ PAGE, >+ REQUEST, >+ SESSION, >+ APPLICATION >+ } >+ >+ // Namespace URIs for JSTL implicit variables >+ private static final String PARAM_NS_URL = "http://java.sun.com/jstl/xpath/param"; >+ private static final String HEADER_NS_URL = "http://java.sun.com/jstl/xpath/header"; >+ private static final String COOKIE_NS_URL = "http://java.sun.com/jstl/xpath/cookie"; >+ private static final String INITPARAM_NS_URL = "http://java.sun.com/jstl/xpath/initParam"; >+ 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"; >+ >+ // Prefixes for JSTL implicit variables >+ private static final String PARAM_PREFIX = "param"; >+ private static final String HEADER_PREFIX = "header"; >+ private static final String COOKIE_PREFIX = "cookie"; >+ private static final String INITPARAM_PREFIX = "initParam"; >+ private static final String PAGE_PREFIX = "pageScope"; >+ private static final String REQUEST_PREFIX = "requestScope"; >+ private static final String SESSION_PREFIX = "sessionScope"; >+ private static final String APP_PREFIX = "applicationScope"; >+ >+ // map prefixes to namespaces >+ private static final Map<String, String> NAMESPACES; >+ >+ static { >+ NAMESPACES = new HashMap<String, String>(8); >+ NAMESPACES.put(XMLConstants.DEFAULT_NS_PREFIX, XMLConstants.NULL_NS_URI); >+ NAMESPACES.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI); >+ NAMESPACES.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI); >+ NAMESPACES.put(PARAM_PREFIX, PARAM_NS_URL); >+ NAMESPACES.put(HEADER_PREFIX, HEADER_NS_URL); >+ NAMESPACES.put(COOKIE_PREFIX, COOKIE_NS_URL); >+ NAMESPACES.put(INITPARAM_PREFIX, INITPARAM_NS_URL); >+ NAMESPACES.put(PAGE_PREFIX, PAGE_NS_URL); >+ NAMESPACES.put(REQUEST_PREFIX, REQUEST_NS_URL); >+ NAMESPACES.put(SESSION_PREFIX, SESSION_NS_URL); >+ NAMESPACES.put(APP_PREFIX, APP_NS_URL); >+ } >+ >+ // map namespaces to scopes >+ private static final Map<String, Scope> SCOPES; >+ >+ static { >+ SCOPES = new HashMap<String, Scope>(8); >+ SCOPES.put(XMLConstants.NULL_NS_URI, Scope.JSP); >+ SCOPES.put(PARAM_NS_URL, Scope.PARAM); >+ SCOPES.put(HEADER_NS_URL, Scope.HEADER); >+ SCOPES.put(COOKIE_NS_URL, Scope.COOKIE); >+ SCOPES.put(INITPARAM_NS_URL, Scope.INITPARAM); >+ SCOPES.put(PAGE_NS_URL, Scope.PAGE); >+ SCOPES.put(REQUEST_NS_URL, Scope.REQUEST); >+ SCOPES.put(SESSION_NS_URL, Scope.SESSION); >+ SCOPES.put(APP_NS_URL, Scope.APPLICATION); >+ } >+ >+ >+ private PageContext pageContext; >+ >+ public void setPageContext(PageContext pageContext) { >+ this.pageContext = pageContext; >+ } >+ >+ public Object resolveVariable(QName variableName) { >+ String name = variableName.getLocalPart(); >+ Scope scope = SCOPES.get(variableName.getNamespaceURI()); >+ if (scope == null) { >+ return null; >+ } >+ switch (scope) { >+ case JSP: >+ return pageContext.findAttribute(name); >+ case PARAM: >+ return pageContext.getRequest().getParameter(name); >+ case HEADER: >+ return ((HttpServletRequest) pageContext.getRequest()).getHeader(name); >+ case COOKIE: >+ Cookie[] cookies = ((HttpServletRequest) pageContext.getRequest()).getCookies(); >+ if (cookies != null) { >+ for (Cookie cookie : cookies) { >+ if (cookie.getName().equals(name)) { >+ return cookie.getValue(); >+ } >+ } >+ } >+ return null; >+ case INITPARAM: >+ return pageContext.getServletContext().getInitParameter(name); >+ case PAGE: >+ return pageContext.getAttribute(name, PageContext.PAGE_SCOPE); >+ case REQUEST: >+ return pageContext.getAttribute(name, PageContext.REQUEST_SCOPE); >+ case SESSION: >+ return pageContext.getAttribute(name, PageContext.SESSION_SCOPE); >+ case APPLICATION: >+ return pageContext.getAttribute(name, PageContext.APPLICATION_SCOPE); >+ default: >+ throw new AssertionError(); >+ } >+ } >+ >+ public String getNamespaceURI(String prefix) { >+ if (prefix == null) { >+ throw new IllegalArgumentException("prefix is null"); >+ } >+ String uri = NAMESPACES.get(prefix); >+ if (uri != null) { >+ return uri; >+ } >+ return XMLConstants.NULL_NS_URI; >+ } >+ >+ public String getPrefix(String namespaceURI) { >+ throw new UnsupportedOperationException(); >+ } >+ >+ public Iterator getPrefixes(String namespaceURI) { >+ throw new UnsupportedOperationException(); >+ } >+} > >Property changes on: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java >___________________________________________________________________ >Added: svn:eol-style > + native > >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathContext.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathContext.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathContext.java (revision 0) >@@ -0,0 +1,24 @@ >+/* >+ * 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.xpath; >+ >+/** >+ */ >+public interface JSTLXPathContext { >+ boolean hasNext(); >+ Object next(); >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java (revision 0) >@@ -0,0 +1,32 @@ >+/* >+ * 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.xpath; >+ >+import org.apache.taglibs.standard.xpath.jaxp.JAXPXPathFactory; >+ >+/** >+ */ >+public abstract class JSTLXPathFactory { >+ >+ private static final JAXPXPathFactory factory = new JAXPXPathFactory(); >+ >+ public static JSTLXPathFactory getFactory() { >+ return factory; >+ } >+ >+ public abstract JSTLXPathCompiler newCompiler(); >+} > >Property changes on: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java >___________________________________________________________________ >Added: svn:eol-style > + native > >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/InvalidXPathException.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/InvalidXPathException.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/InvalidXPathException.java (revision 0) >@@ -0,0 +1,36 @@ >+/* >+ * 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.xpath; >+ >+/** >+ */ >+public class InvalidXPathException extends RuntimeException { >+ public InvalidXPathException() { >+ } >+ >+ public InvalidXPathException(String s) { >+ super(s); >+ } >+ >+ public InvalidXPathException(String s, Throwable throwable) { >+ super(s, throwable); >+ } >+ >+ public InvalidXPathException(Throwable throwable) { >+ super(throwable); >+ } >+} >Index: impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathCompiler.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathCompiler.java (revision 0) >+++ impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathCompiler.java (revision 0) >@@ -0,0 +1,31 @@ >+/* >+ * 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.xpath; >+ >+/** >+ */ >+public interface JSTLXPathCompiler { >+ >+ /** >+ * Pre-compiles an XPath expression for future evaluation; >+ * >+ * @param xpath the xpath to compile >+ * @return an JSTLXPathExpression that can be used to evaluate the XPath >+ * @throws InvalidXPathException if the supplied XPath is not valid >+ */ >+ JSTLXPathExpression compile(String xpath) throws InvalidXPathException; >+} >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java (working copy) >@@ -1,896 +0,0 @@ >-/* >- * 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.Enumeration; >-import java.util.HashMap; >-import java.util.List; >-import java.util.Vector; >- >-import javax.servlet.http.Cookie; >-import javax.servlet.http.HttpServletRequest; >-import javax.servlet.jsp.JspTagException; >-import javax.servlet.jsp.PageContext; >-import javax.servlet.jsp.tagext.Tag; >-import javax.servlet.jsp.tagext.TagSupport; >-import javax.xml.parsers.DocumentBuilder; >-import javax.xml.parsers.DocumentBuilderFactory; >-import javax.xml.transform.TransformerException; >- >-import org.apache.taglibs.standard.resources.Resources; >-import org.apache.xml.utils.QName; >-import org.apache.xpath.VariableStack; >-import org.apache.xpath.XPathContext; >-import org.apache.xpath.objects.XBoolean; >-import org.apache.xpath.objects.XNodeSetForDOM; >-import org.apache.xpath.objects.XNumber; >-import org.apache.xpath.objects.XObject; >-import org.apache.xpath.objects.XString; >-import org.w3c.dom.DOMImplementation; >-import org.w3c.dom.Document; >-import org.w3c.dom.Element; >-import org.w3c.dom.Node; >-import org.w3c.dom.NodeList; >- >-/** >- * <p>Support for tag handlers that evaluate XPath expressions.</p> >- * >- * @author Shawn Bayern >- * @author Ramesh Mandava ( ramesh.mandava@sun.com ) >- * @author Pierre Delisle ( pierre.delisle@sun.com ) >- */ >-// would ideally be a base class, but some of our user handlers already >-// have their own parents >-public class XPathUtil { >- >- //********************************************************************* >- // Constructor >- >- /** >- * Constructs a new XPathUtil object associated with the given >- * PageContext. >- */ >- public XPathUtil(PageContext pc) { >- pageContext = pc; >- } >- >- int globalVarSize = 0; >- >- public Vector getVariableQNames() { >- >- globalVarSize = 0; >- Vector variableVector = new Vector(); >- // Now construct attributes in different scopes >- Enumeration enum_ = pageContext.getAttributeNamesInScope( >- PageContext.PAGE_SCOPE); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(PAGE_NS_URL, PAGE_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- >- variableVector.addElement(new QName(null, varName)); >- globalVarSize++; >- } >- enum_ = pageContext.getAttributeNamesInScope( >- PageContext.REQUEST_SCOPE); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(REQUEST_NS_URL, REQUEST_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- variableVector.addElement(new QName(null, varName)); >- globalVarSize++; >- } >- >- if (pageContext.getSession() != null) { >- // we may have a page directive preventing session creation/access >- // do not attempt to retrieve attribute names in session scope >- // @see [ http://issues.apache.org/bugzilla/show_bug.cgi?id=35216 ] >- enum_ = pageContext.getAttributeNamesInScope( >- PageContext.SESSION_SCOPE); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(SESSION_NS_URL, SESSION_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- variableVector.addElement(new QName(null, varName)); >- globalVarSize++; >- } >- } >- >- enum_ = pageContext.getAttributeNamesInScope( >- PageContext.APPLICATION_SCOPE); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(APP_NS_URL, APP_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- variableVector.addElement(new QName(null, varName)); >- globalVarSize++; >- } >- enum_ = pageContext.getRequest().getParameterNames(); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(PARAM_NS_URL, PARAM_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- } >- enum_ = pageContext.getServletContext().getInitParameterNames(); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(INITPARAM_NS_URL, INITPARAM_P, varName); >- //Adding both namespace qualified QName and just localName >- variableVector.addElement(varQName); >- globalVarSize++; >- } >- enum_ = ((HttpServletRequest) pageContext.getRequest()).getHeaderNames(); >- while (enum_.hasMoreElements()) { >- String varName = (String) enum_.nextElement(); >- QName varQName = new QName(HEADER_NS_URL, HEADER_P, varName); >- //Adding namespace qualified QName >- variableVector.addElement(varQName); >- globalVarSize++; >- } >- Cookie[] c = ((HttpServletRequest) pageContext.getRequest()).getCookies(); >- if (c != null) { >- for (int i = 0; i < c.length; i++) { >- String varName = c[i].getName(); >- QName varQName = new QName(COOKIE_NS_URL, COOKIE_P, varName); >- //Adding namespace qualified QName >- variableVector.addElement(varQName); >- globalVarSize++; >- } >- } >- >- return variableVector; >- >- } >- >- //********************************************************************* >- // 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"; >- >- // The prefixes >- private static final String PAGE_P = "pageScope"; >- private static final String REQUEST_P = "requestScope"; >- private static final String SESSION_P = "sessionScope"; >- private static final String APP_P = "applicationScope"; >- private static final String PARAM_P = "param"; >- private static final String INITPARAM_P = "initParam"; >- private static final String COOKIE_P = "cookie"; >- private static final String HEADER_P = "header"; >- >- /** >- * org.apache.xpath.VariableStack defines a class to keep track of a stack >- * for template arguments and variables. >- * JstlVariableContext customizes it so it handles JSTL custom >- * variable-mapping rules. >- */ >- protected class JstlVariableContext extends org.apache.xpath.VariableStack { >- >- public JstlVariableContext() { >- super(); >- } >- >- /** >- * Get a variable as an XPath object based on it's qualified name. >- * We override the base class method so JSTL's custom variable-mapping >- * rules can be applied. >- * >- * @param xctxt The XPath context. @@@ we don't use it... >- * (from xalan: which must be passed in order to lazy evaluate variables.) >- * @param qname The qualified name of the variable. >- */ >- @Override >- public XObject getVariableOrParam( >- XPathContext xctxt, >- org.apache.xml.utils.QName qname) >- throws javax.xml.transform.TransformerException, UnresolvableException { >- //p( "***********************************getVariableOrParam begin****"); >- String namespace = qname.getNamespaceURI(); >- String prefix = qname.getPrefix(); >- String localName = qname.getLocalName(); >- >- //p("namespace:prefix:localname=>"+ namespace >- // + ":" + prefix +":" + localName ); >- >- try { >- Object varObject = getVariableValue(namespace, prefix, localName); >- >- >- //XObject varObject = myvs.getVariableOrParam( xpathSupport, varQName); >- XObject newXObject = new XObject(varObject); >- >- if (Class.forName("org.w3c.dom.Document").isInstance(varObject)) { >- >- NodeList nl = ((Document) varObject).getChildNodes(); >- // To allow non-welformed document >- Vector nodeVector = new Vector(); >- for (int i = 0; i < nl.getLength(); i++) { >- Node currNode = nl.item(i); >- if (currNode.getNodeType() == Node.ELEMENT_NODE) { >- nodeVector.addElement(currNode); >- } >- } >- JSTLNodeList jstlNodeList = new JSTLNodeList(nodeVector); >- newXObject = new XNodeSetForDOM(jstlNodeList, xctxt); >- >- return newXObject; >- >- } >- if (Class.forName( >- "org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance( >- varObject)) { >- JSTLNodeList jstlNodeList = (JSTLNodeList) varObject; >- if ((jstlNodeList.getLength() == 1) && >- (!Class.forName("org.w3c.dom.Node").isInstance(jstlNodeList.elementAt(0)))) { >- varObject = jstlNodeList.elementAt(0); >- //Now we need to allow this primitive type to be coverted >- // to type which Xalan XPath understands >- } else { >- return new XNodeSetForDOM(jstlNodeList, xctxt); >- } >- } >- if (Class.forName("org.w3c.dom.Node").isInstance(varObject)) { >- newXObject = new XNodeSetForDOM(new JSTLNodeList((Node) varObject), xctxt); >- } else if (Class.forName("java.lang.String").isInstance(varObject)) { >- newXObject = new XString((String) varObject); >- } else if (Class.forName("java.lang.Boolean").isInstance(varObject)) { >- newXObject = new XBoolean((Boolean) varObject); >- } else if (Class.forName("java.lang.Number").isInstance(varObject)) { >- newXObject = new XNumber((Number) varObject); >- } >- >- return newXObject; >- // myvs.setGlobalVariable( i, newXObject ); >- } catch (ClassNotFoundException cnfe) { >- // This shouldn't happen (TODO: LOG) >- System.out.println("CLASS NOT FOUND EXCEPTION :" + cnfe); >- } >- //System.out.println("*****getVariableOrParam returning *null*" ); >- return null; >- } >- >- /** >- * Retrieve an XPath's variable value using JSTL's custom >- * variable-mapping rules >- */ >- public Object getVariableValue( >- String namespace, >- String prefix, >- String localName) >- throws UnresolvableException { >- // p("resolving: ns=" + namespace + " prefix=" + prefix + " localName=" + localName); >- // We can match on namespace with Xalan but leaving as is >- // [ I 'd prefer to match on namespace, but this doesn't appear >- // to work in Jaxen] >- if (prefix == null || prefix.equals("")) { >- return notNull( >- pageContext.findAttribute(localName), >- prefix, >- localName); >- } else if (prefix.equals(PAGE_P)) { >- return notNull( >- pageContext.getAttribute(localName, PageContext.PAGE_SCOPE), >- prefix, >- localName); >- } else if (prefix.equals(REQUEST_P)) { >- return notNull( >- pageContext.getAttribute(localName, >- PageContext.REQUEST_SCOPE), >- prefix, >- localName); >- } else if (prefix.equals(SESSION_P)) { >- return notNull( >- pageContext.getAttribute(localName, >- PageContext.SESSION_SCOPE), >- prefix, >- localName); >- } else if (prefix.equals(APP_P)) { >- return notNull( >- pageContext.getAttribute(localName, >- PageContext.APPLICATION_SCOPE), >- prefix, >- localName); >- } else if (prefix.equals(PARAM_P)) { >- return notNull( >- pageContext.getRequest().getParameter(localName), >- prefix, >- localName); >- } else if (prefix.equals(INITPARAM_P)) { >- return notNull( >- pageContext.getServletContext(). >- getInitParameter(localName), >- prefix, >- localName); >- } else if (prefix.equals(HEADER_P)) { >- HttpServletRequest hsr = >- (HttpServletRequest) pageContext.getRequest(); >- return notNull( >- hsr.getHeader(localName), >- prefix, >- localName); >- } else if (prefix.equals(COOKIE_P)) { >- HttpServletRequest hsr = >- (HttpServletRequest) pageContext.getRequest(); >- Cookie[] c = hsr.getCookies(); >- for (int i = 0; i < c.length; i++) { >- if (c[i].getName().equals(localName)) { >- return c[i].getValue(); >- } >- } >- throw new UnresolvableException("$" + prefix + ":" + localName); >- } else { >- throw new UnresolvableException("$" + prefix + ":" + localName); >- } >- } >- >- /** >- * Validate that the Object returned is not null. If it is >- * null, throw an exception. >- */ >- private Object notNull(Object o, String prefix, String localName) >- throws UnresolvableException { >- if (o == null) { >- throw new UnresolvableException("$" + (prefix == null ? "" : prefix + ":") + localName); >- } >- //p("resolved to: " + o); >- return o; >- } >- } >- >- //********************************************************************* >- // Support for XPath evaluation >- >- private PageContext pageContext; >- private static HashMap exprCache; >- private static JSTLPrefixResolver jstlPrefixResolver = null; >- >- /** >- * Initialize globally useful data. >- */ >- private synchronized static void staticInit() { >- if (jstlPrefixResolver == null) { >- // register supported namespaces >- jstlPrefixResolver = new JSTLPrefixResolver(); >- jstlPrefixResolver.addNamespace("pageScope", PAGE_NS_URL); >- jstlPrefixResolver.addNamespace("requestScope", REQUEST_NS_URL); >- jstlPrefixResolver.addNamespace("sessionScope", SESSION_NS_URL); >- jstlPrefixResolver.addNamespace("applicationScope", APP_NS_URL); >- jstlPrefixResolver.addNamespace("param", PARAM_NS_URL); >- jstlPrefixResolver.addNamespace("initParam", INITPARAM_NS_URL); >- jstlPrefixResolver.addNamespace("header", HEADER_NS_URL); >- jstlPrefixResolver.addNamespace("cookie", COOKIE_NS_URL); >- >- >- // create a HashMap to cache the expressions >- exprCache = new HashMap(); >- } >- } >- >- static DocumentBuilderFactory dbf = null; >- static DocumentBuilder db = null; >- static Document d = null; >- >- static Document getDummyDocument() { >- try { >- if (dbf == null) { >- dbf = DocumentBuilderFactory.newInstance(); >- dbf.setNamespaceAware(true); >- dbf.setValidating(false); >- } >- db = dbf.newDocumentBuilder(); >- >- DOMImplementation dim = db.getDOMImplementation(); >- d = dim.createDocument("http://java.sun.com/jstl", "dummyroot", null); >- //d = db.newDocument(); >- return d; >- } catch (Exception e) { >- e.printStackTrace(); >- } >- return null; >- } >- >- static Document getDummyDocumentWithoutRoot() { >- try { >- if (dbf == null) { >- dbf = DocumentBuilderFactory.newInstance(); >- dbf.setNamespaceAware(true); >- dbf.setValidating(false); >- } >- db = dbf.newDocumentBuilder(); >- >- d = db.newDocument(); >- return d; >- } catch (Exception e) { >- e.printStackTrace(); >- } >- return null; >- } >- >- private static Document getDocumentForNode(Node node) { >- Document doc = getDummyDocumentWithoutRoot(); >- Node importedNode = doc.importNode(node, true); >- doc.appendChild(importedNode); >- return doc; >- } >- >- // The following variable is used for holding the modified xpath string >- // when adapting parameter for Xalan XPath engine, where we need to have >- // a Non null context node. >- String modifiedXPath = null; >- >- >- /** >- * Evaluate an XPath expression to a String value. >- */ >- public String valueOf(Node n, String xpath) throws JspTagException { >- //p("******** valueOf(" + n + ", " + xpath + ")"); >- staticInit(); >- // @@@ but where do we set the Pag4eContext for the varaiblecontext? >- JstlVariableContext vs = new JstlVariableContext(); >- XPathContext xpathSupport = new XPathContext(); >- xpathSupport.setVarStack(vs); >- >- Vector varVector = fillVarStack(vs, xpathSupport); >- >- Node contextNode = adaptParamsForXalan(vs, n, xpath.trim()); >- >- xpath = modifiedXPath; >- >- //p("******** valueOf: modified xpath: " + xpath); >- >- XObject result = JSTLXPathAPI.eval(contextNode, xpath, >- jstlPrefixResolver, xpathSupport, varVector); >- >- >- //p("******Result TYPE => " + result.getTypeString() ); >- >- String resultString = result.str(); >- //p("******** valueOf: after eval: " + resultString); >- >- return resultString; >- >- } >- >- /** >- * Evaluate an XPath expression to a boolean value. >- */ >- public boolean booleanValueOf(Node n, String xpath) >- throws JspTagException { >- >- staticInit(); >- JstlVariableContext vs = new JstlVariableContext(); >- XPathContext xpathSupport = new XPathContext(); >- xpathSupport.setVarStack(vs); >- >- Vector varVector = fillVarStack(vs, xpathSupport); >- >- Node contextNode = adaptParamsForXalan(vs, n, xpath.trim()); >- xpath = modifiedXPath; >- >- XObject result = JSTLXPathAPI.eval(contextNode, xpath, >- jstlPrefixResolver, xpathSupport, varVector); >- >- try { >- return result.bool(); >- } catch (TransformerException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex); >- } >- } >- >- /** >- * Evaluate an XPath expression to a List of nodes. >- */ >- public List selectNodes(Node n, String xpath) throws JspTagException { >- >- staticInit(); >- JstlVariableContext vs = new JstlVariableContext(); >- XPathContext xpathSupport = new XPathContext(); >- xpathSupport.setVarStack(vs); >- >- Vector varVector = fillVarStack(vs, xpathSupport); >- >- Node contextNode = adaptParamsForXalan(vs, n, xpath.trim()); >- xpath = modifiedXPath; >- >- XObject result = JSTLXPathAPI.eval(contextNode, xpath, >- jstlPrefixResolver, xpathSupport, varVector); >- try { >- NodeList nl = JSTLXPathAPI.getNodeList(result); >- return new JSTLNodeList(nl); >- } catch (JspTagException e) { >- try { >- //If result can't be converted to NodeList we receive exception >- // In this case we may have single primitive value as the result >- // Populating List with this value ( String, Boolean or Number ) >- >- //System.out.println("JSTLXPathAPI.getNodeList thrown exception:"+ e); >- Vector vector = new Vector(); >- Object resultObject = null; >- if (result.getType() == XObject.CLASS_BOOLEAN) { >- resultObject = result.bool(); >- } else if (result.getType() == XObject.CLASS_NUMBER) { >- resultObject = result.num(); >- } else if (result.getType() == XObject.CLASS_STRING) { >- resultObject = result.str(); >- } >- >- vector.add(resultObject); >- return new JSTLNodeList(vector); >- } catch (TransformerException te) { >- throw new JspTagException(te.toString(), te); >- } >- } >- >- >- } >- >- /** >- * Evaluate an XPath expression to a single node. >- */ >- public Node selectSingleNode(Node n, String xpath) >- throws JspTagException { >- //p("selectSingleNode of XPathUtil = passed node:" + >- // "xpath => " + n + " : " + xpath ); >- >- staticInit(); >- JstlVariableContext vs = new JstlVariableContext(); >- XPathContext xpathSupport = new XPathContext(); >- xpathSupport.setVarStack(vs); >- >- Vector varVector = fillVarStack(vs, xpathSupport); >- >- Node contextNode = adaptParamsForXalan(vs, n, xpath.trim()); >- xpath = modifiedXPath; >- >- return (Node) JSTLXPathAPI.selectSingleNode(contextNode, xpath, >- jstlPrefixResolver, xpathSupport); >- } >- >- /** >- * Returns a locally appropriate context given a node. >- */ >- private VariableStack getLocalContext() { >- // set up instance-specific contexts >- VariableStack vc = new JstlVariableContext(); >- return vc; >- } >- >- //********************************************************************* >- // Adapt XPath expression for integration with Xalan >- >- /** >- * To evaluate an XPath expression using Xalan, we need >- * to create an XPath object, which wraps an expression object and provides >- * general services for execution of that expression. >- * <p>An XPath object can be instantiated with the following information: >- * - XPath expression to evaluate >- * - SourceLocator >- * (reports where an error occurred in the XML source or >- * transformation instructions) >- * - PrefixResolver >- * (resolve prefixes to namespace URIs) >- * - type >- * (one of SELECT or MATCH) >- * - ErrorListener >- * (customized error handling) >- * <p>Execution of the XPath expression represented by an XPath object >- * is done via method execute which takes the following parameters: >- * - XPathContext >- * The execution context >- * - Node contextNode >- * The node that "." expresses >- * - PrefixResolver namespaceContext >- * The context in which namespaces in the XPath are supposed to be >- * expanded. >- * <p>Given all of this, if no context node is set for the evaluation >- * of the XPath expression, one must be set so Xalan >- * can successfully evaluate a JSTL XPath expression. >- * (it will not work if the context node is given as a varialbe >- * at the beginning of the expression) >- * >- * @@@ Provide more details... >- */ >- protected Node adaptParamsForXalan(JstlVariableContext jvc, Node n, >- String xpath) { >- Node boundDocument = null; >- >- modifiedXPath = xpath; >- String origXPath = xpath; >- boolean whetherOrigXPath = true; >- >- // If contextNode is not null then just pass the values to Xalan XPath >- // unless this is an expression that starts off with an xml document >- if (n != null && !xpath.startsWith("$")) { >- return n; >- } >- >- if (xpath.startsWith("$")) { >- // JSTL uses $scopePrefix:varLocalName/xpath expression >- >- String varQName = xpath.substring(xpath.indexOf("$") + 1); >- if (varQName.indexOf("/") > 0) { >- varQName = varQName.substring(0, varQName.indexOf("/")); >- } >- String varPrefix = null; >- String varLocalName = varQName; >- if (varQName.indexOf(":") >= 0) { >- varPrefix = varQName.substring(0, varQName.indexOf(":")); >- varLocalName = varQName.substring(varQName.indexOf(":") + 1); >- } >- >- if (xpath.indexOf("/") > 0) { >- xpath = xpath.substring(xpath.indexOf("/")); >- } else { >- xpath = "/*"; >- whetherOrigXPath = false; >- } >- >- >- try { >- Object varObject = jvc.getVariableValue(null, varPrefix, >- varLocalName); >- //System.out.println( "varObject => : its Class " +varObject + >- // ":" + varObject.getClass() ); >- >- if (Class.forName("org.w3c.dom.Document").isInstance( >- varObject)) { >- //boundDocument = ((Document)varObject).getDocumentElement(); >- boundDocument = ((Document) varObject); >- } else { >- >- //System.out.println("Creating a Dummy document to pass " + >- // " onto as context node " ); >- >- if (Class.forName("org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance(varObject)) { >- Document newDocument = getDummyDocument(); >- >- JSTLNodeList jstlNodeList = (JSTLNodeList) varObject; >- if (jstlNodeList.getLength() == 1) { >- if (Class.forName("org.w3c.dom.Node").isInstance( >- jstlNodeList.elementAt(0))) { >- Node node = (Node) jstlNodeList.elementAt(0); >- boundDocument = getDocumentForNode(node); >- if (whetherOrigXPath) { >- xpath = "/*" + xpath; >- } >- >- } else { >- >- //Nodelist with primitive type >- Object myObject = jstlNodeList.elementAt(0); >- >- //p("Single Element of primitive type"); >- //p("Type => " + myObject.getClass()); >- >- xpath = myObject.toString(); >- >- //p("String value ( xpathwould be this) => " + xpath); >- boundDocument = newDocument; >- } >- >- } else { >- >- Element dummyroot = newDocument.getDocumentElement(); >- for (int i = 0; i < jstlNodeList.getLength(); i++) { >- Node currNode = (Node) jstlNodeList.item(i); >- >- Node importedNode = newDocument.importNode( >- currNode, true); >- >- //printDetails ( newDocument); >- >- dummyroot.appendChild(importedNode); >- >- //p( "Details of the document After importing"); >- //printDetails ( newDocument); >- } >- boundDocument = newDocument; >- // printDetails ( boundDocument ); >- //Verify :As we are adding Document element we need >- // to change the xpath expression.Hopefully this >- // won't change the result >- >- xpath = "/*" + xpath; >- } >- } else if (Class.forName("org.w3c.dom.Node").isInstance( >- varObject)) { >- boundDocument = getDocumentForNode((Node) varObject); >- if (whetherOrigXPath) { >- xpath = "/*" + xpath; >- } >- } else { >- boundDocument = getDummyDocument(); >- xpath = origXPath; >- } >- >- >- } >- } catch (UnresolvableException ue) { >- // TODO: LOG >- System.out.println("Variable Unresolvable :" + ue.getMessage()); >- ue.printStackTrace(); >- } catch (ClassNotFoundException cnf) { >- // Will never happen >- } >- } else { >- //System.out.println("Not encountered $ Creating a Dummydocument 2 "+ >- // "pass onto as context node " ); >- boundDocument = getDummyDocument(); >- } >- >- modifiedXPath = xpath; >- //System.out.println("Modified XPath::boundDocument =>" + modifiedXPath + >- // "::" + boundDocument ); >- >- return boundDocument; >- } >- >- >- //********************************************************************* >- // >- >- /** >- * * @@@ why do we have to pass varVector in the varStack first, and then >- * to XPath object? >- */ >- private Vector fillVarStack(JstlVariableContext vs, XPathContext xpathSupport) >- throws JspTagException { >- org.apache.xpath.VariableStack myvs = xpathSupport.getVarStack(); >- Vector varVector = getVariableQNames(); >- for (int i = 0; i < varVector.size(); i++) { >- >- QName varQName = (QName) varVector.elementAt(i); >- >- try { >- XObject variableValue = vs.getVariableOrParam(xpathSupport, varQName); >- //p("&&&&Variable set to => " + variableValue.toString() ); >- //p("&&&&Variable type => " + variableValue.getTypeString() ); >- myvs.setGlobalVariable(i, variableValue); >- >- } catch (TransformerException te) { >- throw new JspTagException(te.toString(), te); >- } >- >- } >- return varVector; >- } >- >- >- //********************************************************************* >- // Static support for context retrieval from parent <forEach> tag >- >- public static Node getContext(Tag t) throws JspTagException { >- ForEachTag xt = >- (ForEachTag) TagSupport.findAncestorWithClass( >- t, ForEachTag.class); >- if (xt == null) { >- return null; >- } else { >- return (xt.getContext()); >- } >- } >- >- //********************************************************************* >- // Utility methods >- >- private static void p(String s) { >- System.out.println("[XPathUtil] " + s); >- } >- >- public static void printDetails(Node n) { >- System.out.println("\n\nDetails of Node = > " + n); >- System.out.println("Name:Type:Node Value = > " + n.getNodeName() + >- ":" + n.getNodeType() + ":" + n.getNodeValue()); >- System.out.println("Namespace URI : Prefix : localName = > " + >- n.getNamespaceURI() + ":" + n.getPrefix() + ":" + n.getLocalName()); >- System.out.println("\n Node has children => " + n.hasChildNodes()); >- if (n.hasChildNodes()) { >- NodeList nl = n.getChildNodes(); >- System.out.println("Number of Children => " + nl.getLength()); >- for (int i = 0; i < nl.getLength(); i++) { >- Node childNode = nl.item(i); >- printDetails(childNode); >- } >- } >- } >-} >- >-class JSTLNodeList extends Vector implements NodeList { >- >- Vector nodeVector; >- >- public JSTLNodeList(Vector nodeVector) { >- this.nodeVector = nodeVector; >- } >- >- public JSTLNodeList(NodeList nl) { >- nodeVector = new Vector(); >- //System.out.println("[JSTLNodeList] nodelist details"); >- for (int i = 0; i < nl.getLength(); i++) { >- Node currNode = nl.item(i); >- //XPathUtil.printDetails ( currNode ); >- nodeVector.add(i, nl.item(i)); >- } >- } >- >- public JSTLNodeList(Node n) { >- nodeVector = new Vector(); >- nodeVector.addElement(n); >- } >- >- >- 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); >- } >- >- public int getLength() { >- return nodeVector.size(); >- } >- >- @Override >- public int size() { >- //System.out.println("JSTL node list size => " + nodeVector.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 >- >-} >- >- >- >- >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (working copy) >@@ -17,12 +17,15 @@ > > package org.apache.taglibs.standard.tag.common.xml; > >-import java.util.List; >- > import javax.servlet.jsp.JspTagException; > import javax.servlet.jsp.jstl.core.LoopTagSupport; >+import javax.servlet.jsp.tagext.Tag; >+import javax.servlet.jsp.tagext.TagSupport; > >-import org.apache.taglibs.standard.resources.Resources; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathContext; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; > > /** > * <p>Support for the XML library's <forEach> tag.</p> >@@ -32,60 +35,44 @@ > */ > public class ForEachTag extends LoopTagSupport { > >- //********************************************************************* >- // Private state >+ private JSTLXPathCompiler compiler; >+ private JSTLXPathExpression select; >+ private JSTLXPathContext context; > >- private String select; // tag attribute >- private List nodes; // XPath result >- private int nodesIndex; // current index >- private org.w3c.dom.Node current; // current node >+ public ForEachTag() { >+ JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); >+ compiler = xpf.newCompiler(); >+ } > >- //********************************************************************* >- // Iteration control methods >+ @Override >+ public void release() { >+ super.release(); >+ compiler = null; >+ select = null; >+ context = null; >+ } > >- // (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 = select.iterate(getContext(this), pageContext); > } > > @Override > protected boolean hasNext() throws JspTagException { >- return (nodesIndex < nodes.size()); >+ return context.hasNext(); > } > > @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; >+ return context.next(); > } > > > //********************************************************************* >- // Tag logic and lifecycle management >- >- // Releases any resources we may have (or inherit) >- >- @Override >- public void release() { >- init(); >- super.release(); >- } >- >- >- //********************************************************************* > // Attribute accessors > > public void setSelect(String select) { >- this.select = select; >+ this.select = compiler.compile(select); > } > > public void setBegin(int begin) throws JspTagException { >@@ -111,20 +98,13 @@ > > /* Retrieves the current context. */ > >- public org.w3c.dom.Node getContext() throws JspTagException { >- // expose the current node as the context >- return current; >+ public static JSTLXPathContext getContext(Tag child) { >+ ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class); >+ if (forEachTag == null) { >+ return null; >+ } else { >+ return forEachTag.context; >+ } > } >- >- >- //********************************************************************* >- // Private utility methods >- >- private void init() { >- select = null; >- nodes = null; >- nodesIndex = 0; >- current = null; >- } > } > >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (working copy) >@@ -17,13 +17,14 @@ > > package org.apache.taglibs.standard.tag.common.xml; > >-import java.util.List; >- > import javax.servlet.jsp.JspException; > import javax.servlet.jsp.PageContext; > import javax.servlet.jsp.tagext.TagSupport; > > import org.apache.taglibs.standard.tag.common.core.Util; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; > > /** > * <p>Tag handler for <set> in JSTL's XML library.</p> >@@ -32,13 +33,11 @@ > */ > public class SetTag extends TagSupport { > >- //********************************************************************* >- // Internal state >+ private JSTLXPathCompiler compiler; >+ private JSTLXPathExpression 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 > >@@ -48,19 +47,18 @@ > * superclass constructor. > */ > public SetTag() { >- super(); >- init(); >+ JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); >+ compiler = xpf.newCompiler(); > } > >- // resets local state >- >- private void init() { >- var = null; >+ @Override >+ public void release() { >+ super.release(); >+ compiler = null; > select = null; >- scope = PageContext.PAGE_SCOPE; >+ var = null; > } > >- > //********************************************************************* > // Tag logic > >@@ -68,40 +66,16 @@ > > @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; >- } >- } >- >- // expose the final result >- pageContext.setAttribute(var, ret, scope); >+ Object result = select.evaluateObject(ForEachTag.getContext(this), pageContext); >+ pageContext.setAttribute(var, result, scope); > return SKIP_BODY; > } > >- // Releases any resources we may have (or inherit) >- >- @Override >- public void release() { >- super.release(); >- init(); >- } >- >- > //********************************************************************* > // Attribute accessors > > public void setSelect(String select) { >- this.select = select; >+ this.select = compiler.compile(select); > } > > public void setVar(String var) { >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (working copy) >@@ -20,6 +20,10 @@ > import javax.servlet.jsp.JspTagException; > import javax.servlet.jsp.jstl.core.ConditionalTagSupport; > >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; >+ > /** > * <p>Tag handler for <if> in JSTL's XML library.</p> > * >@@ -28,55 +32,27 @@ > > public class IfTag extends ConditionalTagSupport { > >- //********************************************************************* >- // Constructor and lifecycle management >+ private JSTLXPathCompiler compiler; >+ private JSTLXPathExpression select; > >- // initialize inherited and local state >- > public IfTag() { >- super(); >- init(); >+ JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); >+ compiler = xpf.newCompiler(); > } > >- // Releases any resources we may have (or inherit) >- > @Override > public void release() { > super.release(); >- init(); >+ compiler = null; >+ select = null; > } > >- >- //********************************************************************* >- // Supplied conditional logic >- > @Override > protected boolean condition() throws JspTagException { >- XPathUtil xu = new XPathUtil(pageContext); >- return (xu.booleanValueOf(XPathUtil.getContext(this), select)); >+ return select.evaluateBoolean(ForEachTag.getContext(this), pageContext); > } > >- >- //********************************************************************* >- // Private state >- >- private String select; // the value of the 'test' attribute >- >- >- //********************************************************************* >- // Attribute accessors >- > public void setSelect(String select) { >- this.select = select; >+ this.select = compiler.compile(select); > } >- >- >- //********************************************************************* >- // Private utility methods >- >- // resets internal state >- >- private void init() { >- select = null; >- } > } >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (working copy) >@@ -5,9 +5,9 @@ > * 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. >@@ -22,52 +22,42 @@ > import javax.servlet.jsp.tagext.TagSupport; > > import org.apache.taglibs.standard.util.EscapeXML; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; > > /** >- * <p>Tag handler for <out> in JSTL's XML library.</p> >- * <p>TODO: should we rename this to OutSupport to match the tag name? >+ * 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 JSTLXPathCompiler compiler; >+ private JSTLXPathExpression 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(); >+ JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); >+ compiler = xpf.newCompiler(); > } > >- // resets local state >- >- private void init() { >+ @Override >+ public void release() { >+ super.release(); >+ compiler = null; > 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); >+ String result = select.evaluateString(ForEachTag.getContext(this), pageContext); > EscapeXML.emit(result, escapeXml, pageContext.getOut()); > return SKIP_BODY; > } catch (java.io.IOException ex) { >@@ -75,19 +65,7 @@ > } > } > >- // Releases any resources we may have (or inherit) >- >- @Override >- public void release() { >- super.release(); >- init(); >- } >- >- >- //********************************************************************* >- // Attribute accessors >- > public void setSelect(String select) { >- this.select = select; >+ this.select = compiler.compile(select); > } > } >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.java (working copy) >@@ -1,296 +0,0 @@ >-/* >- * 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.Vector; >- >-import javax.servlet.jsp.JspTagException; >-import javax.xml.transform.TransformerException; >- >-import org.apache.taglibs.standard.resources.Resources; >-import org.apache.xml.utils.PrefixResolver; >-import org.apache.xpath.XPath; >-import org.apache.xpath.XPathAPI; >-import org.apache.xpath.XPathContext; >-import org.apache.xpath.objects.XObject; >-import org.w3c.dom.Node; >-import org.w3c.dom.NodeList; >-import org.w3c.dom.traversal.NodeIterator; >- >-/** >- * The methods in this class are convenience methods into the >- * low-level XPath API. >- * These functions tend to be a little slow, since a number of objects must be >- * created for each evaluation. A faster way is to precompile the >- * XPaths using the low-level API, and then just use the XPaths >- * over and over. >- * <p>NOTE: In particular, each call to this method will create a new >- * XPathContext, a new DTMManager... and thus a new DTM. That's very >- * safe, since it guarantees that you're always processing against a >- * fully up-to-date view of your document. But it's also portentially >- * very expensive, since you're rebuilding the DTM every time. You should >- * consider using an instance of CachedXPathAPI rather than these static >- * methods. >- * >- * @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a> >- */ >-public class JSTLXPathAPI extends XPathAPI { >- /** >- * Use an XPath string to select a single node. >- * XPath namespace prefixes are resolved using the prefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return The first node found that matches the XPath, or null. >- * @throws JspTagException >- */ >- public static Node selectSingleNode( >- Node contextNode, String str, PrefixResolver prefixResolver) >- throws JspTagException { >- >- // Have the XObject return its result as a NodeSetDTM. >- NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver); >- >- // Return the first node, or null >- return nl.nextNode(); >- } >- >- /** >- * Use an XPath string to select a single node. >- * XPath namespace prefixes are resolved using the prefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return The first node found that matches the XPath, or null. >- * @throws JspTagException >- */ >- public static Node selectSingleNode( >- Node contextNode, String str, PrefixResolver prefixResolver, >- XPathContext xpathSupport) throws JspTagException { >- >- // Have the XObject return its result as a NodeSetDTM. >- NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver, xpathSupport); >- >- // Return the first node, or null >- return nl.nextNode(); >- } >- >- /** >- * Use an XPath string to select a nodelist. >- * XPath namespace prefixes are resolved using PrefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return A NodeIterator, should never be null. >- * @throws JspTagException >- */ >- public static NodeIterator selectNodeIterator( >- Node contextNode, String str, PrefixResolver prefixResolver) >- throws JspTagException { >- >- // Execute the XPath, and have it return the result >- XObject list = eval(contextNode, str, prefixResolver, null); >- >- // Have the XObject return its result as a NodeSetDTM. >- return getNodeIterator(list); >- } >- >- /** >- * Use an XPath string to select a nodelist. >- * XPath namespace prefixes are resolved using PrefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return A NodeIterator, should never be null. >- * @throws JspTagException >- */ >- public static NodeIterator selectNodeIterator( >- Node contextNode, String str, PrefixResolver prefixResolver, >- XPathContext xpathSupport) throws JspTagException { >- >- // Execute the XPath, and have it return the result >- XObject list = eval(contextNode, str, prefixResolver, xpathSupport); >- >- // Have the XObject return its result as a NodeSetDTM. >- return getNodeIterator(list); >- } >- >- /** >- * Use an XPath string to select a nodelist. >- * XPath namespace prefixes are resolved using the prefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return A NodeIterator, should never be null. >- * @throws JspTagException >- */ >- private static NodeList selectNodeList( >- Node contextNode, String str, PrefixResolver prefixResolver) >- throws JspTagException { >- // Execute the XPath, and have it return the result >- XObject list = eval(contextNode, str, prefixResolver, null); >- >- // Return a NodeList. >- return getNodeList(list); >- } >- >- /** >- * Use an XPath string to select a nodelist. >- * XPath namespace prefixes are resolved using the prefixResolver. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces. >- * @return A NodeIterator, should never be null. >- * @throws JspTagException >- */ >- public static NodeList selectNodeList( >- Node contextNode, String str, PrefixResolver prefixResolver, >- XPathContext xpathSupport) >- throws JspTagException { >- // Execute the XPath, and have it return the result >- XObject list = eval(contextNode, str, prefixResolver, xpathSupport); >- >- // Return a NodeList. >- return getNodeList(list); >- } >- >- /** >- * Returns a NodeIterator from an XObject. >- * >- * @param list The XObject from which a NodeIterator is returned. >- * @return A NodeIterator, should never be null. >- * @throws JspTagException >- */ >- private static NodeIterator getNodeIterator(XObject list) >- throws JspTagException { >- try { >- return list.nodeset(); >- } catch (TransformerException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex); >- } >- } >- >- /** >- * Returns a NodeList from an XObject. >- * >- * @param list The XObject from which a NodeList is returned. >- * @return A NodeList, should never be null. >- * @throws JspTagException >- */ >- static NodeList getNodeList(XObject list) >- throws JspTagException { >- try { >- return list.nodelist(); >- } catch (TransformerException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex); >- } >- } >- >- /** >- * Evaluate XPath string to an XObject. >- * XPath namespace prefixes are resolved from the namespaceNode. >- * The implementation of this is a little slow, since it creates >- * a number of objects each time it is called. This could be optimized >- * to keep the same objects around, but then thread-safety issues would arise. >- * >- * @param contextNode The node to start searching from. >- * @param str A valid XPath string. >- * @param xpathSupport The node from which prefixes in the XPath will be resolved to namespaces. >- * @param prefixResolver Will be called if the parser encounters namespace >- * prefixes, to resolve the prefixes to URLs. >- * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null. >- * @throws JspTagException >- * @see org.apache.xpath.objects.XObject >- * @see org.apache.xpath.objects.XNull >- * @see org.apache.xpath.objects.XBoolean >- * @see org.apache.xpath.objects.XNumber >- * @see org.apache.xpath.objects.XString >- * @see org.apache.xpath.objects.XRTreeFrag >- */ >- public static XObject eval( >- Node contextNode, String str, PrefixResolver prefixResolver, >- XPathContext xpathSupport) throws JspTagException { >- //System.out.println("eval of XPathContext params: contextNode:str(xpath)"+ >- // ":prefixResolver:xpathSupport => " + contextNode + ":" + str + ":" + >- // prefixResolver + ":" + xpathSupport ); >- try { >- if (xpathSupport == null) { >- return eval(contextNode, str, prefixResolver); >- } >- >- // Since we don't have a XML Parser involved here, install some default support >- // for things like namespaces, etc. >- // (Changed from: XPathContext xpathSupport = new XPathContext(); >- // because XPathContext is weak in a number of areas... perhaps >- // XPathContext should be done away with.) >- // Create the XPath object. >- XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null); >- >- // Execute the XPath, and have it return the result >- int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); >- >- // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode ); >- XObject xobj = xpath.execute(xpathSupport, ctxtNode, prefixResolver); >- return xobj; >- } catch (TransformerException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex); >- } catch (IllegalArgumentException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex); >- } >- } >- >- public static XObject eval( >- Node contextNode, String str, PrefixResolver prefixResolver, >- XPathContext xpathSupport, Vector varQNames) throws JspTagException { >- //p("***************** eval "); >- //p( "contextNode => " + contextNode ); >- //p( "XPath str => " + str ); >- //p( "PrefixResolver => " + prefixResolver ); >- //p( "XPath Context => " + xpathSupport ); >- //p( "Var QNames => " + varQNames ); >- //p( "Global Var Size => " + varQNames.size() ); >- try { >- XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null); >- xpath.fixupVariables(varQNames, varQNames.size()); >- // Execute the XPath, and have it return the result >- int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); >- // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode ); >- return xpath.execute(xpathSupport, ctxtNode, prefixResolver); >- } catch (TransformerException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex); >- } catch (IllegalArgumentException ex) { >- throw new JspTagException( >- Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex); >- } >- } >- >- private static void p(String s) { >- System.out.println("[JSTLXPathAPI] " + s); >- } >-} >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.java (working copy) >@@ -1,145 +0,0 @@ >-/* >- * 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.HashMap; >- >-import org.apache.xml.utils.PrefixResolver; >-import org.w3c.dom.NamedNodeMap; >-import org.w3c.dom.Node; >- >-/** >- * <meta name="usage" content="general"/> >- * This class implements a JSTL PrefixResolver that >- * can be used to perform prefix-to-namespace lookup >- * for the XPath object. >- */ >-public class JSTLPrefixResolver implements PrefixResolver { >- >- /** >- * The context to resolve the prefix from, if the context >- * is not given. >- */ >- >- HashMap namespaces; >- >- /** >- * The URI for the XML namespace. >- * (Duplicate of that found in org.apache.xpath.XPathContext). >- */ >- >- public static final String S_XMLNAMESPACEURI = >- "http://www.w3.org/XML/1998/namespace"; >- >- /** >- * No-arg constructor which would create empty HashMap of namespaces >- */ >- public JSTLPrefixResolver() { >- namespaces = new HashMap(); >- } >- >- public JSTLPrefixResolver(HashMap nses) { >- namespaces = nses; >- } >- >- /** >- * Given a namespace, get the corresponding prefix. This assumes that >- * the PrevixResolver hold's it's own namespace context, or is a namespace >- * context itself. >- * >- * @param prefix Prefix to resolve. >- * @return Namespace that prefix resolves to, or null if prefix >- * is not bound. >- */ >- public String getNamespaceForPrefix(String prefix) { >- return (String) namespaces.get(prefix); >- } >- >- /** >- * Given a prefix and a Context Node, get the corresponding namespace. >- * Warning: This will not work correctly if namespaceContext >- * is an attribute node. >- * >- * @param prefix Prefix to resolve. >- * @param namespaceContext Node from which to start searching for a >- * xmlns attribute that binds a prefix to a namespace. >- * @return Namespace that prefix resolves to, or null if prefix >- * is not bound. >- */ >- public String getNamespaceForPrefix(String prefix, >- org.w3c.dom.Node namespaceContext) { >- >- Node parent = namespaceContext; >- String namespace = null; >- >- if (prefix.equals("xml")) { >- namespace = S_XMLNAMESPACEURI; >- } else { >- int type; >- >- while ((null != parent) && (null == namespace) >- && (((type = parent.getNodeType()) == Node.ELEMENT_NODE) >- || (type == Node.ENTITY_REFERENCE_NODE))) { >- if (type == Node.ELEMENT_NODE) { >- NamedNodeMap nnm = parent.getAttributes(); >- >- for (int i = 0; i < nnm.getLength(); i++) { >- Node attr = nnm.item(i); >- String aname = attr.getNodeName(); >- boolean isPrefix = aname.startsWith("xmlns:"); >- >- if (isPrefix || aname.equals("xmlns")) { >- int index = aname.indexOf(':'); >- String p = isPrefix ? aname.substring(index + 1) : ""; >- >- if (p.equals(prefix)) { >- namespace = attr.getNodeValue(); >- >- break; >- } >- } >- } >- } >- >- parent = parent.getParentNode(); >- } >- } >- >- return namespace; >- } >- >- /** >- * Return the base identifier. >- * >- * @return null >- */ >- public String getBaseIdentifier() { >- return null; >- } >- >- /** >- * @see PrefixResolver#handlesNullPrefixes() >- */ >- public boolean handlesNullPrefixes() { >- return false; >- } >- >- public void addNamespace(String prefix, String uri) { >- namespaces.put(prefix, uri); >- } >- >-} >Index: impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java >=================================================================== >--- impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (revision 1050272) >+++ impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (working copy) >@@ -20,6 +20,9 @@ > import javax.servlet.jsp.JspTagException; > > import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; >+import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; >+import org.apache.taglibs.standard.xpath.JSTLXPathExpression; >+import org.apache.taglibs.standard.xpath.JSTLXPathFactory; > > /** > * <p>Tag handler for <if> in JSTL's XML library.</p> >@@ -29,54 +32,27 @@ > > public class WhenTag extends WhenTagSupport { > >- //********************************************************************* >- // Constructor and lifecycle management >+ private JSTLXPathCompiler compiler; >+ private JSTLXPathExpression select; > >- // initialize inherited and local state >- > public WhenTag() { >- super(); >- init(); >+ JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); >+ compiler = xpf.newCompiler(); > } > >- // Releases any resources we may have (or inherit) >- > @Override > public void release() { > super.release(); >- init(); >+ compiler = null; >+ select = null; > } > >- >- //********************************************************************* >- // Supplied conditional logic >- > @Override > protected boolean condition() throws JspTagException { >- XPathUtil xu = new XPathUtil(pageContext); >- return (xu.booleanValueOf(XPathUtil.getContext(this), select)); >+ return select.evaluateBoolean(ForEachTag.getContext(this), pageContext); > } > >- //********************************************************************* >- // Private state >- >- private String select; // the value of the 'test' attribute >- >- >- //********************************************************************* >- // Attribute accessors >- > public void setSelect(String select) { >- this.select = select; >+ this.select = compiler.compile(select); > } >- >- >- //********************************************************************* >- // Private utility methods >- >- // resets internal state >- >- private void init() { >- select = null; >- } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 27717
:
12261
|
12262
|
12263
|
12264
|
25749
|
25750
|
26445
|
26448
|
26452