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 }