View | Details | Raw Unified | Return to bug 27717
Collapse All | Expand All

(-)impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java (+59 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package org.apache.taglibs.standard.tag.common.xml;
18
19
import javax.servlet.jsp.PageContext;
20
import javax.servlet.jsp.tagext.Tag;
21
22
import org.apache.xpath.XPathContext;
23
import org.junit.Assert;
24
import org.junit.Before;
25
import org.junit.Test;
26
import org.w3c.dom.Document;
27
import org.w3c.dom.Node;
28
29
import static org.easymock.EasyMock.createMock;
30
import static org.easymock.EasyMock.expect;
31
import static org.easymock.EasyMock.replay;
32
import static org.easymock.EasyMock.verify;
33
34
/**
35
 */
36
public class XalanUtilTest {
37
38
    private Tag tag;
39
    private PageContext pageContext;
40
41
    @Before
42
    public void setup() {
43
        tag = createMock(Tag.class);
44
        pageContext = createMock(PageContext.class);
45
    }
46
47
    @Test
48
    public void testEmptyContext() {
49
        expect(tag.getParent()).andReturn(null);
50
        replay(pageContext, tag);
51
        XPathContext context = XalanUtil.getContext(tag, pageContext);
52
        // verify current node is an empty Document
53
        int node = context.getCurrentNode();
54
        Node doc = context.getDTM(node).getNode(node);
55
        Assert.assertTrue(doc instanceof Document);
56
        Assert.assertNull(doc.getFirstChild());
57
        verify(pageContext, tag);
58
    }
59
}
(-)impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java (+76 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package org.apache.taglibs.standard.tag.common.xml;
18
19
import javax.servlet.jsp.JspWriter;
20
import javax.servlet.jsp.PageContext;
21
22
import org.junit.Before;
23
import org.junit.Test;
24
25
import static org.easymock.EasyMock.createMock;
26
import static org.easymock.EasyMock.expect;
27
import static org.easymock.EasyMock.replay;
28
import static org.easymock.EasyMock.verify;
29
30
/**
31
 */
32
public class ExprSupportTest {
33
34
    private ExprSupport tag;
35
    private PageContext pageContext;
36
    private JspWriter out;
37
38
    @Before
39
    public void setup() {
40
        out = createMock(JspWriter.class);
41
        pageContext = createMock(PageContext.class);
42
        expect(pageContext.getOut()).andStubReturn(out);
43
        tag = new ExprSupport() {
44
        };
45
        tag.setPageContext(pageContext);
46
    }
47
48
    @Test
49
    public void testStringLiteral() throws Exception {
50
        tag.setSelect("\"Hello\"");
51
        out.write("Hello", 0, 5);
52
        replay(pageContext, out);
53
        tag.doStartTag();
54
        verify(pageContext, out);
55
    }
56
57
    @Test
58
    public void testBooleanVariable() throws Exception {
59
        tag.setSelect("$a");
60
        expect(pageContext.findAttribute("a")).andReturn(Boolean.TRUE);
61
        out.write("true", 0, 4);
62
        replay(pageContext, out);
63
        tag.doStartTag();
64
        verify(pageContext, out);
65
    }
66
67
    @Test
68
    public void testNumberVariable() throws Exception {
69
        tag.setSelect("$a");
70
        expect(pageContext.findAttribute("a")).andReturn(12345.678);
71
        out.write("12345.678", 0, 9);
72
        replay(pageContext, out);
73
        tag.doStartTag();
74
        verify(pageContext, out);
75
    }
76
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java (+90 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package org.apache.taglibs.standard.tag.common.xml;
18
19
import javax.servlet.jsp.PageContext;
20
import javax.servlet.jsp.tagext.Tag;
21
import javax.servlet.jsp.tagext.TagSupport;
22
import javax.xml.parsers.DocumentBuilder;
23
import javax.xml.parsers.DocumentBuilderFactory;
24
import javax.xml.parsers.ParserConfigurationException;
25
import javax.xml.transform.TransformerException;
26
27
import org.apache.xpath.VariableStack;
28
import org.apache.xpath.XPathContext;
29
import org.apache.xpath.objects.XBoolean;
30
import org.apache.xpath.objects.XNodeSet;
31
import org.apache.xpath.objects.XNumber;
32
import org.apache.xpath.objects.XObject;
33
import org.apache.xpath.objects.XString;
34
import org.w3c.dom.Document;
35
import org.w3c.dom.NodeList;
36
37
/**
38
 */
39
public class XalanUtil {
40
    private static final DocumentBuilderFactory dbf;
41
42
    static {
43
        dbf = DocumentBuilderFactory.newInstance();
44
        dbf.setNamespaceAware(true);
45
        dbf.setValidating(false);
46
    }
47
48
    public static XPathContext getContext(Tag child, PageContext pageContext) {
49
        ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class);
50
        if (forEachTag != null) {
51
            return forEachTag.getContext();
52
        }
53
        XPathContext context = new XPathContext(false);
54
        VariableStack variableStack = new JSTLVariableStack(pageContext);
55
        context.setVarStack(variableStack);
56
        int dtm = context.getDTMHandleFromNode(getEmptyDocument());
57
        context.pushCurrentNodeAndExpression(dtm, dtm);
58
        return context;
59
    }
60
61
    private static Document getEmptyDocument() {
62
        try {
63
            DocumentBuilder db = dbf.newDocumentBuilder();
64
            return db.newDocument();
65
        } catch (ParserConfigurationException e) {
66
            throw new AssertionError();
67
        }
68
    }
69
70
    static Object coerceToJava(XObject xo) throws TransformerException {
71
        if (xo instanceof XBoolean) {
72
            return xo.bool();
73
        } else if (xo instanceof XNumber) {
74
            return xo.num();
75
        } else if (xo instanceof XString) {
76
            return xo.str();
77
        } else if (xo instanceof XNodeSet) {
78
            NodeList nodes = xo.nodelist();
79
            // if there is only one node in the nodeset return that rather than the list
80
            if (nodes.getLength() == 1) {
81
                return nodes.item(0);
82
            } else {
83
                return nodes;
84
            }
85
        } else {
86
            // unexpected result type
87
            throw new AssertionError();
88
        }
89
    }
90
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XPathUtil.java (-896 lines)
Lines 1-896 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
package org.apache.taglibs.standard.tag.common.xml;
19
20
import java.util.Enumeration;
21
import java.util.HashMap;
22
import java.util.List;
23
import java.util.Vector;
24
25
import javax.servlet.http.Cookie;
26
import javax.servlet.http.HttpServletRequest;
27
import javax.servlet.jsp.JspTagException;
28
import javax.servlet.jsp.PageContext;
29
import javax.servlet.jsp.tagext.Tag;
30
import javax.servlet.jsp.tagext.TagSupport;
31
import javax.xml.parsers.DocumentBuilder;
32
import javax.xml.parsers.DocumentBuilderFactory;
33
import javax.xml.transform.TransformerException;
34
35
import org.apache.taglibs.standard.resources.Resources;
36
import org.apache.xml.utils.QName;
37
import org.apache.xpath.VariableStack;
38
import org.apache.xpath.XPathContext;
39
import org.apache.xpath.objects.XBoolean;
40
import org.apache.xpath.objects.XNodeSetForDOM;
41
import org.apache.xpath.objects.XNumber;
42
import org.apache.xpath.objects.XObject;
43
import org.apache.xpath.objects.XString;
44
import org.w3c.dom.DOMImplementation;
45
import org.w3c.dom.Document;
46
import org.w3c.dom.Element;
47
import org.w3c.dom.Node;
48
import org.w3c.dom.NodeList;
49
50
/**
51
 * <p>Support for tag handlers that evaluate XPath expressions.</p>
52
 *
53
 * @author Shawn Bayern
54
 * @author Ramesh Mandava ( ramesh.mandava@sun.com )
55
 * @author Pierre Delisle ( pierre.delisle@sun.com )
56
 */
57
// would ideally be a base class, but some of our user handlers already
58
// have their own parents
59
public class XPathUtil {
60
61
    //*********************************************************************
62
    // Constructor
63
64
    /**
65
     * Constructs a new XPathUtil object associated with the given
66
     * PageContext.
67
     */
68
    public XPathUtil(PageContext pc) {
69
        pageContext = pc;
70
    }
71
72
    int globalVarSize = 0;
73
74
    public Vector getVariableQNames() {
75
76
        globalVarSize = 0;
77
        Vector variableVector = new Vector();
78
        // Now construct attributes in different scopes
79
        Enumeration enum_ = pageContext.getAttributeNamesInScope(
80
                PageContext.PAGE_SCOPE);
81
        while (enum_.hasMoreElements()) {
82
            String varName = (String) enum_.nextElement();
83
            QName varQName = new QName(PAGE_NS_URL, PAGE_P, varName);
84
            //Adding both namespace qualified QName and just localName
85
            variableVector.addElement(varQName);
86
            globalVarSize++;
87
88
            variableVector.addElement(new QName(null, varName));
89
            globalVarSize++;
90
        }
91
        enum_ = pageContext.getAttributeNamesInScope(
92
                PageContext.REQUEST_SCOPE);
93
        while (enum_.hasMoreElements()) {
94
            String varName = (String) enum_.nextElement();
95
            QName varQName = new QName(REQUEST_NS_URL, REQUEST_P, varName);
96
            //Adding both namespace qualified QName and just localName
97
            variableVector.addElement(varQName);
98
            globalVarSize++;
99
            variableVector.addElement(new QName(null, varName));
100
            globalVarSize++;
101
        }
102
103
        if (pageContext.getSession() != null) {
104
            // we may have a page directive preventing session creation/access
105
            // do not attempt to retrieve attribute names in session scope
106
            // @see [ http://issues.apache.org/bugzilla/show_bug.cgi?id=35216 ]
107
            enum_ = pageContext.getAttributeNamesInScope(
108
                    PageContext.SESSION_SCOPE);
109
            while (enum_.hasMoreElements()) {
110
                String varName = (String) enum_.nextElement();
111
                QName varQName = new QName(SESSION_NS_URL, SESSION_P, varName);
112
                //Adding both namespace qualified QName and just localName
113
                variableVector.addElement(varQName);
114
                globalVarSize++;
115
                variableVector.addElement(new QName(null, varName));
116
                globalVarSize++;
117
            }
118
        }
119
120
        enum_ = pageContext.getAttributeNamesInScope(
121
                PageContext.APPLICATION_SCOPE);
122
        while (enum_.hasMoreElements()) {
123
            String varName = (String) enum_.nextElement();
124
            QName varQName = new QName(APP_NS_URL, APP_P, varName);
125
            //Adding both namespace qualified QName and just localName
126
            variableVector.addElement(varQName);
127
            globalVarSize++;
128
            variableVector.addElement(new QName(null, varName));
129
            globalVarSize++;
130
        }
131
        enum_ = pageContext.getRequest().getParameterNames();
132
        while (enum_.hasMoreElements()) {
133
            String varName = (String) enum_.nextElement();
134
            QName varQName = new QName(PARAM_NS_URL, PARAM_P, varName);
135
            //Adding both namespace qualified QName and just localName
136
            variableVector.addElement(varQName);
137
            globalVarSize++;
138
        }
139
        enum_ = pageContext.getServletContext().getInitParameterNames();
140
        while (enum_.hasMoreElements()) {
141
            String varName = (String) enum_.nextElement();
142
            QName varQName = new QName(INITPARAM_NS_URL, INITPARAM_P, varName);
143
            //Adding both namespace qualified QName and just localName
144
            variableVector.addElement(varQName);
145
            globalVarSize++;
146
        }
147
        enum_ = ((HttpServletRequest) pageContext.getRequest()).getHeaderNames();
148
        while (enum_.hasMoreElements()) {
149
            String varName = (String) enum_.nextElement();
150
            QName varQName = new QName(HEADER_NS_URL, HEADER_P, varName);
151
            //Adding namespace qualified QName 
152
            variableVector.addElement(varQName);
153
            globalVarSize++;
154
        }
155
        Cookie[] c = ((HttpServletRequest) pageContext.getRequest()).getCookies();
156
        if (c != null) {
157
            for (int i = 0; i < c.length; i++) {
158
                String varName = c[i].getName();
159
                QName varQName = new QName(COOKIE_NS_URL, COOKIE_P, varName);
160
                //Adding namespace qualified QName 
161
                variableVector.addElement(varQName);
162
                globalVarSize++;
163
            }
164
        }
165
166
        return variableVector;
167
168
    }
169
170
    //*********************************************************************
171
    // Support for JSTL variable resolution
172
173
    // The URLs
174
    private static final String PAGE_NS_URL
175
            = "http://java.sun.com/jstl/xpath/page";
176
    private static final String REQUEST_NS_URL
177
            = "http://java.sun.com/jstl/xpath/request";
178
    private static final String SESSION_NS_URL
179
            = "http://java.sun.com/jstl/xpath/session";
180
    private static final String APP_NS_URL
181
            = "http://java.sun.com/jstl/xpath/app";
182
    private static final String PARAM_NS_URL
183
            = "http://java.sun.com/jstl/xpath/param";
184
    private static final String INITPARAM_NS_URL
185
            = "http://java.sun.com/jstl/xpath/initParam";
186
    private static final String COOKIE_NS_URL
187
            = "http://java.sun.com/jstl/xpath/cookie";
188
    private static final String HEADER_NS_URL
189
            = "http://java.sun.com/jstl/xpath/header";
190
191
    // The prefixes
192
    private static final String PAGE_P = "pageScope";
193
    private static final String REQUEST_P = "requestScope";
194
    private static final String SESSION_P = "sessionScope";
195
    private static final String APP_P = "applicationScope";
196
    private static final String PARAM_P = "param";
197
    private static final String INITPARAM_P = "initParam";
198
    private static final String COOKIE_P = "cookie";
199
    private static final String HEADER_P = "header";
200
201
    /**
202
     * org.apache.xpath.VariableStack defines a class to keep track of a stack
203
     * for template arguments and variables.
204
     * JstlVariableContext customizes it so it handles JSTL custom
205
     * variable-mapping rules.
206
     */
207
    protected class JstlVariableContext extends org.apache.xpath.VariableStack {
208
209
        public JstlVariableContext() {
210
            super();
211
        }
212
213
        /**
214
         * Get a variable as an XPath object based on it's qualified name.
215
         * We override the base class method so JSTL's custom variable-mapping
216
         * rules can be applied.
217
         *
218
         * @param xctxt The XPath context. @@@ we don't use it...
219
         *              (from xalan: which must be passed in order to lazy evaluate variables.)
220
         * @param qname The qualified name of the variable.
221
         */
222
        @Override
223
        public XObject getVariableOrParam(
224
                XPathContext xctxt,
225
                org.apache.xml.utils.QName qname)
226
                throws javax.xml.transform.TransformerException, UnresolvableException {
227
            //p( "***********************************getVariableOrParam begin****");
228
            String namespace = qname.getNamespaceURI();
229
            String prefix = qname.getPrefix();
230
            String localName = qname.getLocalName();
231
232
            //p("namespace:prefix:localname=>"+ namespace
233
            //     + ":" + prefix +":" + localName );
234
235
            try {
236
                Object varObject = getVariableValue(namespace, prefix, localName);
237
238
239
                //XObject varObject = myvs.getVariableOrParam( xpathSupport, varQName);
240
                XObject newXObject = new XObject(varObject);
241
242
                if (Class.forName("org.w3c.dom.Document").isInstance(varObject)) {
243
244
                    NodeList nl = ((Document) varObject).getChildNodes();
245
                    // To allow non-welformed document
246
                    Vector nodeVector = new Vector();
247
                    for (int i = 0; i < nl.getLength(); i++) {
248
                        Node currNode = nl.item(i);
249
                        if (currNode.getNodeType() == Node.ELEMENT_NODE) {
250
                            nodeVector.addElement(currNode);
251
                        }
252
                    }
253
                    JSTLNodeList jstlNodeList = new JSTLNodeList(nodeVector);
254
                    newXObject = new XNodeSetForDOM(jstlNodeList, xctxt);
255
256
                    return newXObject;
257
258
                }
259
                if (Class.forName(
260
                        "org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance(
261
                        varObject)) {
262
                    JSTLNodeList jstlNodeList = (JSTLNodeList) varObject;
263
                    if ((jstlNodeList.getLength() == 1) &&
264
                            (!Class.forName("org.w3c.dom.Node").isInstance(jstlNodeList.elementAt(0)))) {
265
                        varObject = jstlNodeList.elementAt(0);
266
                        //Now we need to allow this primitive type to be coverted 
267
                        // to type which Xalan XPath understands 
268
                    } else {
269
                        return new XNodeSetForDOM(jstlNodeList, xctxt);
270
                    }
271
                }
272
                if (Class.forName("org.w3c.dom.Node").isInstance(varObject)) {
273
                    newXObject = new XNodeSetForDOM(new JSTLNodeList((Node) varObject), xctxt);
274
                } else if (Class.forName("java.lang.String").isInstance(varObject)) {
275
                    newXObject = new XString((String) varObject);
276
                } else if (Class.forName("java.lang.Boolean").isInstance(varObject)) {
277
                    newXObject = new XBoolean((Boolean) varObject);
278
                } else if (Class.forName("java.lang.Number").isInstance(varObject)) {
279
                    newXObject = new XNumber((Number) varObject);
280
                }
281
282
                return newXObject;
283
                // myvs.setGlobalVariable( i, newXObject );
284
            } catch (ClassNotFoundException cnfe) {
285
                // This shouldn't happen (TODO: LOG)
286
                System.out.println("CLASS NOT FOUND EXCEPTION :" + cnfe);
287
            }
288
            //System.out.println("*****getVariableOrParam returning *null*" );
289
            return null;
290
        }
291
292
        /**
293
         * Retrieve an XPath's variable value using JSTL's custom
294
         * variable-mapping rules
295
         */
296
        public Object getVariableValue(
297
                String namespace,
298
                String prefix,
299
                String localName)
300
                throws UnresolvableException {
301
            // p("resolving: ns=" + namespace + " prefix=" + prefix + " localName=" + localName);
302
            // We can match on namespace with Xalan but leaving as is
303
            // [ I 'd prefer to match on namespace, but this doesn't appear
304
            // to work in Jaxen]
305
            if (prefix == null || prefix.equals("")) {
306
                return notNull(
307
                        pageContext.findAttribute(localName),
308
                        prefix,
309
                        localName);
310
            } else if (prefix.equals(PAGE_P)) {
311
                return notNull(
312
                        pageContext.getAttribute(localName, PageContext.PAGE_SCOPE),
313
                        prefix,
314
                        localName);
315
            } else if (prefix.equals(REQUEST_P)) {
316
                return notNull(
317
                        pageContext.getAttribute(localName,
318
                                PageContext.REQUEST_SCOPE),
319
                        prefix,
320
                        localName);
321
            } else if (prefix.equals(SESSION_P)) {
322
                return notNull(
323
                        pageContext.getAttribute(localName,
324
                                PageContext.SESSION_SCOPE),
325
                        prefix,
326
                        localName);
327
            } else if (prefix.equals(APP_P)) {
328
                return notNull(
329
                        pageContext.getAttribute(localName,
330
                                PageContext.APPLICATION_SCOPE),
331
                        prefix,
332
                        localName);
333
            } else if (prefix.equals(PARAM_P)) {
334
                return notNull(
335
                        pageContext.getRequest().getParameter(localName),
336
                        prefix,
337
                        localName);
338
            } else if (prefix.equals(INITPARAM_P)) {
339
                return notNull(
340
                        pageContext.getServletContext().
341
                                getInitParameter(localName),
342
                        prefix,
343
                        localName);
344
            } else if (prefix.equals(HEADER_P)) {
345
                HttpServletRequest hsr =
346
                        (HttpServletRequest) pageContext.getRequest();
347
                return notNull(
348
                        hsr.getHeader(localName),
349
                        prefix,
350
                        localName);
351
            } else if (prefix.equals(COOKIE_P)) {
352
                HttpServletRequest hsr =
353
                        (HttpServletRequest) pageContext.getRequest();
354
                Cookie[] c = hsr.getCookies();
355
                for (int i = 0; i < c.length; i++) {
356
                    if (c[i].getName().equals(localName)) {
357
                        return c[i].getValue();
358
                    }
359
                }
360
                throw new UnresolvableException("$" + prefix + ":" + localName);
361
            } else {
362
                throw new UnresolvableException("$" + prefix + ":" + localName);
363
            }
364
        }
365
366
        /**
367
         * Validate that the Object returned is not null. If it is
368
         * null, throw an exception.
369
         */
370
        private Object notNull(Object o, String prefix, String localName)
371
                throws UnresolvableException {
372
            if (o == null) {
373
                throw new UnresolvableException("$" + (prefix == null ? "" : prefix + ":") + localName);
374
            }
375
            //p("resolved to: " + o);
376
            return o;
377
        }
378
    }
379
380
    //*********************************************************************
381
    // Support for XPath evaluation
382
383
    private PageContext pageContext;
384
    private static HashMap exprCache;
385
    private static JSTLPrefixResolver jstlPrefixResolver = null;
386
387
    /**
388
     * Initialize globally useful data.
389
     */
390
    private synchronized static void staticInit() {
391
        if (jstlPrefixResolver == null) {
392
            // register supported namespaces
393
            jstlPrefixResolver = new JSTLPrefixResolver();
394
            jstlPrefixResolver.addNamespace("pageScope", PAGE_NS_URL);
395
            jstlPrefixResolver.addNamespace("requestScope", REQUEST_NS_URL);
396
            jstlPrefixResolver.addNamespace("sessionScope", SESSION_NS_URL);
397
            jstlPrefixResolver.addNamespace("applicationScope", APP_NS_URL);
398
            jstlPrefixResolver.addNamespace("param", PARAM_NS_URL);
399
            jstlPrefixResolver.addNamespace("initParam", INITPARAM_NS_URL);
400
            jstlPrefixResolver.addNamespace("header", HEADER_NS_URL);
401
            jstlPrefixResolver.addNamespace("cookie", COOKIE_NS_URL);
402
403
404
            // create a HashMap to cache the expressions
405
            exprCache = new HashMap();
406
        }
407
    }
408
409
    static DocumentBuilderFactory dbf = null;
410
    static DocumentBuilder db = null;
411
    static Document d = null;
412
413
    static Document getDummyDocument() {
414
        try {
415
            if (dbf == null) {
416
                dbf = DocumentBuilderFactory.newInstance();
417
                dbf.setNamespaceAware(true);
418
                dbf.setValidating(false);
419
            }
420
            db = dbf.newDocumentBuilder();
421
422
            DOMImplementation dim = db.getDOMImplementation();
423
            d = dim.createDocument("http://java.sun.com/jstl", "dummyroot", null);
424
            //d = db.newDocument();
425
            return d;
426
        } catch (Exception e) {
427
            e.printStackTrace();
428
        }
429
        return null;
430
    }
431
432
    static Document getDummyDocumentWithoutRoot() {
433
        try {
434
            if (dbf == null) {
435
                dbf = DocumentBuilderFactory.newInstance();
436
                dbf.setNamespaceAware(true);
437
                dbf.setValidating(false);
438
            }
439
            db = dbf.newDocumentBuilder();
440
441
            d = db.newDocument();
442
            return d;
443
        } catch (Exception e) {
444
            e.printStackTrace();
445
        }
446
        return null;
447
    }
448
449
    private static Document getDocumentForNode(Node node) {
450
        Document doc = getDummyDocumentWithoutRoot();
451
        Node importedNode = doc.importNode(node, true);
452
        doc.appendChild(importedNode);
453
        return doc;
454
    }
455
456
    // The following variable is used for holding the modified xpath string
457
    // when adapting parameter for Xalan XPath engine, where we need to have
458
    // a Non null context node.
459
    String modifiedXPath = null;
460
461
462
    /**
463
     * Evaluate an XPath expression to a String value.
464
     */
465
    public String valueOf(Node n, String xpath) throws JspTagException {
466
        //p("******** valueOf(" + n + ", " + xpath + ")");
467
        staticInit();
468
        // @@@ but where do we set the Pag4eContext for the varaiblecontext?
469
        JstlVariableContext vs = new JstlVariableContext();
470
        XPathContext xpathSupport = new XPathContext();
471
        xpathSupport.setVarStack(vs);
472
473
        Vector varVector = fillVarStack(vs, xpathSupport);
474
475
        Node contextNode = adaptParamsForXalan(vs, n, xpath.trim());
476
477
        xpath = modifiedXPath;
478
479
        //p("******** valueOf: modified xpath: " + xpath);
480
481
        XObject result = JSTLXPathAPI.eval(contextNode, xpath,
482
                jstlPrefixResolver, xpathSupport, varVector);
483
484
485
        //p("******Result TYPE => " + result.getTypeString() );
486
487
        String resultString = result.str();
488
        //p("******** valueOf: after eval: " + resultString);
489
490
        return resultString;
491
492
    }
493
494
    /**
495
     * Evaluate an XPath expression to a boolean value.
496
     */
497
    public boolean booleanValueOf(Node n, String xpath)
498
            throws JspTagException {
499
500
        staticInit();
501
        JstlVariableContext vs = new JstlVariableContext();
502
        XPathContext xpathSupport = new XPathContext();
503
        xpathSupport.setVarStack(vs);
504
505
        Vector varVector = fillVarStack(vs, xpathSupport);
506
507
        Node contextNode = adaptParamsForXalan(vs, n, xpath.trim());
508
        xpath = modifiedXPath;
509
510
        XObject result = JSTLXPathAPI.eval(contextNode, xpath,
511
                jstlPrefixResolver, xpathSupport, varVector);
512
513
        try {
514
            return result.bool();
515
        } catch (TransformerException ex) {
516
            throw new JspTagException(
517
                    Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);
518
        }
519
    }
520
521
    /**
522
     * Evaluate an XPath expression to a List of nodes.
523
     */
524
    public List selectNodes(Node n, String xpath) throws JspTagException {
525
526
        staticInit();
527
        JstlVariableContext vs = new JstlVariableContext();
528
        XPathContext xpathSupport = new XPathContext();
529
        xpathSupport.setVarStack(vs);
530
531
        Vector varVector = fillVarStack(vs, xpathSupport);
532
533
        Node contextNode = adaptParamsForXalan(vs, n, xpath.trim());
534
        xpath = modifiedXPath;
535
536
        XObject result = JSTLXPathAPI.eval(contextNode, xpath,
537
                jstlPrefixResolver, xpathSupport, varVector);
538
        try {
539
            NodeList nl = JSTLXPathAPI.getNodeList(result);
540
            return new JSTLNodeList(nl);
541
        } catch (JspTagException e) {
542
            try {
543
                //If result can't be converted to NodeList we receive exception
544
                // In this case we may have single primitive value as the result
545
                // Populating List with this value ( String, Boolean or Number )
546
547
                //System.out.println("JSTLXPathAPI.getNodeList thrown exception:"+ e);
548
                Vector vector = new Vector();
549
                Object resultObject = null;
550
                if (result.getType() == XObject.CLASS_BOOLEAN) {
551
                    resultObject = result.bool();
552
                } else if (result.getType() == XObject.CLASS_NUMBER) {
553
                    resultObject = result.num();
554
                } else if (result.getType() == XObject.CLASS_STRING) {
555
                    resultObject = result.str();
556
                }
557
558
                vector.add(resultObject);
559
                return new JSTLNodeList(vector);
560
            } catch (TransformerException te) {
561
                throw new JspTagException(te.toString(), te);
562
            }
563
        }
564
565
566
    }
567
568
    /**
569
     * Evaluate an XPath expression to a single node.
570
     */
571
    public Node selectSingleNode(Node n, String xpath)
572
            throws JspTagException {
573
        //p("selectSingleNode of XPathUtil = passed node:" +
574
        //   "xpath => " + n + " : " + xpath );
575
576
        staticInit();
577
        JstlVariableContext vs = new JstlVariableContext();
578
        XPathContext xpathSupport = new XPathContext();
579
        xpathSupport.setVarStack(vs);
580
581
        Vector varVector = fillVarStack(vs, xpathSupport);
582
583
        Node contextNode = adaptParamsForXalan(vs, n, xpath.trim());
584
        xpath = modifiedXPath;
585
586
        return (Node) JSTLXPathAPI.selectSingleNode(contextNode, xpath,
587
                jstlPrefixResolver, xpathSupport);
588
    }
589
590
    /**
591
     * Returns a locally appropriate context given a node.
592
     */
593
    private VariableStack getLocalContext() {
594
        // set up instance-specific contexts
595
        VariableStack vc = new JstlVariableContext();
596
        return vc;
597
    }
598
599
    //*********************************************************************
600
    // Adapt XPath expression for integration with Xalan
601
602
    /**
603
     * To evaluate an XPath expression using Xalan, we need
604
     * to create an XPath object, which wraps an expression object and provides
605
     * general services for execution of that expression.
606
     * <p>An XPath object can be instantiated with the following information:
607
     * - XPath expression to evaluate
608
     * - SourceLocator
609
     * (reports where an error occurred in the XML source or
610
     * transformation instructions)
611
     * - PrefixResolver
612
     * (resolve prefixes to namespace URIs)
613
     * - type
614
     * (one of SELECT or MATCH)
615
     * - ErrorListener
616
     * (customized error handling)
617
     * <p>Execution of the XPath expression represented by an XPath object
618
     * is done via method execute which takes the following parameters:
619
     * - XPathContext
620
     * The execution context
621
     * - Node contextNode
622
     * The node that "." expresses
623
     * - PrefixResolver namespaceContext
624
     * The context in which namespaces in the XPath are supposed to be
625
     * expanded.
626
     * <p>Given all of this, if no context node is set for the evaluation
627
     * of the XPath expression, one must be set so Xalan
628
     * can successfully evaluate a JSTL XPath expression.
629
     * (it will not work if the context node is given as a varialbe
630
     * at the beginning of the expression)
631
     *
632
     * @@@ Provide more details...
633
     */
634
    protected Node adaptParamsForXalan(JstlVariableContext jvc, Node n,
635
                                       String xpath) {
636
        Node boundDocument = null;
637
638
        modifiedXPath = xpath;
639
        String origXPath = xpath;
640
        boolean whetherOrigXPath = true;
641
642
        // If contextNode is not null then  just pass the values to Xalan XPath
643
        // unless this is an expression that starts off with an xml document 
644
        if (n != null && !xpath.startsWith("$")) {
645
            return n;
646
        }
647
648
        if (xpath.startsWith("$")) {
649
            // JSTL uses $scopePrefix:varLocalName/xpath expression
650
651
            String varQName = xpath.substring(xpath.indexOf("$") + 1);
652
            if (varQName.indexOf("/") > 0) {
653
                varQName = varQName.substring(0, varQName.indexOf("/"));
654
            }
655
            String varPrefix = null;
656
            String varLocalName = varQName;
657
            if (varQName.indexOf(":") >= 0) {
658
                varPrefix = varQName.substring(0, varQName.indexOf(":"));
659
                varLocalName = varQName.substring(varQName.indexOf(":") + 1);
660
            }
661
662
            if (xpath.indexOf("/") > 0) {
663
                xpath = xpath.substring(xpath.indexOf("/"));
664
            } else {
665
                xpath = "/*";
666
                whetherOrigXPath = false;
667
            }
668
669
670
            try {
671
                Object varObject = jvc.getVariableValue(null, varPrefix,
672
                        varLocalName);
673
                //System.out.println( "varObject => : its Class " +varObject +
674
                // ":" + varObject.getClass() );
675
676
                if (Class.forName("org.w3c.dom.Document").isInstance(
677
                        varObject)) {
678
                    //boundDocument = ((Document)varObject).getDocumentElement();
679
                    boundDocument = ((Document) varObject);
680
                } else {
681
682
                    //System.out.println("Creating a Dummy document to pass " +
683
                    // " onto as context node " );
684
685
                    if (Class.forName("org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance(varObject)) {
686
                        Document newDocument = getDummyDocument();
687
688
                        JSTLNodeList jstlNodeList = (JSTLNodeList) varObject;
689
                        if (jstlNodeList.getLength() == 1) {
690
                            if (Class.forName("org.w3c.dom.Node").isInstance(
691
                                    jstlNodeList.elementAt(0))) {
692
                                Node node = (Node) jstlNodeList.elementAt(0);
693
                                boundDocument = getDocumentForNode(node);
694
                                if (whetherOrigXPath) {
695
                                    xpath = "/*" + xpath;
696
                                }
697
698
                            } else {
699
700
                                //Nodelist with primitive type
701
                                Object myObject = jstlNodeList.elementAt(0);
702
703
                                //p("Single Element of primitive type");
704
                                //p("Type => " + myObject.getClass());
705
706
                                xpath = myObject.toString();
707
708
                                //p("String value ( xpathwould be this) => " + xpath);
709
                                boundDocument = newDocument;
710
                            }
711
712
                        } else {
713
714
                            Element dummyroot = newDocument.getDocumentElement();
715
                            for (int i = 0; i < jstlNodeList.getLength(); i++) {
716
                                Node currNode = (Node) jstlNodeList.item(i);
717
718
                                Node importedNode = newDocument.importNode(
719
                                        currNode, true);
720
721
                                //printDetails ( newDocument);
722
723
                                dummyroot.appendChild(importedNode);
724
725
                                //p( "Details of the document After importing");
726
                                //printDetails ( newDocument);
727
                            }
728
                            boundDocument = newDocument;
729
                            // printDetails ( boundDocument );
730
                            //Verify :As we are adding Document element we need
731
                            // to change the xpath expression.Hopefully this
732
                            // won't  change the result
733
734
                            xpath = "/*" + xpath;
735
                        }
736
                    } else if (Class.forName("org.w3c.dom.Node").isInstance(
737
                            varObject)) {
738
                        boundDocument = getDocumentForNode((Node) varObject);
739
                        if (whetherOrigXPath) {
740
                            xpath = "/*" + xpath;
741
                        }
742
                    } else {
743
                        boundDocument = getDummyDocument();
744
                        xpath = origXPath;
745
                    }
746
747
748
                }
749
            } catch (UnresolvableException ue) {
750
                // TODO: LOG
751
                System.out.println("Variable Unresolvable :" + ue.getMessage());
752
                ue.printStackTrace();
753
            } catch (ClassNotFoundException cnf) {
754
                // Will never happen
755
            }
756
        } else {
757
            //System.out.println("Not encountered $ Creating a Dummydocument 2 "+
758
            //   "pass onto as context node " );
759
            boundDocument = getDummyDocument();
760
        }
761
762
        modifiedXPath = xpath;
763
        //System.out.println("Modified XPath::boundDocument =>" + modifiedXPath +
764
        //    "::" + boundDocument );
765
766
        return boundDocument;
767
    }
768
769
770
    //*********************************************************************
771
    // 
772
773
    /**
774
     * * @@@ why do we have to pass varVector in the varStack first, and then
775
     * to XPath object?
776
     */
777
    private Vector fillVarStack(JstlVariableContext vs, XPathContext xpathSupport)
778
            throws JspTagException {
779
        org.apache.xpath.VariableStack myvs = xpathSupport.getVarStack();
780
        Vector varVector = getVariableQNames();
781
        for (int i = 0; i < varVector.size(); i++) {
782
783
            QName varQName = (QName) varVector.elementAt(i);
784
785
            try {
786
                XObject variableValue = vs.getVariableOrParam(xpathSupport, varQName);
787
                //p("&&&&Variable set to => " + variableValue.toString() );
788
                //p("&&&&Variable type => " + variableValue.getTypeString() );
789
                myvs.setGlobalVariable(i, variableValue);
790
791
            } catch (TransformerException te) {
792
                throw new JspTagException(te.toString(), te);
793
            }
794
795
        }
796
        return varVector;
797
    }
798
799
800
    //*********************************************************************
801
    // Static support for context retrieval from parent <forEach> tag
802
803
    public static Node getContext(Tag t) throws JspTagException {
804
        ForEachTag xt =
805
                (ForEachTag) TagSupport.findAncestorWithClass(
806
                        t, ForEachTag.class);
807
        if (xt == null) {
808
            return null;
809
        } else {
810
            return (xt.getContext());
811
        }
812
    }
813
814
    //*********************************************************************
815
    // Utility methods
816
817
    private static void p(String s) {
818
        System.out.println("[XPathUtil] " + s);
819
    }
820
821
    public static void printDetails(Node n) {
822
        System.out.println("\n\nDetails of Node = > " + n);
823
        System.out.println("Name:Type:Node Value = > " + n.getNodeName() +
824
                ":" + n.getNodeType() + ":" + n.getNodeValue());
825
        System.out.println("Namespace URI : Prefix : localName = > " +
826
                n.getNamespaceURI() + ":" + n.getPrefix() + ":" + n.getLocalName());
827
        System.out.println("\n Node has children => " + n.hasChildNodes());
828
        if (n.hasChildNodes()) {
829
            NodeList nl = n.getChildNodes();
830
            System.out.println("Number of Children => " + nl.getLength());
831
            for (int i = 0; i < nl.getLength(); i++) {
832
                Node childNode = nl.item(i);
833
                printDetails(childNode);
834
            }
835
        }
836
    }
837
}
838
839
class JSTLNodeList extends Vector implements NodeList {
840
841
    Vector nodeVector;
842
843
    public JSTLNodeList(Vector nodeVector) {
844
        this.nodeVector = nodeVector;
845
    }
846
847
    public JSTLNodeList(NodeList nl) {
848
        nodeVector = new Vector();
849
        //System.out.println("[JSTLNodeList] nodelist details");
850
        for (int i = 0; i < nl.getLength(); i++) {
851
            Node currNode = nl.item(i);
852
            //XPathUtil.printDetails ( currNode );
853
            nodeVector.add(i, nl.item(i));
854
        }
855
    }
856
857
    public JSTLNodeList(Node n) {
858
        nodeVector = new Vector();
859
        nodeVector.addElement(n);
860
    }
861
862
863
    public Node item(int index) {
864
        return (Node) nodeVector.elementAt(index);
865
    }
866
867
    @Override
868
    public Object elementAt(int index) {
869
        return nodeVector.elementAt(index);
870
    }
871
872
    @Override
873
    public Object get(int index) {
874
        return nodeVector.get(index);
875
    }
876
877
    public int getLength() {
878
        return nodeVector.size();
879
    }
880
881
    @Override
882
    public int size() {
883
        //System.out.println("JSTL node list size => " + nodeVector.size() );
884
        return nodeVector.size();
885
    }
886
887
    // Can implement other Vector methods to redirect those methods to 
888
    // the vector in the variable param. As we are not using them as part 
889
    // of this implementation we are not doing that here. If this changes
890
    // then we need to override those methods accordingly  
891
892
}
893
         
894
895
896
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java (-51 / +40 lines)
Lines 17-28 Link Here
17
17
18
package org.apache.taglibs.standard.tag.common.xml;
18
package org.apache.taglibs.standard.tag.common.xml;
19
19
20
import java.util.List;
21
22
import javax.servlet.jsp.JspTagException;
20
import javax.servlet.jsp.JspTagException;
23
import javax.servlet.jsp.jstl.core.LoopTagSupport;
21
import javax.servlet.jsp.jstl.core.LoopTagSupport;
22
import javax.xml.transform.TransformerException;
24
23
25
import org.apache.taglibs.standard.resources.Resources;
24
import org.apache.xml.dtm.DTMIterator;
25
import org.apache.xpath.XPath;
26
import org.apache.xpath.XPathContext;
27
import org.apache.xpath.objects.XObject;
26
28
27
/**
29
/**
28
 * <p>Support for the XML library's &lt;forEach&gt; tag.</p>
30
 * <p>Support for the XML library's &lt;forEach&gt; tag.</p>
Lines 32-91 Link Here
32
 */
34
 */
33
public class ForEachTag extends LoopTagSupport {
35
public class ForEachTag extends LoopTagSupport {
34
36
35
    //*********************************************************************
37
    private XPath select;
36
    // Private state
38
    private XPathContext context;
39
    private DTMIterator iterator;
37
40
38
    private String select;                // tag attribute
41
    @Override
39
    private List nodes;                    // XPath result
42
    public void release() {
40
    private int nodesIndex;                // current index
43
        super.release();
41
    private org.w3c.dom.Node current;            // current node
44
        select = null;
45
        context = null;
46
    }
42
47
43
    //*********************************************************************
44
    // Iteration control methods
45
46
    // (We inherit semantics and Javadoc from LoopTagSupport.) 
47
48
    @Override
48
    @Override
49
    protected void prepare() throws JspTagException {
49
    protected void prepare() throws JspTagException {
50
        nodesIndex = 0;
50
        context = XalanUtil.getContext(this, pageContext);
51
        XPathUtil xu = new XPathUtil(pageContext);
51
        try {
52
        nodes = xu.selectNodes(XPathUtil.getContext(this), select);
52
            XObject nodes = select.execute(context, context.getCurrentNode(), null);
53
            iterator = nodes.iter();
54
            context.pushContextNodeList(iterator);
55
        } catch (TransformerException e) {
56
            throw new JspTagException(e);
57
        }
53
    }
58
    }
54
59
55
    @Override
60
    @Override
56
    protected boolean hasNext() throws JspTagException {
61
    protected boolean hasNext() throws JspTagException {
57
        return (nodesIndex < nodes.size());
62
        return iterator.getCurrentPos() < iterator.getLength();
58
    }
63
    }
59
64
60
    @Override
65
    @Override
61
    protected Object next() throws JspTagException {
66
    protected Object next() throws JspTagException {
62
        Object o = nodes.get(nodesIndex++);
67
        int next = iterator.nextNode();
63
        if (!(o instanceof org.w3c.dom.Node)) {
68
        return iterator.getDTM(next).getNode(next);
64
            throw new JspTagException(
65
                    Resources.getMessage("FOREACH_NOT_NODESET"));
66
        }
67
        current = (org.w3c.dom.Node) o;
68
        return current;
69
    }
69
    }
70
70
71
72
    //*********************************************************************
73
    // Tag logic and lifecycle management
74
75
    // Releases any resources we may have (or inherit)
76
77
    @Override
71
    @Override
78
    public void release() {
72
    public void doFinally() {
79
        init();
73
        if (iterator != null) {
80
        super.release();
74
            context.popContextNodeList();
75
            iterator = null;
76
        }
77
        context = null;
78
        super.doFinally();
81
    }
79
    }
82
80
83
81
//*********************************************************************
84
    //*********************************************************************
85
    // Attribute accessors
82
    // Attribute accessors
86
83
87
    public void setSelect(String select) {
84
    public void setSelect(String select) {
88
        this.select = select;
85
        try {
86
            this.select = new XPath(select, null, null, XPath.SELECT);
87
        } catch (TransformerException e) {
88
            throw new AssertionError();
89
        }
89
    }
90
    }
90
91
91
    public void setBegin(int begin) throws JspTagException {
92
    public void setBegin(int begin) throws JspTagException {
Lines 111-130 Link Here
111
112
112
    /* Retrieves the current context. */
113
    /* Retrieves the current context. */
113
114
114
    public org.w3c.dom.Node getContext() throws JspTagException {
115
    XPathContext getContext() {
115
        // expose the current node as the context
116
        return context;
116
        return current;
117
    }
117
    }
118
119
120
    //*********************************************************************
121
    // Private utility methods
122
123
    private void init() {
124
        select = null;
125
        nodes = null;
126
        nodesIndex = 0;
127
        current = null;
128
    }
129
}
118
}
130
119
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java (-51 / +24 lines)
Lines 17-29 Link Here
17
17
18
package org.apache.taglibs.standard.tag.common.xml;
18
package org.apache.taglibs.standard.tag.common.xml;
19
19
20
import java.util.List;
21
22
import javax.servlet.jsp.JspException;
20
import javax.servlet.jsp.JspException;
21
import javax.servlet.jsp.JspTagException;
23
import javax.servlet.jsp.PageContext;
22
import javax.servlet.jsp.PageContext;
24
import javax.servlet.jsp.tagext.TagSupport;
23
import javax.servlet.jsp.tagext.TagSupport;
24
import javax.xml.transform.TransformerException;
25
25
26
import org.apache.taglibs.standard.tag.common.core.Util;
26
import org.apache.taglibs.standard.tag.common.core.Util;
27
import org.apache.xpath.XPath;
28
import org.apache.xpath.XPathContext;
29
import org.apache.xpath.objects.XObject;
27
30
28
/**
31
/**
29
 * <p>Tag handler for &lt;set&gt; in JSTL's XML library.</p>
32
 * <p>Tag handler for &lt;set&gt; in JSTL's XML library.</p>
Lines 32-66 Link Here
32
 */
35
 */
33
public class SetTag extends TagSupport {
36
public class SetTag extends TagSupport {
34
37
35
    //*********************************************************************
38
    private XPath select;
36
    // Internal state
39
    private String var;
40
    private int scope = PageContext.PAGE_SCOPE;
37
41
38
    private String select;                    // tag attribute
39
    private String var;                       // tag attribute
40
    private int scope;                  // processed tag attribute
41
42
    //*********************************************************************
42
    //*********************************************************************
43
    // Construction and initialization
43
    // Construction and initialization
44
44
45
    /**
45
    @Override
46
     * Constructs a new handler.  As with TagSupport, subclasses should
46
    public void release() {
47
     * not provide other constructors and are expected to call the
47
        super.release();
48
     * superclass constructor.
49
     */
50
    public SetTag() {
51
        super();
52
        init();
53
    }
54
55
    // resets local state
56
57
    private void init() {
58
        var = null;
59
        select = null;
48
        select = null;
60
        scope = PageContext.PAGE_SCOPE;
49
        var = null;
61
    }
50
    }
62
51
63
64
    //*********************************************************************
52
    //*********************************************************************
65
    // Tag logic
53
    // Tag logic
66
54
Lines 68-107 Link Here
68
56
69
    @Override
57
    @Override
70
    public int doStartTag() throws JspException {
58
    public int doStartTag() throws JspException {
71
        // process the query
59
        try {
72
        XPathUtil xu = new XPathUtil(pageContext);
60
            XPathContext context = XalanUtil.getContext(this, pageContext);
73
        List result =
61
            XObject result = select.execute(context, context.getCurrentNode(), null);
74
                xu.selectNodes(XPathUtil.getContext(this), select);
62
            pageContext.setAttribute(var, XalanUtil.coerceToJava(result), scope);
75
        Object ret = result;
63
            return SKIP_BODY;
76
64
        } catch (TransformerException e) {
77
        // unwrap primitive types if that's what we received
65
            throw new JspTagException(e);
78
        if (result.size() == 1) {
79
            Object o = result.get(0);
80
            if (o instanceof String || o instanceof Boolean
81
                    || o instanceof Number) {
82
                ret = o;
83
            }
84
        }
66
        }
85
86
        // expose the final result
87
        pageContext.setAttribute(var, ret, scope);
88
        return SKIP_BODY;
89
    }
67
    }
90
68
91
    // Releases any resources we may have (or inherit)
92
93
    @Override
94
    public void release() {
95
        super.release();
96
        init();
97
    }
98
99
100
    //*********************************************************************
69
    //*********************************************************************
101
    // Attribute accessors
70
    // Attribute accessors
102
71
103
    public void setSelect(String select) {
72
    public void setSelect(String select) {
104
        this.select = select;
73
        try {
74
            this.select = new XPath(select, null, null, XPath.SELECT);
75
        } catch (TransformerException e) {
76
            throw new AssertionError();
77
        }
105
    }
78
    }
106
79
107
    public void setVar(String var) {
80
    public void setVar(String var) {
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java (+125 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package org.apache.taglibs.standard.tag.common.xml;
18
19
import java.util.HashMap;
20
import java.util.Map;
21
22
import javax.servlet.http.Cookie;
23
import javax.servlet.http.HttpServletRequest;
24
import javax.servlet.jsp.PageContext;
25
import javax.xml.transform.TransformerException;
26
27
import org.apache.xml.utils.QName;
28
import org.apache.xpath.VariableStack;
29
import org.apache.xpath.XPathContext;
30
import org.apache.xpath.objects.XObject;
31
import org.apache.xpath.objects.XObjectFactory;
32
33
/**
34
 */
35
public class JSTLVariableStack extends VariableStack {
36
37
    private static enum Scope {
38
        PARAM,
39
        HEADER,
40
        COOKIE,
41
        INITPARAM,
42
        PAGE,
43
        REQUEST,
44
        SESSION,
45
        APPLICATION
46
    }
47
48
    // Prefixes for JSTL implicit variables
49
    private static final String PARAM_PREFIX = "param";
50
    private static final String HEADER_PREFIX = "header";
51
    private static final String COOKIE_PREFIX = "cookie";
52
    private static final String INITPARAM_PREFIX = "initParam";
53
    private static final String PAGE_PREFIX = "pageScope";
54
    private static final String REQUEST_PREFIX = "requestScope";
55
    private static final String SESSION_PREFIX = "sessionScope";
56
    private static final String APP_PREFIX = "applicationScope";
57
58
    // map prefixes to scopes
59
    private static final Map<String, Scope> SCOPES;
60
61
    static {
62
        SCOPES = new HashMap<String, Scope>(8);
63
        SCOPES.put(PARAM_PREFIX, Scope.PARAM);
64
        SCOPES.put(HEADER_PREFIX, Scope.HEADER);
65
        SCOPES.put(COOKIE_PREFIX, Scope.COOKIE);
66
        SCOPES.put(INITPARAM_PREFIX, Scope.INITPARAM);
67
        SCOPES.put(PAGE_PREFIX, Scope.PAGE);
68
        SCOPES.put(REQUEST_PREFIX, Scope.REQUEST);
69
        SCOPES.put(SESSION_PREFIX, Scope.SESSION);
70
        SCOPES.put(APP_PREFIX, Scope.APPLICATION);
71
    }
72
73
    private final PageContext pageContext;
74
75
    public JSTLVariableStack(PageContext pageContext) {
76
        super(2);
77
        this.pageContext = pageContext;
78
    }
79
80
    @Override
81
    public XObject getVariableOrParam(XPathContext xctxt, QName qname) throws TransformerException {
82
        String prefix = qname.getNamespaceURI();
83
        String name = qname.getLocalPart();
84
        Object value = getValue(prefix, name);
85
        if (value == null) {
86
            throw new TransformerException("Variable " + qname + " not found");
87
        }
88
        return XObjectFactory.create(value, xctxt);
89
    }
90
91
    private Object getValue(String prefix, String name) {
92
        if (prefix == null) {
93
            return pageContext.findAttribute(name);
94
        }
95
        Scope scope = SCOPES.get(prefix);
96
        switch (scope) {
97
            case PARAM:
98
                return pageContext.getRequest().getParameter(name);
99
            case HEADER:
100
                return ((HttpServletRequest) pageContext.getRequest()).getHeader(name);
101
            case COOKIE:
102
                Cookie[] cookies = ((HttpServletRequest) pageContext.getRequest()).getCookies();
103
                if (cookies != null) {
104
                    for (Cookie cookie : cookies) {
105
                        if (cookie.getName().equals(name)) {
106
                            return cookie.getValue();
107
                        }
108
                    }
109
                }
110
                return null;
111
            case INITPARAM:
112
                return pageContext.getServletContext().getInitParameter(name);
113
            case PAGE:
114
                return pageContext.getAttribute(name, PageContext.PAGE_SCOPE);
115
            case REQUEST:
116
                return pageContext.getAttribute(name, PageContext.REQUEST_SCOPE);
117
            case SESSION:
118
                return pageContext.getAttribute(name, PageContext.SESSION_SCOPE);
119
            case APPLICATION:
120
                return pageContext.getAttribute(name, PageContext.APPLICATION_SCOPE);
121
            default:
122
                throw new AssertionError();
123
        }
124
    }
125
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java (-38 / +17 lines)
Lines 19-25 Link Here
19
19
20
import javax.servlet.jsp.JspTagException;
20
import javax.servlet.jsp.JspTagException;
21
import javax.servlet.jsp.jstl.core.ConditionalTagSupport;
21
import javax.servlet.jsp.jstl.core.ConditionalTagSupport;
22
import javax.xml.transform.TransformerException;
22
23
24
import org.apache.xpath.XPath;
25
import org.apache.xpath.XPathContext;
26
23
/**
27
/**
24
 * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
28
 * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
25
 *
29
 *
Lines 28-82 Link Here
28
32
29
public class IfTag extends ConditionalTagSupport {
33
public class IfTag extends ConditionalTagSupport {
30
34
31
    //*********************************************************************
35
    private XPath select;
32
    // Constructor and lifecycle management
33
36
34
    // initialize inherited and local state
35
37
36
    public IfTag() {
37
        super();
38
        init();
39
    }
40
41
    // Releases any resources we may have (or inherit)
42
43
    @Override
38
    @Override
44
    public void release() {
39
    public void release() {
45
        super.release();
40
        super.release();
46
        init();
41
        select = null;
47
    }
42
    }
48
43
49
50
    //*********************************************************************
51
    // Supplied conditional logic
52
53
    @Override
44
    @Override
54
    protected boolean condition() throws JspTagException {
45
    protected boolean condition() throws JspTagException {
55
        XPathUtil xu = new XPathUtil(pageContext);
46
        XPathContext context = XalanUtil.getContext(this, pageContext);
56
        return (xu.booleanValueOf(XPathUtil.getContext(this), select));
47
        try {
48
            return select.bool(context, context.getCurrentNode(), null);
49
        } catch (TransformerException e) {
50
            throw new JspTagException(e);
51
        }
57
    }
52
    }
58
53
59
60
    //*********************************************************************
61
    // Private state
62
63
    private String select;               // the value of the 'test' attribute
64
65
66
    //*********************************************************************
67
    // Attribute accessors
68
69
    public void setSelect(String select) {
54
    public void setSelect(String select) {
70
        this.select = select;
55
        try {
56
            this.select = new XPath(select, null, null, XPath.SELECT);
57
        } catch (TransformerException e) {
58
            throw new AssertionError();
59
        }
71
    }
60
    }
72
73
74
    //*********************************************************************
75
    // Private utility methods
76
77
    // resets internal state
78
79
    private void init() {
80
        select = null;
81
    }
82
}
61
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java (-44 / +24 lines)
Lines 5-13 Link Here
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
7
 * the License.  You may obtain a copy of the License at
8
 * 
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Lines 17-93 Link Here
17
17
18
package org.apache.taglibs.standard.tag.common.xml;
18
package org.apache.taglibs.standard.tag.common.xml;
19
19
20
import java.io.IOException;
21
20
import javax.servlet.jsp.JspException;
22
import javax.servlet.jsp.JspException;
21
import javax.servlet.jsp.JspTagException;
23
import javax.servlet.jsp.JspTagException;
22
import javax.servlet.jsp.tagext.TagSupport;
24
import javax.servlet.jsp.tagext.TagSupport;
25
import javax.xml.transform.TransformerException;
23
26
24
import org.apache.taglibs.standard.util.EscapeXML;
27
import org.apache.taglibs.standard.util.EscapeXML;
28
import org.apache.xpath.XPath;
29
import org.apache.xpath.XPathContext;
25
30
26
/**
31
/**
27
 * <p>Tag handler for &lt;out&gt; in JSTL's XML library.</p>
32
 * Tag handler for &lt;out&gt; in JSTL's XML library.
28
 * <p>TODO: should we rename this to OutSupport to match the tag name?
33
 * TODO: should we rename this to OutSupport to match the tag name?
29
 *
34
 *
30
 * @author Shawn Bayern
35
 * @author Shawn Bayern
31
 */
36
 */
32
public abstract class ExprSupport extends TagSupport {
37
public abstract class ExprSupport extends TagSupport {
33
38
34
    //*********************************************************************
39
    private XPath select;
35
    // Internal state
40
    protected boolean escapeXml = true;  // tag attribute
36
41
37
    private String select;                       // tag attribute
42
    @Override
38
    protected boolean escapeXml;         // tag attribute
43
    public void release() {
39
44
        super.release();
40
    //*********************************************************************
41
    // Construction and initialization
42
43
    /**
44
     * Constructs a new handler.  As with TagSupport, subclasses should
45
     * not provide other constructors and are expected to call the
46
     * superclass constructor.
47
     */
48
    public ExprSupport() {
49
        super();
50
        init();
51
    }
52
53
    // resets local state
54
55
    private void init() {
56
        select = null;
45
        select = null;
57
        escapeXml = true;
58
    }
46
    }
59
47
60
61
    //*********************************************************************
48
    //*********************************************************************
62
    // Tag logic
49
    // Tag logic
63
50
64
    // applies XPath expression from 'select' and prints the result
51
    // applies XPath expression from 'select' and prints the result
65
66
    @Override
52
    @Override
67
    public int doStartTag() throws JspException {
53
    public int doStartTag() throws JspException {
68
        try {
54
        try {
69
            XPathUtil xu = new XPathUtil(pageContext);
55
            XPathContext context = XalanUtil.getContext(this, pageContext);
70
            String result = xu.valueOf(XPathUtil.getContext(this), select);
56
            String result = select.execute(context, context.getCurrentNode(), null).str();
71
            EscapeXML.emit(result, escapeXml, pageContext.getOut());
57
            EscapeXML.emit(result, escapeXml, pageContext.getOut());
72
            return SKIP_BODY;
58
            return SKIP_BODY;
73
        } catch (java.io.IOException ex) {
59
        } catch (IOException ex) {
74
            throw new JspTagException(ex.toString(), ex);
60
            throw new JspTagException(ex.toString(), ex);
61
        } catch (TransformerException e) {
62
            throw new JspTagException(e);
75
        }
63
        }
76
    }
64
    }
77
65
78
    // Releases any resources we may have (or inherit)
79
80
    @Override
81
    public void release() {
82
        super.release();
83
        init();
84
    }
85
86
87
    //*********************************************************************
88
    // Attribute accessors
89
90
    public void setSelect(String select) {
66
    public void setSelect(String select) {
91
        this.select = select;
67
        try {
68
            this.select = new XPath(select, null, null, XPath.SELECT);
69
        } catch (TransformerException e) {
70
            throw new AssertionError();
71
        }
92
    }
72
    }
93
}
73
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLXPathAPI.java (-296 lines)
Lines 1-296 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
package org.apache.taglibs.standard.tag.common.xml;
19
20
import java.util.Vector;
21
22
import javax.servlet.jsp.JspTagException;
23
import javax.xml.transform.TransformerException;
24
25
import org.apache.taglibs.standard.resources.Resources;
26
import org.apache.xml.utils.PrefixResolver;
27
import org.apache.xpath.XPath;
28
import org.apache.xpath.XPathAPI;
29
import org.apache.xpath.XPathContext;
30
import org.apache.xpath.objects.XObject;
31
import org.w3c.dom.Node;
32
import org.w3c.dom.NodeList;
33
import org.w3c.dom.traversal.NodeIterator;
34
35
/**
36
 * The methods in this class are convenience methods into the
37
 * low-level XPath API.
38
 * These functions tend to be a little slow, since a number of objects must be
39
 * created for each evaluation.  A faster way is to precompile the
40
 * XPaths using the low-level API, and then just use the XPaths
41
 * over and over.
42
 * <p>NOTE: In particular, each call to this method will create a new
43
 * XPathContext, a new DTMManager... and thus a new DTM. That's very
44
 * safe, since it guarantees that you're always processing against a
45
 * fully up-to-date view of your document. But it's also portentially
46
 * very expensive, since you're rebuilding the DTM every time. You should
47
 * consider using an instance of CachedXPathAPI rather than these static
48
 * methods.
49
 *
50
 * @see <a href="http://www.w3.org/TR/xpath">XPath Specification</a>
51
 */
52
public class JSTLXPathAPI extends XPathAPI {
53
    /**
54
     * Use an XPath string to select a single node.
55
     * XPath namespace prefixes are resolved using the prefixResolver.
56
     *
57
     * @param contextNode    The node to start searching from.
58
     * @param str            A valid XPath string.
59
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
60
     * @return The first node found that matches the XPath, or null.
61
     * @throws JspTagException
62
     */
63
    public static Node selectSingleNode(
64
            Node contextNode, String str, PrefixResolver prefixResolver)
65
            throws JspTagException {
66
67
        // Have the XObject return its result as a NodeSetDTM.
68
        NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver);
69
70
        // Return the first node, or null
71
        return nl.nextNode();
72
    }
73
74
    /**
75
     * Use an XPath string to select a single node.
76
     * XPath namespace prefixes are resolved using the prefixResolver.
77
     *
78
     * @param contextNode    The node to start searching from.
79
     * @param str            A valid XPath string.
80
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
81
     * @return The first node found that matches the XPath, or null.
82
     * @throws JspTagException
83
     */
84
    public static Node selectSingleNode(
85
            Node contextNode, String str, PrefixResolver prefixResolver,
86
            XPathContext xpathSupport) throws JspTagException {
87
88
        // Have the XObject return its result as a NodeSetDTM.
89
        NodeIterator nl = selectNodeIterator(contextNode, str, prefixResolver, xpathSupport);
90
91
        // Return the first node, or null
92
        return nl.nextNode();
93
    }
94
95
    /**
96
     * Use an XPath string to select a nodelist.
97
     * XPath namespace prefixes are resolved using PrefixResolver.
98
     *
99
     * @param contextNode    The node to start searching from.
100
     * @param str            A valid XPath string.
101
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
102
     * @return A NodeIterator, should never be null.
103
     * @throws JspTagException
104
     */
105
    public static NodeIterator selectNodeIterator(
106
            Node contextNode, String str, PrefixResolver prefixResolver)
107
            throws JspTagException {
108
109
        // Execute the XPath, and have it return the result
110
        XObject list = eval(contextNode, str, prefixResolver, null);
111
112
        // Have the XObject return its result as a NodeSetDTM.
113
        return getNodeIterator(list);
114
    }
115
116
    /**
117
     * Use an XPath string to select a nodelist.
118
     * XPath namespace prefixes are resolved using PrefixResolver.
119
     *
120
     * @param contextNode    The node to start searching from.
121
     * @param str            A valid XPath string.
122
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
123
     * @return A NodeIterator, should never be null.
124
     * @throws JspTagException
125
     */
126
    public static NodeIterator selectNodeIterator(
127
            Node contextNode, String str, PrefixResolver prefixResolver,
128
            XPathContext xpathSupport) throws JspTagException {
129
130
        // Execute the XPath, and have it return the result
131
        XObject list = eval(contextNode, str, prefixResolver, xpathSupport);
132
133
        // Have the XObject return its result as a NodeSetDTM.
134
        return getNodeIterator(list);
135
    }
136
137
    /**
138
     * Use an XPath string to select a nodelist.
139
     * XPath namespace prefixes are resolved using the prefixResolver.
140
     *
141
     * @param contextNode    The node to start searching from.
142
     * @param str            A valid XPath string.
143
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
144
     * @return A NodeIterator, should never be null.
145
     * @throws JspTagException
146
     */
147
    private static NodeList selectNodeList(
148
            Node contextNode, String str, PrefixResolver prefixResolver)
149
            throws JspTagException {
150
        // Execute the XPath, and have it return the result
151
        XObject list = eval(contextNode, str, prefixResolver, null);
152
153
        // Return a NodeList.
154
        return getNodeList(list);
155
    }
156
157
    /**
158
     * Use an XPath string to select a nodelist.
159
     * XPath namespace prefixes are resolved using the prefixResolver.
160
     *
161
     * @param contextNode    The node to start searching from.
162
     * @param str            A valid XPath string.
163
     * @param prefixResolver The PrefixResolver using which prefixes in the XPath will be resolved to namespaces.
164
     * @return A NodeIterator, should never be null.
165
     * @throws JspTagException
166
     */
167
    public static NodeList selectNodeList(
168
            Node contextNode, String str, PrefixResolver prefixResolver,
169
            XPathContext xpathSupport)
170
            throws JspTagException {
171
        // Execute the XPath, and have it return the result
172
        XObject list = eval(contextNode, str, prefixResolver, xpathSupport);
173
174
        // Return a NodeList.
175
        return getNodeList(list);
176
    }
177
178
    /**
179
     * Returns a NodeIterator from an XObject.
180
     *
181
     * @param list The XObject from which a NodeIterator is returned.
182
     * @return A NodeIterator, should never be null.
183
     * @throws JspTagException
184
     */
185
    private static NodeIterator getNodeIterator(XObject list)
186
            throws JspTagException {
187
        try {
188
            return list.nodeset();
189
        } catch (TransformerException ex) {
190
            throw new JspTagException(
191
                    Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);
192
        }
193
    }
194
195
    /**
196
     * Returns a NodeList from an XObject.
197
     *
198
     * @param list The XObject from which a NodeList is returned.
199
     * @return A NodeList, should never be null.
200
     * @throws JspTagException
201
     */
202
    static NodeList getNodeList(XObject list)
203
            throws JspTagException {
204
        try {
205
            return list.nodelist();
206
        } catch (TransformerException ex) {
207
            throw new JspTagException(
208
                    Resources.getMessage("XPATH_ERROR_XOBJECT", ex.toString()), ex);
209
        }
210
    }
211
212
    /**
213
     * Evaluate XPath string to an XObject.
214
     * XPath namespace prefixes are resolved from the namespaceNode.
215
     * The implementation of this is a little slow, since it creates
216
     * a number of objects each time it is called.  This could be optimized
217
     * to keep the same objects around, but then thread-safety issues would arise.
218
     *
219
     * @param contextNode    The node to start searching from.
220
     * @param str            A valid XPath string.
221
     * @param xpathSupport   The node from which prefixes in the XPath will be resolved to namespaces.
222
     * @param prefixResolver Will be called if the parser encounters namespace
223
     *                       prefixes, to resolve the prefixes to URLs.
224
     * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never be null.
225
     * @throws JspTagException
226
     * @see org.apache.xpath.objects.XObject
227
     * @see org.apache.xpath.objects.XNull
228
     * @see org.apache.xpath.objects.XBoolean
229
     * @see org.apache.xpath.objects.XNumber
230
     * @see org.apache.xpath.objects.XString
231
     * @see org.apache.xpath.objects.XRTreeFrag
232
     */
233
    public static XObject eval(
234
            Node contextNode, String str, PrefixResolver prefixResolver,
235
            XPathContext xpathSupport) throws JspTagException {
236
        //System.out.println("eval of XPathContext params: contextNode:str(xpath)"+
237
        // ":prefixResolver:xpathSupport => " + contextNode + ":" + str + ":" +
238
        //  prefixResolver + ":" + xpathSupport );        
239
        try {
240
            if (xpathSupport == null) {
241
                return eval(contextNode, str, prefixResolver);
242
            }
243
244
            // Since we don't have a XML Parser involved here, install some default support
245
            // for things like namespaces, etc.
246
            // (Changed from: XPathContext xpathSupport = new XPathContext();
247
            //    because XPathContext is weak in a number of areas... perhaps
248
            //    XPathContext should be done away with.)
249
            // Create the XPath object.
250
            XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
251
252
            // Execute the XPath, and have it return the result
253
            int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
254
255
            // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode );
256
            XObject xobj = xpath.execute(xpathSupport, ctxtNode, prefixResolver);
257
            return xobj;
258
        } catch (TransformerException ex) {
259
            throw new JspTagException(
260
                    Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex);
261
        } catch (IllegalArgumentException ex) {
262
            throw new JspTagException(
263
                    Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex);
264
        }
265
    }
266
267
    public static XObject eval(
268
            Node contextNode, String str, PrefixResolver prefixResolver,
269
            XPathContext xpathSupport, Vector varQNames) throws JspTagException {
270
        //p("***************** eval ");
271
        //p( "contextNode => " + contextNode );
272
        //p( "XPath str => " + str );
273
        //p( "PrefixResolver => " + prefixResolver );
274
        //p( "XPath Context => " + xpathSupport );
275
        //p( "Var QNames => " + varQNames );
276
        //p( "Global Var Size => " + varQNames.size() );        
277
        try {
278
            XPath xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null);
279
            xpath.fixupVariables(varQNames, varQNames.size());
280
            // Execute the XPath, and have it return the result
281
            int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
282
            // System.out.println("Context Node id ( after getDTMHandlerFromNode) => " + ctxtNode );            
283
            return xpath.execute(xpathSupport, ctxtNode, prefixResolver);
284
        } catch (TransformerException ex) {
285
            throw new JspTagException(
286
                    Resources.getMessage("XPATH_ERROR_EVALUATING_EXPR", str, ex.toString()), ex);
287
        } catch (IllegalArgumentException ex) {
288
            throw new JspTagException(
289
                    Resources.getMessage("XPATH_ILLEGAL_ARG_EVALUATING_EXPR", str, ex.toString()), ex);
290
        }
291
    }
292
293
    private static void p(String s) {
294
        System.out.println("[JSTLXPathAPI] " + s);
295
    }
296
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLPrefixResolver.java (-145 lines)
Lines 1-145 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 * 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 * 
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
package org.apache.taglibs.standard.tag.common.xml;
18
19
import java.util.HashMap;
20
21
import org.apache.xml.utils.PrefixResolver;
22
import org.w3c.dom.NamedNodeMap;
23
import org.w3c.dom.Node;
24
25
/**
26
 * <meta name="usage" content="general"/>
27
 * This class implements a JSTL PrefixResolver that
28
 * can be used to perform prefix-to-namespace lookup
29
 * for the XPath object.
30
 */
31
public class JSTLPrefixResolver implements PrefixResolver {
32
33
    /**
34
     * The context to resolve the prefix from, if the context
35
     * is not given.
36
     */
37
38
    HashMap namespaces;
39
40
    /**
41
     * The URI for the XML namespace.
42
     * (Duplicate of that found in org.apache.xpath.XPathContext).
43
     */
44
45
    public static final String S_XMLNAMESPACEURI =
46
            "http://www.w3.org/XML/1998/namespace";
47
48
    /**
49
     * No-arg constructor which would create empty HashMap of namespaces
50
     */
51
    public JSTLPrefixResolver() {
52
        namespaces = new HashMap();
53
    }
54
55
    public JSTLPrefixResolver(HashMap nses) {
56
        namespaces = nses;
57
    }
58
59
    /**
60
     * Given a namespace, get the corresponding prefix.  This assumes that
61
     * the PrevixResolver hold's it's own namespace context, or is a namespace
62
     * context itself.
63
     *
64
     * @param prefix Prefix to resolve.
65
     * @return Namespace that prefix resolves to, or null if prefix
66
     *         is not bound.
67
     */
68
    public String getNamespaceForPrefix(String prefix) {
69
        return (String) namespaces.get(prefix);
70
    }
71
72
    /**
73
     * Given a prefix and a Context Node, get the corresponding namespace.
74
     * Warning: This will not work correctly if namespaceContext
75
     * is an attribute node.
76
     *
77
     * @param prefix           Prefix to resolve.
78
     * @param namespaceContext Node from which to start searching for a
79
     *                         xmlns attribute that binds a prefix to a namespace.
80
     * @return Namespace that prefix resolves to, or null if prefix
81
     *         is not bound.
82
     */
83
    public String getNamespaceForPrefix(String prefix,
84
                                        org.w3c.dom.Node namespaceContext) {
85
86
        Node parent = namespaceContext;
87
        String namespace = null;
88
89
        if (prefix.equals("xml")) {
90
            namespace = S_XMLNAMESPACEURI;
91
        } else {
92
            int type;
93
94
            while ((null != parent) && (null == namespace)
95
                    && (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
96
                    || (type == Node.ENTITY_REFERENCE_NODE))) {
97
                if (type == Node.ELEMENT_NODE) {
98
                    NamedNodeMap nnm = parent.getAttributes();
99
100
                    for (int i = 0; i < nnm.getLength(); i++) {
101
                        Node attr = nnm.item(i);
102
                        String aname = attr.getNodeName();
103
                        boolean isPrefix = aname.startsWith("xmlns:");
104
105
                        if (isPrefix || aname.equals("xmlns")) {
106
                            int index = aname.indexOf(':');
107
                            String p = isPrefix ? aname.substring(index + 1) : "";
108
109
                            if (p.equals(prefix)) {
110
                                namespace = attr.getNodeValue();
111
112
                                break;
113
                            }
114
                        }
115
                    }
116
                }
117
118
                parent = parent.getParentNode();
119
            }
120
        }
121
122
        return namespace;
123
    }
124
125
    /**
126
     * Return the base identifier.
127
     *
128
     * @return null
129
     */
130
    public String getBaseIdentifier() {
131
        return null;
132
    }
133
134
    /**
135
     * @see PrefixResolver#handlesNullPrefixes()
136
     */
137
    public boolean handlesNullPrefixes() {
138
        return false;
139
    }
140
141
    public void addNamespace(String prefix, String uri) {
142
        namespaces.put(prefix, uri);
143
    }
144
145
}
(-)impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java (-38 / +16 lines)
Lines 18-25 Link Here
18
package org.apache.taglibs.standard.tag.common.xml;
18
package org.apache.taglibs.standard.tag.common.xml;
19
19
20
import javax.servlet.jsp.JspTagException;
20
import javax.servlet.jsp.JspTagException;
21
import javax.xml.transform.TransformerException;
21
22
22
import org.apache.taglibs.standard.tag.common.core.WhenTagSupport;
23
import org.apache.taglibs.standard.tag.common.core.WhenTagSupport;
24
import org.apache.xpath.XPath;
25
import org.apache.xpath.XPathContext;
23
26
24
/**
27
/**
25
 * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
28
 * <p>Tag handler for &lt;if&gt; in JSTL's XML library.</p>
Lines 29-82 Link Here
29
32
30
public class WhenTag extends WhenTagSupport {
33
public class WhenTag extends WhenTagSupport {
31
34
32
    //*********************************************************************
35
    private XPath select;
33
    // Constructor and lifecycle management
34
36
35
    // initialize inherited and local state
36
37
    public WhenTag() {
38
        super();
39
        init();
40
    }
41
42
    // Releases any resources we may have (or inherit)
43
44
    @Override
37
    @Override
45
    public void release() {
38
    public void release() {
46
        super.release();
39
        super.release();
47
        init();
40
        select = null;
48
    }
41
    }
49
42
50
51
    //*********************************************************************
52
    // Supplied conditional logic
53
54
    @Override
43
    @Override
55
    protected boolean condition() throws JspTagException {
44
    protected boolean condition() throws JspTagException {
56
        XPathUtil xu = new XPathUtil(pageContext);
45
        XPathContext context = XalanUtil.getContext(this, pageContext);
57
        return (xu.booleanValueOf(XPathUtil.getContext(this), select));
46
        try {
47
            return select.bool(context, context.getCurrentNode(), null);
48
        } catch (TransformerException e) {
49
            throw new JspTagException(e);
50
        }
58
    }
51
    }
59
52
60
    //*********************************************************************
61
    // Private state
62
63
    private String select;               // the value of the 'test' attribute
64
65
66
    //*********************************************************************
67
    // Attribute accessors
68
69
    public void setSelect(String select) {
53
    public void setSelect(String select) {
70
        this.select = select;
54
        try {
55
            this.select = new XPath(select, null, null, XPath.SELECT);
56
        } catch (TransformerException e) {
57
            throw new AssertionError();
58
        }
71
    }
59
    }
72
73
74
    //*********************************************************************
75
    // Private utility methods
76
77
    // resets internal state
78
79
    private void init() {
80
        select = null;
81
    }
82
}
60
}

Return to bug 27717