You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by jk...@apache.org on 2001/11/02 22:02:15 UTC

cvs commit: xml-xalan/java/src/org/apache/xml/dtm/ref DTMManagerDefault.java IncrementalSAXSource_Xerces.java

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: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org