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 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()); 99 if (tfactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING)) 100 xsltc.setSecureProcessing(true); 101 102 if ("true".equals(tfactory.getAttribute(TransformerFactoryImpl.ENABLE_INLINING))) 103 xsltc.setTemplateInlining(true); 104 else 105 xsltc.setTemplateInlining(false); 106 107 _parser = xsltc.getParser(); 108 } 109 110 /** 111 * Implements javax.xml.transform.sax.TemplatesHandler.getSystemId() 112 * Get the base ID (URI or system ID) from where relative URLs will be 113 * resolved. 114 * @return The systemID that was set with setSystemId(String id) 115 */ 116 public String getSystemId() { 117 return _systemId; 118 } 119 120 /** 121 * Implements javax.xml.transform.sax.TemplatesHandler.setSystemId() 122 * Get the base ID (URI or system ID) from where relative URLs will be 123 * resolved. 124 * @param id Base URI for this stylesheet 125 */ 126 public void setSystemId(String id) { 127 _systemId = id; 128 } 129 130 /** 131 * Store URIResolver needed for Transformers. 132 */ 133 public void setURIResolver(URIResolver resolver) { 134 _uriResolver = resolver; 135 } 136 137 /** 138 * Implements javax.xml.transform.sax.TemplatesHandler.getTemplates() 139 * When a TemplatesHandler object is used as a ContentHandler or 140 * DocumentHandler for the parsing of transformation instructions, it 141 * creates a Templates object, which the caller can get once the SAX 142 * events have been completed. 143 * @return The Templates object that was created during the SAX event 144 * process, or null if no Templates object has been created. 145 */ 146 public Templates getTemplates() { 147 return _templates; 148 } 149 150 /** 151 * This method implements XSLTC's SourceLoader interface. It is used to 152 * glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes. 153 * 154 * @param href The URI of the document to load 155 * @param context The URI of the currently loaded document 156 * @param xsltc The compiler that resuests the document 157 * @return An InputSource with the loaded document 158 */ 159 public InputSource loadSource(String href, String context, XSLTC xsltc) { 160 try { 161 // A _uriResolver must be set if this method is called 162 final Source source = _uriResolver.resolve(href, context); 163 if (source != null) { 164 return Util.getInputSource(xsltc, source); 165 } 166 } 167 catch (TransformerException e) { 168 // Falls through 169 } 170 return null; 171 } 172 173 // -- ContentHandler -------------------------------------------------- 174 175 /** 176 * Re-initialize parser and forward SAX2 event. 177 */ 178 public void startDocument() { 179 XSLTC xsltc = _parser.getXSLTC(); 180 xsltc.init(); // calls _parser.init() 181 xsltc.setOutputType(XSLTC.BYTEARRAY_OUTPUT); 182 _parser.startDocument(); 183 } 184 185 /** 186 * Just forward SAX2 event to parser object. 187 */ 188 public void endDocument() throws SAXException { 189 _parser.endDocument(); 190 191 // create the templates 192 try { 193 XSLTC xsltc = _parser.getXSLTC(); 194 195 // Set the translet class name if not already set 196 String transletName; 197 if (_systemId != null) { 198 transletName = Util.baseName(_systemId); 199 } 200 else { 201 transletName = (String)_tfactory.getAttribute("translet-name"); 202 } 203 xsltc.setClassName(transletName); 204 205 // Get java-legal class name from XSLTC module 206 transletName = xsltc.getClassName(); 207 208 Stylesheet stylesheet = null; 209 SyntaxTreeNode root = _parser.getDocumentRoot(); 210 211 // Compile the translet - this is where the work is done! 212 if (!_parser.errorsFound() && root != null) { 213 // Create a Stylesheet element from the root node 214 stylesheet = _parser.makeStylesheet(root); 215 stylesheet.setSystemId(_systemId); 216 stylesheet.setParentStylesheet(null); 217 218 if (xsltc.getTemplateInlining()) 219 stylesheet.setTemplateInlining(true); 220 else 221 stylesheet.setTemplateInlining(false); 222 223 // Set a document loader (for xsl:include/import) if defined 224 if (_uriResolver != null) { 225 stylesheet.setSourceLoader(this); 226 } 227 228 _parser.setCurrentStylesheet(stylesheet); 229 230 // Set it as top-level in the XSLTC object 231 xsltc.setStylesheet(stylesheet); 232 233 // Create AST under the Stylesheet element 234 _parser.createAST(stylesheet); 235 } 236 237 // Generate the bytecodes and output the translet class(es) 238 if (!_parser.errorsFound() && stylesheet != null) { 239 stylesheet.setMultiDocument(xsltc.isMultiDocument()); 240 stylesheet.setHasIdCall(xsltc.hasIdCall()); 241 242 // Class synchronization is needed for BCEL 243 synchronized (xsltc.getClass()) { 244 stylesheet.translate(); 245 } 246 } 247 248 if (!_parser.errorsFound()) { 249 // Check that the transformation went well before returning 250 final byte[][] bytecodes = xsltc.getBytecodes(); 251 if (bytecodes != null) { 252 _templates = 253 new TemplatesImpl(xsltc.getBytecodes(), transletName, 254 _parser.getOutputProperties(), _indentNumber, _tfactory); 255 256 // Set URIResolver on templates object 257 if (_uriResolver != null) { 258 _templates.setURIResolver(_uriResolver); 259 } 260 } 261 } 262 else { 263 StringBuffer errorMessage = new StringBuffer(); 264 Vector errors = _parser.getErrors(); 265 final int count = errors.size(); 266 for (int i = 0; i < count; i++) { 267 if (errorMessage.length() > 0) 268 errorMessage.append('\n'); 269 errorMessage.append(errors.elementAt(i).toString()); 270 } 271 throw new SAXException(ErrorMsg.JAXP_COMPILE_ERR, new TransformerException(errorMessage.toString())); 272 } 273 } 274 catch (CompilerException e) { 275 throw new SAXException(ErrorMsg.JAXP_COMPILE_ERR, e); 276 } 277 } 278 279 /** 280 * Just forward SAX2 event to parser object. 281 */ 282 public void startPrefixMapping(String prefix, String uri) { 283 _parser.startPrefixMapping(prefix, uri); 284 } 285 286 /** 287 * Just forward SAX2 event to parser object. 288 */ 289 public void endPrefixMapping(String prefix) { 290 _parser.endPrefixMapping(prefix); 291 } 292 293 /** 294 * Just forward SAX2 event to parser object. 295 */ 296 public void startElement(String uri, String localname, String qname, 297 Attributes attributes) throws SAXException 298 { 299 _parser.startElement(uri, localname, qname, attributes); 300 } 301 302 /** 303 * Just forward SAX2 event to parser object. 304 */ 305 public void endElement(String uri, String localname, String qname) { 306 _parser.endElement(uri, localname, qname); 307 } 308 309 /** 310 * Just forward SAX2 event to parser object. 311 */ 312 public void characters(char[] ch, int start, int length) { 313 _parser.characters(ch, start, length); 314 } 315 316 /** 317 * Just forward SAX2 event to parser object. 318 */ 319 public void processingInstruction(String name, String value) { 320 _parser.processingInstruction(name, value); 321 } 322 323 /** 324 * Just forward SAX2 event to parser object. 325 */ 326 public void ignorableWhitespace(char[] ch, int start, int length) { 327 _parser.ignorableWhitespace(ch, start, length); 328 } 329 330 /** 331 * Just forward SAX2 event to parser object. 332 */ 333 public void skippedEntity(String name) { 334 _parser.skippedEntity(name); 335 } 336 337 /** 338 * Set internal system Id and forward SAX2 event to parser object. 339 */ 340 public void setDocumentLocator(Locator locator) { 341 setSystemId(locator.getSystemId()); 342 _parser.setDocumentLocator(locator); 343 } 344 }