KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xpath > internal > jaxp > XPathExpressionImpl


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 // $Id: XPathExpressionImpl.java,v 1.8 2004/07/10 21:39:19 rameshm Exp $
17

18 package com.sun.org.apache.xpath.internal.jaxp;
19
20 import com.sun.org.apache.xpath.internal.*;
21 import javax.xml.transform.TransformerException JavaDoc;
22
23 import com.sun.org.apache.xpath.internal.objects.XObject;
24 import com.sun.org.apache.xml.internal.utils.PrefixResolver;
25 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
26 import com.sun.org.apache.xalan.internal.res.XSLMessages;
27
28 import javax.xml.namespace.NamespaceContext JavaDoc;
29 import javax.xml.namespace.QName JavaDoc;
30 import javax.xml.xpath.XPathExpressionException JavaDoc;
31 import javax.xml.xpath.XPathConstants JavaDoc;
32 import javax.xml.xpath.XPathFunctionResolver JavaDoc;
33 import javax.xml.xpath.XPathVariableResolver JavaDoc;
34 import javax.xml.xpath.XPathConstants JavaDoc;
35
36 import org.w3c.dom.Node JavaDoc;
37 import org.w3c.dom.Document JavaDoc;
38 import org.w3c.dom.DOMImplementation JavaDoc;
39 import org.w3c.dom.traversal.NodeIterator;
40 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
41 import javax.xml.parsers.DocumentBuilder JavaDoc;
42
43 import org.xml.sax.InputSource JavaDoc;
44
45 /**
46  * The XPathExpression interface encapsulates a (compiled) XPath expression.
47  *
48  * @version $Revision: 1.8 $
49  * @author Ramesh Mandava
50  */

51 public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression JavaDoc{
52
53     private XPathFunctionResolver JavaDoc functionResolver;
54     private XPathVariableResolver JavaDoc variableResolver;
55     private JAXPPrefixResolver prefixResolver;
56     private com.sun.org.apache.xpath.internal.XPath xpath;
57
58     // By default Extension Functions are allowed in XPath Expressions. If
59
// Secure Processing Feature is set on XPathFactory then the invocation of
60
// extensions function need to throw XPathFunctionException
61
private boolean featureSecureProcessing = false;
62
63     /** Protected constructor to prevent direct instantiation; use compile()
64      * from the context.
65      */

66     protected XPathExpressionImpl() { };
67
68     protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
69             JAXPPrefixResolver prefixResolver,
70             XPathFunctionResolver JavaDoc functionResolver,
71             XPathVariableResolver JavaDoc variableResolver ) {
72         this.xpath = xpath;
73         this.prefixResolver = prefixResolver;
74         this.functionResolver = functionResolver;
75         this.variableResolver = variableResolver;
76         this.featureSecureProcessing = false;
77     };
78
79     protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
80             JAXPPrefixResolver prefixResolver,
81             XPathFunctionResolver JavaDoc functionResolver,
82             XPathVariableResolver JavaDoc variableResolver,
83             boolean featureSecureProcessing ) {
84         this.xpath = xpath;
85         this.prefixResolver = prefixResolver;
86         this.functionResolver = functionResolver;
87         this.variableResolver = variableResolver;
88         this.featureSecureProcessing = featureSecureProcessing;
89     };
90
91     public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath ) {
92         this.xpath = xpath;
93     }
94
95     public Object JavaDoc eval(Object JavaDoc item, QName JavaDoc returnType)
96             throws javax.xml.transform.TransformerException JavaDoc {
97         XObject resultObject = eval ( item );
98         return getResultAsType( resultObject, returnType );
99     }
100     
101     private XObject eval ( Object JavaDoc contextItem )
102             throws javax.xml.transform.TransformerException JavaDoc {
103         com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
104         if ( functionResolver != null ) {
105             JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
106                     functionResolver, featureSecureProcessing );
107             xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
108         } else {
109             xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
110         }
111
112         xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
113         XObject xobj = null;
114           
115         Node JavaDoc contextNode = (Node JavaDoc)contextItem;
116         // We always need to have a ContextNode with Xalan XPath implementation
117
// To allow simple expression evaluation like 1+1 we are setting
118
// dummy Document as Context Node
119
if ( contextNode == null ) {
120               contextNode = getDummyDocument();
121         }
122
123         xobj = xpath.execute(xpathSupport, contextNode, prefixResolver );
124         return xobj;
125     }
126
127
128     /**
129      * <p>Evaluate the compiled XPath expression in the specified context and
130      * return the result as the specified type.</p>
131      *
132      * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
133      * for context item evaluation,
134      * variable, function and QName resolution and return type conversion.</p>
135      *
136      * <p>If <code>returnType</code> is not one of the types defined
137      * in {@link XPathConstants},
138      * then an <code>IllegalArgumentException</code> is thrown.</p>
139      *
140      * <p>If a <code>null</code> value is provided for
141      * <code>item</code>, an empty document will be used for the
142      * context.
143      * If <code>returnType</code> is <code>null</code>, then a
144      * <code>NullPointerException</code> is thrown.</p>
145      *
146      * @param item The starting context (node or node list, for example).
147      * @param returnType The desired return type.
148      *
149      * @return The <code>Object</code> that is the result of evaluating the
150      * expression and converting the result to
151      * <code>returnType</code>.
152      *
153      * @throws XPathExpressionException If the expression cannot be evaluated.
154      * @throws IllegalArgumentException If <code>returnType</code> is not one
155      * of the types defined in {@link XPathConstants}.
156      * @throws NullPointerException If <code>returnType</code> is
157      * <code>null</code>.
158      */

