Package org.codehaus.staxmate

Source Code of org.codehaus.staxmate.SMInputFactory

package org.codehaus.staxmate;

import java.io.*;
import java.net.URL;

import javax.xml.stream.*;

import org.codehaus.stax2.XMLInputFactory2;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.io.Stax2ByteArraySource;
import org.codehaus.stax2.ri.Stax2ReaderAdapter;

import org.codehaus.staxmate.in.*;

/**
* Factory class used to create {@link SMInputCursor} instances.
* Cursor come in two major flavors: "nested" and "flattening" cursors.
*<p>
* Nested cursor are used to iterate a single level nested events,
* so they can only traverse over immediate children of the event
* (generally, START_ELEEMENT) that the parent cursor points to.
* Flattening cursors on the other hand traverse over all the
* descendants (children, children of children etc) of the parent
* START_ELEMENT. One additional difference is that the flattening
* cursors do expose END_ELEMENTS so that matching of actual levels
* is still possible.
*<p>
* Beyond nested/flat (aka "child vs descendant") cursors, there
* are additional varieties, such as:
*<ul>
* <li>Filtered cursors: these will only expose events you want to
*   see, and silently skip any other events. Most commonly
*   needed ones (element-only, text-only, element-and-text-only;
*   all of which skip comments, processing instructions) exist
*   for your convenience using
{@link org.codehaus.staxmate.in.SMFilterFactory}.
*   Filters are passed to the factory methods.
*</ul>
*
* @author Tatu Saloranta
*/
public final class SMInputFactory
{
    /**
     * Xml input stream factory used for constructing stream readers.
     */
    final XMLInputFactory mStaxFactory;

    /**
     * If the configured stax input factory implements Stax2 API,
     * will contain upcast factory instance, otherwise null.
     */
    final XMLInputFactory2 mStax2Factory;

    public SMInputFactory(XMLInputFactory staxF)
    {
        mStaxFactory = staxF;
        mStax2Factory = (staxF instanceof XMLInputFactory2) ?
            (XMLInputFactory2) staxF : null;
    }

    /*
    /////////////////////////////////////////////////
    // Access to underlying Stax factory
    /////////////////////////////////////////////////
     */

    public XMLInputFactory getStaxFactory() { return mStaxFactory; }

    /*
    /////////////////////////////////////////////////
    // Cursor construction, underlying methods
    /////////////////////////////////////////////////
     */

    /**
     * Static factory method used to construct root-level hierarchic (child)
     * cursor, when starting to process an xml document or fragment.
     * Additional cursors are usually constructed via methods
     * within this cursor and its child cursors).
     *
     * @param sr Underlying stream reader cursor will use
     * @param f (optional) Filter to use for the cursor, if any; null
     *   means that no filtering will be done.
     */
    public static SMHierarchicCursor hierarchicCursor(XMLStreamReader sr, SMFilter f) {
        return constructHierarchic(Stax2ReaderAdapter.wrapIfNecessary(sr), f);
    }

    /**
     * Static factory method used to construct root-level flattening (descendant)
     * cursor, when starting to process an xml document or fragment.
     * Additional cursors are usually constructed via methods
     * within this cursor and its child cursors).
     *
     * @param sr Underlying stream reader cursor will use
     * @param f (optional) Filter to use for the cursor, if any; null
     *   means that no filtering will be done.
     */
    public static SMFlatteningCursor flatteningCursor(XMLStreamReader sr, SMFilter f) {
        return constructFlattening(Stax2ReaderAdapter.wrapIfNecessary(sr), f);
    }

    /**
     * Convenience method that will construct and return
     * a nested cursor that will only ever iterate to one node, that
     * is, the root element of the document reader is reading.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     */
    public static SMHierarchicCursor rootElementCursor(XMLStreamReader sr)
    {
        return hierarchicCursor(sr, SMFilterFactory.getElementOnlyFilter());
    }

    /**
     * Convenience method that will construct and return
     * a nested cursor that will iterate over root-level events
     * (comments, PIs, root element), without filtering any events.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     */
    public static SMHierarchicCursor rootCursor(XMLStreamReader sr)
    {
        return hierarchicCursor(sr, null);
    }

    /*
    /////////////////////////////////////////////////
    // Stream reader construction
    /////////////////////////////////////////////////
     */

