View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: TemplatesHandlerImpl.java,v 1.2.4.1 2005/09/06 12:09:03 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.trax;
25  
26  import javax.xml.XMLConstants;
27  import javax.xml.transform.Source;
28  import javax.xml.transform.Templates;
29  import javax.xml.transform.TransformerException;
30  import javax.xml.transform.URIResolver;
31  import javax.xml.transform.sax.TemplatesHandler;
32  import com.sun.org.apache.xalan.internal.XalanConstants;
33  import com.sun.org.apache.xalan.internal.xsltc.compiler.CompilerException;
34  import com.sun.org.apache.xalan.internal.xsltc.compiler.Parser;
35  import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader;
36  import com.sun.org.apache.xalan.internal.xsltc.compiler.Stylesheet;
37  import com.sun.org.apache.xalan.internal.xsltc.compiler.SyntaxTreeNode;
38  import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
39  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
40  
41  import org.xml.sax.ContentHandler;
42  import org.xml.sax.InputSource;
43  import org.xml.sax.Locator;
44  import org.xml.sax.SAXException;
45  import org.xml.sax.Attributes;
46  
47  import java.util.Vector;
48  
49  /**
50   * Implementation of a JAXP1.1 TemplatesHandler
51   * @author Morten Jorgensen
52   * @author Santiago Pericas-Geertsen
53   */
54  public class TemplatesHandlerImpl
55      implements ContentHandler, TemplatesHandler, SourceLoader
56  {
57      /**
58       * System ID for this stylesheet.
59       */
60      private String _systemId;
61  
62      /**
63       * Number of spaces to add for output indentation.
64       */
65      private int _indentNumber;
66  
67      /**
68       * This URIResolver is passed to all Transformers.
69       */
70      private URIResolver _uriResolver = null;
71  
72      /**
73       * A reference to the transformer factory that this templates
74       * object belongs to.
75       */
76      private TransformerFactoryImpl _tfactory = null;
77  
78      /**
79       * A reference to XSLTC's parser object.
80       */
81      private Parser _parser = null;
82  
83      /**
84       * The created Templates object.
85       */
86      private TemplatesImpl _templates = null;
87  
88      /**
89       * Default constructor
90       */
91      protected TemplatesHandlerImpl(int indentNumber,
92          TransformerFactoryImpl tfactory)
93      {
94          _indentNumber = indentNumber;
95          _tfactory = tfactory;
96  
97          // Instantiate XSLTC and get reference to parser object
98          XSLTC xsltc = new XSLTC(tfactory.useServicesMechnism(), tfactory.getFeatureManager());
99          if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING))
100             xsltc.setSecureProcessing(true);
101 
102         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET,
103                 (String)tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET));
104         xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD,
105                 (String)tfactory.getAttribute(XMLConstants.ACCESS_EXTERNAL_DTD));
106         xsltc.setProperty(XalanConstants.SECURITY_MANAGER,
107                 tfactory.getAttribute(XalanConstants.SECURITY_MANAGER));
108 
109 
110         if ("true".equals(tfactory.getAttribute(TransformerFactoryImpl.ENABLE_INLINING)))
111             xsltc.setTemplateInlining(true);
112         else
113             xsltc.setTemplateInlining(false);
114 
115         _parser = xsltc.getParser();
116     }
117 
118     /**
119      * Implements javax.xml.transform.sax.TemplatesHandler.getSystemId()
120      * Get the base ID (URI or system ID) from where relative URLs will be
121      * resolved.
122      * @return The systemID that was set with setSystemId(String id)
123      */
124     public String getSystemId() {
125         return _systemId;
126     }
127 
128     /**
129      * Implements javax.xml.transform.sax.TemplatesHandler.setSystemId()
130      * Get the base ID (URI or system ID) from where relative URLs will be
131      * resolved.
132      * @param id Base URI for this stylesheet
133      */
134     public void setSystemId(String id) {
135         _systemId = id;
136     }
137 
138     /**
139      * Store URIResolver needed for Transformers.
140      */
141     public void setURIResolver(URIResolver resolver) {
142         _uriResolver = resolver;
143     }
144 
145     /**
146      * Implements javax.xml.transform.sax.TemplatesHandler.getTemplates()
147      * When a TemplatesHandler object is used as a ContentHandler or
148      * DocumentHandler for the parsing of transformation instructions, it
149      * creates a Templates object, which the caller can get once the SAX
150      * events have been completed.
151      * @return The Templates object that was created during the SAX event
152      *         process, or null if no Templates object has been created.
153      */
154     public Templates getTemplates() {
155         return _templates;
156     }
157 
158     /**
159      * This method implements XSLTC's SourceLoader interface. It is used to
160      * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
161      *
162      * @param href The URI of the document to load
163      * @param context The URI of the currently loaded document
164      * @param xsltc The compiler that resuests the document
165      * @return An InputSource with the loaded document
166      */
167     public InputSource loadSource(String href, String context, XSLTC xsltc) {
168         try {
169             // A _uriResolver must be set if this method is called
170             final Source source = _uriResolver.resolve(href, context);
171             if (source != null) {
172                 return Util.getInputSource(xsltc, source);
173             }
174         }
175         catch (TransformerException e) {
176             // Falls through
177         }
178         return null;
179     }
180 
181     // -- ContentHandler --------------------------------------------------
182 
183     /**
184      * Re-initialize parser and forward SAX2 event.
185      */
186     public void startDocument() {
187         XSLTC xsltc = _parser.getXSLTC();
188         xsltc.init();   // calls _parser.init()
189         xsltc.setOutputType(XSLTC.BYTEARRAY_OUTPUT);
190         _parser.startDocument();
191     }
192 
193     /**
194      * Just forward SAX2 event to parser object.
195      */
196     public void endDocument() throws SAXException {
197         _parser.endDocument();
198 
199         // create the templates
200         try {
201             XSLTC xsltc = _parser.getXSLTC();
202 
203             // Set the translet class name if not already set
204             String transletName;
205             if (_systemId != null) {
206                 transletName = Util.baseName(_systemId);
207             }
208             else {
209                 transletName = (String)_tfactory.getAttribute("translet-name");
210             }
211             xsltc.setClassName(transletName);
212 
213             // Get java-legal class name from XSLTC module
214             transletName = xsltc.getClassName();
215 
216             Stylesheet stylesheet = null;
217             SyntaxTreeNode root = _parser.getDocumentRoot();
218 
219             // Compile the translet - this is where the work is done!
220             if (!_parser.errorsFound() && root != null) {
221                 // Create a Stylesheet element from the root node
222                 stylesheet = _parser.makeStylesheet(root);
223                 stylesheet.setSystemId(_systemId);
224                 stylesheet.setParentStylesheet(null);
225 
226                 if (xsltc.getTemplateInlining())
227                    stylesheet.setTemplateInlining(true);
228                 else
229                    stylesheet.setTemplateInlining(false);
230 
231                 // Set a document loader (for xsl:include/import) if defined
232                 if (_uriResolver != null) {
233                     stylesheet.setSourceLoader(this);
234                 }
235 
236                 _parser.setCurrentStylesheet(stylesheet);
237 
238                 // Set it as top-level in the XSLTC object
239                 xsltc.setStylesheet(stylesheet);
240 
241                 // Create AST under the Stylesheet element
242                 _parser.createAST(stylesheet);
243             }
244 
245             // Generate the bytecodes and output the translet class(es)
246             if (!_parser.errorsFound() && stylesheet != null) {
247                 stylesheet.setMultiDocument(xsltc.isMultiDocument());
248                 stylesheet.setHasIdCall(xsltc.hasIdCall());
249 
250                 // Class synchronization is needed for BCEL
251                 synchronized (xsltc.getClass()) {
252                     stylesheet.translate();
253                 }
254             }
255 
256             if (!_parser.errorsFound()) {
257                 // Check that the transformation went well before returning
258                 final byte[][] bytecodes = xsltc.getBytecodes();
259                 if (bytecodes != null) {
260                     _templates =
261                     new TemplatesImpl(xsltc.getBytecodes(), transletName,
262                         _parser.getOutputProperties(), _indentNumber, _tfactory);
263 
264                     // Set URIResolver on templates object
265                     if (_uriResolver != null) {
266                         _templates.setURIResolver(_uriResolver);
267                     }
268                 }
269             }
270             else {
271                 StringBuffer errorMessage = new StringBuffer();
272                 Vector errors = _parser.getErrors();
273                 final int count = errors.size();
274                 for (int i = 0; i < count; i++) {
275                     if (errorMessage.length() > 0)
276                         errorMessage.append('\n');
277                     errorMessage.append(errors.elementAt(i).toString());
278                 }
279                 throw new SAXException(ErrorMsg.JAXP_COMPILE_ERR, new TransformerException(errorMessage.toString()));
280             }
281         }
282         catch (CompilerException e) {
283             throw new SAXException(ErrorMsg.JAXP_COMPILE_ERR, e);
284         }
285     }
286 
287     /**
288      * Just forward SAX2 event to parser object.
289      */
290     public void startPrefixMapping(String prefix, String uri) {
291         _parser.startPrefixMapping(prefix, uri);
292     }
293 
294     /**
295      * Just forward SAX2 event to parser object.
296      */
297     public void endPrefixMapping(String prefix) {
298         _parser.endPrefixMapping(prefix);
299     }
300 
301     /**
302      * Just forward SAX2 event to parser object.
303      */
304     public void startElement(String uri, String localname, String qname,
305         Attributes attributes) throws SAXException
306     {
307         _parser.startElement(uri, localname, qname, attributes);
308     }
309 
310     /**
311      * Just forward SAX2 event to parser object.
312      */
313     public void endElement(String uri, String localname, String qname) {
314         _parser.endElement(uri, localname, qname);
315     }
316 
317     /**
318      * Just forward SAX2 event to parser object.
319      */
320     public void characters(char[] ch, int start, int length) {
321         _parser.characters(ch, start, length);
322     }
323 
324     /**
325      * Just forward SAX2 event to parser object.
326      */
327     public void processingInstruction(String name, String value) {
328         _parser.processingInstruction(name, value);
329     }
330 
331     /**
332      * Just forward SAX2 event to parser object.
333      */
334     public void ignorableWhitespace(char[] ch, int start, int length) {
335         _parser.ignorableWhitespace(ch, start, length);
336     }
337 
338     /**
339      * Just forward SAX2 event to parser object.
340      */
341     public void skippedEntity(String name) {
342         _parser.skippedEntity(name);
343     }
344 
345     /**
346      * Set internal system Id and forward SAX2 event to parser object.
347      */
348     public void setDocumentLocator(Locator locator) {
349         setSystemId(locator.getSystemId());
350         _parser.setDocumentLocator(locator);
351     }
352 }