159     public Object JavaDoc evaluate(Object JavaDoc item, QName JavaDoc returnType)
160         throws XPathExpressionException JavaDoc {
161         //Validating parameters to enforce constraints defined by JAXP spec
162
if ( returnType == null ) {
163            //Throwing NullPointerException as defined in spec
164
String JavaDoc fmsg = XSLMessages.createXPATHMessage(
165                     XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
166                     new Object JavaDoc[] {"returnType"} );
167             throw new NullPointerException JavaDoc( fmsg );
168         }
169         // Checking if requested returnType is supported. returnType need to be
170
// defined in XPathConstants
171
if ( !isSupported ( returnType ) ) {
172             String JavaDoc fmsg = XSLMessages.createXPATHMessage(
173                     XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
174                     new Object JavaDoc[] { returnType.toString() } );
175             throw new IllegalArgumentException JavaDoc ( fmsg );
176         }
177         try {
178             return eval( item, returnType);
179         } catch ( java.lang.NullPointerException JavaDoc npe ) {
180             // If VariableResolver returns null Or if we get
181
// NullPointerException at this stage for some other reason
182
// then we have to reurn XPathException
183
throw new XPathExpressionException JavaDoc ( npe );
184         } catch ( javax.xml.transform.TransformerException JavaDoc te ) {
185             Throwable JavaDoc nestedException = te.getException();
186             if ( nestedException instanceof javax.xml.xpath.XPathFunctionException JavaDoc ) {
187                 throw (javax.xml.xpath.XPathFunctionException JavaDoc)nestedException;
188             } else {
189                 // For any other exceptions we need to throw
190
// XPathExpressionException ( as per spec )
191
throw new XPathExpressionException JavaDoc( te);
192             }
193         }
194
195     }
196     
197     /**
198      * <p>Evaluate the compiled XPath expression in the specified context and
199      * return the result as a <code>String</code>.</p>
200      *
201      * <p>This method calls {@link #evaluate(Object item, QName returnType)}
202      * with a <code>returnType</code> of
203      * {@link XPathConstants#STRING}.</p>
204      *
205      * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
206      * for context item evaluation,
207      * variable, function and QName resolution and return type conversion.</p>
208      *
209      * <p>If a <code>null</code> value is provided for
210      * <code>item</code>, an empty document will be used for the
211      * context.
212      *
213      * @param item The starting context (node or node list, for example).
214      *
215      * @return The <code>String</code> that is the result of evaluating the
216      * expression and converting the result to a
217      * <code>String</code>.
218      *
219      * @throws XPathExpressionException If the expression cannot be evaluated.
220      */

221     public String JavaDoc evaluate(Object JavaDoc item)
222         throws XPathExpressionException JavaDoc {
223         return (String JavaDoc)this.evaluate( item, XPathConstants.STRING );
224     }
225
226
227
228     static DocumentBuilderFactory JavaDoc dbf = null;
229     static DocumentBuilder JavaDoc db = null;
230     static Document JavaDoc d = null;
231
232     /**
233      * <p>Evaluate the compiled XPath expression in the context of the
234      * specified <code>InputSource</code> and return the result as the
235      * specified type.</p>
236      *
237      * <p>This method builds a data model for the {@link InputSource} and calls
238      * {@link #evaluate(Object item, QName returnType)} on the resulting
239      * document object.</p>
240      *
241      * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
242      * for context item evaluation,
243      * variable, function and QName resolution and return type conversion.</p>
244      *
245      * <p>If <code>returnType</code> is not one of the types defined in
246      * {@link XPathConstants},
247      * then an <code>IllegalArgumentException</code> is thrown.</p>
248      *
249      *<p>If <code>source</code> or <code>returnType</code> is <code>null</code>,
250      * then a <code>NullPointerException</code> is thrown.</p>
251      *
252      * @param source The <code>InputSource</code> of the document to evaluate
253      * over.
254      * @param returnType The desired return type.
255      *
256      * @return The <code>Object</code> that is the result of evaluating the
257      * expression and converting the result to
258      * <code>returnType</code>.
259      *
260      * @throws XPathExpressionException If the expression cannot be evaluated.
261      * @throws IllegalArgumentException If <code>returnType</code> is not one
262      * of the types defined in {@link XPathConstants}.
263      * @throws NullPointerException If <code>source</code> or
264      * <code>returnType</code> is <code>null</code>.
265      */

