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@sun.com )
43  */
44 public class JAXPExtensionsProvider implements ExtensionsProvider {
45 
46     private final XPathFunctionResolver resolver;
47     private boolean extensionInvocationDisabled = false;
48 
JAXPExtensionsProvider(XPathFunctionResolver resolver)49     public JAXPExtensionsProvider(XPathFunctionResolver resolver) {
50         this.resolver = resolver;
51         this.extensionInvocationDisabled = false;
52     }
53 
JAXPExtensionsProvider(XPathFunctionResolver resolver, boolean featureSecureProcessing )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 
functionAvailable(String ns, String funcName)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      */
elementAvailable(String ns, String elemName)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      */
extFunction(String ns, String funcName, Vector argVec, Object methodKey)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      */
extFunction(FuncExtFunction extFunction, Vector argVec)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