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: ExtensionsTable.java 469672 2006-10-31 21:56:19Z minchau $
020     */
021    package org.apache.xalan.extensions;
022    
023    import java.util.Hashtable;
024    import java.util.Vector;
025    
026    import org.apache.xalan.res.XSLMessages;
027    import org.apache.xalan.res.XSLTErrorResources;
028    import org.apache.xalan.templates.StylesheetRoot;
029    import org.apache.xpath.XPathProcessorException;
030    import org.apache.xpath.functions.FuncExtFunction;
031    
032    /**
033     * Class holding a table registered extension namespace handlers
034     * @xsl.usage internal
035     */
036    public class ExtensionsTable
037    {  
038      /**
039       * Table of extensions that may be called from the expression language
040       * via the call(name, ...) function.  Objects are keyed on the call
041       * name.
042       * @xsl.usage internal
043       */
044      public Hashtable m_extensionFunctionNamespaces = new Hashtable();
045      
046      /**
047       * The StylesheetRoot associated with this extensions table.
048       */
049      private StylesheetRoot m_sroot;
050      
051      /**
052       * The constructor (called from TransformerImpl) registers the
053       * StylesheetRoot for the transformation and instantiates an
054       * ExtensionHandler for each extension namespace.
055       * @xsl.usage advanced
056       */
057      public ExtensionsTable(StylesheetRoot sroot)
058        throws javax.xml.transform.TransformerException
059      {
060        m_sroot = sroot;
061        Vector extensions = m_sroot.getExtensions();
062        for (int i = 0; i < extensions.size(); i++)
063        {
064          ExtensionNamespaceSupport extNamespaceSpt = 
065                     (ExtensionNamespaceSupport)extensions.get(i);
066          ExtensionHandler extHandler = extNamespaceSpt.launch();
067            if (extHandler != null)
068              addExtensionNamespace(extNamespaceSpt.getNamespace(), extHandler);
069          }
070        }
071           
072      /**
073       * Get an ExtensionHandler object that represents the
074       * given namespace.
075       * @param extns A valid extension namespace.
076       *
077       * @return ExtensionHandler object that represents the
078       * given namespace.
079       */
080      public ExtensionHandler get(String extns)
081      {
082        return (ExtensionHandler) m_extensionFunctionNamespaces.get(extns);
083      }
084    
085      /**
086       * Register an extension namespace handler. This handler provides
087       * functions for testing whether a function is known within the
088       * namespace and also for invoking the functions.
089       *
090       * @param uri the URI for the extension.
091       * @param extNS the extension handler.
092       * @xsl.usage advanced
093       */
094      public void addExtensionNamespace(String uri, ExtensionHandler extNS)
095      {
096        m_extensionFunctionNamespaces.put(uri, extNS);
097      }
098    
099      /**
100       * Execute the function-available() function.
101       * @param ns       the URI of namespace in which the function is needed
102       * @param funcName the function name being tested
103       *
104       * @return whether the given function is available or not.
105       *
106       * @throws javax.xml.transform.TransformerException
107       */
108      public boolean functionAvailable(String ns, String funcName)
109              throws javax.xml.transform.TransformerException
110      {
111        boolean isAvailable = false;
112        
113        if (null != ns)
114        {
115          ExtensionHandler extNS = 
116               (ExtensionHandler) m_extensionFunctionNamespaces.get(ns);
117          if (extNS != null)
118            isAvailable = extNS.isFunctionAvailable(funcName);
119        }
120        return isAvailable;
121      }
122      
123      /**
124       * Execute the element-available() function.
125       * @param ns       the URI of namespace in which the function is needed
126       * @param elemName name of element being tested
127       *
128       * @return whether the given element is available or not.
129       *
130       * @throws javax.xml.transform.TransformerException
131       */
132      public boolean elementAvailable(String ns, String elemName)
133              throws javax.xml.transform.TransformerException
134      {
135        boolean isAvailable = false;
136        if (null != ns)
137        {
138          ExtensionHandler extNS = 
139                   (ExtensionHandler) m_extensionFunctionNamespaces.get(ns);
140          if (extNS != null) // defensive
141            isAvailable = extNS.isElementAvailable(elemName);
142        } 
143        return isAvailable;        
144      }  
145      
146      /**
147       * Handle an extension function.
148       * @param ns        the URI of namespace in which the function is needed
149       * @param funcName  the function name being called
150       * @param argVec    arguments to the function in a vector
151       * @param methodKey a unique key identifying this function instance in the
152       *                  stylesheet
153       * @param exprContext a context which may be passed to an extension function
154       *                  and provides callback functions to access various
155       *                  areas in the environment
156       *
157       * @return result of executing the function
158       *
159       * @throws javax.xml.transform.TransformerException
160       */
161      public Object extFunction(String ns, String funcName, 
162                                Vector argVec, Object methodKey, 
163                                ExpressionContext exprContext)
164                throws javax.xml.transform.TransformerException
165      {
166        Object result = null;
167        if (null != ns)
168        {
169          ExtensionHandler extNS =
170            (ExtensionHandler) m_extensionFunctionNamespaces.get(ns);
171          if (null != extNS)
172          {
173            try
174            {
175              result = extNS.callFunction(funcName, argVec, methodKey,
176                                          exprContext);
177            }
178            catch (javax.xml.transform.TransformerException e)
179            {
180              throw e;
181            }
182            catch (Exception e)
183            {
184              throw new javax.xml.transform.TransformerException(e);
185            }
186          }
187          else
188          {
189            throw new XPathProcessorException(XSLMessages.createMessage(XSLTErrorResources.ER_EXTENSION_FUNC_UNKNOWN, new Object[]{ns, funcName })); 
190            //"Extension function '" + ns + ":" + funcName + "' is unknown");
191          }
192        }
193        return result;    
194      }
195      
196      /**
197       * Handle an extension function.
198       * @param extFunction  the extension function
199       * @param argVec    arguments to the function in a vector
200       * @param exprContext a context which may be passed to an extension function
201       *                  and provides callback functions to access various
202       *                  areas in the environment
203       *
204       * @return result of executing the function
205       *
206       * @throws javax.xml.transform.TransformerException
207       */
208      public Object extFunction(FuncExtFunction extFunction, Vector argVec, 
209                                ExpressionContext exprContext)
210             throws javax.xml.transform.TransformerException
211      {
212        Object result = null;
213        String ns = extFunction.getNamespace();
214        if (null != ns)
215        {
216          ExtensionHandler extNS =
217            (ExtensionHandler) m_extensionFunctionNamespaces.get(ns);
218          if (null != extNS)
219          {
220            try
221            {
222              result = extNS.callFunction(extFunction, argVec, exprContext);
223            }
224            catch (javax.xml.transform.TransformerException e)
225            {
226              throw e;
227            }
228            catch (Exception e)
229            {
230              throw new javax.xml.transform.TransformerException(e);
231            }
232          }
233          else
234          {
235            throw new XPathProcessorException(XSLMessages.createMessage(XSLTErrorResources.ER_EXTENSION_FUNC_UNKNOWN, 
236                                              new Object[]{ns, extFunction.getFunctionName()})); 
237          }
238        }
239        return result;        
240      }
241    }