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    */
startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)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    */
getStylesheetRoot(StylesheetHandler handler)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    */
endElement( StylesheetHandler handler, String uri, String localName, String rawName)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 
declaredXSLNS(Stylesheet stylesheet)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