    /**
     * Method for constructing Stax stream reader to read contents
     * of specified URL, using Stax input factory
     * this StaxMate factory was constructed with.
     */
    public XMLStreamReader2 createStax2Reader(URL url)
        throws XMLStreamException
    {
        if (mStax2Factory != null) {
            return mStax2Factory.createXMLStreamReader(url);
        }
        try {
            XMLStreamReader sr = mStaxFactory.createXMLStreamReader(url.toExternalForm(), url.openStream());
            return Stax2ReaderAdapter.wrapIfNecessary(sr);
        } catch (IOException ioe) {
            throw new XMLStreamException(ioe);
        }
    }

    /**
     * Method for constructing Stax stream reader to read contents
     * of specified file, using Stax input factory
     * this StaxMate factory was constructed with.
     */
    public XMLStreamReader2 createStax2Reader(File f)
        throws XMLStreamException
    {
        if (mStax2Factory != null) {
            return mStax2Factory.createXMLStreamReader(f);
        }
        try {
            String sysId = f.toURL().toExternalForm();
            XMLStreamReader sr = mStaxFactory.createXMLStreamReader(sysId, new FileInputStream(f));
            return Stax2ReaderAdapter.wrapIfNecessary(sr);
        } catch (IOException ioe) {
            throw new XMLStreamException(ioe);
        }
    }

    /**
     * Method for constructing Stax stream reader to read contents
     * of (portion of) specified byte array, using Stax input factory
     * this StaxMate factory was constructed with.
     */
    public XMLStreamReader2 createStax2Reader(byte[] data, int offset, int len)
        throws XMLStreamException
    {
        Stax2ByteArraySource src = new Stax2ByteArraySource(data, offset, len);
        if (mStax2Factory != null) {
            return (XMLStreamReader2) mStax2Factory.createXMLStreamReader(src);
        }
        try {
            XMLStreamReader sr = mStaxFactory.createXMLStreamReader(src.constructInputStream());
            return Stax2ReaderAdapter.wrapIfNecessary(sr);
        } catch (IOException ioe) {
            throw new XMLStreamException(ioe);
        }
    }

    /**
     * Method for constructing Stax stream reader to read contents
     * accessible through Inputstream provided.
     * Underlying stream reader is constucted using Stax factory
     * this StaxMate factory was constructed with.
     *<p>
     * NOTE: this method should only be used if no other overloaded
     * methods matches input source. For example, if input comes from
     * a file, then the method that takes File argument should be used
     * instead. This because more specific methods can provide better
     * error reporting and entity resolution support.
     */
    public XMLStreamReader2 createStax2Reader(InputStream in)
        throws XMLStreamException
    {
        return Stax2ReaderAdapter.wrapIfNecessary(mStaxFactory.createXMLStreamReader(in));
    }

    /*
    /////////////////////////////////////////////////
    // Cursor construction, "full service" (non-static)
    /////////////////////////////////////////////////
     */

    /**
     * Method that will construct and return
     * a nested cursor that will only ever iterate to one node, that
     * is, the root element of the document reader is reading.
     *<p>
     * Cursor is built based on Stax stream reader constructed to
     * read contents of resource specified by the URL argument.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     */
    public SMHierarchicCursor rootElementCursor(URL url)
        throws XMLStreamException
    {
        return constructHierarchic(createStax2Reader(url), SMFilterFactory.getElementOnlyFilter());
    }

    /**
     * Method that will construct and return
     * a nested cursor that will only ever iterate to one node, that
     * is, the root element of the document reader is reading.
     *<p>
     * Cursor is built based on Stax stream reader constructed to
     * read contents of specified File.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     */
    public SMHierarchicCursor rootElementCursor(File f)
        throws XMLStreamException
    {
        return constructHierarchic(createStax2Reader(f), SMFilterFactory.getElementOnlyFilter());
    }

    /**
     * Method that will construct and return
     * a nested cursor that will only ever iterate to one node, that
     * is, the root element of the document reader is reading.
     *<p>
     * Cursor is built based on Stax stream reader constructed to
     * read contents of the specified byte array.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     */
    public SMHierarchicCursor rootElementCursor(byte[] data, int offset, int len)
        throws XMLStreamException
    {
        return constructHierarchic(createStax2Reader(data, offset, len), SMFilterFactory.getElementOnlyFilter());
    }

