jkesselm    01/11/02 13:02:15

  Modified:    java/src/org/apache/xml/dtm/ref DTMManagerDefault.java
                        IncrementalSAXSource_Xerces.java
  Log:
  Leverage Xerces-2 incremental parsing feature, when possible,
  
  Making this compile _and_ run under both the old and new versions of
  the parser involves a lot of reflection... especially since Xerces-2
  no longer provides a way to directly request incremental delivery
  of SAX events; we now have to assemble that concept ourselves,
  using XNI components.
  
  Note that if you pass an existing Xerces-2 SAXParser into the
  IncrementalSAXSource_Xerces wrapper, there is currently no way
  for us to access its incremental controls. In that case, we are
  forced to fall back on the _Filter solution and coroutines.
  
  Revision  Changes    Path
  1.28      +2 -10     
xml-xalan/java/src/org/apache/xml/dtm/ref/DTMManagerDefault.java
  
  Index: DTMManagerDefault.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xml/dtm/ref/DTMManagerDefault.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- DTMManagerDefault.java    2001/10/18 13:08:32     1.27
  +++ DTMManagerDefault.java    2001/11/02 21:02:15     1.28
  @@ -254,18 +254,10 @@
           boolean haveXercesParser =
             (null != reader)
             && 
(reader.getClass().getName().equals("org.apache.xerces.parsers.SAXParser") );
  -
  +     
           if (haveXercesParser)
             incremental = true;  // No matter what.  %REVIEW%
  -
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             //m_incremental=true;                   
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             //*********** JJK DEBUGGING KLUGE -- GONK GONK 
GONK
  -                             
  +     
           // If the reader is null, but they still requested an incremental 
build,
           // then we still want to set up the IncrementalSAXSource stuff.
           if (this.m_incremental && incremental /* || ((null == reader) && 
incremental) */)
  
  
  
  1.6       +151 -28   
xml-xalan/java/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java
  
  Index: IncrementalSAXSource_Xerces.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/java/src/org/apache/xml/dtm/ref/IncrementalSAXSource_Xerces.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- IncrementalSAXSource_Xerces.java  2001/10/22 21:13:19     1.5
  +++ IncrementalSAXSource_Xerces.java  2001/11/02 21:02:15     1.6
  @@ -65,6 +65,8 @@
   
   import org.apache.xalan.res.XSLTErrorResources;
   import org.apache.xalan.res.XSLMessages;
  +import java.lang.reflect.Constructor;
  +import java.lang.reflect.Method;
   
   
   /** <p>IncrementalSAXSource_Xerces takes advantage of the fact that Xerces1
  @@ -79,14 +81,22 @@
     implements IncrementalSAXSource
   {
        //
  -     // Reflection. To allow this to compile with Xerces2, which doesn't 
support
  -     // the old parseSome() incremental API, we need to avoid static 
references 
  -     // to those. Until Xerces2 is pervasive and we're willing to make it a
  -     // prerequisite, we will support it only via the filtering solution.
  +     // 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.
        //
  -     java.lang.reflect.Method fParseSomeSetup=null;
  -     java.lang.reflect.Method fParseSome=null;
  -
  +     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
  +             
     //
     // Data
     //
  @@ -97,34 +107,102 @@
     // Constructors
     //
   
  -  /** Create a IncrementalSAXSource_Xerces, and create a SAXParsre
  -   * to go with it
  +  /** 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
        {
  -             this(new SAXParser());
  +             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.
  +                     Class me=this.getClass();
  +                     
  +                     // If we can't get the magic constructor, no need to 
look further.
  +                     Class 
xniConfigClass=me.forName("org.apache.xerces.xni.parser.XMLParserConfiguration");
  +                     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=me.forName("org.apache.xerces.parsers.StandardParserConfiguration");
  +                     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=me.forName("org.apache.xerces.xni.parser.XMLInputSource");
  +                     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);                        
  +             }
  +             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. At some point we expect to cut over
  -   * and make it work only for Xerces-2, but that involves some
  -   * compile-time inheritance dependencies which we aren't yet
  -   * ready to buy into.
  +   * 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  
  -     {
  +    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[] parms={InputSource.class};
  -             
fParseSomeSetup=parser.getClass().getMethod("parseSomeSetup",parms);
  -             parms=new Class[0];
  -             fParseSome=parser.getClass().getMethod("parseSome",parms);
  +             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.
     }
   
     //
  @@ -132,7 +210,18 @@
     //
     static public IncrementalSAXSource createIncrementalSAXSource() 
        {
  -                     return createIncrementalSAXSource(new SAXParser());
  +             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
  @@ -143,7 +232,8 @@
                }
                catch(NoSuchMethodException e)
                {
  -                     // Xerces version mismatch. Fall back on the filtering 
solution
  +                     // Xerces version mismatch; neither Xerces1 nor Xerces2 
succeeded.
  +                     // Fall back on filtering solution.
                        IncrementalSAXSource_Filter iss=new 
IncrementalSAXSource_Filter();
                        iss.setXMLReader(parser);
                        return iss;
  @@ -251,19 +341,52 @@
        // Private methods -- conveniences to hide the reflection details
        private boolean parseSomeSetup(InputSource source) 
                throws SAXException, IOException, IllegalAccessException, 
  -                                      
java.lang.reflect.InvocationTargetException
  +                                      
java.lang.reflect.InvocationTargetException,
  +                                      java.lang.InstantiationException
        {
  -             Object[] parm={source};
  -             Object ret=fParseSomeSetup.invoke(fIncrementalParser,parm);
  -             return ((Boolean)ret).booleanValue();
  +             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);
  +                     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();
  +             }
        }
  +     
        static final Object[] noparms=new Object[0]; // Would null work???
  +     static final Object[] parmsfalse={Boolean.FALSE};
        private boolean parseSome()
                throws SAXException, IOException, IllegalAccessException,
                                         
java.lang.reflect.InvocationTargetException
        {
  -             Object ret=fParseSome.invoke(fIncrementalParser,noparms);
  -             return ((Boolean)ret).booleanValue();
  +             // 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();
  +             }
        }
        
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to