1 /*
   2  * Copyright (c) 2013, 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.xalan.internal.res.XSLMessages;
  24 import com.sun.org.apache.xpath.internal.ExtensionsProvider;
  25 import com.sun.org.apache.xpath.internal.functions.FuncExtFunction;
  26 import com.sun.org.apache.xpath.internal.objects.XNodeSet;
  27 import com.sun.org.apache.xpath.internal.objects.XObject;
  28 import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 import javax.xml.namespace.QName;
  32 import javax.xml.xpath.XPathFunction;
  33 import javax.xml.xpath.XPathFunctionException;
  34 import javax.xml.xpath.XPathFunctionResolver;
  35 import jdk.xml.internal.JdkXmlFeatures;
  36 
  37 /**
  38  *
  39  * @author Ramesh Mandava ( ramesh.mandava@sun.com )
  40  * @LastModified: Nov 2017
  41  */
  42 public class JAXPExtensionsProvider implements ExtensionsProvider {
  43 
  44     private final XPathFunctionResolver resolver;
  45     private boolean extensionInvocationDisabled = false;
  46 
  47     public JAXPExtensionsProvider(XPathFunctionResolver resolver) {
  48         this.resolver = resolver;
  49         this.extensionInvocationDisabled = false;
  50     }
  51 
  52     public JAXPExtensionsProvider(XPathFunctionResolver resolver,
  53         boolean featureSecureProcessing, JdkXmlFeatures featureManager ) {
  54         this.resolver = resolver;
  55         if (featureSecureProcessing &&
  56                 !featureManager.getFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION)) {
  57             this.extensionInvocationDisabled = true;
  58         }
  59     }
  60 
  61     /**
  62      * Is the extension function available?
  63      */
  64 
  65     public boolean functionAvailable(String ns, String funcName)
  66           throws javax.xml.transform.TransformerException {
  67       try {
  68         if ( funcName == null ) {
  69             String fmsg = XSLMessages.createXPATHMessage(
  70                 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
  71                 new Object[] {"Function Name"} );
  72             throw new NullPointerException ( fmsg );
  73         }
  74         //Find the XPathFunction corresponding to namespace and funcName
  75         javax.xml.namespace.QName myQName = new QName( ns, funcName );
  76         javax.xml.xpath.XPathFunction xpathFunction =
  77             resolver.resolveFunction ( myQName, 0 );
  78         if (  xpathFunction == null ) {
  79             return false;
  80         }
  81         return true;
  82       } catch ( Exception e ) {
  83         return false;
  84       }
  85 
  86 
  87     }
  88 
  89 
  90     /**
  91      * Is the extension element available?
  92      */
  93     public boolean elementAvailable(String ns, String elemName)
  94           throws javax.xml.transform.TransformerException {
  95         return false;
  96     }
  97 
  98     /**
  99      * Execute the extension function.
 100      */
 101     public Object extFunction(String ns, String funcName, List<XObject> argVec,
 102         Object methodKey) throws javax.xml.transform.TransformerException {
 103         try {
 104 
 105             if ( funcName == null ) {
 106                 String fmsg = XSLMessages.createXPATHMessage(
 107                     XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
 108                     new Object[] {"Function Name"} );
 109                 throw new NullPointerException ( fmsg );
 110             }
 111             //Find the XPathFunction corresponding to namespace and funcName
 112             javax.xml.namespace.QName myQName = new QName( ns, funcName );
 113 
 114             // JAXP 1.3 spec says When XMLConstants.FEATURE_SECURE_PROCESSING
 115             // feature is set then invocation of extension functions need to
 116             // throw XPathFunctionException
 117             if ( extensionInvocationDisabled ) {
 118                 String fmsg = XSLMessages.createXPATHMessage(
 119                     XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED,
 120                     new Object[] { myQName.toString() } );
 121                 throw new XPathFunctionException ( fmsg );
 122             }
 123 
 124             // Assuming user is passing all the needed parameters ( including
 125             // default values )
 126             int arity = argVec.size();
 127 
 128             javax.xml.xpath.XPathFunction xpathFunction =
 129                 resolver.resolveFunction ( myQName, arity );
 130 
 131             // not using methodKey
 132             List<Object> argList = new ArrayList<>( arity);
 133             for ( int i=0; i<arity; i++ ) {
 134                 XObject argument = argVec.get( i );
 135                 // XNodeSet object() returns NodeVector and not NodeList
 136                 // Explicitly getting NodeList by using nodelist()
 137                 if ( argument instanceof XNodeSet ) {
 138                     argList.add ( i, ((XNodeSet)argument).nodelist() );
 139                 } else if ( argument instanceof XObject ) {
 140                     Object passedArgument = argument.object();
 141                     argList.add ( i, passedArgument );
 142                 } else {
 143                     argList.add ( i, argument );
 144                 }
 145             }
 146 
 147             return ( xpathFunction.evaluate ( argList ));
 148         } catch ( XPathFunctionException xfe ) {
 149             // If we get XPathFunctionException then we want to terminate
 150             // further execution by throwing WrappedRuntimeException
 151             throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException ( xfe );
 152         } catch ( Exception e ) {
 153             throw new javax.xml.transform.TransformerException ( e );
 154         }
 155 
 156     }
 157 
 158     /**
 159      * Execute the extension function.
 160      */
 161     public Object extFunction(FuncExtFunction extFunction, List<XObject> argVec)
 162         throws javax.xml.transform.TransformerException {
 163         try {
 164             String namespace = extFunction.getNamespace();
 165             String functionName = extFunction.getFunctionName();
 166             int arity = extFunction.getArgCount();
 167             javax.xml.namespace.QName myQName =
 168                 new javax.xml.namespace.QName( namespace, functionName );
 169 
 170             // JAXP 1.3 spec says  When XMLConstants.FEATURE_SECURE_PROCESSING
 171             // feature is set then invocation of extension functions need to
 172             // throw XPathFunctionException
 173             if ( extensionInvocationDisabled ) {
 174                 String fmsg = XSLMessages.createXPATHMessage(
 175                     XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED,
 176                         new Object[] { myQName.toString() } );
 177                 throw new XPathFunctionException ( fmsg );
 178             }
 179 
 180             XPathFunction xpathFunction =
 181                 resolver.resolveFunction( myQName, arity );
 182 
 183             List<Object> argList = new ArrayList<>( arity);
 184             for ( int i=0; i<arity; i++ ) {
 185                 XObject argument = argVec.get( i );
 186                 // XNodeSet object() returns NodeVector and not NodeList
 187                 // Explicitly getting NodeList by using nodelist()
 188                 if ( argument instanceof XNodeSet ) {
 189                     argList.add ( i, ((XNodeSet)argument).nodelist() );
 190                 } else if ( argument instanceof XObject ) {
 191                     Object passedArgument = argument.object();
 192                     argList.add ( i, passedArgument );
 193                 } else {
 194                     argList.add ( i, argument );
 195                 }
 196             }
 197 
 198             return ( xpathFunction.evaluate ( argList ));
 199 
 200         } catch ( XPathFunctionException xfe ) {
 201             // If we get XPathFunctionException then we want to terminate
 202             // further execution by throwing WrappedRuntimeException
 203             throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException ( xfe );
 204         } catch ( Exception e ) {
 205             throw new javax.xml.transform.TransformerException ( e );
 206         }
 207     }
 208 
 209 }