FileDocCategorySizeDatePackage
DTMManagerDefault.javaAPI DocJava SE 5 API29322Fri Aug 26 14:56:00 BST 2005com.sun.org.apache.xml.internal.dtm.ref

DTMManagerDefault

public class DTMManagerDefault extends DTMManager
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 synchronized. 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.

Fields Summary
private static final boolean
DUMPTREE
Set this to true if you want a dump of the DTM after creation.
private static final boolean
DEBUG
Set this to true if you want a basic diagnostics.
protected DTM[]
m_dtms
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.
int[]
m_dtm_offsets
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.)
protected XMLReaderManager
m_readerManager
The cache for XMLReader objects to be used if the user did not supply an XMLReader for a SAXSource or supplied a StreamSource.
private ExpandedNameTable
m_expandedNameTable
The default table for exandedNameID lookups.
Constructors Summary
public DTMManagerDefault()
Constructor DTMManagerDefault


       
   
Methods Summary
public synchronized voidaddDTM(com.sun.org.apache.xml.internal.dtm.DTM dtm, int id)
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


                                                                   
         	addDTM(dtm,id,0); 
public synchronized voidaddDTM(com.sun.org.apache.xml.internal.dtm.DTM dtm, int id, int offset)
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<

		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?
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMIteratorcreateDTMIterator(int whatToShow, com.sun.org.apache.xml.internal.dtm.DTMFilter filter, boolean entityReferenceExpansion)
NEEDSDOC Method createDTMIterator NEEDSDOC @param whatToShow NEEDSDOC @param filter NEEDSDOC @param entityReferenceExpansion NEEDSDOC (createDTMIterator) @return


    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMIteratorcreateDTMIterator(java.lang.String xpathString, com.sun.org.apache.xml.internal.utils.PrefixResolver presolver)
NEEDSDOC Method createDTMIterator NEEDSDOC @param xpathString NEEDSDOC @param presolver NEEDSDOC (createDTMIterator) @return


    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMIteratorcreateDTMIterator(int node)
NEEDSDOC Method createDTMIterator NEEDSDOC @param node NEEDSDOC (createDTMIterator) @return


    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMIteratorcreateDTMIterator(java.lang.Object xpathCompiler, int pos)
NEEDSDOC Method createDTMIterator NEEDSDOC @param xpathCompiler NEEDSDOC @param pos NEEDSDOC (createDTMIterator) @return


    /** @todo: implement this com.sun.org.apache.xml.internal.dtm.DTMManager abstract method */
    return null;
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMcreateDocumentFragment()
Method createDocumentFragment NEEDSDOC (createDocumentFragment) @return


    try
    {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

      dbf.setNamespaceAware(true);

      DocumentBuilder db = dbf.newDocumentBuilder();
      Document doc = db.newDocument();
      Node df = doc.createDocumentFragment();

      return getDTM(new DOMSource(df), true, null, false, false);
    }
    catch (Exception e)
    {
      throw new DTMException(e);
    }
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMgetDTM(javax.xml.transform.Source source, boolean unique, com.sun.org.apache.xml.internal.dtm.DTMWSFilter whiteSpaceFilter, boolean incremental, boolean doIndexing)
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.


    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;

        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);
            }
          }

          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.
            //
            // %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 {
              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 com.sun.org.apache.xml.internal.utils.WrappedRuntimeException(e);
            }
          }

          if (DUMPTREE) {
            System.out.println("Dumping SAX2DOM");
            dtm.dumpDTM(System.err);
          }

          return dtm;
        } finally {
          releaseXMLReader(reader);
        }
      } else {

        // It should have been handled by a derived class or the caller
        // made a mistake.
        throw new DTMException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NOT_SUPPORTED, new Object[]{source})); //"Not supported: " + source);
      }
    }
  
public synchronized com.sun.org.apache.xml.internal.dtm.DTMgetDTM(int nodeHandle)
Return the DTM object containing a representation of this node.

param
nodeHandle DTM Handle indicating which node to retrieve
return
a reference to the DTM object containing this node.

    try
    {
      // Performance critical function.
      return m_dtms[nodeHandle >>> IDENT_DTM_NODE_BITS];
    }
    catch(java.lang.ArrayIndexOutOfBoundsException e)
    {
      if(nodeHandle==DTM.NULL)
				return null;		// Accept as a special case.
      else
				throw e;		// Programming error; want to know about it.
    }    
  
public synchronized intgetDTMHandleFromNode(org.w3c.dom.Node node)
Given a W3C DOM node, try and return a DTM handle. Note: calling this may be non-optimal, and there is no guarantee that the node will be found in any particular DTM.

