org.apache.axiom.om.util.StAXUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.axiom.om.util.StAXUtils.java

Source

/*
 * 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.om.OMConstants;
import org.apache.axiom.util.stax.XMLEventUtils;
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.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;

/**
 * Utility class containing StAX related methods.
 * <p>This class defines a set of methods to get {@link XMLStreamReader} and {@link XMLStreamWriter}
 * instances. This class caches the corresponding factories ({@link XMLInputFactory}
 * and {@link XMLOutputFactory} objects) by classloader (default) or as singletons.
 * The behavior can be changed using {@link #setFactoryPerClassLoader(boolean)}.</p>
 * <p>Default properties for these factories can be specified using
 * <tt>XMLInputFactory.properties</tt> and <tt>XMLOutputFactory.properties</tt> files.
 * When a new factory is instantiated, this class will attempt to load the corresponding file using
 * the context classloader. This class supports properties with boolean, integer and string values.
 * 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 <tt>XMLInputFactory.properties</tt> are:</p>
 * <dl>
 *   <dt><tt>javax.xml.stream.isCoalescing</tt></dt>
 *   <dd>Requires the processor to coalesce adjacent character data (text nodes and CDATA
 *       sections). This property also controls whether CDATA sections are reported or not.</dd>
 *   <dt><tt>com.ctc.wstx.inputBufferLength</tt></dt>
 *   <dd>Size of input buffer (in chars), to use for reading XML content from input stream/reader.
 *       This property is Woodstox specific.</dd>
 *   <dt><tt>com.ctc.wstx.minTextSegment</tt></dt>
 *   <dd>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.</dt>
 * </dl>
 * <p>Good candidates for <tt>XMLOutputFactory.properties</tt> are:</p>
 * <dl>
 *   <dt><tt>com.ctc.wstx.outputEscapeCr</tt></dt>
 *   <dd>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.</dd>
 * </dl>
 */
public class StAXUtils {
    private static Log log = LogFactory.getLog(StAXUtils.class);
    private static boolean isDebugEnabled = log.isDebugEnabled();

    // If isFactoryPerClassLoader is true (default), then 
    // a separate singleton XMLInputFactory and XMLOutputFactory is maintained
    // for the each classloader.  The different classloaders may be using different
    // implementations of STAX.
    // 
    // If isFactoryPerClassLoader is false, then
    // a single XMLInputFactory and XMLOutputFactory is constructed using
    // the classloader that loaded StAXUtils. 
    private static boolean isFactoryPerClassLoader = true;

    // These static singletons are used when the XML*Factory is created with
    // the StAXUtils classloader.
    private static final Map/*<StAXParserConfiguration,XMLInputFactory>*/ inputFactoryMap = Collections
            .synchronizedMap(new WeakHashMap());
    private static final Map/*<StAXWriterConfiguration,XMLOutputFactory>*/ outputFactoryMap = Collections
            .synchronizedMap(new WeakHashMap());

    // These maps are used for the isFactoryPerClassLoader==true case
    // The maps are synchronized and weak.
    private static final Map/*<StAXParserConfiguration,Map<ClassLoader,XMLInputFactory>>*/ inputFactoryPerCLMap = Collections
            .synchronizedMap(new WeakHashMap());
    private static final Map/*<StAXWriterConfiguration,Map<ClassLoader,XMLInputFactory>>*/ outputFactoryPerCLMap = Collections
            .synchronizedMap(new WeakHashMap());

    /**
     * Get a cached {@link XMLInputFactory} instance using the default
     * configuration and cache policy (i.e. one instance per class loader).
     * 
     * @return an {@link XMLInputFactory} instance.
     */
    public static XMLInputFactory getXMLInputFactory() {
        return getXMLInputFactory(null, isFactoryPerClassLoader);
    }

