Home | History | Annotate | Download | only in processor
      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: ProcessorLRE.java 475981 2006-11-16 23:35:53Z minchau $
     20  */
     21 package org.apache.xalan.processor;
     22 
     23 import java.util.List;
     24 
     25 import javax.xml.transform.TransformerConfigurationException;
     26 import javax.xml.transform.TransformerException;
     27 
     28 import org.apache.xalan.res.XSLMessages;
     29 import org.apache.xalan.res.XSLTErrorResources;
     30 import org.apache.xalan.templates.Constants;
     31 import org.apache.xalan.templates.ElemExtensionCall;
     32 import org.apache.xalan.templates.ElemLiteralResult;
     33 import org.apache.xalan.templates.ElemTemplate;
     34 import org.apache.xalan.templates.ElemTemplateElement;
     35 import org.apache.xalan.templates.Stylesheet;
     36 import org.apache.xalan.templates.StylesheetRoot;
     37 import org.apache.xalan.templates.XMLNSDecl;
     38 import org.apache.xml.utils.SAXSourceLocator;
     39 import org.apache.xpath.XPath;
     40 
     41 import org.xml.sax.Attributes;
     42 import org.xml.sax.Locator;
     43 import org.xml.sax.helpers.AttributesImpl;
     44 
     45 /**
     46  * Processes an XSLT literal-result-element, or something that looks
     47  * like one.  The actual {@link org.apache.xalan.templates.ElemTemplateElement}
     48  * produced may be a {@link org.apache.xalan.templates.ElemLiteralResult},
     49  * a {@link org.apache.xalan.templates.StylesheetRoot}, or a
     50  * {@link org.apache.xalan.templates.ElemExtensionCall}.
     51  *
     52  * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
     53  * @see org.apache.xalan.templates.ElemLiteralResult
     54  * @xsl.usage internal
     55  */
     56 public class ProcessorLRE extends ProcessorTemplateElem
     57 {
     58     static final long serialVersionUID = -1490218021772101404L;
     59   /**
     60    * Receive notification of the start of an element.
     61    *
     62    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
     63    * @param uri The Namespace URI, or an empty string.
     64    * @param localName The local name (without prefix), or empty string if not namespace processing.
     65    * @param rawName The qualified name (with prefix).
     66    * @param attributes The specified or defaulted attributes.
     67    */
     68   public void startElement(
     69           StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
     70             throws org.xml.sax.SAXException
     71   {
     72 
     73     try
     74     {
     75       ElemTemplateElement p = handler.getElemTemplateElement();
     76       boolean excludeXSLDecl = false;
     77       boolean isLREAsStyleSheet = false;
     78 
     79       if (null == p)
     80       {
     81 
     82         // Literal Result Template as stylesheet.
     83         XSLTElementProcessor lreProcessor = handler.popProcessor();
     84         XSLTElementProcessor stylesheetProcessor =
     85                                                   handler.getProcessorFor(Constants.S_XSLNAMESPACEURL, "stylesheet",
     86                                                                           "xsl:stylesheet");
     87 
     88         handler.pushProcessor(lreProcessor);
     89 
     90         Stylesheet stylesheet;
     91         try
     92         {
     93           stylesheet = getStylesheetRoot(handler);
     94         }
     95         catch(TransformerConfigurationException tfe)
     96         {
     97           throw new TransformerException(tfe);
     98         }
     99 
    100         // stylesheet.setDOMBackPointer(handler.getOriginatingNode());
    101         // ***** Note that we're assigning an empty locator. Is this necessary?
    102         SAXSourceLocator slocator = new SAXSourceLocator();
    103         Locator locator = handler.getLocator();
    104         if(null != locator)
    105         {
    106           slocator.setLineNumber(locator.getLineNumber());
    107           slocator.setColumnNumber(locator.getColumnNumber());
    108           slocator.setPublicId(locator.getPublicId());
    109           slocator.setSystemId(locator.getSystemId());
    110         }
    111         stylesheet.setLocaterInfo(slocator);
    112         stylesheet.setPrefixes(handler.getNamespaceSupport());
    113         handler.pushStylesheet(stylesheet);
    114 
    115         isLREAsStyleSheet = true;
    116 
    117         AttributesImpl stylesheetAttrs = new AttributesImpl();
    118         AttributesImpl lreAttrs = new AttributesImpl();
    119         int n = attributes.getLength();
    120 
    121         for (int i = 0; i < n; i++)
    122         {
    123           String attrLocalName = attributes.getLocalName(i);
    124           String attrUri = attributes.getURI(i);
    125           String value = attributes.getValue(i);
    126 
    127           if ((null != attrUri) && attrUri.equals(Constants.S_XSLNAMESPACEURL))
    128           {
    129             stylesheetAttrs.addAttribute(null, attrLocalName, attrLocalName,
    130                                          attributes.getType(i),
    131                                          attributes.getValue(i));
    132           }
    133           else if ((attrLocalName.startsWith("xmlns:") || attrLocalName.equals(
    134                                                                                "xmlns")) && value.equals(Constants.S_XSLNAMESPACEURL))
    135           {
    136 
    137             // ignore
    138           }
    139           else
    140           {
    141             lreAttrs.addAttribute(attrUri, attrLocalName,
    142                                   attributes.getQName(i),
    143                                   attributes.getType(i),
    144                                   attributes.getValue(i));
    145           }
    146         }
    147 
    148         attributes = lreAttrs;
    149 
    150         // Set properties from the attributes, but don't throw
    151         // an error if there is an attribute defined that is not
    152         // allowed on a stylesheet.
    153 				try{
    154         stylesheetProcessor.setPropertiesFromAttributes(handler, "stylesheet",
    155                                                         stylesheetAttrs, stylesheet);
    156 				}
    157 				catch (Exception e)
    158 				{
    159 					// This is pretty ugly, but it will have to do for now.
    160 					// This is just trying to append some text specifying that
    161 					// this error came from a missing or invalid XSLT namespace
    162 					// declaration.
    163 					// If someone comes up with a better solution, please feel
    164 					// free to contribute it. -mm
    165 
    166 					if (stylesheet.getDeclaredPrefixes() == null ||
    167 						!declaredXSLNS(stylesheet))
    168 					{
    169 						throw new org.xml.sax.SAXException(XSLMessages.createWarning(XSLTErrorResources.WG_OLD_XSLT_NS, null));
    170 					}
    171 					else
    172                     {
    173 						throw new org.xml.sax.SAXException(e);
    174                     }
    175 				}
    176         handler.pushElemTemplateElement(stylesheet);
    177 
    178         ElemTemplate template = new ElemTemplate();
    179         if (slocator != null)
    180             template.setLocaterInfo(slocator);
    181 
    182         appendAndPush(handler, template);
    183 
    184         XPath rootMatch = new XPath("/", stylesheet, stylesheet, XPath.MATCH,
    185              handler.getStylesheetProcessor().getErrorListener());
    186 
    187         template.setMatch(rootMatch);
    188 
    189         // template.setDOMBackPointer(handler.getOriginatingNode());
    190         stylesheet.setTemplate(template);
    191 
    192         p = handler.getElemTemplateElement();
    193         excludeXSLDecl = true;
    194       }
    195 
    196       XSLTElementDef def = getElemDef();
    197       Class classObject = def.getClassObject();
    198       boolean isExtension = false;
    199       boolean isComponentDecl = false;
    200       boolean isUnknownTopLevel = false;
    201 
    202       while (null != p)
    203       {
    204 
    205         // System.out.println("Checking: "+p);
    206         if (p instanceof ElemLiteralResult)
    207         {
    208           ElemLiteralResult parentElem = (ElemLiteralResult) p;
    209 
    210           isExtension = parentElem.containsExtensionElementURI(uri);
    211         }
    212         else if (p instanceof Stylesheet)
    213         {
    214           Stylesheet parentElem = (Stylesheet) p;
    215 
    216           isExtension = parentElem.containsExtensionElementURI(uri);
    217 
    218           if ((false == isExtension) && (null != uri)
    219               && (uri.equals(Constants.S_BUILTIN_EXTENSIONS_URL)
    220                   || uri.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL)))
    221           {
    222             isComponentDecl = true;
    223           }
    224           else
    225           {
    226             isUnknownTopLevel = true;
    227           }
    228         }
    229 
    230         if (isExtension)
    231           break;
    232 
    233         p = p.getParentElem();
    234       }
    235 
    236       ElemTemplateElement elem = null;
    237 
    238       try
    239       {
    240         if (isExtension)
    241         {
    242 
    243           // System.out.println("Creating extension(1): "+uri);
    244           elem = new ElemExtensionCall();
    245         }
    246         else if (isComponentDecl)
    247         {
    248           elem = (ElemTemplateElement) classObject.newInstance();
    249         }
    250         else if (isUnknownTopLevel)
    251         {
    252 
    253           // TBD: Investigate, not sure about this.  -sb
    254           elem = (ElemTemplateElement) classObject.newInstance();
    255         }
    256         else
    257         {
    258           elem = (ElemTemplateElement) classObject.newInstance();
    259         }
    260 
    261         elem.setDOMBackPointer(handler.getOriginatingNode());
    262         elem.setLocaterInfo(handler.getLocator());
    263         elem.setPrefixes(handler.getNamespaceSupport(), excludeXSLDecl);
    264 
    265         if (elem instanceof ElemLiteralResult)
    266         {
    267           ((ElemLiteralResult) elem).setNamespace(uri);
    268           ((ElemLiteralResult) elem).setLocalName(localName);
    269           ((ElemLiteralResult) elem).setRawName(rawName);
    270           ((ElemLiteralResult) elem).setIsLiteralResultAsStylesheet(
    271                                                                     isLREAsStyleSheet);
    272         }
    273       }
    274       catch (InstantiationException ie)
    275       {
    276         handler.error(XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, ie);//"Failed creating ElemLiteralResult instance!", ie);
    277       }
    278       catch (IllegalAccessException iae)
    279       {
    280         handler.error(XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, iae);//"Failed creating ElemLiteralResult instance!", iae);
    281       }
    282 
    283       setPropertiesFromAttributes(handler, rawName, attributes, elem);
    284 
    285       // bit of a hack here...
    286       if (!isExtension && (elem instanceof ElemLiteralResult))
    287       {
    288         isExtension =
    289                      ((ElemLiteralResult) elem).containsExtensionElementURI(uri);
    290 
    291         if (isExtension)
    292         {
    293 
    294           // System.out.println("Creating extension(2): "+uri);
    295           elem = new ElemExtensionCall();
    296 
    297           elem.setLocaterInfo(handler.getLocator());
    298           elem.setPrefixes(handler.getNamespaceSupport());
    299           ((ElemLiteralResult) elem).setNamespace(uri);
    300           ((ElemLiteralResult) elem).setLocalName(localName);
    301           ((ElemLiteralResult) elem).setRawName(rawName);
    302           setPropertiesFromAttributes(handler, rawName, attributes, elem);
    303         }
    304       }
    305 
    306       appendAndPush(handler, elem);
    307     }
    308     catch(TransformerException te)
    309     {
    310       throw new org.xml.sax.SAXException(te);
    311     }
    312   }
    313 
    314   /**
    315    * This method could be over-ridden by a class that extends this class.
    316    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    317    * @return an object that represents the stylesheet element.
    318    */
    319   protected Stylesheet getStylesheetRoot(StylesheetHandler handler) throws TransformerConfigurationException
    320   {
    321     StylesheetRoot stylesheet;
    322     stylesheet = new StylesheetRoot(handler.getSchema(), handler.getStylesheetProcessor().getErrorListener());
    323     if (handler.getStylesheetProcessor().isSecureProcessing())
    324       stylesheet.setSecureProcessing(true);
    325 
    326     return stylesheet;
    327   }
    328 
    329 
    330 /**
    331    * Receive notification of the end of an element.
    332    *
    333    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
    334    * @param uri The Namespace URI, or an empty string.
    335    * @param localName The local name (without prefix), or empty string if not namespace processing.
    336    * @param rawName The qualified name (with prefix).
    337    */
    338   public void endElement(
    339           StylesheetHandler handler, String uri, String localName, String rawName)
    340             throws org.xml.sax.SAXException
    341   {
    342 
    343     ElemTemplateElement elem = handler.getElemTemplateElement();
    344 
    345     if (elem instanceof ElemLiteralResult)
    346     {
    347       if (((ElemLiteralResult) elem).getIsLiteralResultAsStylesheet())
    348       {
    349         handler.popStylesheet();
    350       }
    351     }
    352 
    353     super.endElement(handler, uri, localName, rawName);
    354   }
    355 
    356 	private boolean declaredXSLNS(Stylesheet stylesheet)
    357 	{
    358 		List declaredPrefixes = stylesheet.getDeclaredPrefixes();
    359 		int n = declaredPrefixes.size();
    360 
    361 		for (int i = 0; i < n; i++)
    362 		{
    363 			XMLNSDecl decl = (XMLNSDecl) declaredPrefixes.get(i);
    364 			if(decl.getURI().equals(Constants.S_XSLNAMESPACEURL))
    365 				return true;
    366 		}
    367 		return false;
    368 	}
    369 }
    370