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: ProcessorLRE.java 475981 2006-11-16 23:35:53Z minchau $
020 */
021 package org.apache.xalan.processor;
022
023 import java.util.List;
024
025 import javax.xml.transform.TransformerConfigurationException;
026 import javax.xml.transform.TransformerException;
027
028 import org.apache.xalan.res.XSLMessages;
029 import org.apache.xalan.res.XSLTErrorResources;
030 import org.apache.xalan.templates.Constants;
031 import org.apache.xalan.templates.ElemExtensionCall;
032 import org.apache.xalan.templates.ElemLiteralResult;
033 import org.apache.xalan.templates.ElemTemplate;
034 import org.apache.xalan.templates.ElemTemplateElement;
035 import org.apache.xalan.templates.Stylesheet;
036 import org.apache.xalan.templates.StylesheetRoot;
037 import org.apache.xalan.templates.XMLNSDecl;
038 import org.apache.xml.utils.SAXSourceLocator;
039 import org.apache.xpath.XPath;
040
041 import org.xml.sax.Attributes;
042 import org.xml.sax.Locator;
043 import org.xml.sax.helpers.AttributesImpl;
044
045 /**
046 * Processes an XSLT literal-result-element, or something that looks
047 * like one. The actual {@link org.apache.xalan.templates.ElemTemplateElement}
048 * produced may be a {@link org.apache.xalan.templates.ElemLiteralResult},
049 * a {@link org.apache.xalan.templates.StylesheetRoot}, or a
050 * {@link org.apache.xalan.templates.ElemExtensionCall}.
051 *
052 * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT Specification</a>
053 * @see org.apache.xalan.templates.ElemLiteralResult
054 * @xsl.usage internal
055 */
056 public class ProcessorLRE extends ProcessorTemplateElem
057 {
058 static final long serialVersionUID = -1490218021772101404L;
059 /**
060 * Receive notification of the start of an element.
061 *
062 * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
063 * @param uri The Namespace URI, or an empty string.
064 * @param localName The local name (without prefix), or empty string if not namespace processing.
065 * @param rawName The qualified name (with prefix).
066 * @param attributes The specified or defaulted attributes.
067 */
068 public void startElement(
069 StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
070 throws org.xml.sax.SAXException
071 {
072
073 try
074 {
075 ElemTemplateElement p = handler.getElemTemplateElement();
076 boolean excludeXSLDecl = false;
077 boolean isLREAsStyleSheet = false;
078
079 if (null == p)
080 {
081
082 // Literal Result Template as stylesheet.
083 XSLTElementProcessor lreProcessor = handler.popProcessor();
084 XSLTElementProcessor stylesheetProcessor =
085 handler.getProcessorFor(Constants.S_XSLNAMESPACEURL, "stylesheet",
086 "xsl:stylesheet");
087
088 handler.pushProcessor(lreProcessor);
089
090 Stylesheet stylesheet;
091 try
092 {
093 stylesheet = getStylesheetRoot(handler);
094 }
095 catch(TransformerConfigurationException tfe)
096 {
097 throw new TransformerException(tfe);
098 }
099
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 }