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: ElemExtensionDecl.java 468643 2006-10-28 06:56:03Z minchau $
20 */
21package org.apache.xalan.templates;
22
23import javax.xml.transform.TransformerException;
24
25import org.apache.xalan.extensions.ExtensionNamespaceSupport;
26import org.apache.xalan.extensions.ExtensionNamespacesManager;
27import org.apache.xalan.res.XSLMessages;
28import org.apache.xalan.res.XSLTErrorResources;
29import org.apache.xalan.transformer.TransformerImpl;
30import org.apache.xml.utils.StringVector;
31
32/**
33 * Implement the declaration of an extension element
34 * @xsl.usage internal
35 */
36public class ElemExtensionDecl extends ElemTemplateElement
37{
38    static final long serialVersionUID = -4692738885172766789L;
39
40  /**
41   * Constructor ElemExtensionDecl
42   *
43   */
44  public ElemExtensionDecl()
45  {
46
47    // System.out.println("ElemExtensionDecl ctor");
48  }
49
50  /** Prefix string for this extension element.
51   *  @serial         */
52  private String m_prefix = null;
53
54  /**
55   * Set the prefix for this extension element
56   *
57   *
58   * @param v Prefix to set for this extension element
59   */
60  public void setPrefix(String v)
61  {
62    m_prefix = v;
63  }
64
65  /**
66   * Get the prefix for this extension element
67   *
68   *
69   * @return Prefix for this extension element
70   */
71  public String getPrefix()
72  {
73    return m_prefix;
74  }
75
76  /** StringVector holding the names of functions defined in this extension.
77   *  @serial     */
78  private StringVector m_functions = new StringVector();
79
80  /**
81   * Set the names of functions defined in this extension
82   *
83   *
84   * @param v StringVector holding the names of functions defined in this extension
85   */
86  public void setFunctions(StringVector v)
87  {
88    m_functions = v;
89  }
90
91  /**
92   * Get the names of functions defined in this extension
93   *
94   *
95   * @return StringVector holding the names of functions defined in this extension
96   */
97  public StringVector getFunctions()
98  {
99    return m_functions;
100  }
101
102  /**
103   * Get a function at a given index in this extension element
104   *
105   *
106   * @param i Index of function to get
107   *
108   * @return Name of Function at given index
109   *
110   * @throws ArrayIndexOutOfBoundsException
111   */
112  public String getFunction(int i) throws ArrayIndexOutOfBoundsException
113  {
114
115    if (null == m_functions)
116      throw new ArrayIndexOutOfBoundsException();
117
118    return (String) m_functions.elementAt(i);
119  }
120
121  /**
122   * Get count of functions defined in this extension element
123   *
124   *
125   * @return count of functions defined in this extension element
126   */
127  public int getFunctionCount()
128  {
129    return (null != m_functions) ? m_functions.size() : 0;
130  }
131
132  /** StringVector of elements defined in this extension.
133   *  @serial         */
134  private StringVector m_elements = null;
135
136  /**
137   * Set StringVector of elements for this extension
138   *
139   *
140   * @param v StringVector of elements to set
141   */
142  public void setElements(StringVector v)
143  {
144    m_elements = v;
145  }
146
147  /**
148   * Get StringVector of elements defined for this extension
149   *
150   *
151   * @return StringVector of elements defined for this extension
152   */
153  public StringVector getElements()
154  {
155    return m_elements;
156  }
157
158  /**
159   * Get the element at the given index
160   *
161   *
162   * @param i Index of element to get
163   *
164   * @return The element at the given index
165   *
166   * @throws ArrayIndexOutOfBoundsException
167   */
168  public String getElement(int i) throws ArrayIndexOutOfBoundsException
169  {
170
171    if (null == m_elements)
172      throw new ArrayIndexOutOfBoundsException();
173
174    return (String) m_elements.elementAt(i);
175  }
176
177  /**
178   * Return the count of elements defined for this extension element
179   *
180   *
181   * @return the count of elements defined for this extension element
182   */
183  public int getElementCount()
184  {
185    return (null != m_elements) ? m_elements.size() : 0;
186  }
187
188  /**
189   * Get an int constant identifying the type of element.
190   * @see org.apache.xalan.templates.Constants
191   *
192   * @return The token ID for this element
193   */
194  public int getXSLToken()
195  {
196    return Constants.ELEMNAME_EXTENSIONDECL;
197  }
198
199  public void compose(StylesheetRoot sroot) throws TransformerException
200  {
201    super.compose(sroot);
202    String prefix = getPrefix();
203    String declNamespace = getNamespaceForPrefix(prefix);
204    String lang = null;
205    String srcURL = null;
206    String scriptSrc = null;
207    if (null == declNamespace)
208      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[]{prefix}));
209      //"Prefix " + prefix does not have a corresponding namespace declaration");
210    for (ElemTemplateElement child = getFirstChildElem(); child != null;
211          child = child.getNextSiblingElem())
212    {
213      if (Constants.ELEMNAME_EXTENSIONSCRIPT == child.getXSLToken())
214      {
215        ElemExtensionScript sdecl = (ElemExtensionScript) child;
216        lang = sdecl.getLang();
217        srcURL = sdecl.getSrc();
218        ElemTemplateElement childOfSDecl = sdecl.getFirstChildElem();
219        if (null != childOfSDecl)
220        {
221          if (Constants.ELEMNAME_TEXTLITERALRESULT
222                  == childOfSDecl.getXSLToken())
223          {
224            ElemTextLiteral tl = (ElemTextLiteral) childOfSDecl;
225            char[] chars = tl.getChars();
226            scriptSrc = new String(chars);
227            if (scriptSrc.trim().length() == 0)
228              scriptSrc = null;
229          }
230        }
231      }
232    }
233    if (null == lang)
234      lang = "javaclass";
235    if (lang.equals("javaclass") && (scriptSrc != null))
236        throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[]{scriptSrc}));
237        //"Element content not allowed for lang=javaclass " + scriptSrc);
238
239    // Register the extension namespace if it has not already been registered.
240    ExtensionNamespaceSupport extNsSpt = null;
241    ExtensionNamespacesManager extNsMgr = sroot.getExtensionNamespacesManager();
242    if (extNsMgr.namespaceIndex(declNamespace,
243                                extNsMgr.getExtensions()) == -1)
244    {
245      if (lang.equals("javaclass"))
246      {
247        if (null == srcURL)
248        {
249           extNsSpt = extNsMgr.defineJavaNamespace(declNamespace);
250        }
251        else if (extNsMgr.namespaceIndex(srcURL,
252                                         extNsMgr.getExtensions()) == -1)
253        {
254          extNsSpt = extNsMgr.defineJavaNamespace(declNamespace, srcURL);
255        }
256      }
257      else  // not java
258      {
259        String handler = "org.apache.xalan.extensions.ExtensionHandlerGeneral";
260        Object [] args = {declNamespace, this.m_elements, this.m_functions,
261                          lang, srcURL, scriptSrc, getSystemId()};
262        extNsSpt = new ExtensionNamespaceSupport(declNamespace, handler, args);
263      }
264    }
265    if (extNsSpt != null)
266      extNsMgr.registerExtension(extNsSpt);
267  }
268
269
270  /**
271   * This function will be called on top-level elements
272   * only, just before the transform begins.
273   *
274   * @param transformer The XSLT TransformerFactory.
275   *
276   * @throws TransformerException
277   */
278  public void runtimeInit(TransformerImpl transformer) throws TransformerException
279  {
280/*    //System.out.println("ElemExtensionDecl.runtimeInit()");
281    String lang = null;
282    String srcURL = null;
283    String scriptSrc = null;
284    String prefix = getPrefix();
285    String declNamespace = getNamespaceForPrefix(prefix);
286
287    if (null == declNamespace)
288      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[]{prefix}));
289      //"Prefix " + prefix does not have a corresponding namespace declaration");
290
291    for (ElemTemplateElement child = getFirstChildElem(); child != null;
292            child = child.getNextSiblingElem())
293    {
294      if (Constants.ELEMNAME_EXTENSIONSCRIPT == child.getXSLToken())
295      {
296        ElemExtensionScript sdecl = (ElemExtensionScript) child;
297
298        lang = sdecl.getLang();
299        srcURL = sdecl.getSrc();
300
301        ElemTemplateElement childOfSDecl = sdecl.getFirstChildElem();
302
303        if (null != childOfSDecl)
304        {
305          if (Constants.ELEMNAME_TEXTLITERALRESULT
306                  == childOfSDecl.getXSLToken())
307          {
308            ElemTextLiteral tl = (ElemTextLiteral) childOfSDecl;
309            char[] chars = tl.getChars();
310
311            scriptSrc = new String(chars);
312
313            if (scriptSrc.trim().length() == 0)
314              scriptSrc = null;
315          }
316        }
317      }
318    }
319
320    if (null == lang)
321      lang = "javaclass";
322
323    if (lang.equals("javaclass") && (scriptSrc != null))
324      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[]{scriptSrc}));
325      //"Element content not allowed for lang=javaclass " + scriptSrc);
326
327    // Instantiate a handler for this extension namespace.
328    ExtensionsTable etable = transformer.getExtensionsTable();
329    ExtensionHandler nsh = etable.get(declNamespace);
330
331    // If we have no prior ExtensionHandler for this namespace, we need to
332    // create one.
333    // If the script element is for javaclass, this is our special compiled java.
334    // Element content is not supported for this so we throw an exception if
335    // it is provided.  Otherwise, we look up the srcURL to see if we already have
336    // an ExtensionHandler.
337    if (null == nsh)
338    {
339      if (lang.equals("javaclass"))
340      {
341        if (null == srcURL)
342        {
343          nsh = etable.makeJavaNamespace(declNamespace);
344        }
345        else
346        {
347          nsh = etable.get(srcURL);
348
349          if (null == nsh)
350          {
351            nsh = etable.makeJavaNamespace(srcURL);
352          }
353        }
354      }
355      else  // not java
356      {
357        nsh = new ExtensionHandlerGeneral(declNamespace, this.m_elements,
358                                          this.m_functions, lang, srcURL,
359                                          scriptSrc, getSystemId());
360
361        // System.out.println("Adding NS Handler: declNamespace = "+
362        //                   declNamespace+", lang = "+lang+", srcURL = "+
363        //                   srcURL+", scriptSrc="+scriptSrc);
364      }
365
366      etable.addExtensionNamespace(declNamespace, nsh);
367    }*/
368  }
369}
370