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 + -
显示快捷键?