| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package com.sun.org.apache.xpath.internal.jaxp;  | 
 | 
 | 
 | 
import com.sun.org.apache.xalan.internal.res.XSLMessages;  | 
 | 
import com.sun.org.apache.xml.internal.dtm.DTM;  | 
 | 
import com.sun.org.apache.xpath.internal.axes.LocPathIterator;  | 
 | 
import com.sun.org.apache.xpath.internal.objects.XObject;  | 
 | 
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;  | 
 | 
import java.io.IOException;  | 
 | 
import javax.xml.namespace.QName;  | 
 | 
import javax.xml.parsers.DocumentBuilderFactory;  | 
 | 
import javax.xml.parsers.ParserConfigurationException;  | 
 | 
import javax.xml.transform.TransformerException;  | 
 | 
import javax.xml.xpath.XPathConstants;  | 
 | 
import javax.xml.xpath.XPathEvaluationResult;  | 
 | 
import javax.xml.xpath.XPathExpressionException;  | 
 | 
import javax.xml.xpath.XPathFunctionResolver;  | 
 | 
import javax.xml.xpath.XPathNodes;  | 
 | 
import javax.xml.xpath.XPathVariableResolver;  | 
 | 
import jdk.xml.internal.JdkXmlFeatures;  | 
 | 
import jdk.xml.internal.JdkXmlUtils;  | 
 | 
import org.w3c.dom.Document;  | 
 | 
import org.w3c.dom.Node;  | 
 | 
import org.w3c.dom.traversal.NodeIterator;  | 
 | 
import org.xml.sax.InputSource;  | 
 | 
