tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jboy...@apache.org
Subject svn commit: r1054175 - in /tomcat/taglibs/standard/trunk/impl/src: main/java/org/apache/taglibs/standard/tag/common/xml/ main/resources/org/apache/taglibs/standard/resources/ test/java/org/apache/taglibs/standard/tag/common/xml/ test/resources/ test/re...
Date Fri, 31 Dec 2010 23:14:45 GMT
Author: jboynes
Date: Fri Dec 31 23:14:44 2010
New Revision: 1054175

URL: http://svn.apache.org/viewvc?rev=1054175&view=rev
Log:
Refactor XPath to use low-level Xalan API. Fixes
1) Most of the performance issues with iteration from #27717
2) Support for position() and last() from #22765 and others
3) Support for using the same variable twice from #49578

Added:
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java   (with props)
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java   (with props)
    tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java   (with props)
    tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java   (with props)
    tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java
    tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java   (with props)
    tomcat/taglibs/standard/trunk/impl/src/test/resources/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/
    tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml   (with props)
Removed:
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java
Modified:
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java
    tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java
    tomcat/taglibs/standard/trunk/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties

Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java Fri Dec 31 23:14:44 2010
@@ -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.
@@ -17,77 +17,57 @@
 
 package org.apache.taglibs.standard.tag.common.xml;
 
+import java.io.IOException;
+
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.JspTagException;
 import javax.servlet.jsp.tagext.TagSupport;
+import javax.xml.transform.TransformerException;
 
 import org.apache.taglibs.standard.util.EscapeXML;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
 
 /**
- * <p>Tag handler for &lt;out&gt; in JSTL's XML library.</p>
- * <p>TODO: should we rename this to OutSupport to match the tag name?
+ * Tag handler for &lt;out&gt; 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 String select;                       // tag attribute
-    protected boolean escapeXml;         // tag attribute
-
-    //*********************************************************************
-    // Construction and initialization
+    private XPath select;
+    protected boolean escapeXml = true;  // tag attribute
 
-    /**
-     * 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();
-    }
-
-    // resets local state
-
-    private void init() {
+    @Override
+    public void release() {
+        super.release();
         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);
+            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 (java.io.IOException ex) {
+        } catch (IOException ex) {
             throw new JspTagException(ex.toString(), ex);
+        } catch (TransformerException e) {
+            throw new JspTagException(e);
         }
     }
 
-    // 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;
+        try {
+            this.select = new XPath(select, null, null, XPath.SELECT);
+        } catch (TransformerException e) {
+            throw new AssertionError();
+        }
     }
 }

Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java Fri Dec 31 23:14:44 2010
@@ -17,75 +17,86 @@
 
 package org.apache.taglibs.standard.tag.common.xml;
 
-import java.util.List;
-
+import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.JspTagException;
 import javax.servlet.jsp.jstl.core.LoopTagSupport;
+import javax.xml.transform.TransformerException;
 
-import org.apache.taglibs.standard.resources.Resources;
+import org.apache.xml.dtm.DTMIterator;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
 
 /**
- * <p>Support for the XML library's &lt;forEach&gt; tag.</p>
+ * Implementation of &lt;x:forEach&gt; tag using low-level Xalan API.
  *
  * @author Shawn Bayern
  * @see javax.servlet.jsp.jstl.core.LoopTagSupport
  */
 public class ForEachTag extends LoopTagSupport {
 
-    //*********************************************************************
-    // Private state
-
-    private String select;                // tag attribute
-    private List nodes;                    // XPath result
-    private int nodesIndex;                // current index
-    private org.w3c.dom.Node current;            // current node
+    private XPath select;
+    private XPathContext context;
 
-    //*********************************************************************
-    // Iteration control methods
-
-    // (We inherit semantics and Javadoc from LoopTagSupport.) 
+    @Override
+    public void release() {
+        super.release();
+        select = null;
+        context = null;
+    }
 
     @Override
     protected void prepare() throws JspTagException {
-        nodesIndex = 0;
-        XPathUtil xu = new XPathUtil(pageContext);
-        nodes = xu.selectNodes(XPathUtil.getContext(this), select);
+        context = XalanUtil.getContext(this, pageContext);
+        try {
+            XObject nodes = select.execute(context, context.getCurrentNode(), null);
+
+            // create an iterator over the returned nodes and push into the context
+            DTMIterator iterator = nodes.iter();
+            context.pushContextNodeList(iterator);
+        } catch (TransformerException e) {
+            throw new JspTagException(e);
+        }
     }
 
     @Override
     protected boolean hasNext() throws JspTagException {
-        return (nodesIndex < nodes.size());
+        DTMIterator iterator = context.getContextNodeList();
+        return iterator.getCurrentPos() < iterator.getLength();
     }
 
     @Override
     protected Object next() throws JspTagException {
-        Object o = nodes.get(nodesIndex++);
-        if (!(o instanceof org.w3c.dom.Node)) {
-            throw new JspTagException(
-                    Resources.getMessage("FOREACH_NOT_NODESET"));
-        }
-        current = (org.w3c.dom.Node) o;
-        return current;
+        DTMIterator iterator = context.getContextNodeList();
+        int next = iterator.nextNode();
+        context.pushCurrentNode(next);
+        return iterator.getDTM(next).getNode(next);
     }
 
-
-    //*********************************************************************
-    // Tag logic and lifecycle management
-
-    // Releases any resources we may have (or inherit)
-
     @Override
-    public void release() {
-        init();
-        super.release();
+    public int doAfterBody() throws JspException {
+        // pop the context node after executing the body
+        context.popCurrentNode();
+        return super.doAfterBody();
     }
 
-
-    //*********************************************************************
-    // Attribute accessors
+    @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 setSelect(String select) {
-        this.select = select;
+        try {
+            this.select = new XPath(select, null, null, XPath.SELECT);
+        } catch (TransformerException e) {
+            throw new AssertionError();
+        }
     }
 
     public void setBegin(int begin) throws JspTagException {
@@ -106,25 +117,13 @@ public class ForEachTag extends LoopTagS
         validateStep();
     }
 
-    //*********************************************************************
-    // Public methods for subtags
-
-    /* Retrieves the current context. */
-
-    public org.w3c.dom.Node getContext() throws JspTagException {
-        // expose the current node as the context
-        return current;
-    }
-
-
-    //*********************************************************************
-    // Private utility methods
-
-    private void init() {
-        select = null;
-        nodes = null;
-        nodesIndex = 0;
-        current = null;
+    /**
+     * Return the current XPath context to support expression evaluation in nested tags.
+     *
+     * @return the current XPath context
+     */
+    XPathContext getContext() {
+        return context;
     }
 }
 

Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java Fri Dec 31 23:14:44 2010
@@ -19,6 +19,10 @@ package org.apache.taglibs.standard.tag.
 
 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;
 
 /**
  * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
@@ -28,55 +32,30 @@ import javax.servlet.jsp.jstl.core.Condi
 
 public class IfTag extends ConditionalTagSupport {
 
-    //*********************************************************************
-    // Constructor and lifecycle management
-
-    // initialize inherited and local state
+    private XPath select;
 
-    public IfTag() {
-        super();
-        init();
-    }
-
-    // Releases any resources we may have (or inherit)
 
     @Override
     public void release() {
         super.release();
-        init();
+        select = null;
     }
 
-
-    //*********************************************************************
-    // Supplied conditional logic
-
     @Override
     protected boolean condition() throws JspTagException {
-        XPathUtil xu = new XPathUtil(pageContext);
-        return (xu.booleanValueOf(XPathUtil.getContext(this), select));
+        XPathContext context = XalanUtil.getContext(this, pageContext);
+        try {
+            return select.bool(context, context.getCurrentNode(), null);
+        } catch (TransformerException e) {
+            throw new JspTagException(e);
+        }
     }
 
-
-    //*********************************************************************
-    // Private state
-
-    private String select;               // the value of the 'test' attribute
-
-
-    //*********************************************************************
-    // Attribute accessors
-
     public void setSelect(String select) {
-        this.select = select;
-    }
-
-
-    //*********************************************************************
-    // Private utility methods
-
-    // resets internal state
-
-    private void init() {
-        select = null;
+        try {
+            this.select = new XPath(select, null, null, XPath.SELECT);
+        } catch (TransformerException e) {
+            throw new AssertionError();
+        }
     }
 }

Added: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,132 @@
+/*
+ * 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 java.util.Map;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.PageContext;
+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.XObject;
+import org.apache.xpath.objects.XObjectFactory;
+
+/**
+ */
+public class JSTLVariableStack extends VariableStack {
+
+    private static enum Scope {
+        PARAM,
+        HEADER,
+        COOKIE,
+        INITPARAM,
+        PAGE,
+        REQUEST,
+        SESSION,
+        APPLICATION
+    }
+
+    // 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 scopes
+    private static final Map<String, Scope> SCOPES;
+    static {
+        SCOPES = new HashMap<String, Scope>(8);
+        SCOPES.put(PARAM_PREFIX, Scope.PARAM);
+        SCOPES.put(HEADER_PREFIX, Scope.HEADER);
+        SCOPES.put(COOKIE_PREFIX, Scope.COOKIE);
+        SCOPES.put(INITPARAM_PREFIX, Scope.INITPARAM);
+        SCOPES.put(PAGE_PREFIX, Scope.PAGE);
+        SCOPES.put(REQUEST_PREFIX, Scope.REQUEST);
+        SCOPES.put(SESSION_PREFIX, Scope.SESSION);
+        SCOPES.put(APP_PREFIX, Scope.APPLICATION);
+    }
+
+    private final PageContext pageContext;
+
+    public JSTLVariableStack(PageContext pageContext) {
+        super(2);
+        this.pageContext = pageContext;
+    }
+
+    @Override
+    public XObject getVariableOrParam(XPathContext xctxt, QName qname) throws TransformerException {
+        String prefix = qname.getNamespaceURI();
+        String name = qname.getLocalPart();
+        Object value = getValue(prefix, name);
+        if (value == null) {
+            StringBuilder var = new StringBuilder();
+            var.append('$');
+            if (prefix != null) {
+                var.append(prefix);
+                var.append(':');
+            }
+            var.append(name);
+            throw new TransformerException(Resources.getMessage("XPATH_UNABLE_TO_RESOLVE_VARIABLE", var.toString()));
+        }
+        return XObjectFactory.create(value, xctxt);
+    }
+
+    private Object getValue(String prefix, String name) {
+        if (prefix == null) {
+            return pageContext.findAttribute(name);
+        }
+        Scope scope = SCOPES.get(prefix);
+        switch (scope) {
+            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();
+        }
+    }
+}

Propchange: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java Fri Dec 31 23:14:44 2010
@@ -17,13 +17,16 @@
 
 package org.apache.taglibs.standard.tag.common.xml;
 
-import java.util.List;
-
 import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspTagException;
 import javax.servlet.jsp.PageContext;
 import javax.servlet.jsp.tagext.TagSupport;
+import javax.xml.transform.TransformerException;
 
 import org.apache.taglibs.standard.tag.common.core.Util;
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
 
 /**
  * <p>Tag handler for &lt;set&gt; in JSTL's XML library.</p>
@@ -32,35 +35,20 @@ import org.apache.taglibs.standard.tag.c
  */
 public class SetTag extends TagSupport {
 
-    //*********************************************************************
-    // Internal state
-
-    private String select;                    // tag attribute
-    private String var;                       // tag attribute
-    private int scope;                  // processed tag attribute
+    private XPath select;
+    private String var;
+    private int scope = PageContext.PAGE_SCOPE;
 
     //*********************************************************************
     // Construction and initialization
 
-    /**
-     * Constructs a new handler.  As with TagSupport, subclasses should
-     * not provide other constructors and are expected to call the
-     * superclass constructor.
-     */
-    public SetTag() {
-        super();
-        init();
-    }
-
-    // resets local state
-
-    private void init() {
-        var = null;
+    @Override
+    public void release() {
+        super.release();
         select = null;
-        scope = PageContext.PAGE_SCOPE;
+        var = null;
     }
 
-
     //*********************************************************************
     // Tag logic
 
@@ -68,40 +56,25 @@ public class SetTag extends TagSupport {
 
     @Override
     public int doStartTag() throws JspException {
-        // process the query
-        XPathUtil xu = new XPathUtil(pageContext);
-        List result =
-                xu.selectNodes(XPathUtil.getContext(this), select);
-        Object ret = result;
-
-        // unwrap primitive types if that's what we received
-        if (result.size() == 1) {
-            Object o = result.get(0);
-            if (o instanceof String || o instanceof Boolean
-                    || o instanceof Number) {
-                ret = o;
-            }
+        try {
+            XPathContext context = XalanUtil.getContext(this, pageContext);
+            XObject result = select.execute(context, context.getCurrentNode(), null);
+            pageContext.setAttribute(var, XalanUtil.coerceToJava(result), scope);
+            return SKIP_BODY;
+        } catch (TransformerException e) {
+            throw new JspTagException(e);
         }
-
-        // expose the final result
-        pageContext.setAttribute(var, ret, scope);
-        return SKIP_BODY;
-    }
-
-    // Releases any resources we may have (or inherit)
-
-    @Override
-    public void release() {
-        super.release();
-        init();
     }
 
-
     //*********************************************************************
     // Attribute accessors
 
     public void setSelect(String select) {
-        this.select = select;
+        try {
+            this.select = new XPath(select, null, null, XPath.SELECT);
+        } catch (TransformerException e) {
+            throw new AssertionError();
+        }
     }
 
     public void setVar(String var) {

Modified: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java Fri Dec 31 23:14:44 2010
@@ -18,8 +18,11 @@
 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;
 
 /**
  * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
@@ -29,54 +32,29 @@ import org.apache.taglibs.standard.tag.c
 
 public class WhenTag extends WhenTagSupport {
 
-    //*********************************************************************
-    // Constructor and lifecycle management
-
-    // initialize inherited and local state
-
-    public WhenTag() {
-        super();
-        init();
-    }
-
-    // Releases any resources we may have (or inherit)
+    private XPath select;
 
     @Override
     public void release() {
         super.release();
-        init();
+        select = null;
     }
 
-
-    //*********************************************************************
-    // Supplied conditional logic
-
     @Override
     protected boolean condition() throws JspTagException {
-        XPathUtil xu = new XPathUtil(pageContext);
-        return (xu.booleanValueOf(XPathUtil.getContext(this), select));
+        XPathContext context = XalanUtil.getContext(this, pageContext);
+        try {
+            return select.bool(context, context.getCurrentNode(), null);
+        } catch (TransformerException e) {
+            throw new JspTagException(e);
+        }
     }
 
-    //*********************************************************************
-    // Private state
-
-    private String select;               // the value of the 'test' attribute
-
-
-    //*********************************************************************
-    // Attribute accessors
-
     public void setSelect(String select) {
-        this.select = select;
-    }
-
-
-    //*********************************************************************
-    // Private utility methods
-
-    // resets internal state
-
-    private void init() {
-        select = null;
+        try {
+            this.select = new XPath(select, null, null, XPath.SELECT);
+        } catch (TransformerException e) {
+            throw new AssertionError();
+        }
     }
 }

Added: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.taglibs.standard.tag.common.xml;
+
+import javax.servlet.jsp.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.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xpath.VariableStack;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XBoolean;
+import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XNumber;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XString;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+/**
+ */
+public class XalanUtil {
+    private static final DocumentBuilderFactory dbf;
+
+    static {
+        // from Java5 on DocumentBuilderFactory is thread safe and hence can be cached
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+    }
+
+    /**
+     * Return the XPathContext to be used for evaluating expressions.
+     *
+     * If the child is nested withing a forEach tag its iteration context is used.
+     * Otherwise, a new context is created based on an empty Document.
+     *
+     * @param child the tag whose context should be returned
+     * @param pageContext the current page context
+     * @return the XPath evaluation context
+     */
+    public static XPathContext getContext(Tag child, PageContext pageContext) {
+        // if within a forEach tag, use its context
+        ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class);
+        if (forEachTag != null) {
+            return forEachTag.getContext();
+        }
+
+        // otherwise, create a new context referring to an empty document
+        XPathContext context = new XPathContext(false);
+        VariableStack variableStack = new JSTLVariableStack(pageContext);
+        context.setVarStack(variableStack);
+        int dtm = context.getDTMHandleFromNode(newEmptyDocument());
+        context.pushCurrentNodeAndExpression(dtm, dtm);
+        return context;
+    }
+
+    /**
+     * Create a new empty document.
+     *
+     * This method always allocates a new document as its root node might be
+     * exposed to other tags and potentially be mutated.
+     *
+     * @return a new empty document
+     */
+    private static Document newEmptyDocument() {
+        try {
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            return db.newDocument();
+        } catch (ParserConfigurationException e) {
+            throw new AssertionError();
+        }
+    }
+
+    /**
+     * Return the Java value corresponding to an XPath result.
+     *
+     * @param xo the XPath type
+     * @return the corresponding Java value per the JSTL mapping rules
+     * @throws TransformerException if there was a problem converting the type
+     */
+    static Object coerceToJava(XObject xo) throws TransformerException {
+        if (xo instanceof XBoolean) {
+            return xo.bool();
+        } else if (xo instanceof XNumber) {
+            return xo.num();
+        } else if (xo instanceof XString) {
+            return xo.str();
+        } else if (xo instanceof XNodeSet) {
+            NodeList nodes = xo.nodelist();
+            // if there is only one node in the nodeset return it rather than the list
+            if (nodes.getLength() == 1) {
+                return nodes.item(0);
+            } else {
+                return nodes;
+            }
+        } else {
+            // unexpected result type
+            throw new AssertionError();
+        }
+    }
+}

Propchange: tomcat/taglibs/standard/trunk/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/taglibs/standard/trunk/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties?rev=1054175&r1=1054174&r2=1054175&view=diff
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties (original)
+++ tomcat/taglibs/standard/trunk/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties Fri Dec 31 23:14:44 2010
@@ -275,6 +275,9 @@ TRANSFORM_BODY_IS_EMPTY=\
 UNABLE_TO_RESOLVE_ENTITY=\
     Could not resolve entity reference: "{0}"
 
+XPATH_UNABLE_TO_RESOLVE_VARIABLE=\
+    Could not resolve XPath variable: {0}
+
 #########################################################################
 # JSTL core TLV messages
 #########################################################################
@@ -324,9 +327,3 @@ TLV_EMPTY_VAR=\
 SET_NO_SETTER_METHOD=No setter method in &lt;set&gt; for property "{0}"
 
 IMPORT_ABS_ERROR=Problem accessing the absolute URL "{0}". {1}
-
-XPATH_ERROR_EVALUATING_EXPR=Error evaluating XPath expression "{0}": {1}
-
-XPATH_ILLEGAL_ARG_EVALUATING_EXPR=Illegal argument evaluating XPath expression "{0}": {1}
-
-XPATH_ERROR_XOBJECT=Error accessing data in XObject: {0}

Added: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,108 @@
+/*
+ * 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.io.InputStream;
+
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.PageContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.w3c.dom.Document;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ */
+public class ExprSupportTest {
+
+    private static Document test;
+
+    private ExprSupport tag;
+    private PageContext pageContext;
+    private JspWriter out;
+
+    @BeforeClass
+    public static void loadXml() throws Exception {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        InputStream is = ExprSupportTest.class.getResourceAsStream("test.xml");
+        try {
+            test = db.parse(is);
+        } finally {
+            is.close();
+        }
+    }
+
+    @Before
+    public void setup() {
+        out = createMock(JspWriter.class);
+        pageContext = createMock(PageContext.class);
+        expect(pageContext.getOut()).andStubReturn(out);
+        tag = new ExprSupport() {
+        };
+        tag.setPageContext(pageContext);
+    }
+
+    @Test
+    public void testStringLiteral() throws Exception {
+        tag.setSelect("\"Hello\"");
+        out.write("Hello", 0, 5);
+        replay(pageContext, out);
+        tag.doStartTag();
+        verify(pageContext, out);
+    }
+
+    @Test
+    public void testBooleanVariable() throws Exception {
+        tag.setSelect("$a");
+        expect(pageContext.findAttribute("a")).andReturn(Boolean.TRUE);
+        out.write("true", 0, 4);
+        replay(pageContext, out);
+        tag.doStartTag();
+        verify(pageContext, out);
+    }
+
+    @Test
+    public void testNumberVariable() throws Exception {
+        tag.setSelect("$a");
+        expect(pageContext.findAttribute("a")).andReturn(12345.678);
+        out.write("12345.678", 0, 9);
+        replay(pageContext, out);
+        tag.doStartTag();
+        verify(pageContext, out);
+    }
+
+    @Test
+    public void testElementFromDom() throws Exception {
+        tag.setSelect("$doc/root/b");
+        expect(pageContext.findAttribute("doc")).andReturn(test);
+        out.write("Hello", 0, 5);
+        replay(pageContext, out);
+        tag.doStartTag();
+        verify(pageContext, out);
+    }
+}

Propchange: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,156 @@
+/*
+ * 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.io.InputStream;
+
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.IterationTag;
+import javax.servlet.jsp.tagext.Tag;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.apache.xpath.objects.XObject;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import sun.security.krb5.internal.TGSRep;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ */
+public class ForEachTagTest {
+    private static Document test;
+    private static DocumentBuilderFactory dbf;
+
+    @BeforeClass
+    public static void loadXml() throws Exception {
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        InputStream is = ExprSupportTest.class.getResourceAsStream("test.xml");
+        try {
+            test = db.parse(is);
+        } finally {
+            is.close();
+        }
+    }
+
+    private ForEachTag tag;
+    private PageContext pageContext;
+
+    @Before
+    public void setup() {
+        pageContext = createMock(PageContext.class);
+        tag = new ForEachTag();
+        tag.setPageContext(pageContext);
+    }
+
+    @Test
+    public void testIteration() throws Exception {
+        expect(pageContext.findAttribute("doc")).andStubReturn(test);
+        tag.setSelect("$doc/root/a/num");
+        replay(pageContext);
+        tag.prepare();
+        XPathContext context = tag.getContext();
+        Assert.assertTrue(tag.hasNext());
+        Node one = (Node) tag.next();
+        Assert.assertEquals("one", one.getTextContent());
+        Assert.assertTrue(tag.hasNext());
+        Node two = (Node) tag.next();
+        Assert.assertEquals("two", two.getTextContent());
+        Assert.assertTrue(tag.hasNext());
+        Node three = (Node) tag.next();
+        Assert.assertEquals("three", three.getTextContent());
+        Assert.assertFalse(tag.hasNext());
+        tag.doFinally();
+        Assert.assertTrue(context.getContextNodeListsStack().isEmpty());
+        verify(pageContext);
+    }
+
+    @Test
+    public void testIterationContext() throws Exception {
+        expect(pageContext.findAttribute("doc")).andStubReturn(test);
+        tag.setSelect("$doc/root/a/num");
+        replay(pageContext);
+        XPath dot = new XPath(".", null, null, XPath.SELECT);
+        XPath position = new XPath("position()", null, null, XPath.SELECT);
+        XPath last = new XPath("last()", null, null, XPath.SELECT);
+        tag.prepare();
+        XPathContext context = tag.getContext();
+        tag.hasNext();
+        tag.next();
+        Assert.assertEquals("3", last.execute(context, context.getCurrentNode(), null).str());
+        Assert.assertEquals("one", dot.execute(context, context.getCurrentNode(), null).str());
+        Assert.assertEquals("1", position.execute(context, context.getCurrentNode(), null).str());
+        tag.hasNext();
+        tag.next();
+        Assert.assertEquals("two", dot.execute(context, context.getCurrentNode(), null).str());
+        Assert.assertEquals("2", position.execute(context, context.getCurrentNode(), null).str());
+        tag.hasNext();
+        tag.next();
+        Assert.assertEquals("three", dot.execute(context, context.getCurrentNode(), null).str());
+        Assert.assertEquals("3", position.execute(context, context.getCurrentNode(), null).str());
+        verify(pageContext);
+    }
+
+    @Ignore
+    @Test
+    public void testIterationPerformance() throws Exception {
+        // create a large document
+        final int SIZE = 200000;
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        test = db.newDocument();
+        Element root = test.createElement("root");
+        test.appendChild(root);
+        for (int i = 0; i < SIZE; i++) {
+            Element child = test.createElement("a");
+            child.setTextContent(Integer.toString(i));
+            root.appendChild(child);
+        }
+
+        XPath dot = new XPath(".", null, null, XPath.SELECT);
+        expect(pageContext.findAttribute("doc")).andStubReturn(test);
+        tag.setSelect("$doc/root/a");
+        replay(pageContext);
+        long time = -System.nanoTime();
+        XObject result = null;
+        if (tag.doStartTag() == IterationTag.EVAL_BODY_INCLUDE) {
+            do {
+//                XPathContext context = tag.getContext();
+//                result = dot.execute(context, context.getCurrentNode(), null);
+            } while (tag.doAfterBody() == IterationTag.EVAL_BODY_AGAIN);
+            tag.doFinally();
+        }
+        time += System.nanoTime();
+//        System.err.println("result = " + result.str());
+        System.err.println("time = " + time/1000000 + "ms.");
+    }
+}

Propchange: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.taglibs.standard.tag.common.xml;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.PageContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.xml.utils.QName;
+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.XObjectFactory;
+import org.apache.xpath.objects.XString;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ */
+public class JSTLVariableStackTest {
+
+    private JSTLVariableStack stack;
+    private PageContext pageContext;
+    private XPathContext xpathContext;
+    private XString hello;
+
+    @Before
+    public void setup() {
+        pageContext = createMock(PageContext.class);
+        xpathContext = new XPathContext(false);
+        hello = (XString) XObjectFactory.create("Hello");
+        stack = new JSTLVariableStack(pageContext);
+
+    }
+
+    @Test
+    public void testNoPrefix() throws TransformerException {
+        expect(pageContext.findAttribute("foo")).andReturn("Hello");
+        replay(pageContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName(null, "foo")));
+        verify(pageContext);
+    }
+
+    @Test
+    public void testParamPrefix() throws TransformerException {
+        HttpServletRequest request = createMock(HttpServletRequest.class);
+        expect(pageContext.getRequest()).andReturn(request);
+        expect(request.getParameter("foo")).andReturn("Hello");
+        replay(pageContext, request);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("param", "foo")));
+        verify(pageContext, request);
+    }
+
+    @Test
+    public void testHeaderPrefix() throws TransformerException {
+        HttpServletRequest request = createMock(HttpServletRequest.class);
+        expect(pageContext.getRequest()).andReturn(request);
+        expect(request.getHeader("foo")).andReturn("Hello");
+        replay(pageContext, request);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("header", "foo")));
+        verify(pageContext, request);
+    }
+
+    @Test
+    public void testCookiePrefix() throws TransformerException {
+        HttpServletRequest request = createMock(HttpServletRequest.class);
+        expect(pageContext.getRequest()).andReturn(request);
+        Cookie[] cookies = new Cookie[]{new Cookie("foo", "Hello")};
+        expect(request.getCookies()).andReturn(cookies);
+        replay(pageContext, request);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("cookie", "foo")));
+        verify(pageContext, request);
+    }
+
+    @Test
+    public void testInitParamPrefix() throws TransformerException {
+        ServletContext servletContext = createMock(ServletContext.class);
+        expect(pageContext.getServletContext()).andReturn(servletContext);
+        expect(servletContext.getInitParameter("foo")).andReturn("Hello");
+        replay(pageContext, servletContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("initParam", "foo")));
+        verify(pageContext, servletContext);
+    }
+
+    @Test
+    public void testPagePrefix() throws TransformerException {
+        expect(pageContext.getAttribute("foo", PageContext.PAGE_SCOPE)).andReturn("Hello");
+        replay(pageContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("pageScope", "foo")));
+        verify(pageContext);
+    }
+
+    @Test
+    public void testRequestPrefix() throws TransformerException {
+        expect(pageContext.getAttribute("foo", PageContext.REQUEST_SCOPE)).andReturn("Hello");
+        replay(pageContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("requestScope", "foo")));
+        verify(pageContext);
+    }
+
+    @Test
+    public void testSessionPrefix() throws TransformerException {
+        expect(pageContext.getAttribute("foo", PageContext.SESSION_SCOPE)).andReturn("Hello");
+        replay(pageContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("sessionScope", "foo")));
+        verify(pageContext);
+    }
+
+    @Test
+    public void testApplicationPrefix() throws TransformerException {
+        expect(pageContext.getAttribute("foo", PageContext.APPLICATION_SCOPE)).andReturn("Hello");
+        replay(pageContext);
+        Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("applicationScope", "foo")));
+        verify(pageContext);
+    }
+
+    @Test(expected = TransformerException.class)
+    public void testValueNotFound() throws TransformerException {
+        expect(pageContext.findAttribute("foo")).andReturn(null);
+        replay(pageContext);
+        stack.getVariableOrParam(xpathContext, new QName(null, "foo"));
+        Assert.fail();
+    }
+
+    @Test
+    public void verifyJavaToXPathTypeMapping() throws ParserConfigurationException {
+        Assert.assertTrue(XObjectFactory.create(Boolean.TRUE, xpathContext) instanceof XBoolean);
+        Assert.assertTrue(XObjectFactory.create(1234, xpathContext) instanceof XNumber);
+        Assert.assertTrue(XObjectFactory.create("Hello", xpathContext) instanceof XString);
+
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        Document d = db.newDocument();
+        Element root = d.createElement("root");
+        XNodeSetForDOM xo = (XNodeSetForDOM) XObjectFactory.create(root, xpathContext);
+        Assert.assertEquals(root, xo.object());
+
+    }
+}