    /**
     * Get a cached {@link XMLInputFactory} instance using the specified
     * configuration and the default cache policy.
     * 
     * @param configuration
     *            the configuration applied to the requested factory
     * @return an {@link XMLInputFactory} instance.
     */
    public static XMLInputFactory getXMLInputFactory(StAXParserConfiguration configuration) {
        return getXMLInputFactory(configuration, isFactoryPerClassLoader);
    }

    /**
     * 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.
     */
    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 <code>true</code>, the factory cached for the
     *            current class loader will be returned. If set to
     *            <code>false</code>, the singleton factory (instantiated using
     *            the class loader that loaded {@link StAXUtils}) will be
     *            returned.
     * @return an {@link XMLInputFactory} instance.
     */
    public static XMLInputFactory getXMLInputFactory(StAXParserConfiguration configuration,
            boolean factoryPerClassLoaderPolicy) {

        if (factoryPerClassLoaderPolicy) {
            return getXMLInputFactory_perClassLoader(configuration);
        } else {
            return getXMLInputFactory_singleton(configuration);
        }
    }

    /**
     * @deprecated
     * Returns an XMLInputFactory instance for reuse.
     *
     * @param factory An XMLInputFactory instance that is available for reuse
     */
    public static void releaseXMLInputFactory(XMLInputFactory factory) {
    }

    public static XMLStreamReader createXMLStreamReader(InputStream in, String encoding) throws XMLStreamException {

        return createXMLStreamReader(null, in, encoding);
    }

