001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    // $Id: JAXPExtensionsProvider.java 468655 2006-10-28 07:12:06Z minchau $
020    
021    package org.apache.xpath.jaxp;
022    
023    import javax.xml.transform.TransformerException;
024    import javax.xml.xpath.XPathFunctionResolver;
025    import javax.xml.xpath.XPathFunction;
026    import javax.xml.xpath.XPathFunctionException;
027    
028    import org.apache.xpath.ExtensionsProvider;
029    import org.apache.xpath.XPathContext;
030    import org.apache.xpath.objects.XObject;
031    import org.apache.xpath.objects.XNodeSet;
032    import org.apache.xpath.res.XPATHErrorResources;
033    import org.apache.xalan.res.XSLMessages;
034    
035    import org.apache.xpath.functions.FuncExtFunction;
036    import java.util.Vector;
037    import java.util.ArrayList;
038    import javax.xml.namespace.QName;
039    
040    /**
041     * 
042     * @author Ramesh Mandava ( ramesh.mandava@sun.com )
043     */
044    public class JAXPExtensionsProvider implements ExtensionsProvider {
045            
046        private final XPathFunctionResolver resolver;
047        private boolean extensionInvocationDisabled = false;
048            
049        public JAXPExtensionsProvider(XPathFunctionResolver resolver) {
050            this.resolver = resolver;
051            this.extensionInvocationDisabled = false;
052        }
053    
054        public JAXPExtensionsProvider(XPathFunctionResolver resolver, 
055            boolean featureSecureProcessing ) {
056            this.resolver = resolver;
057            this.extensionInvocationDisabled = featureSecureProcessing;
058        }
059    
060        /**
061         * Is the extension function available?
062         */
063    
064        public boolean functionAvailable(String ns, String funcName)
065              throws javax.xml.transform.TransformerException {
066          try {
067            if ( funcName == null ) {
068                String fmsg = XSLMessages.createXPATHMessage( 
069                    XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
070                    new Object[] {"Function Name"} );
071                throw new NullPointerException ( fmsg ); 
072            }
073            //Find the XPathFunction corresponding to namespace and funcName
074            javax.xml.namespace.QName myQName = new QName( ns, funcName );
075            javax.xml.xpath.XPathFunction xpathFunction = 
076                resolver.resolveFunction ( myQName, 0 );
077            if (  xpathFunction == null ) {
078                return false;
079            }
080            return true;
081          } catch ( Exception e ) {
082            return false;
083          }
084           
085    
086        }
087            
088    
089        /**
090         * Is the extension element available?
091         */
092        public boolean elementAvailable(String ns, String elemName)
093              throws javax.xml.transform.TransformerException {
094            return false;
095        }
096    
097        /**
098         * Execute the extension function.
099         */
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    }