dtmmanagerdefault.java
来自「JAVA 所有包」· Java 代码 · 共 858 行 · 第 1/2 页
JAVA
858 行
/* * 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: DTMManagerDefault.java,v 1.2.4.1 2005/09/15 08:15:02 suresh_emailid Exp $ */package com.sun.org.apache.xml.internal.dtm.ref;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.transform.Source;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.sax.SAXSource;import javax.xml.transform.stream.StreamSource;import com.sun.org.apache.xml.internal.dtm.DTM;import com.sun.org.apache.xml.internal.dtm.DTMException;import com.sun.org.apache.xml.internal.dtm.DTMFilter;import com.sun.org.apache.xml.internal.dtm.DTMIterator;import com.sun.org.apache.xml.internal.dtm.DTMManager;import com.sun.org.apache.xml.internal.dtm.DTMWSFilter;import com.sun.org.apache.xml.internal.dtm.ref.dom2dtm.DOM2DTM;import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM;import com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2RTFDTM;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.PrefixResolver;import com.sun.org.apache.xml.internal.utils.SystemIDResolver;import com.sun.org.apache.xml.internal.utils.XMLReaderManager;import com.sun.org.apache.xml.internal.utils.XMLStringFactory;import org.w3c.dom.Document;import org.w3c.dom.Node;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.SAXNotRecognizedException;import org.xml.sax.SAXNotSupportedException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;/** * The default implementation for the DTMManager. * * %REVIEW% There is currently a reentrancy issue, since the finalizer * for XRTreeFrag (which runs in the GC thread) wants to call * DTMManager.release(), and may do so at the same time that the main * transformation thread is accessing the manager. Our current solution is * to make most of the manager's methods <code>synchronized</code>. * Early tests suggest that doing so is not causing a significant * performance hit in Xalan. However, it should be noted that there * is a possible alternative solution: rewrite release() so it merely * posts a request for release onto a threadsafe queue, and explicitly * process that queue on an infrequent basis during main-thread * activity (eg, when getDTM() is invoked). The downside of that solution * would be a greater delay before the DTM's storage is actually released * for reuse. * */public class DTMManagerDefault extends DTMManager{ //static final boolean JKESS_XNI_EXPERIMENT=true; /** Set this to true if you want a dump of the DTM after creation. */ private static final boolean DUMPTREE = false; /** Set this to true if you want a basic diagnostics. */ private static final boolean DEBUG = false; /** * Map from DTM identifier numbers to DTM objects that this manager manages. * One DTM may have several prefix numbers, if extended node indexing * is in use; in that case, m_dtm_offsets[] will used to control which * prefix maps to which section of the DTM. * * This array grows as necessary; see addDTM(). * * This array grows as necessary; see addDTM(). Growth is uncommon... but * access needs to be blindingly fast since it's used in node addressing. */ protected DTM m_dtms[] = new DTM[256]; /** Map from DTM identifier numbers to offsets. For small DTMs with a * single identifier, this will always be 0. In overflow addressing, where * additional identifiers are allocated to access nodes beyond the range of * a single Node Handle, this table is used to map the handle's node field * into the actual node identifier. * * This array grows as necessary; see addDTM(). * * This array grows as necessary; see addDTM(). Growth is uncommon... but * access needs to be blindingly fast since it's used in node addressing. * (And at the moment, that includes accessing it from DTMDefaultBase, * which is why this is not Protected or Private.) */ int m_dtm_offsets[] = new int[256]; /** * The cache for XMLReader objects to be used if the user did not * supply an XMLReader for a SAXSource or supplied a StreamSource. */ protected XMLReaderManager m_readerManager = null; /** * The default implementation of ContentHandler, DTDHandler and ErrorHandler. */ protected DefaultHandler m_defaultHandler = new DefaultHandler(); /** * Add a DTM to the DTM table. This convenience call adds it as the * "base DTM ID", with offset 0. The other version of addDTM should * be used if you want to add "extended" DTM IDs with nonzero offsets. * * @param dtm Should be a valid reference to a DTM. * @param id Integer DTM ID to be bound to this DTM */ synchronized public void addDTM(DTM dtm, int id) { addDTM(dtm,id,0); } /** * Add a DTM to the DTM table. * * @param dtm Should be a valid reference to a DTM. * @param id Integer DTM ID to be bound to this DTM. * @param offset Integer addressing offset. The internal DTM Node ID is * obtained by adding this offset to the node-number field of the * public DTM Handle. For the first DTM ID accessing each DTM, this is 0; * for overflow addressing it will be a multiple of 1<<IDENT_DTM_NODE_BITS. */ synchronized public void addDTM(DTM dtm, int id, int offset) { if(id>=IDENT_MAX_DTMS) { // TODO: %REVIEW% Not really the right error message. throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NO_DTMIDS_AVAIL, null)); //"No more DTM IDs are available!"); } // We used to just allocate the array size to IDENT_MAX_DTMS. // But we expect to increase that to 16 bits, and I'm not willing // to allocate that much space unless needed. We could use one of our // handy-dandy Fast*Vectors, but this will do for now. // %REVIEW% int oldlen=m_dtms.length; if(oldlen<=id) { // Various growth strategies are possible. I think we don't want // to over-allocate excessively, and I'm willing to reallocate // more often to get that. See also Fast*Vector classes. // // %REVIEW% Should throw a more diagnostic error if we go over the max... int newlen=Math.min((id+256),IDENT_MAX_DTMS); DTM new_m_dtms[] = new DTM[newlen]; System.arraycopy(m_dtms,0,new_m_dtms,0,oldlen); m_dtms=new_m_dtms; int new_m_dtm_offsets[] = new int[newlen]; System.arraycopy(m_dtm_offsets,0,new_m_dtm_offsets,0,oldlen); m_dtm_offsets=new_m_dtm_offsets; } m_dtms[id] = dtm; m_dtm_offsets[id]=offset; dtm.documentRegistration(); // The DTM should have been told who its manager was when we created it. // Do we need to allow for adopting DTMs _not_ created by this manager? } /** * Get the first free DTM ID available. %OPT% Linear search is inefficient! */ synchronized public int getFirstFreeDTMID() { int n = m_dtms.length; for (int i = 1; i < n; i++) { if(null == m_dtms[i]) { return i; } } return n; // count on addDTM() to throw exception if out of range } /** * The default table for exandedNameID lookups. */ private ExpandedNameTable m_expandedNameTable = new ExpandedNameTable(); /** * Constructor DTMManagerDefault * */ public DTMManagerDefault(){} /** * Get an instance of a DTM, loaded with the content from the * specified source. If the unique flag is true, a new instance will * always be returned. Otherwise it is up to the DTMManager to return a * new instance or an instance that it already created and may be being used * by someone else. * * A bit of magic in this implementation: If the source is null, unique is true, * and incremental and doIndexing are both false, we return an instance of * SAX2RTFDTM, which see. * * (I think more parameters will need to be added for error handling, and entity * resolution, and more explicit control of the RTF situation). * * @param source the specification of the source object. * @param unique true if the returned DTM must be unique, probably because it * is going to be mutated. * @param whiteSpaceFilter Enables filtering of whitespace nodes, and may * be null. * @param incremental true if the DTM should be built incrementally, if * possible. * @param doIndexing true if the caller considers it worth it to use * indexing schemes. * * @return a non-null DTM reference. */ synchronized public DTM getDTM(Source source, boolean unique, DTMWSFilter whiteSpaceFilter, boolean incremental, boolean doIndexing) { if(DEBUG && null != source) System.out.println("Starting "+ (unique ? "UNIQUE" : "shared")+ " source: "+source.getSystemId() ); XMLStringFactory xstringFactory = m_xsf; int dtmPos = getFirstFreeDTMID(); int documentID = dtmPos << IDENT_DTM_NODE_BITS; if ((null != source) && source instanceof DOMSource) { DOM2DTM dtm = new DOM2DTM(this, (DOMSource) source, documentID, whiteSpaceFilter, xstringFactory, doIndexing); addDTM(dtm, dtmPos, 0); // if (DUMPTREE) // { // dtm.dumpDTM(); // } return dtm; } else { boolean isSAXSource = (null != source) ? (source instanceof SAXSource) : true; boolean isStreamSource = (null != source) ? (source instanceof StreamSource) : false; if (isSAXSource || isStreamSource) { XMLReader reader = null; SAX2DTM dtm; try { InputSource xmlSource; if (null == source) { xmlSource = null; } else { reader = getXMLReader(source); xmlSource = SAXSource.sourceToInputSource(source); String urlOfSource = xmlSource.getSystemId(); if (null != urlOfSource) { try { urlOfSource = SystemIDResolver.getAbsoluteURI(urlOfSource); } catch (Exception e) { // %REVIEW% Is there a better way to send a warning? System.err.println("Can not absolutize URL: " + urlOfSource); } xmlSource.setSystemId(urlOfSource); } } if (source==null && unique && !incremental && !doIndexing) { // Special case to support RTF construction into shared DTM. // It should actually still work for other uses, // but may be slightly deoptimized relative to the base // to allow it to deal with carrying multiple documents. // // %REVIEW% This is a sloppy way to request this mode; // we need to consider architectural improvements. dtm = new SAX2RTFDTM(this, source, documentID, whiteSpaceFilter, xstringFactory, doIndexing); } /************************************************************** // EXPERIMENTAL 3/22/02 else if(JKESS_XNI_EXPERIMENT && m_incremental) { dtm = new XNI2DTM(this, source, documentID, whiteSpaceFilter, xstringFactory, doIndexing); } **************************************************************/ // Create the basic SAX2DTM. else { dtm = new SAX2DTM(this, source, documentID, whiteSpaceFilter, xstringFactory, doIndexing); } // Go ahead and add the DTM to the lookup table. This needs to be // done before any parsing occurs. Note offset 0, since we've just // created a new DTM. addDTM(dtm, dtmPos, 0); boolean haveXercesParser = (null != reader) && (reader.getClass() .getName() .equals("com.sun.org.apache.xerces.internal.parsers.SAXParser") ); if (haveXercesParser) { incremental = true; // No matter what. %REVIEW% } // If the reader is null, but they still requested an incremental // build, then we still want to set up the IncrementalSAXSource stuff. if (m_incremental && incremental /* || ((null == reader) && incremental) */) { IncrementalSAXSource coParser=null; if (haveXercesParser) { // IncrementalSAXSource_Xerces to avoid threading. try { coParser =(IncrementalSAXSource) Class.forName("com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Xerces").newInstance(); } catch( Exception ex ) { ex.printStackTrace(); coParser=null; } } if (coParser==null ) { // Create a IncrementalSAXSource to run on the secondary thread. if (null == reader) { coParser = new IncrementalSAXSource_Filter(); } else { IncrementalSAXSource_Filter filter = new IncrementalSAXSource_Filter(); filter.setXMLReader(reader); coParser=filter; } } /************************************************************** // EXPERIMENTAL 3/22/02 if (JKESS_XNI_EXPERIMENT && m_incremental && dtm instanceof XNI2DTM && coParser instanceof IncrementalSAXSource_Xerces) { com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration xpc= ((IncrementalSAXSource_Xerces)coParser) .getXNIParserConfiguration(); if (xpc!=null) { // Bypass SAX; listen to the XNI stream ((XNI2DTM)dtm).setIncrementalXNISource(xpc); } else { // Listen to the SAX stream (will fail, diagnostically...) dtm.setIncrementalSAXSource(coParser); } } else ***************************************************************/ // Have the DTM set itself up as IncrementalSAXSource's listener. dtm.setIncrementalSAXSource(coParser); if (null == xmlSource) { // Then the user will construct it themselves. return dtm; } if (null == reader.getErrorHandler()) { reader.setErrorHandler(dtm); } reader.setDTDHandler(dtm); try { // Launch parsing coroutine. Launches a second thread, // if we're using IncrementalSAXSource.filter(). coParser.startParse(xmlSource); } catch (RuntimeException re) { dtm.clearCoRoutine(); throw re; } catch (Exception e) { dtm.clearCoRoutine(); throw new com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e); } } else { if (null == reader) { // Then the user will construct it themselves. return dtm; } // not incremental reader.setContentHandler(dtm); reader.setDTDHandler(dtm); if (null == reader.getErrorHandler()) { reader.setErrorHandler(dtm); } try {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?