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    package org.apache.xalan.extensions;
020    
021    import javax.xml.namespace.QName;
022    import javax.xml.xpath.XPathFunction;
023    import javax.xml.xpath.XPathFunctionResolver;
024    import org.apache.xalan.res.XSLMessages;
025    import org.apache.xalan.res.XSLTErrorResources;
026    
027    /**
028     * A sample implementation of XPathFunctionResolver, with support for
029     * EXSLT extension functions and Java extension functions.
030     */
031    public class XPathFunctionResolverImpl implements XPathFunctionResolver
032    {
033        /**
034         * Resolve an extension function from the qualified name and arity.
035         */
036        public XPathFunction resolveFunction(QName qname, int arity)
037        {
038            if (qname == null)
039                throw new NullPointerException(
040                    XSLMessages.createMessage(
041                        XSLTErrorResources.ER_XPATH_RESOLVER_NULL_QNAME, null));
042            
043            if (arity < 0)
044                throw new IllegalArgumentException(
045                    XSLMessages.createMessage(
046                        XSLTErrorResources.ER_XPATH_RESOLVER_NEGATIVE_ARITY, null));
047            
048            String uri = qname.getNamespaceURI();
049            if (uri == null || uri.length() == 0)
050                return null;
051            
052            String className = null;
053            String methodName = null;
054            if (uri.startsWith("http://exslt.org"))
055            {
056                className = getEXSLTClassName(uri);
057                methodName = qname.getLocalPart();
058            }
059            else if (!uri.equals(ExtensionNamespaceContext.JAVA_EXT_URI))
060            {
061                int lastSlash = className.lastIndexOf('/');
062                if (-1 != lastSlash)
063                    className = className.substring(lastSlash + 1);
064            }           
065     
066            String localPart = qname.getLocalPart();
067            int lastDotIndex = localPart.lastIndexOf('.');
068            if (lastDotIndex > 0)
069            {
070                if (className != null)
071                    className = className + "." + localPart.substring(0, lastDotIndex);
072                else
073                    className = localPart.substring(0, lastDotIndex);
074                    
075                methodName = localPart.substring(lastDotIndex + 1);
076            }
077            else
078                methodName = localPart;
079         
080            if(null == className || className.trim().length() == 0 
081               || null == methodName || methodName.trim().length() == 0) 
082                return null;
083        
084            ExtensionHandler handler = null;
085            try
086            {
087                ExtensionHandler.getClassForName(className);
088                handler = new ExtensionHandlerJavaClass(uri, "javaclass", className);
089            }
090            catch (ClassNotFoundException e)
091            {
092               return null;
093            }
094            return new XPathFunctionImpl(handler, methodName);
095        }
096        
097        /**
098         * Return the implementation class name of an EXSLT extension from
099         * a given namespace uri. The uri must starts with "http://exslt.org".
100         */
101        private String getEXSLTClassName(String uri)
102        {
103            if (uri.equals(ExtensionNamespaceContext.EXSLT_MATH_URI))
104                return "org.apache.xalan.lib.ExsltMath";
105            else if (uri.equals(ExtensionNamespaceContext.EXSLT_SET_URI))
106                return "org.apache.xalan.lib.ExsltSets";
107            else if (uri.equals(ExtensionNamespaceContext.EXSLT_STRING_URI))
108                return "org.apache.xalan.lib.ExsltStrings";
109            else if (uri.equals(ExtensionNamespaceContext.EXSLT_DATETIME_URI))
110                return "org.apache.xalan.lib.ExsltDatetime";
111            else if (uri.equals(ExtensionNamespaceContext.EXSLT_DYNAMIC_URI))
112                return "org.apache.xalan.lib.ExsltDynamic";
113            else if (uri.equals(ExtensionNamespaceContext.EXSLT_URI))
114                return "org.apache.xalan.lib.ExsltCommon";
115            else
116                return null;
117        }
118    }