1 /* 2 * Copyright (c) 2017, 2019, 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.xml.internal.serializer; 22 23 import java.util.Properties; 24 import javax.xml.transform.OutputKeys; 25 import jdk.xml.internal.SecuritySupport; 26 27 /** 28 * This class is a factory to generate a set of default properties 29 * of key/value pairs that are used to create a serializer through the 30 * factory {@link SerializerFactory SerilizerFactory}. 31 * The properties generated by this factory 32 * may be modified to non-default values before the SerializerFactory is used to 33 * create a Serializer. 34 * <p> 35 * The given output types supported are "xml", "text", and "html". 36 * These type strings can be obtained from the 37 * {@link Method Method} class in this package. 38 * <p> 39 * Other constants defined in this class are the non-standard property keys 40 * that can be used to set non-standard property values on a java.util.Properties object 41 * that is used to create or configure a serializer. Here are the non-standard keys: 42 * <ul> 43 * <li> <b>S_KEY_INDENT_AMOUNT </b> - 44 * The non-standard property key to use to set the indentation amount. 45 * The "indent" key needs to have a value of "yes", and this 46 * properties value is a the number of whitespaces to indent by per 47 * indentation level. 48 * 49 * <li> <b>S_KEY_CONTENT_HANDLER </b> - 50 * This non-standard property key is used to set the name of the fully qualified 51 * Java class that implements the ContentHandler interface. 52 * The output of the serializer will be SAX events sent to this an 53 * object of this class. 54 * 55 * <li> <b>S_KEY_ENTITIES </b> - 56 * This non-standard property key is used to specify the name of the property file 57 * that specifies character to entity reference mappings. A line in such a 58 * file is has the name of the entity and the numeric (base 10) value 59 * of the corresponding character, like this one: <br> quot=34 <br> 60 * 61 * <li> <b>S_USE_URL_ESCAPING </b> - 62 * This non-standard property key is used to set a value of "yes" if the href values 63 * for HTML serialization should use %xx escaping. 64 * 65 * <li> <b>S_OMIT_META_TAG </b> - 66 * This non-standard property key is used to set a value of "yes" if the META tag 67 * should be omitted where it would otherwise be supplied. 68 * </ul> 69 * 70 * @see SerializerFactory 71 * @see Method 72 * @see Serializer 73 * @LastModified: Mar 2019 74 */ 75 public final class OutputPropertiesFactory 76 { 77 /** S_BUILTIN_EXTENSIONS_URL is a mnemonic for the XML Namespace 78 *(http://xml.apache.org/xalan) predefined to signify Xalan's 79 * built-in XSLT Extensions. When used in stylesheets, this is often 80 * bound to the "xalan:" prefix. 81 */ 82 private static final String 83 S_BUILTIN_EXTENSIONS_URL = "http://xml.apache.org/xalan"; 84 85 /** 86 * The old built-in extension url. It is still supported for 87 * backward compatibility. 88 */ 89 private static final String 90 S_BUILTIN_OLD_EXTENSIONS_URL = "http://xml.apache.org/xslt"; 91 92 //************************************************************ 93 //* PUBLIC CONSTANTS 94 //************************************************************ 95 /** 96 * This is not a public API. 97 * This is the built-in extensions namespace, 98 * reexpressed in {namespaceURI} syntax 99 * suitable for prepending to a localname to produce a "universal 100 * name". 101 */ 102 public static final String S_BUILTIN_EXTENSIONS_UNIVERSAL = 103 "{" + S_BUILTIN_EXTENSIONS_URL + "}"; 104 105 // Some special Xalan keys. 106 107 /** 108 * The non-standard property key to use to set the 109 * number of whitepaces to indent by, per indentation level, 110 * if indent="yes". 111 */ 112 public static final String S_KEY_INDENT_AMOUNT = 113 S_BUILTIN_EXTENSIONS_UNIVERSAL + "indent-amount"; 114 115 /** 116 * The non-standard property key to use to set the 117 * number of whitepaces to indent by, per indentation level, 118 * if indent="yes". 119 */ 120 public static final String S_KEY_LINE_SEPARATOR = 121 S_BUILTIN_EXTENSIONS_UNIVERSAL + "line-separator"; 122 123 /** This non-standard property key is used to set the name of the fully qualified 124 * Java class that implements the ContentHandler interface. 125 * Fully qualified name of class with a default constructor that 126 * implements the ContentHandler interface, where the result tree events 127 * will be sent to. 128 */ 129 130 public static final String S_KEY_CONTENT_HANDLER = 131 S_BUILTIN_EXTENSIONS_UNIVERSAL + "content-handler"; 132 133 /** 134 * This non-standard property key is used to specify the name of the property file 135 * that specifies character to entity reference mappings. 136 */ 137 public static final String S_KEY_ENTITIES = 138 S_BUILTIN_EXTENSIONS_UNIVERSAL + "entities"; 139 140 /** 141 * This non-standard property key is used to set a value of "yes" if the href 142 * values for HTML serialization should use %xx escaping. 143 */ 144 public static final String S_USE_URL_ESCAPING = 145 S_BUILTIN_EXTENSIONS_UNIVERSAL + "use-url-escaping"; 146 147 /** 148 * This non-standard property key is used to set a value of "yes" if the META 149 * tag should be omitted where it would otherwise be supplied. 150 */ 151 public static final String S_OMIT_META_TAG = 152 S_BUILTIN_EXTENSIONS_UNIVERSAL + "omit-meta-tag"; 153 154 /** 155 * The old built-in extension namespace, this is not a public API. 156 */ 157 public static final String S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL = 158 "{" + S_BUILTIN_OLD_EXTENSIONS_URL + "}"; 159 160 /** 161 * This is not a public API, it is only public because it is used 162 * by outside of this package, 163 * it is the length of the old built-in extension namespace. 164 */ 165 public static final int S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN = 166 S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL.length(); 167 168 /** 169 * This non-standard, Oracle-impl only property key is used as if 170 * OutputKeys.STANDALONE is specified but without writing it out in the declaration; 171 * It can be used to reverse the change by Xalan patch 1495. 172 * Since Xalan patch 1495 can cause incompatible behavior, this property is 173 * added for application to neutralize the effect of Xalan patch 1495 174 */ 175 /** 176 * <p>Is Standalone</p> 177 * 178 * <ul> 179 * <li> 180 * <code>yes</code> to indicate the output is intended to be used as standalone 181 * </li> 182 * <li> 183 * <code>no</code> has no effect. 184 * </li> 185 * </ul> 186 */ 187 public static final String ORACLE_IS_STANDALONE = "http://www.oracle.com/xml/is-standalone"; 188 189 //************************************************************ 190 //* PRIVATE CONSTANTS 191 //************************************************************ 192 193 /* 194 * XSLT properties do not need namespace qualification. 195 * 196 * Xalan-specific output properties can be overridden in the stylesheet 197 * assigning a xalan namespace. For example: 198 * <xsl:stylesheet version="1.0" 199 * xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 200 * xmlns:xalan="http://xml.apache.org/xalan"> 201 * <xsl:output method="html" encoding="UTF-8" 202 * xalan:content-handler="MyContentHandler"/> 203 * ... 204 */ 205 private static final String[] PROP_XML = { 206 "method", 207 "version", 208 "encoding", 209 "indent", 210 "omit-xml-declaration", 211 "standalone", 212 "media-type", 213 "{http://xml.apache.org/xalan}indent-amount", 214 "{http://xml.apache.org/xalan}content-handler", 215 "{http://xml.apache.org/xalan}entities" 216 }; 217 218 private static final String[] PROP_XML_VALUE = { 219 "xml", 220 "1.0", 221 "UTF-8", 222 "no", 223 "no", 224 "no", 225 "text/xml", 226 "0", 227 "com.sun.org.apache.xml.internal.serializer.ToXMLStream", 228 "com/sun/org/apache/xml/internal/serializer/XMLEntities" 229 }; 230 231 private static final String[] PROP_HTML = { 232 "method", 233 "indent", 234 "media-type", 235 "version", 236 "{http://xml.apache.org/xalan}indent-amount", 237 "{http://xml.apache.org/xalan}content-handler", 238 "{http://xml.apache.org/xalan}entities", 239 "{http://xml.apache.org/xalan}use-url-escaping", 240 "{http://xml.apache.org/xalan}omit-meta-tag" 241 }; 242 243 private static final String[] PROP_HTML_VALUE = { 244 "html", 245 "yes", 246 "text/html", 247 "4.0", 248 "4", 249 "com.sun.org.apache.xml.internal.serializer.ToHTMLStream", 250 "com/sun/org/apache/xml/internal/serializer/HTMLEntities", 251 "yes", 252 "no" 253 }; 254 255 private static final String[] PROP_TEXT = { 256 "method", 257 "media-type", 258 "{http://xml.apache.org/xalan}content-handler" 259 }; 260 261 private static final String[] PROP_TEXT_VALUE = { 262 "text", 263 "text/plain", 264 "com.sun.org.apache.xml.internal.serializer.ToTextStream" 265 }; 266 267 private static final String[] PROP_UNKNOWN = { 268 "method", 269 "version", 270 "encoding", 271 "indent", 272 "omit-xml-declaration", 273 "standalone", 274 "media-type", 275 "{http://xml.apache.org/xalan}indent-amount", 276 "{http://xml.apache.org/xalan}content-handler" 277 }; 278 279 private static final String[] PROP_UNKNOWN_VALUE = { 280 "xml", 281 "1.0", 282 "UTF-8", 283 "no", 284 "no", 285 "no", 286 "text/xml", 287 "0", 288 "com.sun.org.apache.xml.internal.serializer.ToUnknownStream", 289 }; 290 291 //************************************************************ 292 //* PRIVATE STATIC FIELDS 293 //************************************************************ 294 295 /** The default properties for all other than html and text. */ 296 private static Properties m_xml_properties = null; 297 298 /** The default properties when method="html". */ 299 private static Properties m_html_properties = null; 300 301 /** The default properties when method="text". */ 302 private static Properties m_text_properties = null; 303 304 /** The properties when method="" for the "unknown" wrapper */ 305 private static Properties m_unknown_properties = null; 306 307 /** 308 * Returns a Properties based on the specified method. The default is xml. 309 * 310 * @param method non-null reference to method name. 311 * 312 * @return Properties object that holds the defaults for the given method. 313 */ 314 static public final Properties getDefaultMethodProperties(String method) 315 { 316 Properties defaultProperties = null; 317 318 if (null == m_xml_properties) { 319 m_xml_properties = initProperties(PROP_XML, PROP_XML_VALUE, null); 320 } 321 322 323 switch (method) { 324 case Method.XML: 325 defaultProperties = m_xml_properties; 326 break; 327 case Method.HTML: 328 if (null == m_html_properties) { 329 m_html_properties = initProperties( 330 PROP_HTML, PROP_HTML_VALUE, m_xml_properties); 331 } 332 defaultProperties = m_html_properties; 333 break; 334 case Method.TEXT: 335 if (null == m_text_properties) { 336 m_text_properties = initProperties( 337 PROP_TEXT, PROP_TEXT_VALUE, m_xml_properties); 338 339 if (null == m_text_properties.getProperty(OutputKeys.ENCODING)) 340 { 341 String mimeEncoding = Encodings.getMimeEncoding(null); 342 m_text_properties.put(OutputKeys.ENCODING, mimeEncoding); 343 } 344 } 345 defaultProperties = m_text_properties; 346 break; 347 case com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN: 348 if (null == m_unknown_properties) { 349 m_unknown_properties = initProperties( 350 PROP_UNKNOWN, PROP_UNKNOWN_VALUE, m_xml_properties); 351 } 352 defaultProperties = m_unknown_properties; 353 break; 354 default: 355 defaultProperties = m_xml_properties; 356 break; 357 } 358 359 // wrap these cached defaultProperties in a new Property object just so 360 // that the caller of this method can't modify the default values 361 return new Properties(defaultProperties); 362 } 363 364 /** 365 * Initiates the properties 366 * 367 * @param keys an array of keys 368 * @param values values corresponding to the keys 369 * @param defaults Default properties, which may be null. 370 */ 371 static private Properties initProperties(String[] keys, String[] values, Properties defaults) 372 { 373 Properties props = new Properties(defaults); 374 375 for (int i = 0; i < keys.length; i++) { 376 // check System Property. This is kept as is for binary compatibility 377 String sys = SecuritySupport.getSystemProperty(keys[i]); 378 props.put(keys[i], (sys == null) ? values[i] : sys); 379 } 380 381 return props; 382 } 383 }