# AbstractXMLInputFactory.java

    /*
     * Copyright 2011, 2012 Odysseus Software GmbH
     *
     * Licensed 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.synapse.commons.staxon.core.base;

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Reader;
    import java.net.URI;
    import java.net.URISyntaxException;

    import javax.xml.stream.StreamFilter;
    import javax.xml.stream.XMLEventReader;
    import javax.xml.stream.XMLInputFactory;
    import javax.xml.stream.XMLReporter;
    import javax.xml.stream.XMLResolver;
    import javax.xml.stream.XMLStreamException;
    import javax.xml.stream.XMLStreamReader;
    import javax.xml.stream.util.StreamReaderDelegate;
    import javax.xml.stream.util.XMLEventAllocator;
    import javax.xml.transform.Source;
    import javax.xml.transform.stream.StreamSource;

    /**
     * Abstract XML input factory.
     */
    public abstract class AbstractXMLInputFactory extends XMLInputFactory {
        private XMLEventAllocator allocator;
        private XMLResolver resolver;
        private XMLReporter reporter;

        private boolean coalescing;
        private boolean namespaceAware;
        private boolean replacingEntityReferences;
        private boolean supportingExternalEntities;
        private boolean validating;
        private boolean supportDTD;

        @Override
        public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
            if (source instanceof StreamSource) {
                StreamSource streamSource = (StreamSource) source;
                InputStream input = streamSource.getInputStream();
                if (input != null) {
                    if (streamSource.getSystemId() != null) {
                        return createXMLStreamReader(streamSource.getSystemId(), input);
                    } else {
                        return createXMLStreamReader(input);
                    }
                }
                Reader reader = streamSource.getReader();
                if (reader != null) {
                    if (streamSource.getSystemId() != null) {
                        return createXMLStreamReader(streamSource.getSystemId(), reader);
                    } else {
                        return createXMLStreamReader(reader);
                    }
                }
                if (streamSource.getSystemId() != null) {
                    try {
                        final InputStream stream = new URI(source.getSystemId()).toURL().openStream();
                        return new StreamReaderDelegate(createXMLStreamReader(streamSource.getSystemId(), stream)) {
                            /*
                             * Close underlying stream, otherwise it could never be done
                             * @see javax.xml.stream.util.StreamReaderDelegate#close()
                             */
                            @Override
                            public void close() throws XMLStreamException {
                                super.close();
                                try {
                                    stream.close();
                                } catch (IOException e) {
                                    // ignore
                                }
                            }
                        };
                    } catch (URISyntaxException e) {
                        throw new XMLStreamException("Cannot parse system id for reading: " + source.getSystemId(), e);
                    } catch (IOException e) {
                        throw new XMLStreamException("Cannot open system id as URL for reading: " + source.getSystemId(), e);
                    }
                } else {
                    throw new XMLStreamException("Invalid stream source: none of input, reader, systemId set");
                }
            }
            throw new XMLStreamException("Unsupported source type: " + source.getClass());
        }

        @Override
        public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(reader));
        }

        @Override
        public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(systemId, reader));
        }

        @Override
        public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(source));
        }

        @Override
        public XMLEventReader createXMLEventReader(InputStream stream) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(stream));
        }

        @Override
        public XMLEventReader createXMLEventReader(InputStream stream, String encoding) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(stream, encoding));
        }

        @Override
        public XMLEventReader createXMLEventReader(String systemId, InputStream stream) throws XMLStreamException {
            return createXMLEventReader(createXMLStreamReader(systemId, stream));
        }

        @Override
        public XMLStreamReader createFilteredReader(XMLStreamReader reader, final StreamFilter filter) throws XMLStreamException {
            return new StreamReaderDelegate(reader) {
                @Override
                public boolean hasNext() throws XMLStreamException {
                    while (super.hasNext()) {
                        if (filter.accept(getParent())) {
                            return true;
                        }
                        super.next();
                    }
                    return false;
                }

                @Override
                public int next() throws XMLStreamException {
                    if (hasNext()) {
                        return getParent().getEventType();
                    }
                    throw new IllegalStateException("No more events");
                }
            };
        }

        @Override
        public XMLEventAllocator getEventAllocator() {
            return allocator;
        }

        @Override
        public void setEventAllocator(XMLEventAllocator allocator) {
            this.allocator = allocator;
        }

        @Override
        public XMLResolver getXMLResolver() {
            return resolver;
        }

        @Override
        public void setXMLResolver(XMLResolver resolver) {
            this.resolver = resolver;
        }

        @Override
        public XMLReporter getXMLReporter() {
            return reporter;
        }

        @Override
        public void setXMLReporter(XMLReporter reporter) {
            this.reporter = reporter;
        }

        @Override
        public boolean isPropertySupported(String name) {
            if (ALLOCATOR.equals(name)) {
                return true;
            } else if (IS_COALESCING.equals(name)) {
                return true;
            } else if (IS_NAMESPACE_AWARE.equals(name)) {
                return true;
            } else if (IS_REPLACING_ENTITY_REFERENCES.equals(name)) {
                return true;
            } else if (IS_SUPPORTING_EXTERNAL_ENTITIES.equals(name)) {
                return true;
            } else if (IS_VALIDATING.equals(name)) {
                return true;
            } else if (REPORTER.equals(name)) {
                return true;
            } else if (RESOLVER.equals(name)) {
                return true;
            } else if (SUPPORT_DTD.equals(name)) {
                return true;
            } else {
                return false;
            }
        }

        @Override
        public Object getProperty(String name) throws IllegalArgumentException {
            if (ALLOCATOR.equals(name)) {
                return allocator;
            } else if (IS_COALESCING.equals(name)) {
                return Boolean.valueOf(coalescing);
            } else if (IS_NAMESPACE_AWARE.equals(name)) {
                return Boolean.valueOf(namespaceAware);
            } else if (IS_REPLACING_ENTITY_REFERENCES.equals(name)) {
                return Boolean.valueOf(replacingEntityReferences);
            } else if (IS_SUPPORTING_EXTERNAL_ENTITIES.equals(name)) {
                return Boolean.valueOf(supportingExternalEntities);
            } else if (IS_VALIDATING.equals(name)) {
                return Boolean.valueOf(validating);
            } else if (REPORTER.equals(name)) {
                return reporter;
            } else if (RESOLVER.equals(name)) {
                return resolver;
            } else if (SUPPORT_DTD.equals(name)) {
                return Boolean.valueOf(supportDTD);
            } else {
                throw new IllegalArgumentException("Unsupported property: " + name);
            }
        }

        @Override
        public void setProperty(String name, Object value) throws IllegalArgumentException {
            if (ALLOCATOR.equals(name)) {
                allocator = (XMLEventAllocator) value;
            } else if (IS_COALESCING.equals(name)) {
                coalescing = ((Boolean) value).booleanValue();
            } else if (IS_NAMESPACE_AWARE.equals(name)) {
                namespaceAware = ((Boolean) value).booleanValue();
            } else if (IS_REPLACING_ENTITY_REFERENCES.equals(name)) {
                replacingEntityReferences = ((Boolean) value).booleanValue();
            } else if (IS_SUPPORTING_EXTERNAL_ENTITIES.equals(name)) {
                supportingExternalEntities = ((Boolean) value).booleanValue();
            } else if (IS_VALIDATING.equals(name)) {
                validating = ((Boolean) value).booleanValue();
            } else if (REPORTER.equals(name)) {
                reporter = (XMLReporter) value;
            } else if (RESOLVER.equals(name)) {
                resolver = (XMLResolver) value;
            } else if (SUPPORT_DTD.equals(name)) {
                supportDTD = ((Boolean) value).booleanValue();
            } else {
                throw new IllegalArgumentException("Unsupported property: " + name);
            }
        }
    }