import org.xml.sax.SAXException;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
class XPathImplUtil { | 
 | 
    XPathFunctionResolver functionResolver;  | 
 | 
    XPathVariableResolver variableResolver;  | 
 | 
    JAXPPrefixResolver prefixResolver;  | 
 | 
    boolean overrideDefaultParser;  | 
 | 
    // By default Extension Functions are allowed in XPath Expressions. If  | 
 | 
    // Secure Processing Feature is set on XPathFactory then the invocation of  | 
 | 
      | 
 | 
    boolean featureSecureProcessing = false;  | 
 | 
    JdkXmlFeatures featureManager;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath)  | 
 | 
            throws javax.xml.transform.TransformerException { | 
 | 
        com.sun.org.apache.xpath.internal.XPathContext xpathSupport;  | 
 | 
        if (contextItem == null && xpath.getExpression() instanceof LocPathIterator) { | 
 | 
              | 
 | 
            throw new TransformerException(XSLMessages.createXPATHMessage(  | 
 | 
                    XPATHErrorResources.ER_CONTEXT_CAN_NOT_BE_NULL,  | 
 | 
                    new Object[] {})); | 
 | 
        }  | 
 | 
        if (functionResolver != null) { | 
 | 
            JAXPExtensionsProvider jep = new JAXPExtensionsProvider(  | 
 | 
                    functionResolver, featureSecureProcessing, featureManager);  | 
 | 
            xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(jep);  | 
 | 
        } else { | 
 | 
            xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();  | 
 | 
        }  | 
 | 
 | 
 | 
        xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));  | 
 | 
        XObject xobj;  | 
 | 
 | 
 | 
        Node contextNode = (Node)contextItem;  | 
 | 
        // We always need to have a ContextNode with Xalan XPath implementation  | 
 | 
        // To allow simple expression evaluation like 1+1 we are setting  | 
 | 
          | 
 | 
        if (contextNode == null) { | 
 | 
            xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver);  | 
 | 
        } else { | 
 | 
            xobj = xpath.execute(xpathSupport, contextNode, prefixResolver);  | 
 | 
        }  | 
 | 
 | 
 | 
        return xobj;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    Document getDocument(InputSource source)  | 
 | 
        throws XPathExpressionException { | 
 | 
        requireNonNull(source, "Source");  | 
 | 
        try { | 
 | 
            // we'd really like to cache those DocumentBuilders, but we can't because:  | 
 | 
            // 1. thread safety. parsers are not thread-safe, so at least  | 
 | 
            //    we need one instance per a thread.  | 
 | 
            // 2. parsers are non-reentrant, so now we are looking at having a  | 
 | 
            // pool of parsers.  | 
 | 
            // 3. then the class loading issue. The look-up procedure of  | 
 | 
            //    DocumentBuilderFactory.newInstance() depends on context class loader  | 
 | 
            //    and system properties, which may change during the execution of JVM.  | 
 | 
            //  | 
 | 
            // so we really have to create a fresh DocumentBuilder every time we need one  | 
 | 
              | 
 | 
            DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser);  | 
 | 
            return dbf.newDocumentBuilder().parse(source);  | 
 | 
        } catch (ParserConfigurationException | SAXException | IOException e) { | 
 | 
            throw new XPathExpressionException (e);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    Object getResultAsType(XObject resultObject, QName returnType)  | 
 | 
        throws TransformerException { | 
 | 
          | 
 | 
        if (returnType.equals(XPathConstants.STRING)) { | 
 | 
            return resultObject.str();  | 
 | 
        }  | 
 | 
          | 
 | 
        if (returnType.equals(XPathConstants.NUMBER)) { | 
 | 
            return resultObject.num();  | 
 | 
        }  | 
 | 
          | 
 | 
        if (returnType.equals(XPathConstants.BOOLEAN)) { | 
 | 
            return resultObject.bool();  | 
 | 
        }  | 
 | 
          | 
 | 
        if (returnType.equals(XPathConstants.NODESET)) { | 
 | 
            return resultObject.nodelist();  | 
 | 
        }  | 
 | 
          | 
 | 
        if (returnType.equals(XPathConstants.NODE)) { | 
 | 
            NodeIterator ni = resultObject.nodeset();  | 
 | 
              | 
 | 
            return ni.nextNode();  | 
 | 
        }  | 
 | 
        // If isSupported check is already done then the execution path  | 
 | 
          | 
 | 
        String fmsg = XSLMessages.createXPATHMessage(  | 
 | 
                XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,  | 
 | 
                new Object[] { returnType.toString()}); | 
 | 
        throw new IllegalArgumentException (fmsg);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    <T> T getXPathResult(XObject resultObject, Class<T> type)  | 
 | 
            throws TransformerException { | 
 | 
        int resultType = resultObject.getType();  | 
 | 
 | 
 | 
        switch (resultType) { | 
 | 
            case XObject.CLASS_BOOLEAN :  | 
 | 
                return type.cast(new XPathResultImpl<>(resultObject, Boolean.class));  | 
 | 
            case XObject.CLASS_NUMBER :  | 
 | 
                return type.cast(new XPathResultImpl<>(resultObject, Double.class));  | 
 | 
            case XObject.CLASS_STRING :  | 
 | 
                return type.cast(new XPathResultImpl<>(resultObject, String.class));  | 
 | 
            case XObject.CLASS_NODESET :  | 
 | 
                return type.cast(new XPathResultImpl<>(resultObject, XPathNodes.class));  | 
 | 
            case XObject.CLASS_RTREEFRAG :    | 
 | 
                return type.cast(new XPathResultImpl<>(resultObject, Node.class));  | 
 | 
        }  | 
 | 
 | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    <T> void isSupportedClassType(Class<T> type) { | 
 | 
        requireNonNull(type, "The class type");  | 
 | 
        if (type.isAssignableFrom(Boolean.class) ||  | 
 | 
                type.isAssignableFrom(Double.class) ||  | 
 | 
                type.isAssignableFrom(Integer.class) ||  | 
 | 
                type.isAssignableFrom(Long.class) ||  | 
 | 
                type.isAssignableFrom(String.class) ||  | 
 | 
                type.isAssignableFrom(XPathNodes.class) ||  | 
 | 
                type.isAssignableFrom(Node.class) ||  | 
 | 
                type.isAssignableFrom(XPathEvaluationResult.class)) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        String fmsg = XSLMessages.createXPATHMessage(  | 
 | 
                XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,  | 
 | 
                new Object[] { type.toString() }); | 
 | 
        throw new IllegalArgumentException (fmsg);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    void isSupported(QName returnType) { | 
 | 
        requireNonNull(returnType, "returnType");  | 
 | 
        if (returnType.equals(XPathConstants.STRING) ||  | 
 | 
                returnType.equals(XPathConstants.NUMBER) ||  | 
 | 
                returnType.equals(XPathConstants.BOOLEAN) ||  | 
 | 
                returnType.equals(XPathConstants.NODE) ||  | 
 | 
                returnType.equals(XPathConstants.NODESET)) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        String fmsg = XSLMessages.createXPATHMessage(  | 
 | 
                XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,  | 
 | 
                new Object[] { returnType.toString() }); | 
 | 
        throw new IllegalArgumentException (fmsg);  | 
 | 
     }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    <T> void requireNonNull(T param, String paramName) { | 
 | 
        if (param == null) { | 
 | 
            String fmsg = XSLMessages.createXPATHMessage(  | 
 | 
                    XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,  | 
 | 
                    new Object[] {paramName}); | 
 | 
            throw new NullPointerException (fmsg);  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |