org.apache.axiom.om.util.StAXUtils Maven / Gradle / Ivy
/*
* 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 org.apache.axiom.om.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.axiom.util.stax.dialect.StAXDialect;
import org.apache.axiom.util.stax.dialect.StAXDialectDetector;
import org.apache.axiom.util.stax.wrapper.ImmutableXMLInputFactory;
import org.apache.axiom.util.stax.wrapper.ImmutableXMLOutputFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;
/**
* Utility class containing StAX related methods.
* This class defines a set of methods to get {@link XMLStreamReader} and {@link XMLStreamWriter}
* instances. This class caches the corresponding factories, i.e. {@link XMLInputFactory}
* and {@link XMLOutputFactory} objects.
* Default properties for these factories can be specified using
* {@code XMLInputFactory.properties} and {@code XMLOutputFactory.properties} files.
* These files are loaded using the class loader that loaded the {@link StAXUtils} class.
* Properties with boolean, integer and string values are supported.
* Both standard StAX properties and implementation specific properties can be specified. This
* feature should be used with care since changing some properties to non default values will break
* Axiom. Good candidates for {@code XMLInputFactory.properties} are:
*
* - {@code javax.xml.stream.isCoalescing}
* - Requires the processor to coalesce adjacent character data (text nodes and CDATA
* sections). This property also controls whether CDATA sections are reported or not.
* - {@code com.ctc.wstx.inputBufferLength}
* - Size of input buffer (in chars), to use for reading XML content from input stream/reader.
* This property is Woodstox specific.
* - {@code com.ctc.wstx.minTextSegment}
* - Property to specify shortest non-complete text segment (part of CDATA section or text
* content) that the parser is allowed to return, if not required to coalesce text.
* This property is Woodstox specific.
*
* Good candidates for {@code XMLOutputFactory.properties} are:
*
* - {@code com.ctc.wstx.outputEscapeCr}
* - Property that determines whether Carriage Return (\r) characters are to be escaped when
* output or not. If enabled, all instances of of character \r are escaped using a character
* entity (where possible, that is, within CHARACTERS events, and attribute values).
* Otherwise they are output as is. The main reason to enable this property is to ensure
* that carriage returns are preserved as is through parsing, since otherwise they will be
* converted to canonical XML linefeeds (\n), when occurring along or as part of \r\n pair.
* This property is Woodstox specific.
*
*/
public class StAXUtils {
private static final Log log = LogFactory.getLog(StAXUtils.class);
private static final Map inputFactoryMap
= Collections.synchronizedMap(new WeakHashMap());
@SuppressWarnings("deprecation")
private static final Map outputFactoryMap
= Collections.synchronizedMap(new WeakHashMap());
/**
* Get a cached {@link XMLInputFactory} instance using the default
* configuration.
*
* @return an {@link XMLInputFactory} instance.
*/
public static XMLInputFactory getXMLInputFactory() {
return getXMLInputFactory(null);
}
/**
* Get a cached {@link XMLInputFactory} instance using the default
* configuration and the specified cache policy.
*
* @param factoryPerClassLoaderPolicy
* the cache policy; see
* {@link #getXMLInputFactory(StAXParserConfiguration, boolean)}
* for more details
* @return an {@link XMLInputFactory} instance.
* @deprecated
*/
public static XMLInputFactory getXMLInputFactory(boolean factoryPerClassLoaderPolicy) {
return getXMLInputFactory(null, factoryPerClassLoaderPolicy);
}
/**
* Get a cached {@link XMLInputFactory} instance using the specified
* configuration and cache policy.
*
* @param configuration
* the configuration applied to the requested factory
* @param factoryPerClassLoaderPolicy
* If set to true
, the factory cached for the
* current class loader will be returned. If set to
* false
, the singleton factory (instantiated using
* the class loader that loaded {@link StAXUtils}) will be
* returned.
* @return an {@link XMLInputFactory} instance.
* @deprecated
*/
public static XMLInputFactory getXMLInputFactory(StAXParserConfiguration configuration,
boolean factoryPerClassLoaderPolicy) {
if (factoryPerClassLoaderPolicy) {
throw new UnsupportedOperationException();
} else {
return getXMLInputFactory(configuration);
}
}
public static XMLStreamReader createXMLStreamReader(InputStream in, String encoding)
throws XMLStreamException {
return createXMLStreamReader(null, in, encoding);
}
public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration,
InputStream in, String encoding) throws XMLStreamException {
XMLStreamReader reader = getXMLInputFactory(configuration).createXMLStreamReader(in, encoding);
if (log.isDebugEnabled()) {
log.debug("XMLStreamReader is " + reader.getClass().getName());
}
return reader;
}
public static XMLStreamReader createXMLStreamReader(InputStream in)
throws XMLStreamException {
return createXMLStreamReader(null, in);
}
public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration,
InputStream in) throws XMLStreamException {
XMLStreamReader reader = getXMLInputFactory(configuration).createXMLStreamReader(in);
if (log.isDebugEnabled()) {
log.debug("XMLStreamReader is " + reader.getClass().getName());
}
return reader;
}
public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration,
String systemId, InputStream in) throws XMLStreamException {
XMLStreamReader reader = getXMLInputFactory(configuration).createXMLStreamReader(systemId, in);
if (log.isDebugEnabled()) {
log.debug("XMLStreamReader is " + reader.getClass().getName());
}
return reader;
}
public static XMLStreamReader createXMLStreamReader(Reader in)
throws XMLStreamException {
return createXMLStreamReader(null, in);
}
public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration,
Reader in) throws XMLStreamException {
XMLStreamReader reader = getXMLInputFactory(configuration).createXMLStreamReader(in);
if (log.isDebugEnabled()) {
log.debug("XMLStreamReader is " + reader.getClass().getName());
}
return reader;
}
/**
* Get a cached {@link XMLOutputFactory} instance using the default
* configuration.
*
* @return an {@link XMLOutputFactory} instance.
* @deprecated
*/
public static XMLOutputFactory getXMLOutputFactory() {
return getXMLOutputFactory(null);
}
/**
* Get a cached {@link XMLOutputFactory} instance using the default
* configuration and the specified cache policy.
*
* @param factoryPerClassLoaderPolicy
* the cache policy; see
* {@link #getXMLOutputFactory(StAXWriterConfiguration, boolean)}
* for more details
* @return an {@link XMLOutputFactory} instance.
* @deprecated
*/
public static XMLOutputFactory getXMLOutputFactory(boolean factoryPerClassLoaderPolicy) {
return getXMLOutputFactory(null, factoryPerClassLoaderPolicy);
}
/**
* Get a cached {@link XMLOutputFactory} instance using the specified
* configuration and cache policy.
*
* @param configuration
* the configuration applied to the requested factory
* @param factoryPerClassLoaderPolicy
* If set to true
, the factory cached for the
* current class loader will be returned. If set to
* false
, the singleton factory (instantiated using
* the class loader that loaded {@link StAXUtils}) will be
* returned.
* @return an {@link XMLOutputFactory} instance.
* @deprecated
*/
public static XMLOutputFactory getXMLOutputFactory(StAXWriterConfiguration configuration,
boolean factoryPerClassLoaderPolicy) {
if (factoryPerClassLoaderPolicy) {
throw new UnsupportedOperationException();
} else {
return getXMLOutputFactory(configuration);
}
}
/**
* @deprecated Per class loader factories are no longer supported. The code now always uses the
* class loader that loaded the {@link StAXUtils} class.
*/
public static void setFactoryPerClassLoader(boolean value) {
if (value) {
throw new UnsupportedOperationException();
}
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(OutputStream out)
throws XMLStreamException {
return createXMLStreamWriter(null, out);
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration,
OutputStream out) throws XMLStreamException {
XMLStreamWriter writer = getXMLOutputFactory(configuration).createXMLStreamWriter(out, "utf-8");
if (log.isDebugEnabled()) {
log.debug("XMLStreamWriter is " + writer.getClass().getName());
}
return writer;
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(OutputStream out, String encoding)
throws XMLStreamException {
return createXMLStreamWriter(null, out, encoding);
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration,
OutputStream out, String encoding) throws XMLStreamException {
XMLStreamWriter writer = getXMLOutputFactory(configuration).createXMLStreamWriter(out, encoding);
if (log.isDebugEnabled()) {
log.debug("XMLStreamWriter is " + writer.getClass().getName());
}
return writer;
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(final Writer out)
throws XMLStreamException {
return createXMLStreamWriter(null, out);
}
/**
* @deprecated
*/
public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration,
Writer out) throws XMLStreamException {
XMLStreamWriter writer = getXMLOutputFactory(configuration).createXMLStreamWriter(out);
if (log.isDebugEnabled()) {
log.debug("XMLStreamWriter is " + writer.getClass().getName());
}
return writer;
}
/**
* Load factory properties from a resource. The method converts boolean and integer values to the right Java types.
* All other values are returned as strings.
*
* @param cl
* @param name
* @return the factory properties
*/
// This has package access since it is used from within anonymous inner classes
static Map loadFactoryProperties(ClassLoader cl, String name) {
InputStream in = cl.getResourceAsStream(name);
if (in == null) {
return null;
} else {
try {
Properties rawProps = new Properties();
Map props = new HashMap();
rawProps.load(in);
for (Map.Entry