| package org.apache.xml.dtm.ref; |
| |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.ext.LexicalHandler; |
| import org.xml.sax.ContentHandler; |
| import org.xml.sax.Locator; |
| import org.xml.sax.Attributes; |
| import org.xml.sax.XMLReader; |
| import java.io.IOException; |
| import javax.xml.parsers.*; |
| |
| /** Primitive unit test for CoroutineSAXParser in filtering mode: |
| * Attempt coroutine parsing of documents indicated by arguments (as |
| * URIs), report progress. If a URI is followed by "!" as the next |
| * argument, we cancel the parse early. |
| * |
| * This version tests the filtering mode, where the CoroutineParser |
| * is managing a SAX stream generated by other code. Normally this |
| * would be used when you've launched the consumer in a secondary |
| * thread and are running the SAX event generation in the primary |
| * thread. Of course it could be used the other way round as well. |
| * |
| * Note that unlike the fully-encapsulated version (see the inline |
| * test in CoroutineSAXParser), this version does _not_ have a |
| * dialog for starting the parse, or for restarting it with a new |
| * file. |
| * */ |
| class CoroutineSAXFilterTest implements Runnable |
| { |
| // Statics are a sloppy way of passing data to the test thread, |
| // but for this quick-hack I don't much care. |
| static boolean TEST_EARLY_STOP=false; |
| static int appCoroutineID=-1; |
| static CoroutineSAXParser filter; |
| |
| public static void main(String args[]) |
| { |
| System.out.println("Starting in Filtering mode..."); |
| |
| org.xml.sax.XMLReader theSAXParser=null; |
| try { |
| SAXParserFactory factory=SAXParserFactory.newInstance(); |
| SAXParser parser=factory.newSAXParser(); |
| theSAXParser=parser.getXMLReader(); |
| } catch( Exception ex ) { |
| ex.printStackTrace(); |
| return; |
| } |
| |
| CoroutineManager co = new CoroutineManager(); |
| |
| appCoroutineID = co.co_joinCoroutineSet(appCoroutineID); |
| if (appCoroutineID == -1) |
| { |
| System.out.println("ERROR: Couldn't allocate coroutine number.\n"); |
| return; |
| } |
| |
| // Note that this is a global -- sloppy connection to the thread. |
| filter=new CoroutineSAXParser(co, appCoroutineID); |
| |
| // Convenience function... Set handlers |
| filter.setXMLReader(theSAXParser); |
| |
| // Use a serializer as our sample output |
| org.apache.xml.serialize.XMLSerializer trace; |
| trace=new org.apache.xml.serialize.XMLSerializer(System.out,null); |
| filter.setContentHandler(trace); |
| filter.setLexHandler(trace); |
| |
| // Launch the listener. |
| Thread listener=new Thread(new CoroutineSAXFilterTest()); |
| listener.setDaemon(false); |
| listener.start(); |
| |
| // Check stop-early flag |
| if(args.length>1 && "!".equals(args[1])) |
| TEST_EARLY_STOP=true; |
| |
| // Run the parser |
| System.out.println("*** Parser start ***"); |
| try |
| { |
| theSAXParser.parse(new InputSource(args[0])); |
| } |
| catch(java.io.IOException e) |
| { |
| e.printStackTrace(); |
| } |
| catch(org.xml.sax.SAXException e) |
| { |
| e.printStackTrace(); |
| |
| // %REVIEW% We'll should probably expose these special types, |
| // if we might be testing them outside the filtering code... |
| |
| Exception embedded=e.getException(); |
| if(embedded!=null && embedded.getClass().getName().equals("org.apache.xml.dtm.CoroutineSAXParser$UserRequestedStopException")) |
| System.out.println("... NORMAL response to doTerminate()."); |
| } |
| System.out.println("*** Parser end ***"); |
| filter.doTerminate(appCoroutineID); |
| } |
| |
| // Issue coroutine transactions to simulate dialog with the parser |
| // for a single file. Note that the sequence of calls here is |
| // identical to that when talking to the fully encapsulated |
| // parser... though doParse() will be a no-op since the parse |
| // is launched separately. |
| public void run() { |
| { |
| // %TBD% PROBLEM: Parser error hangs this process... |
| |
| Object result; |
| boolean more=true; |
| |
| for(result = filter.doParse(null, appCoroutineID); |
| (result instanceof Boolean && ((Boolean)result)==Boolean.TRUE); |
| result = filter.doMore(more, appCoroutineID)) |
| { |
| // Special test: Terminate parsing early. |
| if(TEST_EARLY_STOP) |
| { |
| System.out.println("\nSome parsing successful, trying to stop.\n"); |
| more=false; |
| } |
| else |
| System.out.println("\nSome parsing successful, trying more.\n"); |
| } |
| |
| if (result instanceof Boolean && ((Boolean)result)==Boolean.FALSE) |
| { |
| System.out.println("\nfilter ended (EOF or on request).\n"); |
| } |
| else if (result == null) { |
| System.out.println("\nUNEXPECTED: filter says shut down prematurely.\n"); |
| } |
| else if (result instanceof Exception) { |
| System.out.println("\nfilter threw exception:"); |
| ((Exception)result).printStackTrace(); |
| } |
| |
| } |
| |
| filter.doTerminate(appCoroutineID); |
| } |
| |
| } |