/*
 * reserved comment block
 * DO NOT REMOVE OR ALTER!
 */
/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.
 */
/*
 * $Id: IncrementalSAXSource_Xerces.java,v 1.2.4.1 2005/09/15 08:15:08 suresh_emailid Exp $
 */

package com.sun.org.apache.xml.internal.dtm.ref;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

import com.sun.org.apache.xerces.internal.parsers.SAXParser;
import com.sun.org.apache.xml.internal.res.XMLErrorResources;
import com.sun.org.apache.xml.internal.res.XMLMessages;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;


/** <p>IncrementalSAXSource_Xerces takes advantage of the fact that Xerces1
 * incremental mode is already a coroutine of sorts, and just wraps our
 * IncrementalSAXSource API around it.</p>
 *
 * <p>Usage example: See main().</p>
 *
 * <p>Status: Passes simple main() unit-test. NEEDS JAVADOC.</p>
 * */
public class IncrementalSAXSource_Xerces
  implements IncrementalSAXSource
{
  //
  // Reflection. To allow this to compile with both Xerces1 and Xerces2, which
  // require very different methods and objects, we need to avoid static
  // references to those APIs. So until Xerces2 is pervasive and we're willing
  // to make it a prerequisite, we will rely upon relection.
  //
  Method fParseSomeSetup=null; // Xerces1 method
  Method fParseSome=null; // Xerces1 method
  Object fPullParserConfig=null; // Xerces2 pull control object
  Method fConfigSetInput=null; // Xerces2 method
  Method fConfigParse=null; // Xerces2 method
  Method fSetInputSource=null; // Xerces2 pull control method
  Constructor fConfigInputSourceCtor=null; // Xerces2 initialization method
  Method fConfigSetByteStream=null; // Xerces2 initialization method
  Method fConfigSetCharStream=null; // Xerces2 initialization method
  Method fConfigSetEncoding=null; // Xerces2 initialization method
  Method fReset=null; // Both Xerces1 and Xerces2, but diff. signatures

  //
  // Data
  //
  SAXParser fIncrementalParser;
  private boolean fParseInProgress=false;

  //
  // Constructors
  //

  /** Create a IncrementalSAXSource_Xerces, and create a SAXParser
   * to go with it. Xerces2 incremental parsing is only supported if
   * this constructor is used, due to limitations in the Xerces2 API (as of
   * Beta 3). If you don't like that restriction, tell the Xerces folks that
   * there should be a simpler way to request incremental SAX parsing.
   * */
  public IncrementalSAXSource_Xerces()
                throws NoSuchMethodException
        {
                try
                {
                        // Xerces-2 incremental parsing support (as of Beta 3)
                        // ContentHandlers still get set on fIncrementalParser (to get
                        // conversion from XNI events to SAX events), but
                        // _control_ for incremental parsing must be exercised via the config.
                        //
                        // At this time there's no way to read the existing config, only
                        // to assert a new one... and only when creating a brand-new parser.
                        //
                        // Reflection is used to allow us to continue to compile against
                        // Xerces1. If/when we can abandon the older versions of the parser,
                        // this will simplify significantly.

                        // If we can't get the magic constructor, no need to look further.
                        Class xniConfigClass=ObjectFactory.findProviderClass(
                            "com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",
                            true);
                        Class[] args1={xniConfigClass};
                        Constructor ctor=SAXParser.class.getConstructor(args1);

                        // Build the parser configuration object. StandardParserConfiguration
                        // happens to implement XMLPullParserConfiguration, which is the API
                        // we're going to want to use.
                        Class xniStdConfigClass=ObjectFactory.findProviderClass(
                            "com.sun.org.apache.xerces.internal.parsers.StandardParserConfiguration",
                            true);
                        fPullParserConfig=xniStdConfigClass.newInstance();
                        Object[] args2={fPullParserConfig};
                        fIncrementalParser = (SAXParser)ctor.newInstance(args2);

                        // Preload all the needed the configuration methods... I want to know they're
                        // all here before we commit to trying to use them, just in case the
                        // API changes again.
                        Class fXniInputSourceClass=ObjectFactory.findProviderClass(
                            "com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource",
                            true);
                        Class[] args3={fXniInputSourceClass};
                        fConfigSetInput=xniStdConfigClass.getMethod("setInputSource",args3);

                        Class[] args4={String.class,String.class,String.class};
                        fConfigInputSourceCtor=fXniInputSourceClass.getConstructor(args4);
                        Class[] args5={java.io.InputStream.class};
                        fConfigSetByteStream=fXniInputSourceClass.getMethod("setByteStream",args5);
                        Class[] args6={java.io.Reader.class};
                        fConfigSetCharStream=fXniInputSourceClass.getMethod("setCharacterStream",args6);
                        Class[] args7={String.class};
                        fConfigSetEncoding=fXniInputSourceClass.getMethod("setEncoding",args7);

                        Class[] argsb={Boolean.TYPE};
                        fConfigParse=xniStdConfigClass.getMethod("parse",argsb);
                        Class[] noargs=new Class[0];
                        fReset=fIncrementalParser.getClass().getMethod("reset",noargs);
                }
                catch(Exception e)
                {
            // Fallback if this fails (implemented in createIncrementalSAXSource) is
                        // to attempt Xerces-1 incremental setup. Can't do tail-call in
                        // constructor, so create new, copy Xerces-1 initialization,
                        // then throw it away... Ugh.
                        IncrementalSAXSource_Xerces dummy=new IncrementalSAXSource_Xerces(new SAXParser());
                        this.fParseSomeSetup=dummy.fParseSomeSetup;
                        this.fParseSome=dummy.fParseSome;
                        this.fIncrementalParser=dummy.fIncrementalParser;
                }
  }

  /** Create a IncrementalSAXSource_Xerces wrapped around
   * an existing SAXParser. Currently this works only for recent
   * releases of Xerces-1.  Xerces-2 incremental is currently possible
   * only if we are allowed to create the parser instance, due to
   * limitations in the API exposed by Xerces-2 Beta 3; see the
   * no-args constructor for that code.
   *
   * @exception if the SAXParser class doesn't support the Xerces
   * incremental parse operations. In that case, caller should
   * fall back upon the IncrementalSAXSource_Filter approach.
   * */
  public IncrementalSAXSource_Xerces(SAXParser parser)
    throws NoSuchMethodException
  {
                // Reflection is used to allow us to compile against
                // Xerces2. If/when we can abandon the older versions of the parser,
                // this constructor will simply have to fail until/unless the
                // Xerces2 incremental support is made available on previously
                // constructed SAXParser instances.
    fIncrementalParser=parser;
                Class me=parser.getClass();
    Class[] parms={InputSource.class};
    fParseSomeSetup=me.getMethod("parseSomeSetup",parms);
    parms=new Class[0];
    fParseSome=me.getMethod("parseSome",parms);
    // Fallback if this fails (implemented in createIncrementalSAXSource) is
    // to use IncrementalSAXSource_Filter rather than Xerces-specific code.
  }

  //
  // Factories
  //
  static public IncrementalSAXSource createIncrementalSAXSource()
        {
                try
                {
                        return new IncrementalSAXSource_Xerces();
                }
                catch(NoSuchMethodException e)
                {
                        // Xerces version mismatch; neither Xerces1 nor Xerces2 succeeded.
                        // Fall back on filtering solution.
                        IncrementalSAXSource_Filter iss=new IncrementalSAXSource_Filter();
                        iss.setXMLReader(new SAXParser());
                        return iss;
                }
  }

  static public IncrementalSAXSource
  createIncrementalSAXSource(SAXParser parser) {
                try
                {
                        return new IncrementalSAXSource_Xerces(parser);
                }
                catch(NoSuchMethodException e)
                {
                        // Xerces version mismatch; neither Xerces1 nor Xerces2 succeeded.
                        // Fall back on filtering solution.
                        IncrementalSAXSource_Filter iss=new IncrementalSAXSource_Filter();
                        iss.setXMLReader(parser);
                        return iss;
                }
  }

  //
  // Public methods
  //

  // Register handler directly with the incremental parser
  public void setContentHandler(org.xml.sax.ContentHandler handler)
  {
    // Typecast required in Xerces2; SAXParser doesn't inheret XMLReader
    // %OPT% Cast at asignment?
    ((XMLReader)fIncrementalParser).setContentHandler(handler);
  }

  // Register handler directly with the incremental parser
  public void setLexicalHandler(org.xml.sax.ext.LexicalHandler handler)
  {
    // Not supported by all SAX2 parsers but should work in Xerces:
    try
    {
      // Typecast required in Xerces2; SAXParser doesn't inheret XMLReader
      // %OPT% Cast at asignment?
      ((XMLReader)fIncrementalParser).setProperty("http://xml.org/sax/properties/lexical-handler",
                                     handler);
    }
    catch(org.xml.sax.SAXNotRecognizedException e)
    {
      // Nothing we can do about it
    }
    catch(org.xml.sax.SAXNotSupportedException e)
    {
      // Nothing we can do about it
    }
  }

  // Register handler directly with the incremental parser
  public void setDTDHandler(org.xml.sax.DTDHandler handler)
  {
    // Typecast required in Xerces2; SAXParser doesn't inheret XMLReader
    // %OPT% Cast at asignment?
    ((XMLReader)fIncrementalParser).setDTDHandler(handler);
  }

  //================================================================
  /** startParse() is a simple API which tells the IncrementalSAXSource
   * to begin reading a document.
   *
   * @throws SAXException is parse thread is already in progress
   * or parsing can not be started.
   * */
  public void startParse(InputSource source) throws SAXException
  {
    if (fIncrementalParser==null)
      throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_STARTPARSE_NEEDS_SAXPARSER, null)); //"startParse needs a non-null SAXParser.");
    if (fParseInProgress)
      throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_STARTPARSE_WHILE_PARSING, null)); //"startParse may not be called while parsing.");

    boolean ok=false;

    try
    {
      ok = parseSomeSetup(source);
    }
    catch(Exception ex)
    {
      throw new SAXException(ex);
    }

    if(!ok)
      throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_COULD_NOT_INIT_PARSER, null)); //"could not initialize parser with");
  }


  /** deliverMoreNodes() is a simple API which tells the coroutine
   * parser that we need more nodes.  This is intended to be called
   * from one of our partner routines, and serves to encapsulate the
   * details of how incremental parsing has been achieved.
   *
   * @param parsemore If true, tells the incremental parser to generate
   * another chunk of output. If false, tells the parser that we're
   * satisfied and it can terminate parsing of this document.
   * @return Boolean.TRUE if the CoroutineParser believes more data may be available
   * for further parsing. Boolean.FALSE if parsing ran to completion.
   * Exception if the parser objected for some reason.
   * */
  public Object deliverMoreNodes (boolean parsemore)
  {
    if(!parsemore)
    {
      fParseInProgress=false;
      return Boolean.FALSE;
    }

    Object arg;
    try {
      boolean keepgoing = parseSome();
      arg = keepgoing ? Boolean.TRUE : Boolean.FALSE;
    } catch (SAXException ex) {
      arg = ex;
    } catch (IOException ex) {
      arg = ex;
    } catch (Exception ex) {
      arg = new SAXException(ex);
    }
    return arg;
  }

        // Private methods -- conveniences to hide the reflection details
        private boolean parseSomeSetup(InputSource source)
                throws SAXException, IOException, IllegalAccessException,
                                         java.lang.reflect.InvocationTargetException,
                                         java.lang.InstantiationException
        {
                if(fConfigSetInput!=null)
                {
                        // Obtain input from SAX inputSource object, construct XNI version of
                        // that object. Logic adapted from Xerces2.
                        Object[] parms1={source.getPublicId(),source.getSystemId(),null};
                        Object xmlsource=fConfigInputSourceCtor.newInstance(parms1);
                        Object[] parmsa={source.getByteStream()};
                        fConfigSetByteStream.invoke(xmlsource,parmsa);
                        parmsa[0]=source.getCharacterStream();
                        fConfigSetCharStream.invoke(xmlsource,parmsa);
                        parmsa[0]=source.getEncoding();
                        fConfigSetEncoding.invoke(xmlsource,parmsa);

                        // Bugzilla5272 patch suggested by Sandy Gao.
                        // Has to be reflection to run with Xerces2
                        // after compilation against Xerces1. or vice
                        // versa, due to return type mismatches.
                        Object[] noparms=new Object[0];
                        fReset.invoke(fIncrementalParser,noparms);

                        parmsa[0]=xmlsource;
                        fConfigSetInput.invoke(fPullParserConfig,parmsa);

                        // %REVIEW% Do first pull. Should we instead just return true?
                        return parseSome();
                }
                else
                {
                        Object[] parm={source};
                        Object ret=fParseSomeSetup.invoke(fIncrementalParser,parm);
                        return ((Boolean)ret).booleanValue();
                }
        }
