1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 // $Id: JAXPExtensionsProvider.java 468655 2006-10-28 07:12:06Z minchau $ 20 21 package org.apache.xpath.jaxp; 22 23 import javax.xml.transform.TransformerException; 24 import javax.xml.xpath.XPathFunctionResolver; 25 import javax.xml.xpath.XPathFunction; 26 import javax.xml.xpath.XPathFunctionException; 27 28 import org.apache.xpath.ExtensionsProvider; 29 import org.apache.xpath.XPathContext; 30 import org.apache.xpath.objects.XObject; 31 import org.apache.xpath.objects.XNodeSet; 32 import org.apache.xpath.res.XPATHErrorResources; 33 import org.apache.xalan.res.XSLMessages; 34 35 import org.apache.xpath.functions.FuncExtFunction; 36 import java.util.Vector; 37 import java.util.ArrayList; 38 import javax.xml.namespace.QName; 39 40 /** 41 * 42 * @author Ramesh Mandava ( ramesh.mandava (at) sun.com ) 43 */ 44 public class JAXPExtensionsProvider implements ExtensionsProvider { 45 46 private final XPathFunctionResolver resolver; 47 private boolean extensionInvocationDisabled = false; 48 49 public JAXPExtensionsProvider(XPathFunctionResolver resolver) { 50 this.resolver = resolver; 51 this.extensionInvocationDisabled = false; 52 } 53 54 public JAXPExtensionsProvider(XPathFunctionResolver resolver, 55 boolean featureSecureProcessing ) { 56 this.resolver = resolver; 57 this.extensionInvocationDisabled = featureSecureProcessing; 58 } 59 60 /** 61 * Is the extension function available? 62 */ 63 64 public boolean functionAvailable(String ns, String funcName) 65 throws javax.xml.transform.TransformerException { 66 try { 67 if ( funcName == null ) { 68 String fmsg = XSLMessages.createXPATHMessage( 69 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, 70 new Object[] {"Function Name"} ); 71 throw new NullPointerException ( fmsg ); 72 } 73 //Find the XPathFunction corresponding to namespace and funcName 74 javax.xml.namespace.QName myQName = new QName( ns, funcName ); 75 javax.xml.xpath.XPathFunction xpathFunction = 76 resolver.resolveFunction ( myQName, 0 ); 77 if ( xpathFunction == null ) { 78 return false; 79 } 80 return true; 81 } catch ( Exception e ) { 82 return false; 83 } 84 85 86 } 87 88 89 /** 90 * Is the extension element available? 91 */ 92 public boolean elementAvailable(String ns, String elemName) 93 throws javax.xml.transform.TransformerException { 94 return false; 95 } 96 97 /** 98 * Execute the extension function. 99 */ 100 public Object extFunction(String ns, String funcName, Vector argVec, 101 Object methodKey) throws javax.xml.transform.TransformerException { 102 try { 103 104 if ( funcName == null ) { 105 String fmsg = XSLMessages.createXPATHMessage( 106 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, 107 new Object[] {"Function Name"} ); 108 throw new NullPointerException ( fmsg ); 109 } 110 //Find the XPathFunction corresponding to namespace and funcName 111 javax.xml.namespace.QName myQName = new QName( ns, funcName ); 112 113 // JAXP 1.3 spec says When XMLConstants.FEATURE_SECURE_PROCESSING 114 // feature is set then invocation of extension functions need to 115 // throw XPathFunctionException 116 if ( extensionInvocationDisabled ) { 117 String fmsg = XSLMessages.createXPATHMessage( 118 XPATHErrorResources.ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, 119 new Object[] { myQName.toString() } ); 120 throw new XPathFunctionException ( fmsg ); 121 } 122 123 // Assuming user is passing all the needed parameters ( including 124 // default values ) 125 int arity = argVec.size(); 126 127 javax.xml.xpath.XPathFunction xpathFunction = 128 resolver.resolveFunction ( myQName, arity ); 129 130 // not using methodKey 131 ArrayList argList = new ArrayList( arity); 132 for ( int i=0; i<arity; i++ ) { 133 Object argument = argVec.elementAt( i ); 134 // XNodeSet object() returns NodeVector and not NodeList 135 // Explicitly getting NodeList by using nodelist() 136 if ( argument instanceof XNodeSet ) { 137 argList.add ( i, ((XNodeSet)argument).nodelist() ); 138 } else if ( argument instanceof XObject ) { 139 Object passedArgument = ((XObject)argument).object(); 140 argList.add ( i, passedArgument ); 141 } else { 142 argList.add ( i, argument ); 143 } 144 } 145 146 return ( xpathFunction.evaluate ( argList )); 147 } catch ( XPathFunctionException xfe ) { 148 // If we get XPathFunctionException then we want to terminate 149 // further execution by throwing WrappedRuntimeException 150 throw new org.apache.xml.utils.WrappedRuntimeException ( xfe ); 151 } catch ( Exception e ) { 152 throw new javax.xml.transform.TransformerException ( e ); 153 } 154 155 } 156 157 /** 158 * Execute the extension function. 159 */ 160 public Object extFunction(FuncExtFunction extFunction, 161 Vector 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, new Object[] { myQName.toString() } ); 176 throw new XPathFunctionException ( fmsg ); 177 } 178 179 XPathFunction xpathFunction = 180 resolver.resolveFunction( myQName, arity ); 181 182 ArrayList argList = new ArrayList( arity); 183 for ( int i=0; i<arity; i++ ) { 184 Object argument = argVec.elementAt( i ); 185 // XNodeSet object() returns NodeVector and not NodeList 186 // Explicitly getting NodeList by using nodelist() 187 if ( argument instanceof XNodeSet ) { 188 argList.add ( i, ((XNodeSet)argument).nodelist() ); 189 } else if ( argument instanceof XObject ) { 190 Object passedArgument = ((XObject)argument).object(); 191 argList.add ( i, passedArgument ); 192 } else { 193 argList.add ( i, argument ); 194 } 195 } 196 197 return ( xpathFunction.evaluate ( argList )); 198 199 } catch ( XPathFunctionException xfe ) { 200 // If we get XPathFunctionException then we want to terminate 201 // further execution by throwing WrappedRuntimeException 202 throw new org.apache.xml.utils.WrappedRuntimeException ( xfe ); 203 } catch ( Exception e ) { 204 throw new javax.xml.transform.TransformerException ( e ); 205 } 206 } 207 208 } 209