--- apache-taglibs-trunk/impl/pom.xml (revision 1817516) +++ apache-taglibs-trunk/impl/pom.xml (working copy) @@ -91,13 +91,6 @@ 1.0 provided - - xalan - xalan - 2.7.1 - provided - true - junit --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (revision 1817516) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (working copy) @@ -22,52 +22,52 @@ import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.tagext.TagSupport; -import javax.xml.transform.TransformerException; import org.apache.taglibs.standard.util.EscapeXML; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; +import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; +import org.apache.taglibs.standard.xpath.JSTLXPathExpression; +import org.apache.taglibs.standard.xpath.JSTLXPathFactory; /** - * Tag handler for <out> in JSTL's XML library. - * 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 { - private XPath select; - protected boolean escapeXml = true; // tag attribute + private JSTLXPathCompiler compiler; + private JSTLXPathExpression select; + protected boolean escapeXml = true; // tag attribute - @Override - public void release() { - super.release(); - select = null; - } + public ExprSupport() { + JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); + compiler = xpf.newCompiler(); + } - //********************************************************************* - // Tag logic + @Override + public void release() { + super.release(); + compiler = null; + select = null; + } - // applies XPath expression from 'select' and prints the result - @Override - public int doStartTag() throws JspException { - try { - XPathContext context = XalanUtil.getContext(this, pageContext); - String result = select.execute(context, context.getCurrentNode(), null).str(); - EscapeXML.emit(result, escapeXml, pageContext.getOut()); - return SKIP_BODY; - } catch (IOException ex) { - throw new JspTagException(ex.toString(), ex); - } catch (TransformerException e) { - throw new JspTagException(e); - } - } + // ********************************************************************* + // Tag logic - public void setSelect(String select) { - try { - this.select = new XPath(select, null, null, XPath.SELECT); - } catch (TransformerException e) { - throw new AssertionError(); - } - } + // applies XPath expression from 'select' and prints the result + @Override + public int doStartTag() throws JspException { + try { + String result = select.evaluateString(ForEachTag.getContext(this), pageContext); + EscapeXML.emit(result, escapeXml, pageContext.getOut()); + return SKIP_BODY; + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } + } + + public void setSelect(String select) { + this.select = compiler.compile(select); + } } --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (revision 1817516) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (working copy) @@ -17,15 +17,15 @@ package org.apache.taglibs.standard.tag.common.xml; -import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.jstl.core.LoopTagSupport; -import javax.xml.transform.TransformerException; +import javax.servlet.jsp.tagext.Tag; +import javax.servlet.jsp.tagext.TagSupport; -import org.apache.xml.dtm.DTMIterator; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; -import org.apache.xpath.objects.XObject; +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; /** * Implementation of <x:forEach> tag using low-level Xalan API. @@ -35,95 +35,67 @@ */ public class ForEachTag extends LoopTagSupport { - private XPath select; - private XPathContext context; + private JSTLXPathCompiler compiler; + private JSTLXPathExpression select; + private JSTLXPathContext context; - @Override - public void release() { - super.release(); - select = null; - context = null; - } + public ForEachTag() { + JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); + compiler = xpf.newCompiler(); + } - @Override - protected void prepare() throws JspTagException { - context = XalanUtil.getContext(this, pageContext); - try { - XObject nodes = select.execute(context, context.getCurrentNode(), null); + @Override + public void release() { + super.release(); + compiler = null; + select = null; + context = null; + } - // create an iterator over the returned nodes and push into the context - DTMIterator iterator = nodes.iter(); - context.pushContextNodeList(iterator); - } catch (TransformerException e) { - throw new JspTagException(e); - } - } + @Override + protected void prepare() throws JspTagException { + context = select.iterate(getContext(this), pageContext); + } - @Override - protected boolean hasNext() throws JspTagException { - DTMIterator iterator = context.getContextNodeList(); - return iterator.getCurrentPos() < iterator.getLength(); - } + @Override + protected boolean hasNext() throws JspTagException { + return context.hasNext(); + } - @Override - protected Object next() throws JspTagException { - DTMIterator iterator = context.getContextNodeList(); - int next = iterator.nextNode(); - context.pushCurrentNode(next); - return iterator.getDTM(next).getNode(next); - } + @Override + protected Object next() throws JspTagException { + return context.next(); + } - @Override - public int doAfterBody() throws JspException { - // pop the context node after executing the body - context.popCurrentNode(); - return super.doAfterBody(); - } + public void setSelect(String select) { + this.select = compiler.compile(select); + } - @Override - public void doFinally() { - // context might be null as prepare is not called if end < begin - if (context != null) { - // pop the list of nodes being iterated - context.popContextNodeList(); - context = null; - } - super.doFinally(); - } + public void setBegin(int begin) throws JspTagException { + this.beginSpecified = true; + this.begin = begin; + validateBegin(); + } - public void setSelect(String select) { - try { - this.select = new XPath(select, null, null, XPath.SELECT); - } catch (TransformerException e) { - throw new AssertionError(); - } - } + public void setEnd(int end) throws JspTagException { + this.endSpecified = true; + this.end = end; + validateEnd(); + } - public void setBegin(int begin) throws JspTagException { - this.beginSpecified = true; - this.begin = begin; - validateBegin(); - } + public void setStep(int step) throws JspTagException { + this.stepSpecified = true; + this.step = step; + validateStep(); + } - public void setEnd(int end) throws JspTagException { - this.endSpecified = true; - this.end = end; - validateEnd(); - } - - public void setStep(int step) throws JspTagException { - this.stepSpecified = true; - this.step = step; - validateStep(); - } - - /** - * Return the current XPath context to support expression evaluation in nested tags. - * - * @return the current XPath context - */ - XPathContext getContext() { - return context; - } + /* Retrieves the current context. */ + public static JSTLXPathContext getContext(Tag child) { + ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class); + if (forEachTag == null) { + return null; + } else { + return forEachTag.context; + } + } } - --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (revision 1817516) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (working copy) @@ -19,13 +19,15 @@ import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.jstl.core.ConditionalTagSupport; -import javax.xml.transform.TransformerException; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; +import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; +import org.apache.taglibs.standard.xpath.JSTLXPathExpression; +import org.apache.taglibs.standard.xpath.JSTLXPathFactory; /** - *

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

+ *

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

* * @author Shawn Bayern */ @@ -32,30 +34,27 @@ public class IfTag extends ConditionalTagSupport { - private XPath select; + private JSTLXPathCompiler compiler; + private JSTLXPathExpression select; + public IfTag() { + JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); + compiler = xpf.newCompiler(); + } - @Override - public void release() { - super.release(); - select = null; - } + @Override + public void release() { + super.release(); + compiler = null; + select = null; + } - @Override - protected boolean condition() throws JspTagException { - XPathContext context = XalanUtil.getContext(this, pageContext); - try { - return select.bool(context, context.getCurrentNode(), null); - } catch (TransformerException e) { - throw new JspTagException(e); - } - } + @Override + protected boolean condition() throws JspTagException { + return select.evaluateBoolean(ForEachTag.getContext(this), pageContext); + } - public void setSelect(String select) { - try { - this.select = new XPath(select, null, null, XPath.SELECT); - } catch (TransformerException e) { - throw new AssertionError(); - } - } + public void setSelect(String select) { + this.select = compiler.compile(select); + } } --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (revision 1817516) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (working copy) @@ -18,70 +18,73 @@ package org.apache.taglibs.standard.tag.common.xml; import javax.servlet.jsp.JspException; -import javax.servlet.jsp.JspTagException; +//import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.TagSupport; -import javax.xml.transform.TransformerException; +//import javax.xml.transform.TransformerException; import org.apache.taglibs.standard.tag.common.core.Util; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; -import org.apache.xpath.objects.XObject; +import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; +import org.apache.taglibs.standard.xpath.JSTLXPathExpression; +import org.apache.taglibs.standard.xpath.JSTLXPathFactory; +//import org.apache.xpath.XPath; +//import org.apache.xpath.XPathContext; +//import org.apache.xpath.objects.XObject; /** - *

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

+ *

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

* * @author Shawn Bayern */ public class SetTag extends TagSupport { - private XPath select; - private String var; - private int scope = PageContext.PAGE_SCOPE; + private JSTLXPathCompiler compiler; + private JSTLXPathExpression select; + private String var; + private int scope = PageContext.PAGE_SCOPE; - //********************************************************************* - // Construction and initialization + // ********************************************************************* + // Construction and initialization - @Override - public void release() { - super.release(); - select = null; - var = null; - } + public SetTag() { + JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); + compiler = xpf.newCompiler(); + } - //********************************************************************* - // Tag logic + @Override + public void release() { + super.release(); + compiler = null; + select = null; + var = null; + } - // applies XPath expression from 'select' and stores the result in 'var' + // ********************************************************************* + // Tag logic - @Override - public int doStartTag() throws JspException { - try { - XPathContext context = XalanUtil.getContext(this, pageContext); - XObject result = select.execute(context, context.getCurrentNode(), null); - pageContext.setAttribute(var, XalanUtil.coerceToJava(result), scope); - return SKIP_BODY; - } catch (TransformerException e) { - throw new JspTagException(e); - } - } + // applies XPath expression from 'select' and stores the result in 'var' - //********************************************************************* - // Attribute accessors + @Override + public int doStartTag() throws JspException { + Object result = select.evaluateObject(ForEachTag.getContext(this), pageContext); + pageContext.setAttribute(var, result, scope); + return SKIP_BODY; + } - public void setSelect(String select) { - try { - this.select = new XPath(select, null, null, XPath.SELECT); - } catch (TransformerException e) { - throw new AssertionError(); - } - } + // ********************************************************************* + // Attribute accessors - public void setVar(String var) { - this.var = var; - } + public void setSelect(String select) { + this.select = compiler.compile(select); + } - public void setScope(String scope) { - this.scope = Util.getScope(scope); - } + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } } --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (revision 1817516) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (working copy) @@ -18,14 +18,16 @@ package org.apache.taglibs.standard.tag.common.xml; import javax.servlet.jsp.JspTagException; -import javax.xml.transform.TransformerException; import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; -import org.apache.xpath.XPath; -import org.apache.xpath.XPathContext; +import org.apache.taglibs.standard.xpath.JSTLXPathCompiler; +import org.apache.taglibs.standard.xpath.JSTLXPathExpression; +import org.apache.taglibs.standard.xpath.JSTLXPathFactory; /** - *

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

+ *

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

* * @author Shawn Bayern */ @@ -32,29 +34,27 @@ public class WhenTag extends WhenTagSupport { - private XPath select; + private JSTLXPathCompiler compiler; + private JSTLXPathExpression select; - @Override - public void release() { - super.release(); - select = null; - } + public WhenTag() { + JSTLXPathFactory xpf = JSTLXPathFactory.getFactory(); + compiler = xpf.newCompiler(); + } - @Override - protected boolean condition() throws JspTagException { - XPathContext context = XalanUtil.getContext(this, pageContext); - try { - return select.bool(context, context.getCurrentNode(), null); - } catch (TransformerException e) { - throw new JspTagException(e); - } - } + @Override + public void release() { + super.release(); + compiler = null; + select = null; + } - public void setSelect(String select) { - try { - this.select = new XPath(select, null, null, XPath.SELECT); - } catch (TransformerException e) { - throw new AssertionError(); - } - } + @Override + protected boolean condition() throws JspTagException { + return select.evaluateBoolean(ForEachTag.getContext(this), pageContext); + } + + public void setSelect(String select) { + this.select = compiler.compile(select); + } } --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/InvalidXPathException.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/InvalidXPathException.java (working copy) @@ -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); + } +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLVariableResolver.java (working copy) @@ -0,0 +1,154 @@ +/* + * 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 NAMESPACES; + + static { + NAMESPACES = new HashMap(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 SCOPES; + + static { + SCOPES = new HashMap(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(); + } +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathCompiler.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathCompiler.java (working copy) @@ -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; + +/** + */ +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; +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathContext.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathContext.java (working copy) @@ -0,0 +1,25 @@ +/* + * 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(); +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathExpression.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathExpression.java (working copy) @@ -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; +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/JSTLXPathFactory.java (working copy) @@ -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(); +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathCompiler.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathCompiler.java (working copy) @@ -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); + } + } +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathContext.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathContext.java (working copy) @@ -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); + } +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathExpression.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathExpression.java (working copy) @@ -0,0 +1,70 @@ +/* + * 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); + } + } +} --- apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathFactory.java (nonexistent) +++ apache-taglibs-trunk/impl/src/main/java/org/apache/taglibs/standard/xpath/jaxp/JAXPXPathFactory.java (working copy) @@ -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); + } +}