//  Would null work???
    private static final Object[] noparms=new Object[0];
    private static final Object[] parmsfalse={Boolean.FALSE};
    private boolean parseSome()
                throws SAXException, IOException, IllegalAccessException,
                                         java.lang.reflect.InvocationTargetException
        {
                // Take next parsing step, return false iff parsing complete:
                if(fConfigSetInput!=null)
                {
                        Object ret=(Boolean)(fConfigParse.invoke(fPullParserConfig,parmsfalse));
                        return ((Boolean)ret).booleanValue();
                }
                else
                {
                        Object ret=fParseSome.invoke(fIncrementalParser,noparms);
                        return ((Boolean)ret).booleanValue();
                }
        }


  //================================================================
  /** Simple unit test. Attempt coroutine parsing of document indicated
   * by first argument (as a URI), report progress.
   */
  public static void _main(String args[])
  {
    System.out.println("Starting...");

    CoroutineManager co = new CoroutineManager();
    int appCoroutineID = co.co_joinCoroutineSet(-1);
    if (appCoroutineID == -1)
    {
      System.out.println("ERROR: Couldn't allocate coroutine number.\n");
      return;
    }
    IncrementalSAXSource parser=
      createIncrementalSAXSource();

    // Use a serializer as our sample output
    com.sun.org.apache.xml.internal.serialize.XMLSerializer trace;
    trace=new com.sun.org.apache.xml.internal.serialize.XMLSerializer(System.out,null);
    parser.setContentHandler(trace);
    parser.setLexicalHandler(trace);

    // Tell coroutine to begin parsing, run while parsing is in progress

    for(int arg=0;arg<args.length;++arg)
    {
      try
      {
        InputSource source = new InputSource(args[arg]);
        Object result=null;
        boolean more=true;
        parser.startParse(source);
        for(result = parser.deliverMoreNodes(more);
            result==Boolean.TRUE;
            result = parser.deliverMoreNodes(more))
        {
          System.out.println("\nSome parsing successful, trying more.\n");

          // Special test: Terminate parsing early.
          if(arg+1<args.length && "!".equals(args[arg+1]))
          {
            ++arg;
            more=false;
          }

        }

        if (result instanceof Boolean && ((Boolean)result)==Boolean.FALSE)
        {
          System.out.println("\nParser ended (EOF or on request).\n");
        }
        else if (result == null) {
          System.out.println("\nUNEXPECTED: Parser says shut down prematurely.\n");
        }
        else if (result instanceof Exception) {
          throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException((Exception)result);
          //          System.out.println("\nParser threw exception:");
          //          ((Exception)result).printStackTrace();
        }

      }

      catch(SAXException e)
      {
        e.printStackTrace();
      }
    }

  }


} // class IncrementalSAXSource_Xerces
