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  */
21 package org.apache.xalan.templates;
22 
23 import javax.xml.transform.TransformerException;
24 
25 import org.apache.xalan.extensions.ExtensionNamespaceSupport;
26 import org.apache.xalan.extensions.ExtensionNamespacesManager;
27 import org.apache.xalan.res.XSLMessages;
28 import org.apache.xalan.res.XSLTErrorResources;
29 import org.apache.xalan.transformer.TransformerImpl;
30 import org.apache.xml.utils.StringVector;
31 
32 /**
33  * Implement the declaration of an extension element
34  * @xsl.usage internal
35  */
36 public class ElemExtensionDecl extends ElemTemplateElement
37 {
38     static final long serialVersionUID = -4692738885172766789L;
39 
40   /**
41    * Constructor ElemExtensionDecl
42    *
43    */
ElemExtensionDecl()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    */
setPrefix(String v)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    */
getPrefix()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    */
setFunctions(StringVector v)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    */
getFunctions()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    */
getFunction(int i)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    */
getFunctionCount()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    */
setElements(StringVector v)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    */
getElements()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    */
getElement(int i)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    */
getElementCount()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    */
getXSLToken()194   public int getXSLToken()
195   {
196     return Constants.ELEMNAME_EXTENSIONDECL;
197   }
198 
compose(StylesheetRoot sroot)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    */
runtimeInit(TransformerImpl transformer)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