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: ExtensionNamespacesManager.java 1225575 2011-12-29 15:50:25Z mrglavas $
020 */
021 package org.apache.xalan.extensions;
022
023 import java.util.Vector;
024
025 import org.apache.xalan.templates.Constants;
026
027 /**
028 * Used during assembly of a stylesheet to collect the information for each
029 * extension namespace that is required during the transformation process
030 * to generate an {@link ExtensionHandler}.
031 *
032 */
033 public class ExtensionNamespacesManager
034 {
035 /**
036 * Vector of ExtensionNamespaceSupport objects to be used to generate ExtensionHandlers.
037 */
038 private Vector m_extensions = new Vector();
039 /**
040 * Vector of ExtensionNamespaceSupport objects for predefined ExtensionNamespaces. Elements
041 * from this vector are added to the m_extensions vector when encountered in the stylesheet.
042 */
043 private Vector m_predefExtensions = new Vector(7);
044 /**
045 * Vector of extension namespaces for which sufficient information is not yet available to
046 * complete the registration process.
047 */
048 private Vector m_unregisteredExtensions = new Vector();
049
050 /**
051 * An ExtensionNamespacesManager is instantiated the first time an extension function or
052 * element is found in the stylesheet. During initialization, a vector of ExtensionNamespaceSupport
053 * objects is created, one for each predefined extension namespace.
054 */
055 public ExtensionNamespacesManager()
056 {
057 setPredefinedNamespaces();
058 }
059
060 /**
061 * If necessary, register the extension namespace found compiling a function or
062 * creating an extension element.
063 *
064 * If it is a predefined namespace, create a
065 * support object to simplify the instantiate of an appropriate ExtensionHandler
066 * during transformation runtime. Otherwise, add the namespace, if necessary,
067 * to a vector of undefined extension namespaces, to be defined later.
068 *
069 */
070 public void registerExtension(String namespace)
071 {
072 if (namespaceIndex(namespace, m_extensions) == -1)
073 {
074 int predef = namespaceIndex(namespace, m_predefExtensions);
075 if (predef !=-1)
076 m_extensions.add(m_predefExtensions.get(predef));
077 else if (!(m_unregisteredExtensions.contains(namespace)))
078 m_unregisteredExtensions.add(namespace);
079 }
080 }
081
082 /**
083 * Register the extension namespace for an ElemExtensionDecl or ElemFunction,
084 * and prepare a support object to launch the appropriate ExtensionHandler at
085 * transformation runtime.
086 */
087 public void registerExtension(ExtensionNamespaceSupport extNsSpt)
088 {
089 String namespace = extNsSpt.getNamespace();
090 if (namespaceIndex(namespace, m_extensions) == -1)
091 {
092 m_extensions.add(extNsSpt);
093 if (m_unregisteredExtensions.contains(namespace))
094 m_unregisteredExtensions.remove(namespace);
095 }
096
097 }
098
099 /**
100 * Get the index for a namespace entry in the extension namespace Vector, -1 if
101 * no such entry yet exists.
102 */
103 public int namespaceIndex(String namespace, Vector extensions)
104 {
105 for (int i = 0; i < extensions.size(); i++)
106 {
107 if (((ExtensionNamespaceSupport)extensions.get(i)).getNamespace().equals(namespace))
108 return i;
109 }
110 return -1;
111 }
112
113
114 /**
115 * Get the vector of extension namespaces. Used to provide
116 * the extensions table access to a list of extension
117 * namespaces encountered during composition of a stylesheet.
118 */
119 public Vector getExtensions()
120 {
121 return m_extensions;
122 }
123
124 /**
125 * Attempt to register any unregistered extension namespaces.
126 */
127 public void registerUnregisteredNamespaces()
128 {
129 for (int i = 0; i < m_unregisteredExtensions.size(); i++)
130 {
131 String ns = (String)m_unregisteredExtensions.get(i);
132 ExtensionNamespaceSupport extNsSpt = defineJavaNamespace(ns);
133 if (extNsSpt != null)
134 m_extensions.add(extNsSpt);
135 }
136 }
137
138 /**
139 * For any extension namespace that is not either predefined or defined
140 * by a "component" declaration or exslt function declaration, attempt
141 * to create an ExtensionNamespaceSuport object for the appropriate
142 * Java class or Java package Extension Handler.
143 *
144 * Called by StylesheetRoot.recompose(), after all ElemTemplate compose()
145 * operations have taken place, in order to set up handlers for
146 * the remaining extension namespaces.
147 *
148 * @param ns The extension namespace URI.
149 * @return An ExtensionNamespaceSupport object for this namespace
150 * (which defines the ExtensionHandler to be used), or null if such
151 * an object cannot be created.
152 *
153 * @throws javax.xml.transform.TransformerException
154 */
155 public ExtensionNamespaceSupport defineJavaNamespace(String ns)
156 {
157 return defineJavaNamespace(ns, ns);
158 }
159 public ExtensionNamespaceSupport defineJavaNamespace(String ns, String classOrPackage)
160 {
161 if(null == ns || ns.trim().length() == 0) // defensive. I don't think it's needed. -sb
162 return null;
163
164 // Prepare the name of the actual class or package, stripping
165 // out any leading "class:". Next, see if there is a /. If so,
166 // only look at the text to the right of the rightmost /.
167 String className = classOrPackage;
168 if (className.startsWith("class:"))
169 className = className.substring(6);
170
171 int lastSlash = className.lastIndexOf('/');
172 if (-1 != lastSlash)
173 className = className.substring(lastSlash + 1);
174
175 // The className can be null here, and can cause an error in getClassForName
176 // in JDK 1.8.
177 if(null == className || className.trim().length() == 0)
178 return null;
179
180 try
181 {
182 ExtensionHandler.getClassForName(className);
183 return new ExtensionNamespaceSupport(
184 ns,
185 "org.apache.xalan.extensions.ExtensionHandlerJavaClass",
186 new Object[]{ns, "javaclass", className});
187 }
188 catch (ClassNotFoundException e)
189 {
190 return new ExtensionNamespaceSupport(
191 ns,
192 "org.apache.xalan.extensions.ExtensionHandlerJavaPackage",
193 new Object[]{ns, "javapackage", className + "."});
194 }
195 }
196
197 /*
198 public ExtensionNamespaceSupport getSupport(int index, Vector extensions)
199 {
200 return (ExtensionNamespaceSupport)extensions.elementAt(index);
201 }
202 */
203
204
205 /**
206 * Set up a Vector for predefined extension namespaces.
207 */
208 private void setPredefinedNamespaces()
209 {
210 String uri = Constants.S_EXTENSIONS_JAVA_URL;
211 String handlerClassName = "org.apache.xalan.extensions.ExtensionHandlerJavaPackage";
212 String lang = "javapackage";
213 String lib = "";
214 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
215 new Object[]{uri, lang, lib}));
216
217 uri = Constants.S_EXTENSIONS_OLD_JAVA_URL;
218 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
219 new Object[]{uri, lang, lib}));
220
221 uri = Constants.S_EXTENSIONS_LOTUSXSL_JAVA_URL;
222 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
223 new Object[]{uri, lang, lib}));
224
225 uri = Constants.S_BUILTIN_EXTENSIONS_URL;
226 handlerClassName = "org.apache.xalan.extensions.ExtensionHandlerJavaClass";
227 lang = "javaclass"; // for remaining predefined extension namespaces.
228 lib = "org.apache.xalan.lib.Extensions";
229 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
230 new Object[]{uri, lang, lib}));
231
232 uri = Constants.S_BUILTIN_OLD_EXTENSIONS_URL;
233 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
234 new Object[]{uri, lang, lib}));
235
236 // Xalan extension namespaces (redirect, pipe and SQL).
237 uri = Constants.S_EXTENSIONS_REDIRECT_URL;
238 lib = "org.apache.xalan.lib.Redirect";
239 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
240 new Object[]{uri, lang, lib}));
241
242 uri = Constants.S_EXTENSIONS_PIPE_URL;
243 lib = "org.apache.xalan.lib.PipeDocument";
244 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
245 new Object[]{uri, lang, lib}));
246
247 uri = Constants.S_EXTENSIONS_SQL_URL;
248 lib = "org.apache.xalan.lib.sql.XConnection";
249 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
250 new Object[]{uri, lang, lib}));
251
252
253 //EXSLT namespaces (not including EXSLT function namespaces which are
254 // registered by the associated ElemFunction.
255 uri = Constants.S_EXSLT_COMMON_URL;
256 lib = "org.apache.xalan.lib.ExsltCommon";
257 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
258 new Object[]{uri, lang, lib}));
259
260 uri = Constants.S_EXSLT_MATH_URL;
261 lib = "org.apache.xalan.lib.ExsltMath";
262 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
263 new Object[]{uri, lang, lib}));
264
265 uri = Constants.S_EXSLT_SETS_URL;
266 lib = "org.apache.xalan.lib.ExsltSets";
267 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
268 new Object[]{uri, lang, lib}));
269
270 uri = Constants.S_EXSLT_DATETIME_URL;
271 lib = "org.apache.xalan.lib.ExsltDatetime";
272 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
273 new Object[]{uri, lang, lib}));
274
275 uri = Constants.S_EXSLT_DYNAMIC_URL;
276 lib = "org.apache.xalan.lib.ExsltDynamic";
277 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
278 new Object[]{uri, lang, lib}));
279
280 uri = Constants.S_EXSLT_STRINGS_URL;
281 lib = "org.apache.xalan.lib.ExsltStrings";
282 m_predefExtensions.add(new ExtensionNamespaceSupport(uri, handlerClassName,
283 new Object[]{uri, lang, lib}));
284 }
285
286 }