content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  package jaxp.sun.xml.internal.stream;
  
  import java.io.InputStream;
  import java.io.Reader;
  
  import javax.xml.stream.*;
  
  import jaxp.xml.stream.EventFilter;
  import jaxp.xml.stream.StreamFilter;
  import jaxp.xml.stream.XMLEventReader;
  import jaxp.xml.stream.XMLInputFactory;
  import jaxp.xml.stream.XMLReporter;
  import jaxp.xml.stream.XMLResolver;
  import jaxp.xml.stream.XMLStreamException;
  import jaxp.xml.stream.XMLStreamReader;
  import jaxp.xml.stream.util.XMLEventAllocator;
  import jaxp.xml.transform.Source;
  import jaxp.xml.transform.stream.StreamSource;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  import jaxp.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl;
  import jaxp.sun.org.apache.xerces.internal.impl.PropertyManager;
  import jaxp.sun.org.apache.xerces.internal.impl.XMLStreamFilterImpl;
  import jaxp.sun.org.apache.xerces.internal.impl.Constants;
  
  /** Factory Implementation for XMLInputFactory.
   * @author Neeraj Bajaj Sun Microsystems
   * @author K.Venugopal Sun Microsystems
   */
  
  //xxx: Should we be reusing the XMLInputSource object
  public class XMLInputFactoryImpl extends XMLInputFactory {
  
  
      //List of supported properties and default values.
      private PropertyManager fPropertyManager = new PropertyManager(PropertyManager.CONTEXT_READER) ;
      private static final boolean DEBUG = false;
  
      //Maintain a reference to last reader instantiated.
      private XMLStreamReaderImpl fTempReader = null ;
  
      boolean fPropertyChanged = false;
      //no reader reuse by default
      boolean fReuseInstance = false;
  
      /** Creates a new instance of ZephryParserFactory */
      public XMLInputFactoryImpl() {
  
      }
  
      void initEventReader(){
          fPropertyChanged = true;
      }
  
      /**
       * @param inputstream
       * @throws XMLStreamException
       * @return
       */
      public XMLEventReader createXMLEventReader(InputStream inputstream) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(inputstream));
      }
  
      public XMLEventReader createXMLEventReader(Reader reader) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(reader));
      }
  
      public XMLEventReader createXMLEventReader(Source source) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(source));
      }
  
      public XMLEventReader createXMLEventReader(String systemId, InputStream inputstream) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(systemId, inputstream));
      }
  
      public XMLEventReader createXMLEventReader(java.io.InputStream stream, String encoding) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(stream, encoding));
      }
  
      public XMLEventReader createXMLEventReader(String systemId, Reader reader) throws XMLStreamException {
          initEventReader();
          //delegate everything to XMLStreamReader
          return new XMLEventReaderImpl(createXMLStreamReader(systemId, reader));
      }
  
      /** Create a new XMLEventReader from an XMLStreamReader.  After being used
       * to construct the XMLEventReader instance returned from this method
       * the XMLStreamReader must not be used.
       * @param reader the XMLStreamReader to read from (may not be modified)
       * @return a new XMLEventReader
       * @throws XMLStreamException
       */
      public XMLEventReader createXMLEventReader(XMLStreamReader reader) throws XMLStreamException {
  
          //xxx: what do we do now -- instance is passed from the application
          //probably we should check if the state is at the start document,
          //eventreader call to next() should return START_DOCUMENT and
          //then delegate every call to underlying streamReader
          return new XMLEventReaderImpl(reader) ;
      }
  
      public XMLStreamReader createXMLStreamReader(InputStream inputstream) throws XMLStreamException {
          XMLInputSource inputSource = new XMLInputSource(null, null, null, inputstream, null);
          return getXMLStreamReaderImpl(inputSource);
      }
  
      public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException {
          XMLInputSource inputSource = new XMLInputSource(null, null, null, reader, null);
          return getXMLStreamReaderImpl(inputSource);
      }
  
      public XMLStreamReader createXMLStreamReader(String systemId, Reader reader) throws XMLStreamException {
          XMLInputSource inputSource = new XMLInputSource(null,systemId,null,reader,null);
          return getXMLStreamReaderImpl(inputSource);
      }
  
      public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
          return new XMLStreamReaderImpl(jaxpSourcetoXMLInputSource(source),
                  new PropertyManager(fPropertyManager));
      }
  
      public XMLStreamReader createXMLStreamReader(String systemId, InputStream inputstream) throws XMLStreamException {
          XMLInputSource inputSource = new XMLInputSource(null,systemId,null,inputstream,null);
          return getXMLStreamReaderImpl(inputSource);
      }
  
  
      public XMLStreamReader createXMLStreamReader(InputStream inputstream, String encoding) throws XMLStreamException {
          XMLInputSource inputSource = new XMLInputSource(null,null,null,inputstream,encoding);
          return getXMLStreamReaderImpl(inputSource);
      }
  
      public XMLEventAllocator getEventAllocator() {
          return (XMLEventAllocator)getProperty(XMLInputFactory.ALLOCATOR);
      }
  
      public XMLReporter getXMLReporter() {
          return (XMLReporter)fPropertyManager.getProperty(XMLInputFactory.REPORTER);
      }
  
      public XMLResolver getXMLResolver() {
          Object object = fPropertyManager.getProperty(XMLInputFactory.RESOLVER);
          return (XMLResolver)object;
          //return (XMLResolver)fPropertyManager.getProperty(XMLInputFactory.RESOLVER);
      }
  
      public void setXMLReporter(XMLReporter xmlreporter) {
          fPropertyManager.setProperty(XMLInputFactory.REPORTER, xmlreporter);
      }
  
      public void setXMLResolver(XMLResolver xmlresolver) {
          fPropertyManager.setProperty(XMLInputFactory.RESOLVER, xmlresolver);
      }
  
      /** Create a filtered event reader that wraps the filter around the event reader
       * @param reader the event reader to wrap
       * @param filter the filter to apply to the event reader
       * @throws XMLStreamException
       */
      public XMLEventReader createFilteredReader(XMLEventReader reader, EventFilter filter) throws XMLStreamException {
          return new EventFilterSupport(reader, filter);
      }
  
      /** Create a filtered reader that wraps the filter around the reader
       * @param reader the reader to filter
       * @param filter the filter to apply to the reader
       * @throws XMLStreamException
       */
      public XMLStreamReader createFilteredReader(XMLStreamReader reader, StreamFilter filter) throws XMLStreamException {
          if( reader != null && filter != null )
              return new XMLStreamFilterImpl(reader,filter);
  
          return null;
      }
  
  
  
      /** Get the value of a feature/property from the underlying implementation
       * @param name The name of the property (may not be null)
       * @return The value of the property
       * @throws IllegalArgumentException if the property is not supported
       */
      public Object getProperty(java.lang.String name) throws java.lang.IllegalArgumentException {
          if(name == null){
              throw new IllegalArgumentException("Property not supported");
          }
          if(fPropertyManager.containsProperty(name))
              return fPropertyManager.getProperty(name);
          throw new IllegalArgumentException("Property not supported");
      }
  
      /** Query the set of fProperties that this factory supports.
       *
       * @param name The name of the property (may not be null)
       * @return true if the property is supported and false otherwise
       */
      public boolean isPropertySupported(String name) {
          if(name == null)
              return false ;
          else
              return fPropertyManager.containsProperty(name);
      }
  
      /** Set a user defined event allocator for events
       * @param allocator the user defined allocator
       */
      public void setEventAllocator(XMLEventAllocator allocator) {
          fPropertyManager.setProperty(XMLInputFactory.ALLOCATOR, allocator);
      }
  
      /** Allows the user to set specific feature/property on the underlying implementation. The underlying implementation
       * is not required to support every setting of every property in the specification and may use IllegalArgumentException
       * to signal that an unsupported property may not be set with the specified value.
       * @param name The name of the property (may not be null)
       * @param value The value of the property
       * @throws java.lang.IllegalArgumentException if the property is not supported
       */
      public void setProperty(java.lang.String name, Object value) throws java.lang.IllegalArgumentException {
  
          if(name == null || value == null || !fPropertyManager.containsProperty(name) ){
              throw new IllegalArgumentException("Property "+name+" is not supported");
          }
          if(name == Constants.REUSE_INSTANCE || name.equals(Constants.REUSE_INSTANCE)){
              fReuseInstance = ((Boolean)value).booleanValue();
              if(DEBUG)System.out.println("fReuseInstance is set to " + fReuseInstance);
          }else{//for any other property set the flag
              //REVISIT: Even in this case instance can be reused, by passing PropertyManager
              fPropertyChanged = true;
          }
          fPropertyManager.setProperty(name,value);
      }
  
      XMLStreamReader getXMLStreamReaderImpl(XMLInputSource inputSource) throws XMLStreamException {
          //1. if the temp reader is null -- create the instance and return
          if(fTempReader == null){
              fPropertyChanged = false;
              return fTempReader = new XMLStreamReaderImpl(inputSource,
                      new PropertyManager(fPropertyManager));
          }
          //if factory is configured to reuse the instance & this instance can be reused
          //& the setProperty() hasn't been called
          if(fReuseInstance && fTempReader.canReuse() && !fPropertyChanged){
              if(DEBUG)System.out.println("Reusing the instance");
              //we can make setInputSource() call reset() and this way there wont be two function calls
              fTempReader.reset();
              fTempReader.setInputSource(inputSource);
              fPropertyChanged = false;
              return fTempReader;
          }else{
              fPropertyChanged = false;
              //just return the new instance.. note that we are not setting  fTempReader to the newly created instance
              return fTempReader = new XMLStreamReaderImpl(inputSource,
                      new PropertyManager(fPropertyManager));
          }
      }
  
      XMLInputSource jaxpSourcetoXMLInputSource(Source source){
           if(source instanceof StreamSource){
               StreamSource stSource = (StreamSource)source;
               String systemId = stSource.getSystemId();
               String publicId = stSource.getPublicId();
               InputStream istream = stSource.getInputStream();
               Reader reader = stSource.getReader();
  
               if(istream != null){
                   return new XMLInputSource(publicId, systemId, null, istream, null);
               }
               else if(reader != null){
                   return new XMLInputSource(publicId, systemId,null, reader, null);
               }else{
                   return new XMLInputSource(publicId, systemId, null);
               }
           }
  
           throw new UnsupportedOperationException("Cannot create " +
                  "XMLStreamReader or XMLEventReader from a " +
                  source.getClass().getName());
      }
  
  }//XMLInputFactoryImpl
  