1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: ExtensionNamespacesManager.java 469672 2006-10-31 21:56:19Z minchau $
20 */
21package org.apache.xalan.extensions;
22
23import java.util.Vector;
24
25import org.apache.xalan.templates.Constants;
26
27/**
28 * Used during assembly of a stylesheet to collect the information for each
29 * extension namespace that is required during the transformation process
30 * to generate an {@link ExtensionHandler}.
31 *
32 */
33public class ExtensionNamespacesManager
34{
35  /**
36   * Vector of ExtensionNamespaceSupport objects to be used to generate ExtensionHandlers.
37   */
38  private Vector m_extensions = new Vector();
39  /**
40   * Vector of ExtensionNamespaceSupport objects for predefined ExtensionNamespaces. Elements
41   * from this vector are added to the m_extensions vector when encountered in the stylesheet.
42   */
43  private Vector m_predefExtensions = new Vector(7);
44  /**
45   * Vector of extension namespaces for which sufficient information is not yet available to
46   * complete the registration process.
47   */
48  private Vector m_unregisteredExtensions = new Vector();
49
50  /**
51   * An ExtensionNamespacesManager is instantiated the first time an extension function or
52   * element is found in the stylesheet. During initialization, a vector of ExtensionNamespaceSupport
53   * objects is created, one for each predefined extension namespace.
54   */
55  public ExtensionNamespacesManager()
56  {
57    setPredefinedNamespaces();
58  }
59
60  /**
61   * If necessary, register the extension namespace found compiling a function or
62   * creating an extension element.
63   *
64   * If it is a predefined namespace, create a
65   * support object to simplify the instantiate of an appropriate ExtensionHandler
66   * during transformation runtime. Otherwise, add the namespace, if necessary,
67   * to a vector of undefined extension namespaces, to be defined later.
68   *
69   */
70  public void registerExtension(String namespace)
71  {
72    if (namespaceIndex(namespace, m_extensions) == -1)
73    {
74      int predef = namespaceIndex(namespace, m_predefExtensions);
75      if (predef !=-1)
76        m_extensions.add(m_predefExtensions.get(predef));
77      else if (!(m_unregisteredExtensions.contains(namespace)))
78        m_unregisteredExtensions.add(namespace);
79    }
80  }
81
82  /**
83   * Register the extension namespace for an ElemExtensionDecl or ElemFunction,
84   * and prepare a support object to launch the appropriate ExtensionHandler at
85   * transformation runtime.
86   */
87  public void registerExtension(ExtensionNamespaceSupport extNsSpt)
88  {
89    String namespace = extNsSpt.getNamespace();
90    if (namespaceIndex(namespace, m_extensions) == -1)
91    {
92      m_extensions.add(extNsSpt);
93      if (m_unregisteredExtensions.contains(namespace))
94        m_unregisteredExtensions.remove(namespace);
95    }
96
97  }
98
99  /**
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}
287