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: ElemExtensionDecl.java 468643 2006-10-28 06:56:03Z minchau $
020     */
021    package org.apache.xalan.templates;
022    
023    import javax.xml.transform.TransformerException;
024    
025    import org.apache.xalan.extensions.ExtensionNamespaceSupport;
026    import org.apache.xalan.extensions.ExtensionNamespacesManager;
027    import org.apache.xalan.res.XSLMessages;
028    import org.apache.xalan.res.XSLTErrorResources;
029    import org.apache.xalan.transformer.TransformerImpl;
030    import org.apache.xml.utils.StringVector;
031    
032    /**
033     * Implement the declaration of an extension element 
034     * @xsl.usage internal
035     */
036    public class ElemExtensionDecl extends ElemTemplateElement
037    {
038        static final long serialVersionUID = -4692738885172766789L;
039    
040      /**
041       * Constructor ElemExtensionDecl
042       *
043       */
044      public ElemExtensionDecl()
045      {
046    
047        // System.out.println("ElemExtensionDecl ctor");
048      }
049    
050      /** Prefix string for this extension element.
051       *  @serial         */
052      private String m_prefix = null;
053    
054      /**
055       * Set the prefix for this extension element  
056       *
057       *
058       * @param v Prefix to set for this extension element
059       */
060      public void setPrefix(String v)
061      {
062        m_prefix = v;
063      }
064    
065      /**
066       * Get the prefix for this extension element
067       *
068       *
069       * @return Prefix for this extension element
070       */
071      public String getPrefix()
072      {
073        return m_prefix;
074      }
075    
076      /** StringVector holding the names of functions defined in this extension.
077       *  @serial     */
078      private StringVector m_functions = new StringVector();
079    
080      /**
081       * Set the names of functions defined in this extension  
082       *
083       *
084       * @param v StringVector holding the names of functions defined in this extension
085       */
086      public void setFunctions(StringVector v)
087      {
088        m_functions = v;
089      }
090    
091      /**
092       * Get the names of functions defined in this extension
093       *
094       *
095       * @return StringVector holding the names of functions defined in this extension
096       */
097      public StringVector getFunctions()
098      {
099        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    }