incrementalsaxsource_filter.java
来自「JAVA 所有包」· Java 代码 · 共 806 行 · 第 1/2 页
JAVA
806 行
/* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: IncrementalSAXSource_Filter.java,v 1.2.4.1 2005/09/15 08:15:07 suresh_emailid Exp $ */package com.sun.org.apache.xml.internal.dtm.ref;import java.io.IOException;import com.sun.org.apache.xml.internal.res.XMLErrorResources;import com.sun.org.apache.xml.internal.res.XMLMessages;import com.sun.org.apache.xml.internal.utils.ThreadControllerWrapper;import org.xml.sax.Attributes;import org.xml.sax.ContentHandler;import org.xml.sax.DTDHandler;import org.xml.sax.ErrorHandler;import org.xml.sax.InputSource;import org.xml.sax.Locator;import org.xml.sax.SAXException;import org.xml.sax.SAXNotRecognizedException;import org.xml.sax.SAXNotSupportedException;import org.xml.sax.SAXParseException;import org.xml.sax.XMLReader;import org.xml.sax.ext.LexicalHandler;/** <p>IncrementalSAXSource_Filter implements IncrementalSAXSource, using a * standard SAX2 event source as its input and parcelling out those * events gradually in reponse to deliverMoreNodes() requests. Output from the * filter will be passed along to a SAX handler registered as our * listener, but those callbacks will pass through a counting stage * which periodically yields control back to the controller coroutine. * </p> * * <p>%REVIEW%: This filter is not currenly intended to be reusable * for parsing additional streams/documents. We may want to consider * making it resettable at some point in the future. But it's a * small object, so that'd be mostly a convenience issue; the cost * of allocating each time is trivial compared to the cost of processing * any nontrival stream.</p> * * <p>For a brief usage example, see the unit-test main() method.</p> * * <p>This is a simplification of the old CoroutineSAXParser, focusing * specifically on filtering. The resulting controller protocol is _far_ * simpler and less error-prone; the only controller operation is deliverMoreNodes(), * and the only requirement is that deliverMoreNodes(false) be called if you want to * discard the rest of the stream and the previous deliverMoreNodes() didn't return * false. * */public class IncrementalSAXSource_Filterimplements IncrementalSAXSource, ContentHandler, DTDHandler, LexicalHandler, ErrorHandler, Runnable{ boolean DEBUG=false; //Internal status report // // Data // private CoroutineManager fCoroutineManager = null; private int fControllerCoroutineID = -1; private int fSourceCoroutineID = -1; private ContentHandler clientContentHandler=null; // %REVIEW% support multiple? private LexicalHandler clientLexicalHandler=null; // %REVIEW% support multiple? private DTDHandler clientDTDHandler=null; // %REVIEW% support multiple? private ErrorHandler clientErrorHandler=null; // %REVIEW% support multiple? private int eventcounter; private int frequency=5; // Flag indicating that no more events should be delivered -- either // because input stream ran to completion (endDocument), or because // the user requested an early stop via deliverMoreNodes(false). private boolean fNoMoreEvents=false; // Support for startParse() private XMLReader fXMLReader=null; private InputSource fXMLReaderInputSource=null; // // Constructors // public IncrementalSAXSource_Filter() { this.init( new CoroutineManager(), -1, -1); } /** Create a IncrementalSAXSource_Filter which is not yet bound to a specific * SAX event source. * */ public IncrementalSAXSource_Filter(CoroutineManager co, int controllerCoroutineID) { this.init( co, controllerCoroutineID, -1 ); } // // Factories // static public IncrementalSAXSource createIncrementalSAXSource(CoroutineManager co, int controllerCoroutineID) { return new IncrementalSAXSource_Filter(co, controllerCoroutineID); } // // Public methods // public void init( 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; } /** Bind our input streams to an XMLReader. * * Just a convenience routine; obviously you can explicitly register * this as a listener with the same effect. * */ public void setXMLReader(XMLReader eventsource) { 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) } // Register a content handler for us to output to public void setContentHandler(ContentHandler handler) { clientContentHandler=handler; } // Register a DTD handler for us to output to public void setDTDHandler(DTDHandler handler) { clientDTDHandler=handler; } // Register a lexical handler for us to output to // Not all filters support this... // ??? Should we register directly on the filter? // NOTE NAME -- subclassing issue in the Xerces version public void setLexicalHandler(LexicalHandler handler) { clientLexicalHandler=handler; } // Register an error handler for us to output to // NOTE NAME -- subclassing issue in the Xerces version public void setErrHandler(ErrorHandler handler) { clientErrorHandler=handler; } // Set the number of events between resumes of our coroutine // Immediately resets number of events before _next_ resume as well. public void setReturnFrequency(int events) { if(events<1) events=1; frequency=eventcounter=events; } // // ContentHandler methods // These pass the data to our client ContentHandler... // but they also count the number of events passing through, // and resume our coroutine each time that counter hits zero and // is reset. // // Note that for everything except endDocument and fatalError, we do the count-and-yield // BEFORE passing the call along. I'm hoping that this will encourage JIT // compilers to realize that these are tail-calls, reducing the expense of // the additional layer of data flow. // // %REVIEW% Glenn suggests that pausing after endElement, endDocument, // and characters may be sufficient. I actually may not want to // stop after characters, since in our application these wind up being // concatenated before they're processed... but that risks huge blocks of // text causing greater than usual readahead. (Unlikely? Consider the // possibility of a large base-64 block in a SOAP stream.) // public void characters(char[] ch, int start, int length) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.characters(ch,start,length); } public void endDocument() throws org.xml.sax.SAXException { // 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) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.endElement(namespaceURI,localName,qName); } public void endPrefixMapping(java.lang.String prefix) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.endPrefixMapping(prefix); } public void ignorableWhitespace(char[] ch, int start, int length) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.ignorableWhitespace(ch,start,length); } public void processingInstruction(java.lang.String target, java.lang.String data) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.processingInstruction(target,data); } public void setDocumentLocator(Locator locator) { if(--eventcounter<=0) { // This can cause a hang. -sb // co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.setDocumentLocator(locator); } public void skippedEntity(java.lang.String name) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.skippedEntity(name); } public void startDocument() throws org.xml.sax.SAXException { 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, Attributes atts) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.startElement(namespaceURI, localName, qName, atts); } public void startPrefixMapping(java.lang.String prefix, java.lang.String uri) throws org.xml.sax.SAXException { if(--eventcounter<=0) { co_yield(true); eventcounter=frequency; } if(clientContentHandler!=null) clientContentHandler.startPrefixMapping(prefix,uri); } // // LexicalHandler support. Not all SAX2 filters support these events // but we may want to pass them through when they exist... // // %REVIEW% These do NOT currently affect the eventcounter; I'm asserting // that they're rare enough that it makes little or no sense to // pause after them. As such, it may make more sense for folks who // actually want to use them to register directly with the filter. // But I want 'em here for now, to remind us to recheck this assertion! // public void comment(char[] ch, int start, int length) throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.comment(ch,start,length); } public void endCDATA() throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.endCDATA(); } public void endDTD() throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.endDTD(); } public void endEntity(java.lang.String name) throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.endEntity(name); } public void startCDATA() throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.startCDATA(); } public void startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler. startDTD(name, publicId, systemId); } public void startEntity(java.lang.String name) throws org.xml.sax.SAXException { if(null!=clientLexicalHandler) clientLexicalHandler.startEntity(name); } // // DTDHandler support. public void notationDecl(String a, String b, String c) throws SAXException {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?