26 import javax.xml.xpath.XPathExpressionException; |
25 import javax.xml.xpath.XPathExpressionException; |
27 import javax.xml.xpath.XPathConstants; |
26 import javax.xml.xpath.XPathConstants; |
28 import javax.xml.xpath.XPathFunctionResolver; |
27 import javax.xml.xpath.XPathFunctionResolver; |
29 import javax.xml.xpath.XPathVariableResolver; |
28 import javax.xml.xpath.XPathVariableResolver; |
30 import javax.xml.xpath.XPathExpression; |
29 import javax.xml.xpath.XPathExpression; |
31 |
|
32 import com.sun.org.apache.xml.internal.dtm.DTM; |
|
33 import com.sun.org.apache.xpath.internal.*; |
30 import com.sun.org.apache.xpath.internal.*; |
34 import com.sun.org.apache.xpath.internal.objects.XObject; |
31 import com.sun.org.apache.xpath.internal.objects.XObject; |
35 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; |
|
36 import com.sun.org.apache.xalan.internal.res.XSLMessages; |
|
37 import com.sun.org.apache.xalan.internal.utils.FactoryImpl; |
|
38 import com.sun.org.apache.xalan.internal.utils.FeatureManager; |
32 import com.sun.org.apache.xalan.internal.utils.FeatureManager; |
39 |
|
40 import org.w3c.dom.Node; |
|
41 import org.w3c.dom.Document; |
33 import org.w3c.dom.Document; |
42 import org.w3c.dom.traversal.NodeIterator; |
|
43 |
|
44 import org.xml.sax.InputSource; |
34 import org.xml.sax.InputSource; |
45 import org.xml.sax.SAXException; |
35 import javax.xml.transform.TransformerException; |
46 |
36 import javax.xml.xpath.XPathEvaluationResult; |
47 import javax.xml.parsers.*; |
|
48 |
|
49 import java.io.IOException; |
|
50 |
37 |
51 /** |
38 /** |
52 * The XPathImpl class provides implementation for the methods defined in |
39 * The XPathImpl class provides implementation for the methods defined in |
53 * javax.xml.xpath.XPath interface. This provide simple access to the results |
40 * javax.xml.xpath.XPath interface. This provides simple access to the results |
54 * of an XPath expression. |
41 * of an XPath expression. |
55 * |
42 * |
56 * |
|
57 * @author Ramesh Mandava |
43 * @author Ramesh Mandava |
|
44 * |
|
45 * Updated 12/04/2014: |
|
46 * New methods: evaluateExpression |
|
47 * Refactored to share code with XPathExpressionImpl. |
58 */ |
48 */ |
59 public class XPathImpl implements javax.xml.xpath.XPath { |
49 public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { |
60 |
50 |
61 // Private variables |
51 // Private variables |
62 private XPathVariableResolver variableResolver; |
|
63 private XPathFunctionResolver functionResolver; |
|
64 private XPathVariableResolver origVariableResolver; |
52 private XPathVariableResolver origVariableResolver; |
65 private XPathFunctionResolver origFunctionResolver; |
53 private XPathFunctionResolver origFunctionResolver; |
66 private NamespaceContext namespaceContext=null; |
54 private NamespaceContext namespaceContext=null; |
67 private JAXPPrefixResolver prefixResolver; |
55 |
68 // By default Extension Functions are allowed in XPath Expressions. If |
56 XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { |
69 // Secure Processing Feature is set on XPathFactory then the invocation of |
|
70 // extensions function need to throw XPathFunctionException |
|
71 private boolean featureSecureProcessing = false; |
|
72 private boolean useServiceMechanism = true; |
|
73 private final FeatureManager featureManager; |
|
74 |
|
75 XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) { |
|
76 this(vr, fr, false, true, new FeatureManager()); |
57 this(vr, fr, false, true, new FeatureManager()); |
77 } |
58 } |
78 |
59 |
79 XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr, |
60 XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, |
80 boolean featureSecureProcessing, boolean useServiceMechanism, |
61 boolean featureSecureProcessing, boolean useServiceMechanism, |
81 FeatureManager featureManager) { |
62 FeatureManager featureManager) { |
82 this.origVariableResolver = this.variableResolver = vr; |
63 this.origVariableResolver = this.variableResolver = vr; |
83 this.origFunctionResolver = this.functionResolver = fr; |
64 this.origFunctionResolver = this.functionResolver = fr; |
84 this.featureSecureProcessing = featureSecureProcessing; |
65 this.featureSecureProcessing = featureSecureProcessing; |
85 this.useServiceMechanism = useServiceMechanism; |
66 this.useServiceMechanism = useServiceMechanism; |
86 this.featureManager = featureManager; |
67 this.featureManager = featureManager; |
87 } |
68 } |
88 |
69 |
89 /** |
70 |
90 * <p>Establishes a variable resolver.</p> |
71 //-Override- |
91 * |
|
92 * @param resolver Variable Resolver |
|
93 */ |
|
94 public void setXPathVariableResolver(XPathVariableResolver resolver) { |
72 public void setXPathVariableResolver(XPathVariableResolver resolver) { |
95 if ( resolver == null ) { |
73 requireNonNull(resolver, "XPathVariableResolver"); |
96 String fmsg = XSLMessages.createXPATHMessage( |
|
97 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
98 new Object[] {"XPathVariableResolver"} ); |
|
99 throw new NullPointerException( fmsg ); |
|
100 } |
|
101 this.variableResolver = resolver; |
74 this.variableResolver = resolver; |
102 } |
75 } |
103 |
76 |
104 /** |
77 //-Override- |
105 * <p>Returns the current variable resolver.</p> |
|
106 * |
|
107 * @return Current variable resolver |
|
108 */ |
|
109 public XPathVariableResolver getXPathVariableResolver() { |
78 public XPathVariableResolver getXPathVariableResolver() { |
110 return variableResolver; |
79 return variableResolver; |
111 } |
80 } |
112 |
81 |
113 /** |
82 //-Override- |
114 * <p>Establishes a function resolver.</p> |
|
115 * |
|
116 * @param resolver XPath function resolver |
|
117 */ |
|
118 public void setXPathFunctionResolver(XPathFunctionResolver resolver) { |
83 public void setXPathFunctionResolver(XPathFunctionResolver resolver) { |
119 if ( resolver == null ) { |
84 requireNonNull(resolver, "XPathFunctionResolver"); |
120 String fmsg = XSLMessages.createXPATHMessage( |
|
121 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
122 new Object[] {"XPathFunctionResolver"} ); |
|
123 throw new NullPointerException( fmsg ); |
|
124 } |
|
125 this.functionResolver = resolver; |
85 this.functionResolver = resolver; |
126 } |
86 } |
127 |
87 |
128 /** |
88 //-Override- |
129 * <p>Returns the current function resolver.</p> |
|
130 * |
|
131 * @return Current function resolver |
|
132 */ |
|
133 public XPathFunctionResolver getXPathFunctionResolver() { |
89 public XPathFunctionResolver getXPathFunctionResolver() { |
134 return functionResolver; |
90 return functionResolver; |
135 } |
91 } |
136 |
92 |
137 /** |
93 //-Override- |
138 * <p>Establishes a namespace context.</p> |
|
139 * |
|
140 * @param nsContext Namespace context to use |
|
141 */ |
|
142 public void setNamespaceContext(NamespaceContext nsContext) { |
94 public void setNamespaceContext(NamespaceContext nsContext) { |
143 if ( nsContext == null ) { |
95 requireNonNull(nsContext, "NamespaceContext"); |
144 String fmsg = XSLMessages.createXPATHMessage( |
|
145 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
146 new Object[] {"NamespaceContext"} ); |
|
147 throw new NullPointerException( fmsg ); |
|
148 } |
|
149 this.namespaceContext = nsContext; |
96 this.namespaceContext = nsContext; |
150 this.prefixResolver = new JAXPPrefixResolver ( nsContext ); |
97 this.prefixResolver = new JAXPPrefixResolver (nsContext); |
151 } |
98 } |
152 |
99 |
153 /** |
100 //-Override- |
154 * <p>Returns the current namespace context.</p> |
|
155 * |
|
156 * @return Current Namespace context |
|
157 */ |
|
158 public NamespaceContext getNamespaceContext() { |
101 public NamespaceContext getNamespaceContext() { |
159 return namespaceContext; |
102 return namespaceContext; |
160 } |
103 } |
161 |
104 |
162 private static Document d = null; |
105 /** |
163 |
106 * Evaluate an {@code XPath} expression in the specified context. |
164 private DocumentBuilder getParser() { |
107 * @param expression The XPath expression. |
165 try { |
108 * @param contextItem The starting context. |
166 // we'd really like to cache those DocumentBuilders, but we can't because: |
109 * @return an XObject as the result of evaluating the expression |
167 // 1. thread safety. parsers are not thread-safe, so at least |
110 * @throws TransformerException if evaluating fails |
168 // we need one instance per a thread. |
111 */ |
169 // 2. parsers are non-reentrant, so now we are looking at having a |
|
170 // pool of parsers. |
|
171 // 3. then the class loading issue. The look-up procedure of |
|
172 // DocumentBuilderFactory.newInstance() depends on context class loader |
|
173 // and system properties, which may change during the execution of JVM. |
|
174 // |
|
175 // so we really have to create a fresh DocumentBuilder every time we need one |
|
176 // - KK |
|
177 DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism); |
|
178 dbf.setNamespaceAware( true ); |
|
179 dbf.setValidating( false ); |
|
180 return dbf.newDocumentBuilder(); |
|
181 } catch (ParserConfigurationException e) { |
|
182 // this should never happen with a well-behaving JAXP implementation. |
|
183 throw new Error(e); |
|
184 } |
|
185 } |
|
186 |
|
187 |
|
188 private XObject eval(String expression, Object contextItem) |
112 private XObject eval(String expression, Object contextItem) |
189 throws javax.xml.transform.TransformerException { |
113 throws TransformerException { |
190 com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression, |
114 requireNonNull(expression, "XPath expression"); |
191 null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); |
115 com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression, |
192 com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null; |
116 null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); |
193 if ( functionResolver != null ) { |
117 |
194 JAXPExtensionsProvider jep = new JAXPExtensionsProvider( |
118 return eval(contextItem, xpath); |
195 functionResolver, featureSecureProcessing, featureManager ); |
119 } |
196 xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep ); |
120 |
197 } else { |
121 //-Override- |
198 xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); |
|
199 } |
|
200 |
|
201 XObject xobj = null; |
|
202 |
|
203 xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); |
|
204 |
|
205 // If item is null, then we will create a a Dummy contextNode |
|
206 if ( contextItem instanceof Node ) { |
|
207 xobj = xpath.execute (xpathSupport, (Node)contextItem, |
|
208 prefixResolver ); |
|
209 } else { |
|
210 xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver ); |
|
211 } |
|
212 |
|
213 return xobj; |
|
214 } |
|
215 |
|
216 /** |
|
217 * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p> |
|
218 * |
|
219 * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec |
|
220 * for context item evaluation, |
|
221 * variable, function and <code>QName</code> resolution and return type conversion.</p> |
|
222 * |
|
223 * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} ( |
|
224 * {@link XPathConstants#NUMBER NUMBER}, |
|
225 * {@link XPathConstants#STRING STRING}, |
|
226 * {@link XPathConstants#BOOLEAN BOOLEAN}, |
|
227 * {@link XPathConstants#NODE NODE} or |
|
228 * {@link XPathConstants#NODESET NODESET}) |
|
229 * then an <code>IllegalArgumentException</code> is thrown.</p> |
|
230 * |
|
231 * <p>If a <code>null</code> value is provided for |
|
232 * <code>item</code>, an empty document will be used for the |
|
233 * context. |
|
234 * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a |
|
235 * <code>NullPointerException</code> is thrown.</p> |
|
236 * |
|
237 * @param expression The XPath expression. |
|
238 * @param item The starting context (node or node list, for example). |
|
239 * @param returnType The desired return type. |
|
240 * |
|
241 * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>. |
|
242 * |
|
243 * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. |
|
244 * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. |
|
245 * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>. |
|
246 */ |
|
247 public Object evaluate(String expression, Object item, QName returnType) |
122 public Object evaluate(String expression, Object item, QName returnType) |
248 throws XPathExpressionException { |
123 throws XPathExpressionException { |
249 if ( expression == null ) { |
124 //this check is necessary before calling eval to maintain binary compatibility |
250 String fmsg = XSLMessages.createXPATHMessage( |
125 requireNonNull(expression, "XPath expression"); |
251 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
126 isSupported(returnType); |
252 new Object[] {"XPath expression"} ); |
127 |
253 throw new NullPointerException ( fmsg ); |
128 try { |
254 } |
129 |
255 if ( returnType == null ) { |
130 XObject resultObject = eval(expression, item); |
256 String fmsg = XSLMessages.createXPATHMessage( |
131 return getResultAsType(resultObject, returnType); |
257 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
132 } catch (java.lang.NullPointerException npe) { |
258 new Object[] {"returnType"} ); |
|
259 throw new NullPointerException ( fmsg ); |
|
260 } |
|
261 // Checking if requested returnType is supported. returnType need to |
|
262 // be defined in XPathConstants |
|
263 if ( !isSupported ( returnType ) ) { |
|
264 String fmsg = XSLMessages.createXPATHMessage( |
|
265 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
266 new Object[] { returnType.toString() } ); |
|
267 throw new IllegalArgumentException ( fmsg ); |
|
268 } |
|
269 |
|
270 try { |
|
271 |
|
272 XObject resultObject = eval( expression, item ); |
|
273 return getResultAsType( resultObject, returnType ); |
|
274 } catch ( java.lang.NullPointerException npe ) { |
|
275 // If VariableResolver returns null Or if we get |
133 // If VariableResolver returns null Or if we get |
276 // NullPointerException at this stage for some other reason |
134 // NullPointerException at this stage for some other reason |
277 // then we have to reurn XPathException |
135 // then we have to reurn XPathException |
278 throw new XPathExpressionException ( npe ); |
136 throw new XPathExpressionException (npe); |
279 } catch ( javax.xml.transform.TransformerException te ) { |
137 } catch (TransformerException te) { |
280 Throwable nestedException = te.getException(); |
138 Throwable nestedException = te.getException(); |
281 if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { |
139 if (nestedException instanceof javax.xml.xpath.XPathFunctionException) { |
282 throw (javax.xml.xpath.XPathFunctionException)nestedException; |
140 throw (javax.xml.xpath.XPathFunctionException)nestedException; |
283 } else { |
141 } else { |
284 // For any other exceptions we need to throw |
142 // For any other exceptions we need to throw |
285 // XPathExpressionException ( as per spec ) |
143 // XPathExpressionException (as per spec) |
286 throw new XPathExpressionException ( te ); |
144 throw new XPathExpressionException (te); |
287 } |
145 } |
288 } |
146 } |
289 |
147 |
290 } |
148 } |
291 |
149 |
292 private boolean isSupported( QName returnType ) { |
150 //-Override- |
293 if ( ( returnType.equals( XPathConstants.STRING ) ) || |
|
294 ( returnType.equals( XPathConstants.NUMBER ) ) || |
|
295 ( returnType.equals( XPathConstants.BOOLEAN ) ) || |
|
296 ( returnType.equals( XPathConstants.NODE ) ) || |
|
297 ( returnType.equals( XPathConstants.NODESET ) ) ) { |
|
298 |
|
299 return true; |
|
300 } |
|
301 return false; |
|
302 } |
|
303 |
|
304 private Object getResultAsType( XObject resultObject, QName returnType ) |
|
305 throws javax.xml.transform.TransformerException { |
|
306 // XPathConstants.STRING |
|
307 if ( returnType.equals( XPathConstants.STRING ) ) { |
|
308 return resultObject.str(); |
|
309 } |
|
310 // XPathConstants.NUMBER |
|
311 if ( returnType.equals( XPathConstants.NUMBER ) ) { |
|
312 return new Double ( resultObject.num()); |
|
313 } |
|
314 // XPathConstants.BOOLEAN |
|
315 if ( returnType.equals( XPathConstants.BOOLEAN ) ) { |
|
316 return new Boolean( resultObject.bool()); |
|
317 } |
|
318 // XPathConstants.NODESET ---ORdered, UNOrdered??? |
|
319 if ( returnType.equals( XPathConstants.NODESET ) ) { |
|
320 return resultObject.nodelist(); |
|
321 } |
|
322 // XPathConstants.NODE |
|
323 if ( returnType.equals( XPathConstants.NODE ) ) { |
|
324 NodeIterator ni = resultObject.nodeset(); |
|
325 //Return the first node, or null |
|
326 return ni.nextNode(); |
|
327 } |
|
328 String fmsg = XSLMessages.createXPATHMessage( |
|
329 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
330 new Object[] { returnType.toString()}); |
|
331 throw new IllegalArgumentException( fmsg ); |
|
332 } |
|
333 |
|
334 |
|
335 |
|
336 /** |
|
337 * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p> |
|
338 * |
|
339 * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of |
|
340 * {@link XPathConstants#STRING}.</p> |
|
341 * |
|
342 * <p>See "Evaluation of XPath Expressions" of JAXP 1.3 spec |
|
343 * for context item evaluation, |
|
344 * variable, function and QName resolution and return type conversion.</p> |
|
345 * |
|
346 * <p>If a <code>null</code> value is provided for |
|
347 * <code>item</code>, an empty document will be used for the |
|
348 * context. |
|
349 * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> |
|
350 * |
|
351 * @param expression The XPath expression. |
|
352 * @param item The starting context (node or node list, for example). |
|
353 * |
|
354 * @return The <code>String</code> that is the result of evaluating the expression and |
|
355 * converting the result to a <code>String</code>. |
|
356 * |
|
357 * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. |
|
358 * @throws NullPointerException If <code>expression</code> is <code>null</code>. |
|
359 */ |
|
360 public String evaluate(String expression, Object item) |
151 public String evaluate(String expression, Object item) |
361 throws XPathExpressionException { |
152 throws XPathExpressionException { |
362 return (String)this.evaluate( expression, item, XPathConstants.STRING ); |
153 return (String)this.evaluate(expression, item, XPathConstants.STRING); |
363 } |
154 } |
364 |
155 |
365 /** |
156 //-Override- |
366 * <p>Compile an XPath expression for later evaluation.</p> |
|
367 * |
|
368 * <p>If <code>expression</code> contains any {@link XPathFunction}s, |
|
369 * they must be available via the {@link XPathFunctionResolver}. |
|
370 * An {@link XPathExpressionException} will be thrown if the <code>XPathFunction</code> |
|
371 * cannot be resovled with the <code>XPathFunctionResolver</code>.</p> |
|
372 * |
|
373 * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p> |
|
374 * |
|
375 * @param expression The XPath expression. |
|
376 * |
|
377 * @return Compiled XPath expression. |
|
378 |
|
379 * @throws XPathExpressionException If <code>expression</code> cannot be compiled. |
|
380 * @throws NullPointerException If <code>expression</code> is <code>null</code>. |
|
381 */ |
|
382 public XPathExpression compile(String expression) |
157 public XPathExpression compile(String expression) |
383 throws XPathExpressionException { |
158 throws XPathExpressionException { |
384 if ( expression == null ) { |
159 requireNonNull(expression, "XPath expression"); |
385 String fmsg = XSLMessages.createXPATHMessage( |
|
386 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
387 new Object[] {"XPath expression"} ); |
|
388 throw new NullPointerException ( fmsg ); |
|
389 } |
|
390 try { |
160 try { |
391 com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null, |
161 com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null, |
392 prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); |
162 prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); |
393 // Can have errorListener |
163 // Can have errorListener |
394 XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath, |
164 XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath, |
395 prefixResolver, functionResolver, variableResolver, |
165 prefixResolver, functionResolver, variableResolver, |
396 featureSecureProcessing, useServiceMechanism, featureManager ); |
166 featureSecureProcessing, useServiceMechanism, featureManager); |
397 return ximpl; |
167 return ximpl; |
398 } catch ( javax.xml.transform.TransformerException te ) { |
168 } catch (TransformerException te) { |
399 throw new XPathExpressionException ( te ) ; |
169 throw new XPathExpressionException (te) ; |
400 } |
170 } |
401 } |
171 } |
402 |
172 |
403 |
173 //-Override- |
404 /** |
|
405 * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> |
|
406 * and return the result as the specified type.</p> |
|
407 * |
|
408 * <p>This method builds a data model for the {@link InputSource} and calls |
|
409 * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p> |
|
410 * |
|
411 * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec |
|
412 * for context item evaluation, |
|
413 * variable, function and QName resolution and return type conversion.</p> |
|
414 * |
|
415 * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants}, |
|
416 * then an <code>IllegalArgumentException</code> is thrown.</p> |
|
417 * |
|
418 * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>, |
|
419 * then a <code>NullPointerException</code> is thrown.</p> |
|
420 * |
|
421 * @param expression The XPath expression. |
|
422 * @param source The input source of the document to evaluate over. |
|
423 * @param returnType The desired return type. |
|
424 * |
|
425 * @return The <code>Object</code> that encapsulates the result of evaluating the expression. |
|
426 * |
|
427 * @throws XPathExpressionException If expression cannot be evaluated. |
|
428 * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. |
|
429 * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code> |
|
430 * is <code>null</code>. |
|
431 */ |
|
432 public Object evaluate(String expression, InputSource source, |
174 public Object evaluate(String expression, InputSource source, |
433 QName returnType) throws XPathExpressionException { |
175 QName returnType) throws XPathExpressionException { |
434 // Checking validity of different parameters |
176 isSupported(returnType); |
435 if( source== null ) { |
177 |
436 String fmsg = XSLMessages.createXPATHMessage( |
178 try { |
437 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
179 Document document = getDocument(source); |
438 new Object[] {"source"} ); |
180 XObject resultObject = eval(expression, document); |
439 throw new NullPointerException ( fmsg ); |
181 return getResultAsType(resultObject, returnType); |
440 } |
182 } catch (TransformerException te) { |
441 if ( expression == null ) { |
|
442 String fmsg = XSLMessages.createXPATHMessage( |
|
443 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
444 new Object[] {"XPath expression"} ); |
|
445 throw new NullPointerException ( fmsg ); |
|
446 } |
|
447 if ( returnType == null ) { |
|
448 String fmsg = XSLMessages.createXPATHMessage( |
|
449 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
450 new Object[] {"returnType"} ); |
|
451 throw new NullPointerException ( fmsg ); |
|
452 } |
|
453 |
|
454 //Checking if requested returnType is supported. |
|
455 //returnType need to be defined in XPathConstants |
|
456 if ( !isSupported ( returnType ) ) { |
|
457 String fmsg = XSLMessages.createXPATHMessage( |
|
458 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
459 new Object[] { returnType.toString() } ); |
|
460 throw new IllegalArgumentException ( fmsg ); |
|
461 } |
|
462 |
|
463 try { |
|
464 |
|
465 Document document = getParser().parse( source ); |
|
466 |
|
467 XObject resultObject = eval( expression, document ); |
|
468 return getResultAsType( resultObject, returnType ); |
|
469 } catch ( SAXException e ) { |
|
470 throw new XPathExpressionException ( e ); |
|
471 } catch( IOException e ) { |
|
472 throw new XPathExpressionException ( e ); |
|
473 } catch ( javax.xml.transform.TransformerException te ) { |
|
474 Throwable nestedException = te.getException(); |
183 Throwable nestedException = te.getException(); |
475 if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { |
184 if (nestedException instanceof javax.xml.xpath.XPathFunctionException) { |
476 throw (javax.xml.xpath.XPathFunctionException)nestedException; |
185 throw (javax.xml.xpath.XPathFunctionException)nestedException; |
477 } else { |
186 } else { |
478 throw new XPathExpressionException ( te ); |
187 throw new XPathExpressionException (te); |
479 } |
188 } |
480 } |
189 } |
481 |
190 } |
482 } |
191 |
483 |
192 //-Override- |
484 |
|
485 |
|
486 |
|
487 /** |
|
488 * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> |
|
489 * and return the result as a <code>String</code>.</p> |
|
490 * |
|
491 * <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a |
|
492 * <code>returnType</code> of {@link XPathConstants#STRING}.</p> |
|
493 * |
|
494 * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec |
|
495 * for context item evaluation, |
|
496 * variable, function and QName resolution and return type conversion.</p> |
|
497 * |
|
498 * <p>If <code>expression</code> or <code>source</code> is <code>null</code>, |
|
499 * then a <code>NullPointerException</code> is thrown.</p> |
|
500 * |
|
501 * @param expression The XPath expression. |
|
502 * @param source The <code>InputSource</code> of the document to evaluate over. |
|
503 * |
|
504 * @return The <code>String</code> that is the result of evaluating the expression and |
|
505 * converting the result to a <code>String</code>. |
|
506 * |
|
507 * @throws XPathExpressionException If expression cannot be evaluated. |
|
508 * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>. |
|
509 */ |
|
510 public String evaluate(String expression, InputSource source) |
193 public String evaluate(String expression, InputSource source) |
511 throws XPathExpressionException { |
194 throws XPathExpressionException { |
512 return (String)this.evaluate( expression, source, XPathConstants.STRING ); |
195 return (String)this.evaluate(expression, source, XPathConstants.STRING); |
513 } |
196 } |
514 |
197 |
515 /** |
198 //-Override- |
516 * <p>Reset this <code>XPath</code> to its original configuration.</p> |
|
517 * |
|
518 * <p><code>XPath</code> is reset to the same state as when it was created with |
|
519 * {@link XPathFactory#newXPath()}. |
|
520 * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s |
|
521 * thus saving resources associated with the creation of new <code>XPath</code>s.</p> |
|
522 * |
|
523 * <p>The reset <code>XPath</code> is not guaranteed to have the same |
|
524 * {@link XPathFunctionResolver}, {@link XPathVariableResolver} |
|
525 * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}. |
|
526 * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>, |
|
527 * <code>XPathVariableResolver</code> |
|
528 * and <code>NamespaceContext</code>.</p> |
|
529 */ |
|
530 public void reset() { |
199 public void reset() { |
531 this.variableResolver = this.origVariableResolver; |
200 this.variableResolver = this.origVariableResolver; |
532 this.functionResolver = this.origFunctionResolver; |
201 this.functionResolver = this.origFunctionResolver; |
533 this.namespaceContext = null; |
202 this.namespaceContext = null; |
534 } |
203 } |
535 |
204 |
|
205 //-Override- |
|
206 public <T> T evaluateExpression(String expression, Object item, Class<T> type) |
|
207 throws XPathExpressionException { |
|
208 isSupportedClassType(type); |
|
209 try { |
|
210 XObject resultObject = eval(expression, item); |
|
211 if (type.isAssignableFrom(XPathEvaluationResult.class)) { |
|
212 return getXPathResult(resultObject, type); |
|
213 } else { |
|
214 return XPathResultImpl.getValue(resultObject, type); |
|
215 } |
|
216 } catch (TransformerException te) { |
|
217 throw new XPathExpressionException (te); |
|
218 } |
|
219 } |
|
220 |
|
221 //-Override- |
|
222 public XPathEvaluationResult<?> evaluateExpression(String expression, Object item) |
|
223 throws XPathExpressionException { |
|
224 return evaluateExpression(expression, item, XPathEvaluationResult.class); |
|
225 } |
|
226 |
|
227 //-Override- |
|
228 public <T> T evaluateExpression(String expression, InputSource source, Class<T> type) |
|
229 throws XPathExpressionException { |
|
230 Document document = getDocument(source); |
|
231 return evaluateExpression(expression, document, type); |
|
232 } |
|
233 |
|
234 //-Override- |
|
235 public XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source) |
|
236 throws XPathExpressionException { |
|
237 return evaluateExpression(expression, source, XPathEvaluationResult.class); |
|
238 } |
536 } |
239 } |