    public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration, final InputStream in,
            final String encoding) throws XMLStreamException {

        final XMLInputFactory inputFactory = getXMLInputFactory(configuration);
        try {
            XMLStreamReader reader = (XMLStreamReader) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return inputFactory.createXMLStreamReader(in, encoding);
                        }
                    });
            if (isDebugEnabled) {
                log.debug("XMLStreamReader is " + reader.getClass().getName());
            }
            return reader;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    public static XMLStreamReader createXMLStreamReader(InputStream in) throws XMLStreamException {

        return createXMLStreamReader(null, in);
    }

    public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration, final InputStream in)
            throws XMLStreamException {

        final XMLInputFactory inputFactory = getXMLInputFactory(configuration);
        try {
            XMLStreamReader reader = (XMLStreamReader) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return inputFactory.createXMLStreamReader(in);
                        }
                    });

            if (isDebugEnabled) {
                log.debug("XMLStreamReader is " + reader.getClass().getName());
            }
            return reader;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    public static XMLStreamReader createXMLStreamReader(Reader in) throws XMLStreamException {

        return createXMLStreamReader(null, in);
    }

    public static XMLStreamReader createXMLStreamReader(StAXParserConfiguration configuration, final Reader in)
            throws XMLStreamException {

        final XMLInputFactory inputFactory = getXMLInputFactory(configuration);
        try {
            XMLStreamReader reader = (XMLStreamReader) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return inputFactory.createXMLStreamReader(in);
                        }
                    });
            if (isDebugEnabled) {
                log.debug("XMLStreamReader is " + reader.getClass().getName());
            }
            return reader;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    /**
     * Get a cached {@link XMLOutputFactory} instance using the default
     * configuration and cache policy (i.e. one instance per class loader).
     * 
     * @return an {@link XMLOutputFactory} instance.
     */
    public static XMLOutputFactory getXMLOutputFactory() {
        return getXMLOutputFactory(null, isFactoryPerClassLoader);
    }

    /**
     * Get a cached {@link XMLOutputFactory} instance using the specified
     * configuration and the default cache policy.
     * 
     * @param configuration
     *            the configuration applied to the requested factory
     * @return an {@link XMLOutputFactory} instance.
     */
    public static XMLOutputFactory getXMLOutputFactory(StAXWriterConfiguration configuration) {
        return getXMLOutputFactory(configuration, isFactoryPerClassLoader);
    }

    /**
     * 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.
     */
    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 <code>true</code>, the factory cached for the
     *            current class loader will be returned. If set to
     *            <code>false</code>, the singleton factory (instantiated using
     *            the class loader that loaded {@link StAXUtils}) will be
     *            returned.
     * @return an {@link XMLOutputFactory} instance.
     */
    public static XMLOutputFactory getXMLOutputFactory(StAXWriterConfiguration configuration,
            boolean factoryPerClassLoaderPolicy) {

        if (factoryPerClassLoaderPolicy) {
            return getXMLOutputFactory_perClassLoader(configuration);
        } else {
            return getXMLOutputFactory_singleton(configuration);
        }
    }

    /**
     * Set the policy for how to maintain the XMLInputFactory and XMLOutputFactory
     * @param value (if false, then one singleton...if true...then singleton per class loader 
     *  (default is true)
     */
    public static void setFactoryPerClassLoader(boolean value) {
        isFactoryPerClassLoader = value;
    }

    /**
     * @deprecated
     * Returns an XMLOutputFactory instance for reuse.
     *
     * @param factory An XMLOutputFactory instance that is available for reuse.
     */
    public static void releaseXMLOutputFactory(XMLOutputFactory factory) {
    }

    public static XMLStreamWriter createXMLStreamWriter(OutputStream out) throws XMLStreamException {

        return createXMLStreamWriter(null, out);
    }

    public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration,
            final OutputStream out) throws XMLStreamException {
        final XMLOutputFactory outputFactory = getXMLOutputFactory(configuration);
        try {
            XMLStreamWriter writer = (XMLStreamWriter) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return outputFactory.createXMLStreamWriter(out, OMConstants.DEFAULT_CHAR_SET_ENCODING);
                        }
                    });

            if (isDebugEnabled) {
                log.debug("XMLStreamWriter is " + writer.getClass().getName());
            }
            return writer;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    public static XMLStreamWriter createXMLStreamWriter(OutputStream out, String encoding)
            throws XMLStreamException {

        return createXMLStreamWriter(null, out, encoding);
    }

    public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration,
            final OutputStream out, final String encoding) throws XMLStreamException {
        final XMLOutputFactory outputFactory = getXMLOutputFactory(configuration);
        try {
            XMLStreamWriter writer = (XMLStreamWriter) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return outputFactory.createXMLStreamWriter(out, encoding);
                        }
                    });

            if (isDebugEnabled) {
                log.debug("XMLStreamWriter is " + writer.getClass().getName());
            }
            return writer;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    public static XMLStreamWriter createXMLStreamWriter(final Writer out) throws XMLStreamException {

        return createXMLStreamWriter(null, out);
    }

    public static XMLStreamWriter createXMLStreamWriter(StAXWriterConfiguration configuration, final Writer out)
            throws XMLStreamException {
        final XMLOutputFactory outputFactory = getXMLOutputFactory(configuration);
        try {
            XMLStreamWriter writer = (XMLStreamWriter) AccessController
                    .doPrivileged(new PrivilegedExceptionAction() {
                        public Object run() throws XMLStreamException {
                            return outputFactory.createXMLStreamWriter(out);
                        }
                    });
            if (isDebugEnabled) {
                log.debug("XMLStreamWriter is " + writer.getClass().getName());
            }
            return writer;
        } catch (PrivilegedActionException pae) {
            throw (XMLStreamException) pae.getException();
        }
    }

    /**
     * @deprecated
     */
    public static void reset() {
    }

    /**
     * Load factory properties from a resource. The context class loader is used to locate
     * the resource. The method converts boolean and integer values to the right Java types.
     * All other values are returned as strings.
     * 
     * @param name
     * @return
     */
    // This has package access since it is used from within anonymous inner classes
    static Map loadFactoryProperties(String name) {
        ClassLoader cl = getContextClassLoader();
        InputStream in = cl.getResourceAsStream(name);
        if (in == null) {
            return null;
        } else {
            try {
                Properties rawProps = new Properties();
                Map props = new HashMap();
                rawProps.load(in);
                for (Iterator it = rawProps.entrySet().iterator(); it.hasNext();) {
                    Map.Entry entry = (Map.Entry) it.next();
                    String strValue = (String) entry.getValue();
                    Object value;
                    if (strValue.equals("true")) {
                        value = Boolean.TRUE;
                    } else if (strValue.equals("false")) {
                        value = Boolean.FALSE;
                    } else {
                        try {
                            value = Integer.valueOf(strValue);
                        } catch (NumberFormatException ex) {
                            value = strValue;
                        }
                    }
                    props.put(entry.getKey(), value);
                }
                if (log.isDebugEnabled()) {
                    log.debug("Loaded factory properties from " + name + ": " + props);
                }
                return props;
            } catch (IOException ex) {
                log.error("Failed to read " + name, ex);
                return null;
            } finally {
                try {
                    in.close();
                } catch (IOException ex) {
                    // Ignore
                }
            }
        }
    }

    private static XMLInputFactory newXMLInputFactory(final ClassLoader classLoader,
            final StAXParserConfiguration configuration) {

        return (XMLInputFactory) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ClassLoader savedClassLoader;
                if (classLoader == null) {
                    savedClassLoader = null;
                } else {
                    savedClassLoader = Thread.currentThread().getContextClassLoader();
                    Thread.currentThread().setContextClassLoader(classLoader);
                }
                try {
                    XMLInputFactory factory = XMLInputFactory.newInstance();
                    // Woodstox by default creates coalescing parsers. Even if this violates
                    // the StAX specs, for compatibility with Woodstox, we always enable the
                    // coalescing mode. Note that we need to do that before loading
                    // XMLInputFactory.properties so that this setting can be overridden.
                    factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
                    Map props = loadFactoryProperties("XMLInputFactory.properties");
                    if (props != null) {
                        for (Iterator it = props.entrySet().iterator(); it.hasNext();) {
                            Map.Entry entry = (Map.Entry) it.next();
                            factory.setProperty((String) entry.getKey(), entry.getValue());
                        }
                    }
                    StAXDialect dialect = StAXDialectDetector.getDialect(factory.getClass());
                    if (configuration != null) {
                        factory = configuration.configure(factory, dialect);
                    }
                    return new ImmutableXMLInputFactory(dialect.normalize(dialect.makeThreadSafe(factory)));
                } finally {
                    if (savedClassLoader != null) {
                        Thread.currentThread().setContextClassLoader(savedClassLoader);
                    }
                }
            }
        });
    }

    /**
     * @return XMLInputFactory for the current classloader
     */
    private static XMLInputFactory getXMLInputFactory_perClassLoader(StAXParserConfiguration configuration) {

        ClassLoader cl = getContextClassLoader();
        XMLInputFactory factory;
        if (cl == null) {
            factory = getXMLInputFactory_singleton(configuration);
        } else {
            // Check the cache
            if (configuration == null) {
                configuration = StAXParserConfiguration.DEFAULT;
            }
            Map map = (Map) inputFactoryPerCLMap.get(configuration);
            if (map == null) {
                map = Collections.synchronizedMap(new WeakHashMap());
                inputFactoryPerCLMap.put(configuration, map);
                factory = null;
            } else {
                factory = (XMLInputFactory) map.get(cl);
            }

            // If not found in the cache map, crate a new factory
            if (factory == null) {

                if (log.isDebugEnabled()) {
                    log.debug("About to create XMLInputFactory implementation with " + "classloader=" + cl);
                    log.debug("The classloader for javax.xml.stream.XMLInputFactory is: "
                            + XMLInputFactory.class.getClassLoader());
                }
                try {
                    factory = newXMLInputFactory(null, configuration);
                } catch (ClassCastException cce) {
                    if (log.isDebugEnabled()) {
                        log.debug("Failed creation of XMLInputFactory implementation with " + "classloader=" + cl);
                        log.debug("Exception is=" + cce);
                        log.debug("Attempting with classloader: " + XMLInputFactory.class.getClassLoader());
                    }
                    factory = newXMLInputFactory(XMLInputFactory.class.getClassLoader(), configuration);
                }

                if (factory != null) {
                    // Cache the new factory
                    map.put(cl, factory);

                    if (log.isDebugEnabled()) {
                        log.debug("Created XMLInputFactory = " + factory.getClass() + " with classloader=" + cl);
                        log.debug("Configuration = " + configuration);
                        log.debug("Size of XMLInputFactory map for this configuration = " + map.size());
                        log.debug("Configurations for which factories have been cached = "
                                + inputFactoryPerCLMap.keySet());
                    }
                } else {
                    factory = getXMLInputFactory_singleton(configuration);
                }
            }

        }
        return factory;
    }

    /**
     * @return singleton XMLInputFactory loaded with the StAXUtils classloader
     */
    private static XMLInputFactory getXMLInputFactory_singleton(StAXParserConfiguration configuration) {
        if (configuration == null) {
            configuration = StAXParserConfiguration.DEFAULT;
        }
        XMLInputFactory f = (XMLInputFactory) inputFactoryMap.get(configuration);
        if (f == null) {
            f = newXMLInputFactory(StAXUtils.class.getClassLoader(), configuration);
            inputFactoryMap.put(configuration, f);
            if (log.isDebugEnabled()) {
                if (f != null) {
                    log.debug("Created singleton XMLInputFactory " + f.getClass() + " with configuration "
                            + configuration);
                }
            }
        }

        return f;
    }

    private static XMLOutputFactory newXMLOutputFactory(final ClassLoader classLoader,
            final StAXWriterConfiguration configuration) {
        return (XMLOutputFactory) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                ClassLoader savedClassLoader;
                if (classLoader == null) {
                    savedClassLoader = null;
                } else {
                    savedClassLoader = Thread.currentThread().getContextClassLoader();
                    Thread.currentThread().setContextClassLoader(classLoader);
                }
                try {
                    XMLOutputFactory factory = XMLOutputFactory.newInstance();
                    factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.FALSE);
                    Map props = loadFactoryProperties("XMLOutputFactory.properties");
                    if (props != null) {
                        for (Iterator it = props.entrySet().iterator(); it.hasNext();) {
                            Map.Entry entry = (Map.Entry) it.next();
                            factory.setProperty((String) entry.getKey(), entry.getValue());
                        }
                    }
                    StAXDialect dialect = StAXDialectDetector.getDialect(factory.getClass());
                    if (configuration != null) {
                        factory = configuration.configure(factory, dialect);
                    }
                    return new ImmutableXMLOutputFactory(dialect.normalize(dialect.makeThreadSafe(factory)));
                } finally {
                    if (savedClassLoader != null) {
                        Thread.currentThread().setContextClassLoader(savedClassLoader);
                    }
                }
            }
        });
    }

    /**
     * @return XMLOutputFactory for the current classloader
     */
    private static XMLOutputFactory getXMLOutputFactory_perClassLoader(StAXWriterConfiguration configuration) {
        ClassLoader cl = getContextClassLoader();
        XMLOutputFactory factory;
        if (cl == null) {
            factory = getXMLOutputFactory_singleton(configuration);
        } else {
            if (configuration == null) {
                configuration = StAXWriterConfiguration.DEFAULT;
            }
            Map map = (Map) outputFactoryPerCLMap.get(configuration);
            if (map == null) {
                map = Collections.synchronizedMap(new WeakHashMap());
                outputFactoryPerCLMap.put(configuration, map);
                factory = null;
            } else {
                factory = (XMLOutputFactory) map.get(cl);
            }

            if (factory == null) {
                if (log.isDebugEnabled()) {
                    log.debug("About to create XMLOutputFactory implementation with " + "classloader=" + cl);
                    log.debug("The classloader for javax.xml.stream.XMLOutputFactory is: "
                            + XMLOutputFactory.class.getClassLoader());
                }
                try {
                    factory = newXMLOutputFactory(null, configuration);
                } catch (ClassCastException cce) {
                    if (log.isDebugEnabled()) {
                        log.debug("Failed creation of XMLOutputFactory implementation with " + "classloader=" + cl);
                        log.debug("Exception is=" + cce);
                        log.debug("Attempting with classloader: " + XMLOutputFactory.class.getClassLoader());
                    }
                    factory = newXMLOutputFactory(XMLOutputFactory.class.getClassLoader(), configuration);
                }
                if (factory != null) {
                    map.put(cl, factory);
                    if (log.isDebugEnabled()) {
                        log.debug("Created XMLOutputFactory = " + factory.getClass() + " for classloader=" + cl);
                        log.debug("Configuration = " + configuration);
                        log.debug("Size of XMLOutFactory map for this configuration = " + map.size());
                        log.debug("Configurations for which factories have been cached = "
                                + outputFactoryPerCLMap.keySet());
                    }
                } else {
                    factory = getXMLOutputFactory_singleton(configuration);
                }
            }

        }
        return factory;
    }

    /**
     * @return XMLOutputFactory singleton loaded with the StAXUtils classloader
     */
    private static XMLOutputFactory getXMLOutputFactory_singleton(StAXWriterConfiguration configuration) {
        if (configuration == null) {
            configuration = StAXWriterConfiguration.DEFAULT;
        }
        XMLOutputFactory f = (XMLOutputFactory) outputFactoryMap.get(configuration);
        if (f == null) {
            f = newXMLOutputFactory(StAXUtils.class.getClassLoader(), configuration);
            outputFactoryMap.put(configuration, f);
            if (log.isDebugEnabled()) {
                if (f != null) {
                    log.debug("Created singleton XMLOutputFactory " + f.getClass() + " with configuration "
                            + configuration);
                }
            }
        }
        return f;
    }

    /**
     * @return Trhead Context ClassLoader
     */
    private static ClassLoader getContextClassLoader() {
        ClassLoader cl = (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                return Thread.currentThread().getContextClassLoader();
            }
        });

        return cl;
    }

    /**
     * @deprecated use {@link #createXMLStreamReader(StAXParserConfiguration, InputStream, String)}
     *             with {@link StAXParserConfiguration#STANDALONE}
     */
    public static XMLStreamReader createNetworkDetachedXMLStreamReader(InputStream in, String encoding)
            throws XMLStreamException {

        return createXMLStreamReader(StAXParserConfiguration.STANDALONE, in, encoding);
    }

    /**
     * @deprecated use {@link #getXMLInputFactory(StAXParserConfiguration)} with
     *             {@link StAXParserConfiguration#STANDALONE}
     */
    public static XMLInputFactory getNetworkDetachedXMLInputFactory() {
        return getXMLInputFactory(StAXParserConfiguration.STANDALONE);
    }

    /**
     * @deprecated use {@link #createXMLStreamReader(StAXParserConfiguration, InputStream)}
     *             with {@link StAXParserConfiguration#STANDALONE}
     */
    public static XMLStreamReader createNetworkDetachedXMLStreamReader(InputStream in) throws XMLStreamException {

        return createXMLStreamReader(StAXParserConfiguration.STANDALONE, in);
    }

    /**
     * @deprecated use {@link #createXMLStreamReader(StAXParserConfiguration, Reader)}
     *             with {@link StAXParserConfiguration#STANDALONE}
     */
    public static XMLStreamReader createNetworkDetachedXMLStreamReader(Reader in) throws XMLStreamException {

        return createXMLStreamReader(StAXParserConfiguration.STANDALONE, in);
    }

    /**
     * @deprecated Use {@link XMLEventUtils#getEventTypeString(int)} instead
     */
    public static String getEventTypeString(int event) {
        return XMLEventUtils.getEventTypeString(event);
    }
}