incrementalsaxsource_filter.java

来自「JAVA 所有包」· Java 代码 · 共 806 行 · 第 1/2 页

JAVA
806
字号
  	if(null!=clientDTDHandler)	  	clientDTDHandler.notationDecl(a,b,c);  }  public void unparsedEntityDecl(String a, String b, String c, String d)  throws SAXException  {  	if(null!=clientDTDHandler)	  	clientDTDHandler.unparsedEntityDecl(a,b,c,d);  }    //  // ErrorHandler support.  //  // PROBLEM: Xerces is apparently _not_ calling the ErrorHandler for  // exceptions thrown by the ContentHandler, which prevents us from  // handling this properly when running in filtering mode with Xerces  // as our event source.  It's unclear whether this is a Xerces bug  // or a SAX design flaw.  //   // %REVIEW% Current solution: In filtering mode, it is REQUIRED that  // event source make sure this method is invoked if the event stream  // abends before endDocument is delivered. If that means explicitly calling  // us in the exception handling code because it won't be delivered as part  // of the normal SAX ErrorHandler stream, that's fine; Not Our Problem.  //  public void error(SAXParseException exception) throws SAXException  {    if(null!=clientErrorHandler)      clientErrorHandler.error(exception);  }    public void fatalError(SAXParseException exception) throws SAXException  {    // EXCEPTION: In this case we need to run the event BEFORE we yield --    // just as with endDocument, this terminates the event stream.    if(null!=clientErrorHandler)      clientErrorHandler.error(exception);    eventcounter=0;         co_yield(false);  }    public void warning(SAXParseException exception) throws SAXException  {    if(null!=clientErrorHandler)      clientErrorHandler.error(exception);  }    //  // coroutine support  //  public int getSourceCoroutineID() {    return fSourceCoroutineID;  }  public int getControllerCoroutineID() {    return fControllerCoroutineID;  }  /** @return the CoroutineManager this CoroutineFilter object is bound to.   * If you're using the do...() methods, applications should only   * need to talk to the CoroutineManager once, to obtain the   * application's Coroutine ID.   * */  public CoroutineManager getCoroutineManager()  {    return fCoroutineManager;  }  /** <p>In the SAX delegation code, I've inlined the count-down in   * the hope of encouraging compilers to deliver better   * performance. However, if we subclass (eg to directly connect the   * output to a DTM builder), that would require calling super in   * order to run that logic... which seems inelegant.  Hence this   * routine for the convenience of subclasses: every [frequency]   * invocations, issue a co_yield.</p>   *   * @param moreExepected Should always be true unless this is being called   * at the end of endDocument() handling.   * */  protected void count_and_yield(boolean moreExpected) throws SAXException  {    if(!moreExpected) eventcounter=0;        if(--eventcounter<=0)      {        co_yield(true);        eventcounter=frequency;      }  }  /**   * co_entry_pause is called in startDocument() before anything else   * happens. It causes the filter to wait for a "go ahead" request   * from the controller before delivering any events. Note that   * the very first thing the controller tells us may be "I don't   * need events after all"!   */  private void co_entry_pause() throws SAXException  {    if(fCoroutineManager==null)    {      // Nobody called init()? Do it now...      init(null,-1,-1);    }    try    {      Object arg=fCoroutineManager.co_entry_pause(fSourceCoroutineID);      if(arg==Boolean.FALSE)        co_yield(false);    }    catch(NoSuchMethodException e)    {      // Coroutine system says we haven't registered. That's an      // application coding error, and is unrecoverable.      if(DEBUG) e.printStackTrace();      throw new SAXException(e);    }  }  /**   * Co_Yield handles coroutine interactions while a parse is in progress.   *   * When moreRemains==true, we are pausing after delivering events, to   * ask if more are needed. We will resume the controller thread with    *   co_resume(Boolean.TRUE, ...)   * When control is passed back it may indicate   *      Boolean.TRUE    indication to continue delivering events   *      Boolean.FALSE   indication to discontinue events and shut down.   *    * When moreRemains==false, we shut down immediately without asking the   * controller's permission. Normally this means end of document has been   * reached.   *   * Shutting down a IncrementalSAXSource_Filter requires terminating the incoming   * SAX event stream. If we are in control of that stream (if it came   * from an XMLReader passed to our startReader() method), we can do so   * very quickly by throwing a reserved exception to it. If the stream is   * coming from another source, we can't do that because its caller may   * not be prepared for this "normal abnormal exit", and instead we put   * ourselves in a "spin" mode where events are discarded.   */  private void co_yield(boolean moreRemains) throws SAXException  {    // Horrendous kluge to run filter to completion. See below.    if(fNoMoreEvents)      return;    try // Coroutine manager might throw no-such.    {      Object arg=Boolean.FALSE;      if(moreRemains)      {        // Yield control, resume parsing when done        arg = fCoroutineManager.co_resume(Boolean.TRUE, fSourceCoroutineID,                                          fControllerCoroutineID);              }      // If we're at end of document or were told to stop early      if(arg==Boolean.FALSE)      {        fNoMoreEvents=true;                if(fXMLReader!=null)    // Running under startParseThread()          throw new StopException(); // We'll co_exit from there.                // Yield control. We do NOT expect anyone to ever ask us again.        fCoroutineManager.co_exit_to(Boolean.FALSE, fSourceCoroutineID,                                     fControllerCoroutineID);      }    }    catch(NoSuchMethodException e)    {      // Shouldn't happen unless we've miscoded our coroutine logic      // "Shut down the garbage smashers on the detention level!"      fNoMoreEvents=true;      fCoroutineManager.co_exit(fSourceCoroutineID);      throw new SAXException(e);    }  }  //  // Convenience: Run an XMLReader in a thread  //  /** Launch a thread that will run an XMLReader's parse() operation within   *  a thread, feeding events to this IncrementalSAXSource_Filter. Mostly a convenience   *  routine, but has the advantage that -- since we invoked parse() --   *  we can halt parsing quickly via a StopException rather than waiting   *  for the SAX stream to end by itself.   *   * @throws SAXException is parse thread is already in progress   * or parsing can not be started.   * */  public void startParse(InputSource source) throws SAXException  {    if(fNoMoreEvents)      throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_INCRSAXSRCFILTER_NOT_RESTARTABLE, null)); //"IncrmentalSAXSource_Filter not currently restartable.");    if(fXMLReader==null)      throw new SAXException(XMLMessages.createXMLMessage(XMLErrorResources.ER_XMLRDR_NOT_BEFORE_STARTPARSE, null)); //"XMLReader not before startParse request");    fXMLReaderInputSource=source;        // Xalan thread pooling...    // com.sun.org.apache.xalan.internal.transformer.TransformerImpl.runTransformThread(this);    ThreadControllerWrapper.runThread(this, -1);  }    /* Thread logic to support startParseThread()   */  public void run()  {    // Guard against direct invocation of start().    if(fXMLReader==null) return;    if(DEBUG)System.out.println("IncrementalSAXSource_Filter parse thread launched");    // Initially assume we'll run successfully.    Object arg=Boolean.FALSE;    // For the duration of this operation, all coroutine handshaking    // will occur in the co_yield method. That's the nice thing about    // coroutines; they give us a way to hand off control from the    // middle of a synchronous method.    try    {      fXMLReader.parse(fXMLReaderInputSource);    }    catch(IOException ex)    {      arg=ex;    }    catch(StopException ex)    {      // Expected and harmless      if(DEBUG)System.out.println("Active IncrementalSAXSource_Filter normal stop exception");    }    catch (SAXException ex)    {      Exception inner=ex.getException();      if(inner instanceof StopException){        // Expected and harmless        if(DEBUG)System.out.println("Active IncrementalSAXSource_Filter normal stop exception");      }      else      {        // Unexpected malfunction        if(DEBUG)        {          System.out.println("Active IncrementalSAXSource_Filter UNEXPECTED SAX exception: "+inner);          inner.printStackTrace();        }                        arg=ex;      }    } // end parse        // Mark as no longer running in thread.    fXMLReader=null;    try    {      // Mark as done and yield control to the controller coroutine      fNoMoreEvents=true;      fCoroutineManager.co_exit_to(arg, fSourceCoroutineID,                                   fControllerCoroutineID);    }    catch(java.lang.NoSuchMethodException e)    {      // Shouldn't happen unless we've miscoded our coroutine logic      // "CPO, shut down the garbage smashers on the detention level!"      e.printStackTrace(System.err);      fCoroutineManager.co_exit(fSourceCoroutineID);    }  }  /** Used to quickly terminate parse when running under a      startParse() thread. Only its type is important. */  class StopException extends RuntimeException  {          static final long serialVersionUID = -1129245796185754956L;  }  /** 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 filter to generate   * another chunk of output. If false, tells the filter that we're   * satisfied and it can terminate parsing of this document.   *   * @return Boolean.TRUE if there may be more events available by invoking   * deliverMoreNodes() again. Boolean.FALSE if parsing has run to completion (or been   * terminated by deliverMoreNodes(false). Or an exception object if something   * malfunctioned. %REVIEW% We _could_ actually throw the exception, but   * that would require runinng deliverMoreNodes() in a try/catch... and for many   * applications, exception will be simply be treated as "not TRUE" in   * any case.   * */  public Object deliverMoreNodes(boolean parsemore)  {    // If parsing is already done, we can immediately say so    if(fNoMoreEvents)      return Boolean.FALSE;    try     {      Object result =        fCoroutineManager.co_resume(parsemore?Boolean.TRUE:Boolean.FALSE,                                    fControllerCoroutineID, fSourceCoroutineID);      if(result==Boolean.FALSE)        fCoroutineManager.co_exit(fControllerCoroutineID);      return result;    }          // SHOULD NEVER OCCUR, since the coroutine number and coroutine manager    // are those previously established for this IncrementalSAXSource_Filter...    // So I'm just going to return it as a parsing exception, for now.    catch(NoSuchMethodException e)      {        return e;      }  }    //================================================================  /** 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...");    org.xml.sax.XMLReader theSAXParser=      new com.sun.org.apache.xerces.internal.parsers.SAXParser();      for(int arg=0;arg<args.length;++arg)    {      // The filter is not currently designed to be restartable      // after a parse has ended. Generate a new one each time.      IncrementalSAXSource_Filter filter=        new IncrementalSAXSource_Filter();      // 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);      filter.setContentHandler(trace);      filter.setLexicalHandler(trace);      try      {        InputSource source = new InputSource(args[arg]);        Object result=null;        boolean more=true;        // init not issued; we _should_ automagically Do The Right Thing        // Bind parser, kick off parsing in a thread        filter.setXMLReader(theSAXParser);        filter.startParse(source);              for(result = filter.deliverMoreNodes(more);            (result instanceof Boolean && ((Boolean)result)==Boolean.TRUE);            result = filter.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("\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();        }            }      catch(SAXException e)      {        e.printStackTrace();      }    } // end for  }    */  } // class IncrementalSAXSource_Filter

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?