266     public Object JavaDoc evaluate(InputSource JavaDoc source, QName JavaDoc returnType)
267         throws XPathExpressionException JavaDoc {
268         if ( ( source == null ) || ( returnType == null ) ) {
269             String JavaDoc fmsg = XSLMessages.createXPATHMessage(
270                     XPATHErrorResources.ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL,
271                     null );
272             throw new NullPointerException JavaDoc ( fmsg );
273         }
274         // Checking if requested returnType is supported. returnType need to be
275
// defined in XPathConstants
276
if ( !isSupported ( returnType ) ) {
277             String JavaDoc fmsg = XSLMessages.createXPATHMessage(
278                     XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
279                     new Object JavaDoc[] { returnType.toString() } );
280             throw new IllegalArgumentException JavaDoc ( fmsg );
281         }
282         try {
283             if ( dbf == null ) {
284                 dbf = DocumentBuilderFactory.newInstance();
285                 dbf.setNamespaceAware( true );
286                 dbf.setValidating( false );
287             }
288             db = dbf.newDocumentBuilder();
289             Document JavaDoc document = db.parse( source );
290             return eval( document, returnType );
291         } catch ( Exception JavaDoc e ) {
292             throw new XPathExpressionException JavaDoc ( e );
293         }
294     }
295
296     /**
297      * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a
298      * <code>String</code>.</p>
299      *
300      * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of
301      * {@link XPathConstants#STRING}.</p>
302      *
303      * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
304      * for context item evaluation,
305      * variable, function and QName resolution and return type conversion.</p>
306      *
307      * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
308      *
309      * @param source The <code>InputSource</code> of the document to evaluate over.
310      *
311      * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
312      * <code>String</code>.
313      *
314      * @throws XPathExpressionException If the expression cannot be evaluated.
315      * @throws NullPointerException If <code>source</code> is <code>null</code>.
316      */

317     public String JavaDoc evaluate(InputSource JavaDoc source)
318         throws XPathExpressionException JavaDoc {
319         return (String JavaDoc)this.evaluate( source, XPathConstants.STRING );
320     }
321
322     private boolean isSupported( QName JavaDoc returnType ) {
323         // XPathConstants.STRING
324
if ( ( returnType.equals( XPathConstants.STRING ) ) ||
325              ( returnType.equals( XPathConstants.NUMBER ) ) ||
326              ( returnType.equals( XPathConstants.BOOLEAN ) ) ||
327              ( returnType.equals( XPathConstants.NODE ) ) ||
328              ( returnType.equals( XPathConstants.NODESET ) ) ) {
329     
330             return true;
331         }
332         return false;
333      }
334
335      private Object JavaDoc getResultAsType( XObject resultObject, QName JavaDoc returnType )
336         throws javax.xml.transform.TransformerException JavaDoc {
337         // XPathConstants.STRING
338
if ( returnType.equals( XPathConstants.STRING ) ) {
339             return resultObject.str();
340         }
341         // XPathConstants.NUMBER
342
if ( returnType.equals( XPathConstants.NUMBER ) ) {
343             return new Double JavaDoc ( resultObject.num());
344         }
345         // XPathConstants.BOOLEAN
346
if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
347             return new Boolean JavaDoc( resultObject.bool());
348         }
349         // XPathConstants.NODESET ---ORdered, UNOrdered???
350
if ( returnType.equals( XPathConstants.NODESET ) ) {
351             return resultObject.nodelist();
352         }
353         // XPathConstants.NODE
354
if ( returnType.equals( XPathConstants.NODE ) ) {
355             NodeIterator ni = resultObject.nodeset();
356             //Return the first node, or null
357
return ni.nextNode();
358         }
359         // If isSupported check is already done then the execution path
360
// shouldn't come here. Being defensive
361
String JavaDoc fmsg = XSLMessages.createXPATHMessage(
362                 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
363                 new Object JavaDoc[] { returnType.toString()});
364         throw new IllegalArgumentException JavaDoc ( fmsg );
365     }
366
367
368     private static Document JavaDoc getDummyDocument( ) {
369         try {
370             if ( dbf == null ) {
371                 dbf = DocumentBuilderFactory.newInstance();
372                 dbf.setNamespaceAware( true );
373                 dbf.setValidating( false );
374             }
375             db = dbf.newDocumentBuilder();
376
377             DOMImplementation JavaDoc dim = db.getDOMImplementation();
378             d = dim.createDocument("http://java.sun.com/jaxp/xpath",
379                 "dummyroot", null);
380             return d;
381         } catch ( Exception JavaDoc e ) {
382             e.printStackTrace();
383         }
384         return null;
385     }
386
387
388
389
390 }
391
Popular Tags