}
  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;        InputSource xmlSource;        if (null == source)        {          xmlSource = null;          reader = 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);          }        } 	    SAX2DTM dtm;		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.		  dtm = new SAX2RTFDTM(this, source, documentID, whiteSpaceFilter,				       xstringFactory, doIndexing);		}		else // Create the basic SAX2DTM.		  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.        addDTM(dtm, dtmPos, 0);        boolean haveXercesParser =          (null != reader)          && (reader.getClass().getName().equals("org.apache.xerces.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 (this.m_incremental && incremental /* || ((null == reader) && incremental) */)        {          IncrementalSAXSource coParser=null;          if (haveXercesParser)          {            // IncrementalSAXSource_Xerces to avoid threading.            // System.out.println("Using IncrementalSAXSource_Xerces to avoid threading");            try {              // should be ok, it's in the same package - no need for thread class loader,							// AND theoretically no need for reflection...              // Class c=Class.forName( "org.apache.xml.dtm.ref.IncrementalSAXSource_Xerces" );              // coParser=(IncrementalSAXSource)c.newInstance();							coParser=org.apache.xml.dtm.ref.IncrementalSAXSource_Xerces.createIncrementalSAXSource();            }  catch( Exception ex ) {              ex.printStackTrace();              coParser=null;            }          }          if( coParser==null ) {            // Create a IncrementalSAXSource that will run on the secondary thread.            if (null == reader)              coParser = new IncrementalSAXSource_Filter();            else	    {	      IncrementalSAXSource_Filter filter=new IncrementalSAXSource_Filter();	      filter.setXMLReader(reader);	      coParser=filter;	    }          }          // Have the DTM set itself up as the IncrementalSAXSource's listener.          dtm.setIncrementalSAXSource(coParser);          if (null == xmlSource)          {            // Then the user will construct it themselves.            return dtm;          }          if(null == reader.getErrorHandler())            reader.setDTDHandler(dtm);          reader.setErrorHandler(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 org.apache.xml.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.setDTDHandler(dtm);          try          {            reader.setProperty(              "http://xml.org/sax/properties/lexical-handler", dtm);          }          catch (SAXNotRecognizedException e){}          catch (SAXNotSupportedException e){}          try          {            reader.parse(xmlSource);          }          catch (RuntimeException re)          {            dtm.clearCoRoutine();            throw re;          }          catch (Exception e)          {            dtm.clearCoRoutine();            throw new org.apache.xml.utils.WrappedRuntimeException(e);          }        }        if (DUMPTREE)        {          System.out.println("Dumping SAX2DOM");          dtm.dumpDTM();        }        return dtm;      }      else      {        // It should have been handled by a derived class or the caller        // made a mistake.        throw new DTMException(XSLMessages.createMessage(XSLTErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); //"Not supported: " + source);      }    }  }