/*
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.serializer;
import java.util.Properties;
import javax.xml.transform.OutputKeys;
import jdk.xml.internal.SecuritySupport;
/**
* This class is a factory to generate a set of default properties
* of key/value pairs that are used to create a serializer through the
* factory {@link SerializerFactory SerilizerFactory}.
* The properties generated by this factory
* may be modified to non-default values before the SerializerFactory is used to
* create a Serializer.
*
* The given output types supported are "xml", "text", and "html".
* These type strings can be obtained from the
* {@link Method Method} class in this package.
*
* Other constants defined in this class are the non-standard property keys
* that can be used to set non-standard property values on a java.util.Properties object
* that is used to create or configure a serializer. Here are the non-standard keys:
*
* - S_KEY_INDENT_AMOUNT -
* The non-standard property key to use to set the indentation amount.
* The "indent" key needs to have a value of "yes", and this
* properties value is a the number of whitespaces to indent by per
* indentation level.
*
*
- S_KEY_CONTENT_HANDLER -
* This non-standard property key is used to set the name of the fully qualified
* Java class that implements the ContentHandler interface.
* The output of the serializer will be SAX events sent to this an
* object of this class.
*
*
- S_KEY_ENTITIES -
* This non-standard property key is used to specify the name of the property file
* that specifies character to entity reference mappings. A line in such a
* file is has the name of the entity and the numeric (base 10) value
* of the corresponding character, like this one:
quot=34
*
* - S_USE_URL_ESCAPING -
* This non-standard property key is used to set a value of "yes" if the href values
* for HTML serialization should use %xx escaping.
*
*
- S_OMIT_META_TAG -
* This non-standard property key is used to set a value of "yes" if the META tag
* should be omitted where it would otherwise be supplied.
*
*
* @see SerializerFactory
* @see Method
* @see Serializer
* @LastModified: Mar 2019
*/
public final class OutputPropertiesFactory
{
/** S_BUILTIN_EXTENSIONS_URL is a mnemonic for the XML Namespace
*(http://xml.apache.org/xalan) predefined to signify Xalan's
* built-in XSLT Extensions. When used in stylesheets, this is often
* bound to the "xalan:" prefix.
*/
private static final String
S_BUILTIN_EXTENSIONS_URL = "http://xml.apache.org/xalan";
/**
* The old built-in extension url. It is still supported for
* backward compatibility.
*/
private static final String
S_BUILTIN_OLD_EXTENSIONS_URL = "http://xml.apache.org/xslt";
//************************************************************
//* PUBLIC CONSTANTS
//************************************************************
/**
* This is not a public API.
* This is the built-in extensions namespace,
* reexpressed in {namespaceURI} syntax
* suitable for prepending to a localname to produce a "universal
* name".
*/
public static final String S_BUILTIN_EXTENSIONS_UNIVERSAL =
"{" + S_BUILTIN_EXTENSIONS_URL + "}";
// Some special Xalan keys.
/**
* The non-standard property key to use to set the
* number of whitepaces to indent by, per indentation level,
* if indent="yes".
*/
public static final String S_KEY_INDENT_AMOUNT =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "indent-amount";
/**
* The non-standard property key to use to set the
* number of whitepaces to indent by, per indentation level,
* if indent="yes".
*/
public static final String S_KEY_LINE_SEPARATOR =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "line-separator";
/** This non-standard property key is used to set the name of the fully qualified
* Java class that implements the ContentHandler interface.
* Fully qualified name of class with a default constructor that
* implements the ContentHandler interface, where the result tree events
* will be sent to.
*/
public static final String S_KEY_CONTENT_HANDLER =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "content-handler";
/**
* This non-standard property key is used to specify the name of the property file
* that specifies character to entity reference mappings.
*/
public static final String S_KEY_ENTITIES =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "entities";
/**
* This non-standard property key is used to set a value of "yes" if the href
* values for HTML serialization should use %xx escaping.
*/
public static final String S_USE_URL_ESCAPING =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "use-url-escaping";
/**
* This non-standard property key is used to set a value of "yes" if the META
* tag should be omitted where it would otherwise be supplied.
*/
public static final String S_OMIT_META_TAG =
S_BUILTIN_EXTENSIONS_UNIVERSAL + "omit-meta-tag";
/**
* The old built-in extension namespace, this is not a public API.
*/
public static final String S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL =
"{" + S_BUILTIN_OLD_EXTENSIONS_URL + "}";
/**
* This is not a public API, it is only public because it is used
* by outside of this package,
* it is the length of the old built-in extension namespace.
*/
public static final int S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL_LEN =
S_BUILTIN_OLD_EXTENSIONS_UNIVERSAL.length();
/**
* This non-standard, Oracle-impl only property key is used as if
* OutputKeys.STANDALONE is specified but without writing it out in the declaration;
* It can be used to reverse the change by Xalan patch 1495.
* Since Xalan patch 1495 can cause incompatible behavior, this property is
* added for application to neutralize the effect of Xalan patch 1495
*/
/**
* Is Standalone
*
*
* -
*
yes
to indicate the output is intended to be used as standalone
*
* -
*
no
has no effect.
*
*
*/
public static final String ORACLE_IS_STANDALONE = "http://www.oracle.com/xml/is-standalone";
//************************************************************
//* PRIVATE CONSTANTS
//************************************************************
/*
* XSLT properties do not need namespace qualification.
*
* Xalan-specific output properties can be overridden in the stylesheet
* assigning a xalan namespace. For example:
*
*
* ...
*/
private static final String[] PROP_XML = {
"method",
"version",
"encoding",
"indent",
"omit-xml-declaration",
"standalone",
"media-type",
"{http://xml.apache.org/xalan}indent-amount",
"{http://xml.apache.org/xalan}content-handler",
"{http://xml.apache.org/xalan}entities"
};
private static final String[] PROP_XML_VALUE = {
"xml",
"1.0",
"UTF-8",
"no",
"no",
"no",
"text/xml",
"0",
"com.sun.org.apache.xml.internal.serializer.ToXMLStream",
"com/sun/org/apache/xml/internal/serializer/XMLEntities"
};
private static final String[] PROP_HTML = {
"method",
"indent",
"media-type",
"version",
"{http://xml.apache.org/xalan}indent-amount",
"{http://xml.apache.org/xalan}content-handler",
"{http://xml.apache.org/xalan}entities",
"{http://xml.apache.org/xalan}use-url-escaping",
"{http://xml.apache.org/xalan}omit-meta-tag"
};
private static final String[] PROP_HTML_VALUE = {
"html",
"yes",
"text/html",
"4.0",
"4",
"com.sun.org.apache.xml.internal.serializer.ToHTMLStream",
"com/sun/org/apache/xml/internal/serializer/HTMLEntities",
"yes",
"no"
};
private static final String[] PROP_TEXT = {
"method",
"media-type",
"{http://xml.apache.org/xalan}content-handler"
};
private static final String[] PROP_TEXT_VALUE = {
"text",
"text/plain",
"com.sun.org.apache.xml.internal.serializer.ToTextStream"
};
private static final String[] PROP_UNKNOWN = {
"method",
"version",
"encoding",
"indent",
"omit-xml-declaration",
"standalone",
"media-type",
"{http://xml.apache.org/xalan}indent-amount",
"{http://xml.apache.org/xalan}content-handler"
};
private static final String[] PROP_UNKNOWN_VALUE = {
"xml",
"1.0",
"UTF-8",
"no",
"no",
"no",
"text/xml",
"0",
"com.sun.org.apache.xml.internal.serializer.ToUnknownStream",
};
//************************************************************
//* PRIVATE STATIC FIELDS
//************************************************************
/** The default properties for all other than html and text. */
private static Properties m_xml_properties = null;
/** The default properties when method="html". */
private static Properties m_html_properties = null;
/** The default properties when method="text". */
private static Properties m_text_properties = null;
/** The properties when method="" for the "unknown" wrapper */
private static Properties m_unknown_properties = null;
/**
* Returns a Properties based on the specified method. The default is xml.
*
* @param method non-null reference to method name.
*
* @return Properties object that holds the defaults for the given method.
*/
static public final Properties getDefaultMethodProperties(String method)
{
Properties defaultProperties = null;
if (null == m_xml_properties) {
m_xml_properties = initProperties(PROP_XML, PROP_XML_VALUE, null);
}
switch (method) {
case Method.XML:
defaultProperties = m_xml_properties;
break;
case Method.HTML:
if (null == m_html_properties) {
m_html_properties = initProperties(
PROP_HTML, PROP_HTML_VALUE, m_xml_properties);
}
defaultProperties = m_html_properties;
break;
case Method.TEXT:
if (null == m_text_properties) {
m_text_properties = initProperties(
PROP_TEXT, PROP_TEXT_VALUE, m_xml_properties);
if (null == m_text_properties.getProperty(OutputKeys.ENCODING))
{
String mimeEncoding = Encodings.getMimeEncoding(null);
m_text_properties.put(OutputKeys.ENCODING, mimeEncoding);
}
}
defaultProperties = m_text_properties;
break;
case com.sun.org.apache.xml.internal.serializer.Method.UNKNOWN:
if (null == m_unknown_properties) {
m_unknown_properties = initProperties(
PROP_UNKNOWN, PROP_UNKNOWN_VALUE, m_xml_properties);
}
defaultProperties = m_unknown_properties;
break;
default:
defaultProperties = m_xml_properties;
break;
}
// wrap these cached defaultProperties in a new Property object just so
// that the caller of this method can't modify the default values
return new Properties(defaultProperties);
}
/**
* Initiates the properties
*
* @param keys an array of keys
* @param values values corresponding to the keys
* @param defaults Default properties, which may be null.
*/
static private Properties initProperties(String[] keys, String[] values, Properties defaults)
{
Properties props = new Properties(defaults);
for (int i = 0; i < keys.length; i++) {
// check System Property. This is kept as is for binary compatibility
String sys = SecuritySupport.getSystemProperty(keys[i]);
props.put(keys[i], (sys == null) ? values[i] : sys);
}
return props;
}
}