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
21package org.apache.xpath.jaxp;
22
23import javax.xml.transform.TransformerException;
24import javax.xml.xpath.XPathFunctionResolver;
25import javax.xml.xpath.XPathFunction;
26import javax.xml.xpath.XPathFunctionException;
27
28import org.apache.xpath.ExtensionsProvider;
29import org.apache.xpath.XPathContext;
30import org.apache.xpath.objects.XObject;
31import org.apache.xpath.objects.XNodeSet;
32import org.apache.xpath.res.XPATHErrorResources;
33import org.apache.xalan.res.XSLMessages;
34
35import org.apache.xpath.functions.FuncExtFunction;
36import java.util.Vector;
37import java.util.ArrayList;
38import javax.xml.namespace.QName;
39
40/**
41 *
42 * @author Ramesh Mandava ( ramesh.mandava@sun.com )
43 */
44public 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