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