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     @Override
  71     public void setXPathVariableResolver(XPathVariableResolver resolver) {
  72         requireNonNull(resolver, "XPathVariableResolver");
  73         this.variableResolver = resolver;
  74     }
  75 
  76     @Override
  77     public XPathVariableResolver getXPathVariableResolver() {
  78         return variableResolver;
  79     }
  80 
  81     @Override
  82     public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
  83         requireNonNull(resolver, "XPathFunctionResolver");
  84         this.functionResolver = resolver;
  85     }
  86 
  87     @Override
  88     public XPathFunctionResolver getXPathFunctionResolver() {
  89         return functionResolver;
  90     }
  91 
  92     @Override
  93     public void setNamespaceContext(NamespaceContext nsContext) {
  94         requireNonNull(nsContext, "NamespaceContext");
  95         this.namespaceContext = nsContext;
  96         this.prefixResolver = new JAXPPrefixResolver (nsContext);
  97     }
  98 
  99     @Override
 100     public NamespaceContext getNamespaceContext() {
 101         return namespaceContext;
 102     }
 103 
 104     /**
 105      * Evaluate an {@code XPath} expression in the specified context.
 106      * @param expression The XPath expression.
 107      * @param contextItem The starting context.
 108      * @return an XObject as the result of evaluating the expression
 109      * @throws TransformerException if evaluating fails
 110      */
 111     private XObject eval(String expression, Object contextItem)
 112         throws TransformerException {
 113         requireNonNull(expression, "XPath expression");
 114         com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression,
 115             null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
 116 
 117         return eval(contextItem, xpath);
 118     }
 119 
 120     @Override
 121     public Object evaluate(String expression, Object item, QName returnType)
 122             throws XPathExpressionException {
 123         //this check is necessary before calling eval to maintain binary compatibility
 124         requireNonNull(expression, "XPath expression");
 125         isSupported(returnType);
 126 
 127         try {
 128 
 129             XObject resultObject = eval(expression, item);
 130             return getResultAsType(resultObject, returnType);
 131         } catch (java.lang.NullPointerException npe) {
 132             // If VariableResolver returns null Or if we get
 133             // NullPointerException at this stage for some other reason
 134             // then we have to reurn XPathException
 135             throw new XPathExpressionException (npe);
 136         } catch (TransformerException te) {
 137             Throwable nestedException = te.getException();
 138             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
 139                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
 140             } else {
 141                 // For any other exceptions we need to throw
 142                 // XPathExpressionException (as per spec)
 143                 throw new XPathExpressionException (te);
 144             }
 145         }
 146 
 147     }
 148 
 149     @Override
 150     public String evaluate(String expression, Object item)
 151         throws XPathExpressionException {
 152         return (String)this.evaluate(expression, item, XPathConstants.STRING);
 153     }
 154 
 155     @Override
 156     public XPathExpression compile(String expression)
 157         throws XPathExpressionException {
 158         requireNonNull(expression, "XPath expression");
 159         try {
 160             com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
 161                     prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
 162             // Can have errorListener
 163             XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
 164                     prefixResolver, functionResolver, variableResolver,
 165                     featureSecureProcessing, useServiceMechanism, featureManager);
 166             return ximpl;
 167         } catch (TransformerException te) {
 168             throw new XPathExpressionException (te) ;
 169         }
 170     }
 171 
 172     @Override
 173     public Object evaluate(String expression, InputSource source,
 174             QName returnType) throws XPathExpressionException {
 175         isSupported(returnType);
 176 
 177         try {
 178             Document document = getDocument(source);
 179             XObject resultObject = eval(expression, document);
 180             return getResultAsType(resultObject, returnType);
 181         } catch (TransformerException te) {
 182             Throwable nestedException = te.getException();
 183             if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
 184                 throw (javax.xml.xpath.XPathFunctionException)nestedException;
 185             } else {
 186                 throw new XPathExpressionException (te);
 187             }
 188         }
 189     }
 190 
 191     @Override
 192     public String evaluate(String expression, InputSource source)
 193         throws XPathExpressionException {
 194         return (String)this.evaluate(expression, source, XPathConstants.STRING);
 195     }
 196 
 197     @Override
 198     public void reset() {
 199         this.variableResolver = this.origVariableResolver;
 200         this.functionResolver = this.origFunctionResolver;
 201         this.namespaceContext = null;
 202     }
 203 
 204     @Override
 205     public <T> T evaluateExpression(String expression, Object item, Class<T> type)
 206             throws XPathExpressionException {
 207         isSupportedClassType(type);
 208         try {
 209             XObject resultObject = eval(expression, item);
 210             if (type.isAssignableFrom(XPathEvaluationResult.class)) {
 211                 XPathEvaluationResult<?> x = getXPathResult(resultObject);
 212 
 213                 return (T)x;
 214             } else {
 215                 return XPathResultImpl.getValue(resultObject, type);
 216             }
 217         } catch (TransformerException te) {
 218             throw new XPathExpressionException (te);
 219         }
 220     }
 221 
 222     @Override
 223     public XPathEvaluationResult evaluateExpression(String expression, Object item)
 224             throws XPathExpressionException {
 225         return evaluateExpression(expression, item, XPathEvaluationResult.class);
 226     }
 227 
 228     @Override
 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
 236     public XPathEvaluationResult evaluateExpression(String expression, InputSource source)
 237             throws XPathExpressionException {
 238         return evaluateExpression(expression, source, XPathEvaluationResult.class);
 239     }
 240 }