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: XSLTElementProcessor.java 469688 2006-10-31 22:39:43Z minchau $
20  */
21 package org.apache.xalan.processor;
22 
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Vector;
26 
27 import javax.xml.transform.TransformerException;
28 
29 import org.apache.xalan.res.XSLMessages;
30 import org.apache.xalan.res.XSLTErrorResources;
31 import org.apache.xalan.templates.ElemTemplateElement;
32 import org.apache.xml.utils.IntStack;
33 import org.xml.sax.Attributes;
34 import org.xml.sax.InputSource;
35 import org.xml.sax.helpers.AttributesImpl;
36 
37 /**
38  * This class acts as the superclass for all stylesheet element
39  * processors, and deals with things that are common to all elements.
40  * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
41  */
42 public class XSLTElementProcessor extends ElemTemplateElement
43 {
44     static final long serialVersionUID = 5597421564955304421L;
45 
46   /**
47    * Construct a processor for top-level elements.
48    * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
49    */
XSLTElementProcessor()50   XSLTElementProcessor(){}
51 
52 	private IntStack m_savedLastOrder;
53 
54   /**
55    * The element definition that this processor conforms to.
56    */
57   private XSLTElementDef m_elemDef;
58 
59   /**
60    * Get the element definition that belongs to this element.
61    *
62    * @return The element definition object that produced and constrains this element.
63    */
getElemDef()64   XSLTElementDef getElemDef()
65   {
66     return m_elemDef;
67   }
68 
69   /**
70    * Set the element definition that belongs to this element.
71    *
72    * @param def The element definition object that produced and constrains this element.
73    */
setElemDef(XSLTElementDef def)74   void setElemDef(XSLTElementDef def)
75   {
76     m_elemDef = def;
77   }
78 
79   /**
80    * Resolve an external entity.
81    *
82    *
83    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
84    * @param publicId The public identifer, or null if none is
85    *                 available.
86    * @param systemId The system identifier provided in the XML
87    *                 document.
88    * @return The new input source, or null to require the
89    *         default behaviour.
90    */
resolveEntity( StylesheetHandler handler, String publicId, String systemId)91   public InputSource resolveEntity(
92           StylesheetHandler handler, String publicId, String systemId)
93             throws org.xml.sax.SAXException
94   {
95     return null;
96   }
97 
98   /**
99    * Receive notification of a notation declaration.
100    *
101    *
102    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
103    * @param name The notation name.
104    * @param publicId The notation public identifier, or null if not
105    *                 available.
106    * @param systemId The notation system identifier.
107    * @see org.xml.sax.DTDHandler#notationDecl
108    */
notationDecl(StylesheetHandler handler, String name, String publicId, String systemId)109   public void notationDecl(StylesheetHandler handler, String name,
110                            String publicId, String systemId)
111   {
112 
113     // no op
114   }
115 
116   /**
117    * Receive notification of an unparsed entity declaration.
118    *
119    *
120    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
121    * @param name The entity name.
122    * @param publicId The entity public identifier, or null if not
123    *                 available.
124    * @param systemId The entity system identifier.
125    * @param notationName The name of the associated notation.
126    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
127    */
unparsedEntityDecl(StylesheetHandler handler, String name, String publicId, String systemId, String notationName)128   public void unparsedEntityDecl(StylesheetHandler handler, String name,
129                                  String publicId, String systemId,
130                                  String notationName)
131   {
132 
133     // no op
134   }
135 
136   /**
137    * Receive notification of the start of the non-text event.  This
138    * is sent to the current processor when any non-text event occurs.
139    *
140    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
141    */
startNonText(StylesheetHandler handler)142   public void startNonText(StylesheetHandler handler) throws org.xml.sax.SAXException
143   {
144 
145     // no op
146   }
147 
148   /**
149    * Receive notification of the start of an element.
150    *
151    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
152    * @param uri The Namespace URI, or an empty string.
153    * @param localName The local name (without prefix), or empty string if not namespace processing.
154    * @param rawName The qualified name (with prefix).
155    * @param attributes The specified or defaulted attributes.
156    */
startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)157   public void startElement(
158           StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
159             throws org.xml.sax.SAXException
160   {
161 
162     if (m_savedLastOrder == null)
163 				m_savedLastOrder = new IntStack();
164 			m_savedLastOrder.push(getElemDef().getLastOrder());
165 			getElemDef().setLastOrder(-1);
166   }
167 
168   /**
169    * Receive notification of the end of an element.
170    *
171    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
172    * @param uri The Namespace URI, or an empty string.
173    * @param localName The local name (without prefix), or empty string if not namespace processing.
174    * @param rawName The qualified name (with prefix).
175    */
endElement( StylesheetHandler handler, String uri, String localName, String rawName)176   public void endElement(
177           StylesheetHandler handler, String uri, String localName, String rawName)
178             throws org.xml.sax.SAXException
179   {
180 		if (m_savedLastOrder != null && !m_savedLastOrder.empty())
181 			getElemDef().setLastOrder(m_savedLastOrder.pop());
182 
183 		if (!getElemDef().getRequiredFound())
184 			handler.error(XSLTErrorResources.ER_REQUIRED_ELEM_NOT_FOUND, new Object[]{getElemDef().getRequiredElem()}, null);
185   }
186 
187   /**
188    * Receive notification of character data inside an element.
189    *
190    *
191    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
192    * @param ch The characters.
193    * @param start The start position in the character array.
194    * @param length The number of characters to use from the
195    *               character array.
196    */
characters( StylesheetHandler handler, char ch[], int start, int length)197   public void characters(
198           StylesheetHandler handler, char ch[], int start, int length)
199             throws org.xml.sax.SAXException
200   {
201     handler.error(XSLTErrorResources.ER_CHARS_NOT_ALLOWED, null, null);//"Characters are not allowed at this point in the document!",
202                   //null);
203   }
204 
205   /**
206    * Receive notification of ignorable whitespace in element content.
207    *
208    *
209    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
210    * @param ch The whitespace characters.
211    * @param start The start position in the character array.
212    * @param length The number of characters to use from the
213    *               character array.
214    */
ignorableWhitespace( StylesheetHandler handler, char ch[], int start, int length)215   public void ignorableWhitespace(
216           StylesheetHandler handler, char ch[], int start, int length)
217             throws org.xml.sax.SAXException
218   {
219 
220     // no op
221   }
222 
223   /**
224    * Receive notification of a processing instruction.
225    *
226    *
227    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
228    * @param target The processing instruction target.
229    * @param data The processing instruction data, or null if
230    *             none is supplied.
231    */
processingInstruction( StylesheetHandler handler, String target, String data)232   public void processingInstruction(
233           StylesheetHandler handler, String target, String data)
234             throws org.xml.sax.SAXException
235   {
236 
237     // no op
238   }
239 
240   /**
241    * Receive notification of a skipped entity.
242    *
243    *
244    * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
245    * @param name The name of the skipped entity.
246    */
skippedEntity(StylesheetHandler handler, String name)247   public void skippedEntity(StylesheetHandler handler, String name)
248           throws org.xml.sax.SAXException
249   {
250 
251     // no op
252   }
253 
254   /**
255    * Set the properties of an object from the given attribute list.
256    * @param handler The stylesheet's Content handler, needed for
257    *                error reporting.
258    * @param rawName The raw name of the owner element, needed for
259    *                error reporting.
260    * @param attributes The list of attributes.
261    * @param target The target element where the properties will be set.
262    */
setPropertiesFromAttributes( StylesheetHandler handler, String rawName, Attributes attributes, ElemTemplateElement target)263   void setPropertiesFromAttributes(
264           StylesheetHandler handler, String rawName, Attributes attributes,
265           ElemTemplateElement target)
266             throws org.xml.sax.SAXException
267   {
268     setPropertiesFromAttributes(handler, rawName, attributes, target, true);
269   }
270 
271   /**
272    * Set the properties of an object from the given attribute list.
273    * @param handler The stylesheet's Content handler, needed for
274    *                error reporting.
275    * @param rawName The raw name of the owner element, needed for
276    *                error reporting.
277    * @param attributes The list of attributes.
278    * @param target The target element where the properties will be set.
279    * @param throwError True if it should throw an error if an
280    * attribute is not defined.
281    * @return the attributes not allowed on this element.
282    *
283    * @throws TransformerException
284    */
setPropertiesFromAttributes( StylesheetHandler handler, String rawName, Attributes attributes, ElemTemplateElement target, boolean throwError)285   Attributes setPropertiesFromAttributes(
286           StylesheetHandler handler, String rawName, Attributes attributes,
287           ElemTemplateElement target, boolean throwError)
288             throws org.xml.sax.SAXException
289   {
290 
291     XSLTElementDef def = getElemDef();
292     AttributesImpl undefines = null;
293     boolean isCompatibleMode = ((null != handler.getStylesheet()
294                                  && handler.getStylesheet().getCompatibleMode())
295                                 || !throwError);
296     if (isCompatibleMode)
297       undefines = new AttributesImpl();
298 
299 
300     // Keep track of which XSLTAttributeDefs have been processed, so
301     // I can see which default values need to be set.
302     List processedDefs = new ArrayList();
303 
304     // Keep track of XSLTAttributeDefs that were invalid
305     List errorDefs = new ArrayList();
306     int nAttrs = attributes.getLength();
307 
308     for (int i = 0; i < nAttrs; i++)
309     {
310       String attrUri = attributes.getURI(i);
311       // Hack for Crimson.  -sb
312       if((null != attrUri) && (attrUri.length() == 0)
313                            && (attributes.getQName(i).startsWith("xmlns:") ||
314                                attributes.getQName(i).equals("xmlns")))
315       {
316         attrUri = org.apache.xalan.templates.Constants.S_XMLNAMESPACEURI;
317       }
318       String attrLocalName = attributes.getLocalName(i);
319       XSLTAttributeDef attrDef = def.getAttributeDef(attrUri, attrLocalName);
320 
321       if (null == attrDef)
322       {
323         if (!isCompatibleMode)
324         {
325 
326           // Then barf, because this element does not allow this attribute.
327           handler.error(XSLTErrorResources.ER_ATTR_NOT_ALLOWED, new Object[]{attributes.getQName(i), rawName}, null);//"\""+attributes.getQName(i)+"\""
328                         //+ " attribute is not allowed on the " + rawName
329                        // + " element!", null);
330         }
331         else
332         {
333           undefines.addAttribute(attrUri, attrLocalName,
334                                  attributes.getQName(i),
335                                  attributes.getType(i),
336                                  attributes.getValue(i));
337         }
338       }
339       else
340       {
341         //handle secure processing
342         if(handler.getStylesheetProcessor()==null)
343             System.out.println("stylesheet processor null");
344         if(attrDef.getName().compareTo("*")==0 && handler.getStylesheetProcessor().isSecureProcessing())
345         {
346             //foreign attributes are not allowed in secure processing mode
347             // Then barf, because this element does not allow this attribute.
348             handler.error(XSLTErrorResources.ER_ATTR_NOT_ALLOWED, new Object[]{attributes.getQName(i), rawName}, null);//"\""+attributes.getQName(i)+"\""
349             //+ " attribute is not allowed on the " + rawName
350             // + " element!", null);
351         }
352         else
353         {
354 
355 
356             boolean success = attrDef.setAttrValue(handler, attrUri, attrLocalName,
357                                  attributes.getQName(i), attributes.getValue(i),
358                                  target);
359 
360             // Now we only add the element if it passed a validation check
361             if (success)
362                 processedDefs.add(attrDef);
363             else
364                 errorDefs.add(attrDef);
365         }
366       }
367     }
368 
369     XSLTAttributeDef[] attrDefs = def.getAttributes();
370     int nAttrDefs = attrDefs.length;
371 
372     for (int i = 0; i < nAttrDefs; i++)
373     {
374       XSLTAttributeDef attrDef = attrDefs[i];
375       String defVal = attrDef.getDefault();
376 
377       if (null != defVal)
378       {
379         if (!processedDefs.contains(attrDef))
380         {
381           attrDef.setDefAttrValue(handler, target);
382         }
383       }
384 
385       if (attrDef.getRequired())
386       {
387         if ((!processedDefs.contains(attrDef)) && (!errorDefs.contains(attrDef)))
388           handler.error(
389             XSLMessages.createMessage(
390               XSLTErrorResources.ER_REQUIRES_ATTRIB, new Object[]{ rawName,
391                                                                    attrDef.getName() }), null);
392       }
393     }
394 
395     return undefines;
396   }
397 }
398