Methods Summary |
---|
public void | characters(char[] ch, int start, int length)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.characters(ch,start,length);
|
private void | co_entry_pause()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"!
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);
}
|
private void | co_yield(boolean moreRemains)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.
// 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);
}
|
public void | comment(char[] ch, int start, int length)
if(null!=clientLexicalHandler)
clientLexicalHandler.comment(ch,start,length);
|
protected void | count_and_yield(boolean moreExpected)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.
if(!moreExpected) eventcounter=0;
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
|
public static com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource | createIncrementalSAXSource(com.sun.org.apache.xml.internal.dtm.ref.CoroutineManager co, int controllerCoroutineID)
return new IncrementalSAXSource_Filter(co, controllerCoroutineID);
|
public java.lang.Object | deliverMoreNodes(boolean parsemore)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.
// 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;
}
|
public void | endCDATA()
if(null!=clientLexicalHandler)
clientLexicalHandler.endCDATA();
|
public void | endDTD()
if(null!=clientLexicalHandler)
clientLexicalHandler.endDTD();
|
public void | endDocument()
// EXCEPTION: In this case we need to run the event BEFORE we yield.
if(clientContentHandler!=null)
clientContentHandler.endDocument();
eventcounter=0;
co_yield(false);
|
public void | endElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.endElement(namespaceURI,localName,qName);
|
public void | endEntity(java.lang.String name)
if(null!=clientLexicalHandler)
clientLexicalHandler.endEntity(name);
|
public void | endPrefixMapping(java.lang.String prefix)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.endPrefixMapping(prefix);
|
public void | error(org.xml.sax.SAXParseException exception)
if(null!=clientErrorHandler)
clientErrorHandler.error(exception);
|
public void | fatalError(org.xml.sax.SAXParseException exception)
// 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 int | getControllerCoroutineID()
return fControllerCoroutineID;
|
public com.sun.org.apache.xml.internal.dtm.ref.CoroutineManager | getCoroutineManager()
return fCoroutineManager;
|
public int | getSourceCoroutineID()
return fSourceCoroutineID;
|
public void | ignorableWhitespace(char[] ch, int start, int length)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.ignorableWhitespace(ch,start,length);
|
public void | init(com.sun.org.apache.xml.internal.dtm.ref.CoroutineManager co, int controllerCoroutineID, int sourceCoroutineID)
if(co==null)
co = new CoroutineManager();
fCoroutineManager = co;
fControllerCoroutineID = co.co_joinCoroutineSet(controllerCoroutineID);
fSourceCoroutineID = co.co_joinCoroutineSet(sourceCoroutineID);
if (fControllerCoroutineID == -1 || fSourceCoroutineID == -1)
throw new RuntimeException(XMLMessages.createXMLMessage(XMLErrorResources.ER_COJOINROUTINESET_FAILED, null)); //"co_joinCoroutineSet() failed");
fNoMoreEvents=false;
eventcounter=frequency;
|
public void | notationDecl(java.lang.String a, java.lang.String b, java.lang.String c)
if(null!=clientDTDHandler)
clientDTDHandler.notationDecl(a,b,c);
|
public void | processingInstruction(java.lang.String target, java.lang.String data)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.processingInstruction(target,data);
|
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);
}
|
public void | setContentHandler(org.xml.sax.ContentHandler handler)
clientContentHandler=handler;
|
public void | setDTDHandler(org.xml.sax.DTDHandler handler)
clientDTDHandler=handler;
|
public void | setDocumentLocator(org.xml.sax.Locator locator)
if(--eventcounter<=0)
{
// This can cause a hang. -sb
// co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.setDocumentLocator(locator);
|
public void | setErrHandler(org.xml.sax.ErrorHandler handler)
clientErrorHandler=handler;
|
public void | setLexicalHandler(org.xml.sax.ext.LexicalHandler handler)
clientLexicalHandler=handler;
|
public void | setReturnFrequency(int events)
if(events<1) events=1;
frequency=eventcounter=events;
|
public void | setXMLReader(org.xml.sax.XMLReader eventsource)Bind our input streams to an XMLReader.
Just a convenience routine; obviously you can explicitly register
this as a listener with the same effect.
fXMLReader=eventsource;
eventsource.setContentHandler(this);
eventsource.setDTDHandler(this);
eventsource.setErrorHandler(this); // to report fatal errors in filtering mode
// Not supported by all SAX2 filters:
try
{
eventsource.
setProperty("http://xml.org/sax/properties/lexical-handler",
this);
}
catch(SAXNotRecognizedException e)
{
// Nothing we can do about it
}
catch(SAXNotSupportedException e)
{
// Nothing we can do about it
}
// Should we also bind as other varieties of handler?
// (DTDHandler and so on)
|
public void | skippedEntity(java.lang.String name)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.skippedEntity(name);
|
public void | startCDATA()
if(null!=clientLexicalHandler)
clientLexicalHandler.startCDATA();
|
public void | startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
if(null!=clientLexicalHandler)
clientLexicalHandler. startDTD(name, publicId, systemId);
|
public void | startDocument()
co_entry_pause();
// Otherwise, begin normal event delivery
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.startDocument();
|
public void | startElement(java.lang.String namespaceURI, java.lang.String localName, java.lang.String qName, org.xml.sax.Attributes atts)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.startElement(namespaceURI, localName, qName, atts);
|
public void | startEntity(java.lang.String name)
if(null!=clientLexicalHandler)
clientLexicalHandler.startEntity(name);
|
public void | startParse(org.xml.sax.InputSource source)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.
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);
|
public void | startPrefixMapping(java.lang.String prefix, java.lang.String uri)
if(--eventcounter<=0)
{
co_yield(true);
eventcounter=frequency;
}
if(clientContentHandler!=null)
clientContentHandler.startPrefixMapping(prefix,uri);
|
public void | unparsedEntityDecl(java.lang.String a, java.lang.String b, java.lang.String c, java.lang.String d)
if(null!=clientDTDHandler)
clientDTDHandler.unparsedEntityDecl(a,b,c,d);
|
public void | warning(org.xml.sax.SAXParseException exception)
if(null!=clientErrorHandler)
clientErrorHandler.error(exception);
|