param
node Non-null reference to a DOM node.
return
a valid DTM handle.

    if(null == node)
      throw new IllegalArgumentException(XMLMessages.createXMLMessage(XMLErrorResources.ER_NODE_NON_NULL, null)); //"node must be non-null for getDTMHandleFromNode!");

    if (node instanceof com.sun.org.apache.xml.internal.dtm.ref.DTMNodeProxy)
      return ((com.sun.org.apache.xml.internal.dtm.ref.DTMNodeProxy) node).getDTMNodeNumber();
		
    else
    {
      // Find the DOM2DTMs wrapped around this Document (if any)
      // and check whether they contain the Node in question.
      //
      // NOTE that since a DOM2DTM may represent a subtree rather
      // than a full document, we have to be prepared to check more
      // than one -- and there is no guarantee that we will find
      // one that contains ancestors or siblings of the node we're
      // seeking.
      //
      // %REVIEW% We could search for the one which contains this
      // node at the deepest level, and thus covers the widest
      // subtree, but that's going to entail additional work
      // checking more DTMs... and getHandleOfNode is not a
      // cheap operation in most implementations.
			//
			// TODO: %REVIEW% If overflow addressing, we may recheck a DTM
			// already examined. Ouch. But with the increased number of DTMs,
			// scanning back to check this is painful. 
			// POSSIBLE SOLUTIONS: 
			//   Generate a list of _unique_ DTM objects?
			//   Have each DTM cache last DOM node search?
			int max = m_dtms.length;
      for(int i = 0; i < max; i++)
        {
          DTM thisDTM=m_dtms[i];
          if((null != thisDTM) && thisDTM instanceof DOM2DTM)
          {
            int handle=((DOM2DTM)thisDTM).getHandleOfNode(node);
            if(handle!=DTM.NULL) return handle;
          }
         }

			// Not found; generate a new DTM.
			//
			// %REVIEW% Is this really desirable, or should we return null
			// and make folks explicitly instantiate from a DOMSource? The
			// latter is more work but gives the caller the opportunity to
			// explicitly add the DTM to a DTMManager... and thus to know when
			// it can be discarded again, which is something we need to pay much
			// more attention to. (Especially since only DTMs which are assigned
			// to a manager can use the overflow addressing scheme.)
			//
			// %BUG% If the source node was a DOM2DTM$defaultNamespaceDeclarationNode
			// and the DTM wasn't registered with this DTMManager, we will create
			// a new DTM and _still_ not be able to find the node (since it will
			// be resynthesized). Another reason to push hard on making all DTMs
			// be managed DTMs.

			// Since the real root of our tree may be a DocumentFragment, we need to
      // use getParent to find the root, instead of getOwnerDocument.  Otherwise
      // DOM2DTM#getHandleOfNode will be very unhappy.
      Node root = node;
      Node p = (root.getNodeType() == Node.ATTRIBUTE_NODE) ? ((org.w3c.dom.Attr)root).getOwnerElement() : root.getParentNode();
      for (; p != null; p = p.getParentNode())
      {
        root = p;
      }

      DOM2DTM dtm = (DOM2DTM) getDTM(new javax.xml.transform.dom.DOMSource(root),
																		 false, null, true, true);

      int handle;
      
      if(node instanceof com.sun.org.apache.xml.internal.dtm.ref.dom2dtm.DOM2DTMdefaultNamespaceDeclarationNode)
      {
				// Can't return the same node since it's unique to a specific DTM, 
				// but can return the equivalent node -- find the corresponding 
				// Document Element, then ask it for the xml: namespace decl.
				handle=dtm.getHandleOfNode(((org.w3c.dom.Attr)node).getOwnerElement());
				handle=dtm.getAttributeNode(handle,node.getNamespaceURI(),node.getLocalName());
      }
      else
				handle = ((DOM2DTM)dtm).getHandleOfNode(node);

      if(DTM.NULL == handle)
        throw new RuntimeException(XMLMessages.createXMLMessage(XMLErrorResources.ER_COULD_NOT_RESOLVE_NODE, null)); //"Could not resolve the node to a handle!");

      return handle;
    }
  
public synchronized intgetDTMIdentity(com.sun.org.apache.xml.internal.dtm.DTM dtm)
Given a DTM, find the ID number in the DTM tables which addresses the start of the document. If overflow addressing is in use, other DTM IDs may also be assigned to this DTM.

