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 }