1 /*
   2  * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Copyright 1999-2004 The Apache Software Foundation.
   6  *
   7  * Licensed under the Apache License, Version 2.0 (the "License");
   8  * you may not use this file except in compliance with the License.
   9  * You may obtain a copy of the License at
  10  *
  11  *     http://www.apache.org/licenses/LICENSE-2.0
  12  *
  13  * Unless required by applicable law or agreed to in writing, software
  14  * distributed under the License is distributed on an "AS IS" BASIS,
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16  * See the License for the specific language governing permissions and
  17  * limitations under the License.
  18  */
  19 // $Id: XPathImpl.java,v 1.2 2005/08/16 22:41:08 jeffsuttor Exp $
  20 
  21 package com.sun.org.apache.xpath.internal.jaxp;
  22 
  23 import javax.xml.namespace.QName;
  24 import javax.xml.namespace.NamespaceContext;
  25 import javax.xml.xpath.XPathExpressionException;
  26 import javax.xml.xpath.XPathConstants;
  27 import javax.xml.xpath.XPathFunctionResolver;
  28 import javax.xml.xpath.XPathVariableResolver;
  29 import javax.xml.xpath.XPathExpression;
  30 import com.sun.org.apache.xpath.internal.*;
  31 import com.sun.org.apache.xpath.internal.objects.XObject;
  32 import com.sun.org.apache.xalan.internal.utils.FeatureManager;
  33 import org.w3c.dom.Document;
  34 import org.xml.sax.InputSource;
  35 import javax.xml.transform.TransformerException;
  36 import javax.xml.xpath.XPathEvaluationResult;
  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 
  56     XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
  57         this(vr, fr, false, true, new FeatureManager());
  58     }
  59 
  60     XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
  61             boolean featureSecureProcessing, boolean useServiceMechanism,
  62             FeatureManager featureManager) {
  63         this.origVariableResolver = this.variableResolver = vr;
  64         this.origFunctionResolver = this.functionResolver = fr;
  65         this.featureSecureProcessing = featureSecureProcessing;
  66         this.useServiceMechanism = useServiceMechanism;
  67         this.featureManager = featureManager;
  68     }
  69 
  70 
  71     //-Override-
  72     public void setXPathVariableResolver(XPathVariableResolver resolver) {
  73         requireNonNull(resolver, "XPathVariableResolver");
  74         this.variableResolver = resolver;
  75     }
  76 
  77     //-Override-
  78     public XPathVariableResolver getXPathVariableResolver() {
  79         return variableResolver;
  80     }
  81 
  82     //-Override-
  83     public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
  84         requireNonNull(resolver, "XPathFunctionResolver");
  85         this.functionResolver = resolver;
  86     }
  87 
  88     //-Override-
  89     public XPathFunctionResolver getXPathFunctionResolver() {
  90         return functionResolver;
  91     }
  92 
  93     //-Override-
  94     public void setNamespaceContext(NamespaceContext nsContext) {
  95         requireNonNull(nsContext, "NamespaceContext");
  96         this.namespaceContext = nsContext;
  97         this.prefixResolver = new JAXPPrefixResolver (nsContext);
  98     }
  99 
 100     //-Override-
 101     public NamespaceContext getNamespaceContext() {
 102         return namespaceContext;
 103     }
 104 
 105     /**
 106      * Evaluate an {@code XPath} expression in the specified context.
 107      * @param expression The XPath expression.
 108      * @param contextItem The starting context.
 109      * @return an XObject as the result of evaluating the expression
 110      * @throws TransformerException if evaluating fails
 111      */
 112     private XObject eval(String expression, Object contextItem)
 113         throws TransformerException {
 114         requireNonNull(expression, "XPath expression");
 115         com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression,
 116             null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
 117 
 118         return eval(contextItem, xpath);
 119     }
 120 
 121     //-Override-
 122     public Object evaluate(String expression, Object item, QName returnType)
 123             throws XPathExpressionException {
 124         //this check is necessary before calling eval to maintain binary compatibility
 125         requireNonNull(expression, "XPath expression");
 126         isSupported(returnType);
 127 
 128         try {
 129 
 130             XObject resultObject = eval(expression, item);
 131             return getResultAsType(resultObject, returnType);
 132         } catch (java.lang.NullPointerException npe) {
 133             // If VariableResolver returns null Or if we get
 134             // NullPointerException at this stage for some other reason
 135             // then we have to reurn XPathException
 136             throw new XPathExpressionException (npe);
 137         } catch (TransformerException te) {
 138             Throwable nestedException = te.getException();
 139             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
 140                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
 141             } else {
 142                 // For any other exceptions we need to throw
 143                 // XPathExpressionException (as per spec)
 144                 throw new XPathExpressionException (te);
 145             }
 146         }
 147 
 148     }
 149 
 150     //-Override-
 151     public String evaluate(String expression, Object item)
 152         throws XPathExpressionException {
 153         return (String)this.evaluate(expression, item, XPathConstants.STRING);
 154     }
 155 
 156     //-Override-
 157     public XPathExpression compile(String expression)
 158         throws XPathExpressionException {
 159         requireNonNull(expression, "XPath expression");
 160         try {
 161             com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
 162                     prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
 163             // Can have errorListener
 164             XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
 165                     prefixResolver, functionResolver, variableResolver,
 166                     featureSecureProcessing, useServiceMechanism, featureManager);
 167             return ximpl;
 168         } catch (TransformerException te) {
 169             throw new XPathExpressionException (te) ;
 170         }
 171     }
 172 
 173     //-Override-
 174     public Object evaluate(String expression, InputSource source,
 175             QName returnType) throws XPathExpressionException {
 176         isSupported(returnType);
 177 
 178         try {
 179             Document document = getDocument(source);
 180             XObject resultObject = eval(expression, document);
 181             return getResultAsType(resultObject, returnType);
 182         } catch (TransformerException te) {
 183             Throwable nestedException = te.getException();
 184             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
 185                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
 186             } else {
 187                 throw new XPathExpressionException (te);
 188             }
 189         }
 190     }
 191 
 192     //-Override-
 193     public String evaluate(String expression, InputSource source)
 194         throws XPathExpressionException {
 195         return (String)this.evaluate(expression, source, XPathConstants.STRING);
 196     }
 197 
 198     //-Override-
 199     public void reset() {
 200         this.variableResolver = this.origVariableResolver;
 201         this.functionResolver = this.origFunctionResolver;
 202         this.namespaceContext = null;
 203     }
 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     }
 239 }