param
dtm The DTM which (hopefully) contains this node.
return
The DTM ID (as the high bits of a NodeHandle, not as our internal index), or -1 if the DTM doesn't belong to this manager.

	// Shortcut using DTMDefaultBase's extension hooks
	// %REVIEW% Should the lookup be part of the basic DTM API?
	if(dtm instanceof DTMDefaultBase)
	{
		DTMDefaultBase dtmdb=(DTMDefaultBase)dtm;
		if(dtmdb.getManager()==this)
			return dtmdb.getDTMIDs().elementAt(0);
		else
			return -1;
	}
				
    int n = m_dtms.length;

    for (int i = 0; i < n; i++)
    {
      DTM tdtm = m_dtms[i];

      if (tdtm == dtm && m_dtm_offsets[i]==0)
        return i << IDENT_DTM_NODE_BITS;
    }

    return -1;
  
public com.sun.org.apache.xml.internal.dtm.ref.ExpandedNameTablegetExpandedNameTable(com.sun.org.apache.xml.internal.dtm.DTM dtm)
return the expanded name table. NEEDSDOC @param dtm NEEDSDOC ($objectName$) @return

    return m_expandedNameTable;
  
public synchronized intgetFirstFreeDTMID()
Get the first free DTM ID available. %OPT% Linear search is inefficient!

    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
  
public synchronized org.xml.sax.XMLReadergetXMLReader(javax.xml.transform.Source inputSource)
This method returns the SAX2 parser to use with the InputSource obtained from this URI. It may return null if any SAX2-conformant XML parser can be used, or if getInputSource() will also return null. The parser must be free for use (i.e., not currently in use for another parse(). After use of the parser is completed, the releaseXMLReader(XMLReader) must be called.

param
inputSource The value returned from the URIResolver.
return
a SAX2 XMLReader to use to resolve the inputSource argument.
return
non-null XMLReader reference ready to parse.


    try
    {
      XMLReader reader = (inputSource instanceof SAXSource)
                         ? ((SAXSource) inputSource).getXMLReader() : null;

      // If user did not supply a reader, ask for one from the reader manager
      if (null == reader) {
        if (m_readerManager == null) {
            m_readerManager = XMLReaderManager.getInstance();
        }

        reader = m_readerManager.getXMLReader();
      }

      return reader;

    } catch (SAXException se) {
      throw new DTMException(se.getMessage(), se);
    }
  
public synchronized booleanrelease(com.sun.org.apache.xml.internal.dtm.DTM dtm, boolean shouldHardDelete)
Release the DTMManager's reference(s) to a DTM, making it unmanaged. This is typically done as part of returning the DTM to the heap after we're done with it.

param
dtm the DTM to be released.
param
shouldHardDelete If false, this call is a suggestion rather than an order, and we may not actually release the DTM. This is intended to support intelligent caching of documents... which is not implemented in this version of the DTM manager.
return
true if the DTM was released, false if shouldHardDelete was set and we decided not to.

    if(DEBUG)
    {
      System.out.println("Releasing "+
			 (shouldHardDelete ? "HARD" : "soft")+
			 " dtm="+
			 // Following shouldn't need a nodeHandle, but does...
			 // and doesn't seem to report the intended value
			 dtm.getDocumentBaseURI()
			 );
    }

    if (dtm instanceof SAX2DTM)
    {
      ((SAX2DTM) dtm).clearCoRoutine();
    }

		// Multiple DTM IDs may be assigned to a single DTM. 
		// The Right Answer is to ask which (if it supports
		// extension, the DTM will need a list anyway). The 
		// Wrong Answer, applied if the DTM can't help us,
		// is to linearly search them all; this may be very
		// painful.
		//
		// %REVIEW% Should the lookup move up into the basic DTM API?
		if(dtm instanceof DTMDefaultBase)
		{
			com.sun.org.apache.xml.internal.utils.SuballocatedIntVector ids=((DTMDefaultBase)dtm).getDTMIDs();
			for(int i=ids.size()-1;i>=0;--i)
				m_dtms[ids.elementAt(i)>>>DTMManager.IDENT_DTM_NODE_BITS]=null;
		}
		else
		{
			int i = getDTMIdentity(dtm);
		    if (i >= 0)
			{
				m_dtms[i >>> DTMManager.IDENT_DTM_NODE_BITS] = null;
			}
		}

    dtm.documentRelease();
    return true;
  
public synchronized voidreleaseXMLReader(org.xml.sax.XMLReader reader)
Indicates that the XMLReader object is no longer in use for the transform. Note that the getXMLReader method may return an XMLReader that was specified on the SAXSource object by the application code. Such a reader should still be passed to releaseXMLReader, but the reader manager will only re-use XMLReaders that it created.

param
reader The XMLReader to be released.

    if (m_readerManager != null) {
      m_readerManager.releaseXMLReader(reader);
    }