Home | History | Annotate | Download | only in templates
      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: ElemExtensionCall.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.ExtensionHandler;
     26 import org.apache.xalan.extensions.ExtensionsTable;
     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.xpath.XPathContext;
     31 import org.xml.sax.SAXException;
     32 
     33 /**
     34  * Implement an extension element.
     35  * @see <a href="http://www.w3.org/TR/xslt#extension-element">extension-element in XSLT Specification</a>
     36  * @xsl.usage advanced
     37  */
     38 public class ElemExtensionCall extends ElemLiteralResult
     39 {
     40     static final long serialVersionUID = 3171339708500216920L;
     41 
     42   /** The Namespace URI for this extension call element.
     43    *  @serial          */
     44   String m_extns;
     45 
     46   /** Language used by extension.
     47    *  @serial          */
     48   String m_lang;
     49 
     50   /** URL pointing to extension.
     51    *  @serial          */
     52   String m_srcURL;
     53 
     54   /** Source for script.
     55    *  @serial          */
     56   String m_scriptSrc;
     57 
     58   /** Declaration for Extension element.
     59    *  @serial          */
     60   ElemExtensionDecl m_decl = null;
     61 
     62   /**
     63    * Get an int constant identifying the type of element.
     64    * @see org.apache.xalan.templates.Constants
     65    *
     66    *@return The token ID for this element
     67    */
     68   public int getXSLToken()
     69   {
     70     return Constants.ELEMNAME_EXTENSIONCALL;
     71   }
     72 
     73   /**
     74    * Return the node name.
     75    *
     76    * @return The element's name
     77    */
     78 
     79   // public String getNodeName()
     80   // {
     81   // TODO: Need prefix.
     82   // return localPart;
     83   // }
     84 
     85   /**
     86    * This function is called after everything else has been
     87    * recomposed, and allows the template to set remaining
     88    * values that may be based on some other property that
     89    * depends on recomposition.
     90    */
     91   public void compose(StylesheetRoot sroot) throws TransformerException
     92   {
     93     super.compose(sroot);
     94     m_extns = this.getNamespace();
     95     m_decl = getElemExtensionDecl(sroot, m_extns);
     96     // Register the extension namespace if the extension does not have
     97     // an ElemExtensionDecl ("component").
     98     if (m_decl == null)
     99       sroot.getExtensionNamespacesManager().registerExtension(m_extns);
    100   }
    101 
    102   /**
    103    * Return the ElemExtensionDecl for this extension element
    104    *
    105    *
    106    * @param stylesheet Stylesheet root associated with this extension element
    107    * @param namespace Namespace associated with this extension element
    108    *
    109    * @return the ElemExtensionDecl for this extension element.
    110    */
    111   private ElemExtensionDecl getElemExtensionDecl(StylesheetRoot stylesheet,
    112           String namespace)
    113   {
    114 
    115     ElemExtensionDecl decl = null;
    116     int n = stylesheet.getGlobalImportCount();
    117 
    118     for (int i = 0; i < n; i++)
    119     {
    120       Stylesheet imported = stylesheet.getGlobalImport(i);
    121 
    122       for (ElemTemplateElement child = imported.getFirstChildElem();
    123               child != null; child = child.getNextSiblingElem())
    124       {
    125         if (Constants.ELEMNAME_EXTENSIONDECL == child.getXSLToken())
    126         {
    127           decl = (ElemExtensionDecl) child;
    128 
    129           String prefix = decl.getPrefix();
    130           String declNamespace = child.getNamespaceForPrefix(prefix);
    131 
    132           if (namespace.equals(declNamespace))
    133           {
    134             return decl;
    135           }
    136         }
    137       }
    138     }
    139 
    140     return null;
    141   }
    142 
    143   /**
    144    * Execute the fallbacks when an extension is not available.
    145    *
    146    * @param transformer non-null reference to the the current transform-time state.
    147    *
    148    * @throws TransformerException
    149    */
    150   private void executeFallbacks(
    151           TransformerImpl transformer)
    152             throws TransformerException
    153   {
    154     for (ElemTemplateElement child = m_firstChild; child != null;
    155              child = child.m_nextSibling)
    156     {
    157       if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK)
    158       {
    159         try
    160         {
    161           transformer.pushElemTemplateElement(child);
    162           ((ElemFallback) child).executeFallback(transformer);
    163         }
    164         finally
    165         {
    166           transformer.popElemTemplateElement();
    167         }
    168       }
    169     }
    170 
    171   }
    172 
    173   /**
    174    * Return true if this extension element has a <xsl:fallback> child element.
    175    *
    176    * @return true if this extension element has a <xsl:fallback> child element.
    177    */
    178   private boolean hasFallbackChildren()
    179   {
    180     for (ElemTemplateElement child = m_firstChild; child != null;
    181              child = child.m_nextSibling)
    182     {
    183       if (child.getXSLToken() == Constants.ELEMNAME_FALLBACK)
    184         return true;
    185     }
    186 
    187     return false;
    188   }
    189 
    190 
    191   /**
    192    * Execute an extension.
    193    *
    194    * @param transformer non-null reference to the the current transform-time state.
    195    *
    196    * @throws TransformerException
    197    */
    198   public void execute(TransformerImpl transformer)
    199             throws TransformerException
    200   {
    201     if (transformer.getStylesheet().isSecureProcessing())
    202       throw new TransformerException(
    203         XSLMessages.createMessage(
    204           XSLTErrorResources.ER_EXTENSION_ELEMENT_NOT_ALLOWED_IN_SECURE_PROCESSING,
    205           new Object[] {getRawName()}));
    206 
    207     try
    208     {
    209       transformer.getResultTreeHandler().flushPending();
    210 
    211       ExtensionsTable etable = transformer.getExtensionsTable();
    212       ExtensionHandler nsh = etable.get(m_extns);
    213 
    214       if (null == nsh)
    215       {
    216         if (hasFallbackChildren())
    217         {
    218           executeFallbacks(transformer);
    219         }
    220         else
    221         {
    222 	  TransformerException te = new TransformerException(XSLMessages.createMessage(
    223 	  	XSLTErrorResources.ER_CALL_TO_EXT_FAILED, new Object[]{getNodeName()}));
    224 	  transformer.getErrorListener().fatalError(te);
    225         }
    226 
    227         return;
    228       }
    229 
    230       try
    231       {
    232         nsh.processElement(this.getLocalName(), this, transformer,
    233                            getStylesheet(), this);
    234       }
    235       catch (Exception e)
    236       {
    237 
    238 	if (hasFallbackChildren())
    239 	  executeFallbacks(transformer);
    240 	else
    241 	{
    242           if(e instanceof TransformerException)
    243           {
    244             TransformerException te = (TransformerException)e;
    245             if(null == te.getLocator())
    246               te.setLocator(this);
    247 
    248             transformer.getErrorListener().fatalError(te);
    249           }
    250           else if (e instanceof RuntimeException)
    251           {
    252             transformer.getErrorListener().fatalError(new TransformerException(e));
    253           }
    254           else
    255           {
    256             transformer.getErrorListener().warning(new TransformerException(e));
    257           }
    258         }
    259       }
    260     }
    261     catch(TransformerException e)
    262     {
    263       transformer.getErrorListener().fatalError(e);
    264     }
    265     catch(SAXException se) {
    266       throw new TransformerException(se);
    267     }
    268   }
    269 
    270   /**
    271    * Return the value of the attribute interpreted as an Attribute
    272    * Value Template (in other words, you can use curly expressions
    273    * such as href="http://{website}".
    274    *
    275    * @param rawName Raw name of the attribute to get
    276    * @param sourceNode non-null reference to the <a href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>.
    277    * @param transformer non-null reference to the the current transform-time state.
    278    *
    279    * @return the value of the attribute
    280    *
    281    * @throws TransformerException
    282    */
    283   public String getAttribute(
    284           String rawName, org.w3c.dom.Node sourceNode, TransformerImpl transformer)
    285             throws TransformerException
    286   {
    287 
    288     AVT avt = getLiteralResultAttribute(rawName);
    289 
    290     if ((null != avt) && avt.getRawName().equals(rawName))
    291     {
    292       XPathContext xctxt = transformer.getXPathContext();
    293 
    294       return avt.evaluate(xctxt,
    295             xctxt.getDTMHandleFromNode(sourceNode),
    296             this);
    297     }
    298 
    299     return null;
    300   }
    301 
    302   /**
    303    * Accept a visitor and call the appropriate method
    304    * for this class.
    305    *
    306    * @param visitor The visitor whose appropriate method will be called.
    307    * @return true if the children of the object should be visited.
    308    */
    309   protected boolean accept(XSLTVisitor visitor)
    310   {
    311   	return visitor.visitExtensionElement(this);
    312   }
    313 
    314 
    315 }
    316