Added: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java Fri Dec 31 23:14:44 2010
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.taglibs.standard.tag.common.xml;
+
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.Tag;
+
+import org.apache.xpath.XPath;
+import org.apache.xpath.XPathContext;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+/**
+ */
+public class XalanUtilTest {
+
+    private Tag tag;
+    private PageContext pageContext;
+
+    @Before
+    public void setup() {
+        tag = createMock(Tag.class);
+        pageContext = createMock(PageContext.class);
+    }
+
+    @Test
+    public void testEmptyContext() {
+        expect(tag.getParent()).andReturn(null);
+        replay(pageContext, tag);
+        XPathContext context = XalanUtil.getContext(tag, pageContext);
+        // verify current node is an empty Document
+        int node = context.getCurrentNode();
+        Node doc = context.getDTM(node).getNode(node);
+        Assert.assertTrue(doc instanceof Document);
+        Assert.assertNull(doc.getFirstChild());
+        verify(pageContext, tag);
+    }
+
+    @Test
+    public void testContextSupportsMultipleVariables() throws Exception {
+        expect(tag.getParent()).andReturn(null);
+        expect(pageContext.findAttribute("a")).andReturn("Hello");
+        expect(pageContext.getAttribute("b", PageContext.REQUEST_SCOPE)).andReturn("World");
+        replay(pageContext, tag);
+        XPathContext context = XalanUtil.getContext(tag, pageContext);
+        XPath xpath = new XPath("concat($a, ' ', $requestScope:b)", null, null, XPath.SELECT);
+        Assert.assertEquals("Hello World", xpath.execute(context, context.getCurrentNode(), null).str());
+        verify(pageContext, tag);
+    }
+}

Propchange: tomcat/taglibs/standard/trunk/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml
URL: http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml?rev=1054175&view=auto
==============================================================================
--- tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml (added)
+++ tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml Fri Dec 31 23:14:44 2010
@@ -0,0 +1,25 @@
+<?xml version="1.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.
+-->
+<root>
+    <a>
+        <num>one</num>
+        <num>two</num>
+        <num>three</num>
+    </a>
+    <b>Hello</b>
+</root>
\ No newline at end of file

Propchange: tomcat/taglibs/standard/trunk/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message