    /**
     * Method that will construct and return
     * a nested cursor that will only ever iterate to one node, that
     * is, the root element of the document reader is reading.
     *<p>
     * Cursor is built based on Stax stream reader constructed to
     * read contents of specified File.
     *<p>
     * Method uses standard "element-only" filter from
     *  {@link org.codehaus.staxmate.in.SMFilterFactory}.
     *<p>
     * NOTE: this method should only be used if no other overloaded
     * methods matches input source. For example, if input comes from
     * a file, then the method that takes File argument should be used
     * instead. This because more specific methods can provide better
     * error reporting and entity resolution support.
     */
    public SMHierarchicCursor rootElementCursor(InputStream in)
        throws XMLStreamException
    {
        return constructHierarchic(createStax2Reader(in), SMFilterFactory.getElementOnlyFilter());
    }

    /*
    ///////////////////////////////////////////////////////
    // Convenience methods
    ///////////////////////////////////////////////////////
    */

    /**
     * Convenience method that will get a lazily constructed shared
     * {@link SMInputFactory} instance. Instance is built using
     * similarly shared {@link XMLInputFactory} instance (which
     * is accessed using {@link #getGlobalXMLInputFactory}).
     * See notes on  {@link #getGlobalXMLInputFactory} for limitations
     * on when (if ever) you should use this method.
     *<p>
     * Note that this single(ton) instance is global to the class loader
     * that loaded <code>SMInputFactory</code> (and usually hence
     * global to a single JVM instance).
     *
     * @throws FactoryConfigurationError If there are problems with
     *   configuration of Stax input factory (most likely because
     *   there is no implementation available)
     */
    public static SMInputFactory getGlobalSMInputFactory()
        throws FactoryConfigurationError
    {
        return SMFactoryAccessor.getFactory();
    }

    /**
     * Convenience method that will get a lazily constructed shared
     * {@link XMLInputFactory} instance. Note that this instance
     * should only be used IFF:
     *<ul>
     * <li>Default settings (namespace-aware, dtd-aware but not validating,
     *   non-coalescing)
     *    for the factory are acceptable
     *  </li>
     * <li>Settings of the factory are not modified: thread-safety
     *   of the factory instance is only guaranteed for factory methods,
     *   not for configuration change methods
     *  </li>
     * </ul>
     *<p>
     * Note that this single(ton) instance is global to the class loader
     * that loaded <code>SMInputFactory</code> (and usually hence
     * global to a single JVM instance).
     *
     * @throws FactoryConfigurationError If there are problems with
     *   configuration of Stax input factory (most likely because
     *   there is no implementation available)
     */
    public static XMLInputFactory getGlobalXMLInputFactory()
        throws FactoryConfigurationError
    {
        return XmlFactoryAccessor.getFactory();
    }

    /*
    ///////////////////////////////////////////////////////
    // Internal methods
    ///////////////////////////////////////////////////////
    */

    private final static SMHierarchicCursor constructHierarchic(XMLStreamReader2 sr, SMFilter f)
    {
        return new SMHierarchicCursor(null, sr, f);
    }

    private final static SMFlatteningCursor constructFlattening(XMLStreamReader2 sr, SMFilter f)
    {
        return new SMFlatteningCursor(null, sr, f);
    }

    /*
    ///////////////////////////////////////////////////////
    // Helper classes
    ///////////////////////////////////////////////////////
    */

    /**
     * Helper class used for implementing efficient lazy instantiation of
     * the global xml stream input factory.
     */
    private final static class XmlFactoryAccessor
    {
        final static XmlFactoryAccessor sInstance = new XmlFactoryAccessor();
        XMLInputFactory mFactory = null;

        public static XMLInputFactory getFactory()
            throws FactoryConfigurationError
        {
            return sInstance.get();
        }

        private synchronized XMLInputFactory get()
            throws FactoryConfigurationError
        {
            if (mFactory == null) {
                mFactory = XMLInputFactory.newInstance();
            }
            return mFactory;
        }
    }

    /**
     * Helper class used for implementing efficient lazy instantiation of
     * the global StaxMate input factory.
     */
    private final static class SMFactoryAccessor
    {
        final static SMFactoryAccessor sInstance = new SMFactoryAccessor();
        SMInputFactory mFactory = null;

        public static SMInputFactory getFactory()
            throws FactoryConfigurationError
        {
            return sInstance.get();
        }

        private synchronized SMInputFactory get()
            throws FactoryConfigurationError
        {
            if (mFactory == null) {
                mFactory = new SMInputFactory(XmlFactoryAccessor.getFactory());
            }
            return mFactory;
        }
    }
}
TOP

Related Classes of org.codehaus.staxmate.SMInputFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.