1 /*
2  * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
3  */
4 /*
5  * Licensed to the Apache Software Foundation (ASF) under one or more
6  * contributor license agreements.  See the NOTICE file distributed with
7  * this work for additional information regarding copyright ownership.
8  * The ASF licenses this file to You under the Apache License, Version 2.0
9  * (the "License"); you may not use this file except in compliance with
10  * the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 package com.sun.org.apache.xpath.internal.jaxp;
22 
23 import com.sun.org.apache.xpath.internal.*;
24 import com.sun.org.apache.xpath.internal.objects.XObject;
25 import javax.xml.namespace.NamespaceContext;
26 import javax.xml.namespace.QName;
27 import javax.xml.transform.TransformerException;
28 import javax.xml.xpath.XPathConstants;
29 import javax.xml.xpath.XPathEvaluationResult;
30 import javax.xml.xpath.XPathExpression;
31 import javax.xml.xpath.XPathExpressionException;
32 import javax.xml.xpath.XPathFunctionResolver;
33 import javax.xml.xpath.XPathVariableResolver;
34 import jdk.xml.internal.JdkXmlFeatures;
35 import org.w3c.dom.Document;
36 import org.xml.sax.InputSource;
37 
38 /**
39  * The XPathImpl class provides implementation for the methods defined  in
40  * javax.xml.xpath.XPath interface. This provides simple access to the results
41  * of an XPath expression.
42  *
43  * @author  Ramesh Mandava
44  *
45  * Updated 12/04/2014:
46  * New methods: evaluateExpression
47  * Refactored to share code with XPathExpressionImpl.
48  */
49 public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
50 
51     // Private variables
52     private XPathVariableResolver origVariableResolver;
53     private XPathFunctionResolver origFunctionResolver;
54     private NamespaceContext namespaceContext=null;
55 
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr)56     XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
57         this(vr, fr, false, new JdkXmlFeatures(false));
58     }
59 
XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing, JdkXmlFeatures featureManager)60     XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
61             boolean featureSecureProcessing, JdkXmlFeatures featureManager) {
62         this.origVariableResolver = this.variableResolver = vr;
63         this.origFunctionResolver = this.functionResolver = fr;
64         this.featureSecureProcessing = featureSecureProcessing;
65         this.featureManager = featureManager;
66         overrideDefaultParser = featureManager.getFeature(
67                 JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER);
68 
69     }
70 
71 
72     //-Override-
setXPathVariableResolver(XPathVariableResolver resolver)73     public void setXPathVariableResolver(XPathVariableResolver resolver) {
74         requireNonNull(resolver, "XPathVariableResolver");
75         this.variableResolver = resolver;
76     }
77 
78     //-Override-
getXPathVariableResolver()79     public XPathVariableResolver getXPathVariableResolver() {
80         return variableResolver;
81     }
82 
83     //-Override-
setXPathFunctionResolver(XPathFunctionResolver resolver)84     public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
85         requireNonNull(resolver, "XPathFunctionResolver");
86         this.functionResolver = resolver;
87     }
88 
89     //-Override-
getXPathFunctionResolver()90     public XPathFunctionResolver getXPathFunctionResolver() {
91         return functionResolver;
92     }
93 
94     //-Override-
setNamespaceContext(NamespaceContext nsContext)95     public void setNamespaceContext(NamespaceContext nsContext) {
96         requireNonNull(nsContext, "NamespaceContext");
97         this.namespaceContext = nsContext;
98         this.prefixResolver = new JAXPPrefixResolver (nsContext);
99     }
100 
101     //-Override-
getNamespaceContext()102     public NamespaceContext getNamespaceContext() {
103         return namespaceContext;
104     }
105 
106     /**
107      * Evaluate an {@code XPath} expression in the specified context.
108      * @param expression The XPath expression.
109      * @param contextItem The starting context.
110      * @return an XObject as the result of evaluating the expression
111      * @throws TransformerException if evaluating fails
112      */
eval(String expression, Object contextItem)113     private XObject eval(String expression, Object contextItem)
114         throws TransformerException {
115         requireNonNull(expression, "XPath expression");
116         com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression,
117             null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
118 
119         return eval(contextItem, xpath);
120     }
121 
122     //-Override-
evaluate(String expression, Object item, QName returnType)123     public Object evaluate(String expression, Object item, QName returnType)
124             throws XPathExpressionException {
125         //this check is necessary before calling eval to maintain binary compatibility
126         requireNonNull(expression, "XPath expression");
127         isSupported(returnType);
128 
129         try {
130 
131             XObject resultObject = eval(expression, item);
132             return getResultAsType(resultObject, returnType);
133         } catch (java.lang.NullPointerException npe) {
134             // If VariableResolver returns null Or if we get
135             // NullPointerException at this stage for some other reason
136             // then we have to reurn XPathException
137             throw new XPathExpressionException (npe);
138         } catch (TransformerException te) {
139             Throwable nestedException = te.getException();
140             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
141                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
142             } else {
143                 // For any other exceptions we need to throw
144                 // XPathExpressionException (as per spec)
145                 throw new XPathExpressionException (te);
146             }
147         }
148 
149     }
150 
151     //-Override-
evaluate(String expression, Object item)152     public String evaluate(String expression, Object item)
153         throws XPathExpressionException {
154         return (String)this.evaluate(expression, item, XPathConstants.STRING);
155     }
156 
157     //-Override-
compile(String expression)158     public XPathExpression compile(String expression)
159         throws XPathExpressionException {
160         requireNonNull(expression, "XPath expression");
161         try {
162             com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
163                     prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
164             // Can have errorListener
165             XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
166                     prefixResolver, functionResolver, variableResolver,
167                     featureSecureProcessing, featureManager);
168             return ximpl;
169         } catch (TransformerException te) {
170             throw new XPathExpressionException (te) ;
171         }
172     }
173 
174     //-Override-
evaluate(String expression, InputSource source, QName returnType)175     public Object evaluate(String expression, InputSource source,
176             QName returnType) throws XPathExpressionException {
177         isSupported(returnType);
178 
179         try {
180             Document document = getDocument(source);
181             XObject resultObject = eval(expression, document);
182             return getResultAsType(resultObject, returnType);
183         } catch (TransformerException te) {
184             Throwable nestedException = te.getException();
185             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
186                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
187             } else {
188                 throw new XPathExpressionException (te);
189             }
190         }
191     }
192 
193     //-Override-
evaluate(String expression, InputSource source)194     public String evaluate(String expression, InputSource source)
195         throws XPathExpressionException {
196         return (String)this.evaluate(expression, source, XPathConstants.STRING);
197     }
198 
199     //-Override-
reset()200     public void reset() {
201         this.variableResolver = this.origVariableResolver;
202         this.functionResolver = this.origFunctionResolver;
203         this.namespaceContext = null;
204     }
205 
206     //-Override-
evaluateExpression(String expression, Object item, Class<T> type)207     public <T> T evaluateExpression(String expression, Object item, Class<T> type)
208             throws XPathExpressionException {
209         isSupportedClassType(type);
210         try {
211             XObject resultObject = eval(expression, item);
212             if (type.isAssignableFrom(XPathEvaluationResult.class)) {
213                 return getXPathResult(resultObject, type);
214             } else {
215                 return XPathResultImpl.getValue(resultObject, type);
216             }
217         } catch (TransformerException te) {
218             throw new XPathExpressionException (te);
219         }
220     }
221 
222     //-Override-
evaluateExpression(String expression, Object item)223     public XPathEvaluationResult<?> evaluateExpression(String expression, Object item)
224             throws XPathExpressionException {
225         return evaluateExpression(expression, item, XPathEvaluationResult.class);
226     }
227 
228     //-Override-
evaluateExpression(String expression, InputSource source, Class<T> type)229     public <T> T evaluateExpression(String expression, InputSource source, Class<T> type)
230             throws XPathExpressionException {
231         Document document = getDocument(source);
232         return evaluateExpression(expression, document, type);
233     }
234 
235     //-Override-
evaluateExpression(String expression, InputSource source)236     public XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source)
237             throws XPathExpressionException {
238         return evaluateExpression(expression, source, XPathEvaluationResult.class);
239     }
240 }
241