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 }