You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sb...@locus.apache.org on 2000/08/04 21:33:30 UTC

cvs commit: xml-xalan/java/src/org/apache/xpath SourceTreeManager.java

sboag       00/08/04 12:33:29

  Modified:    java/src/org/apache/xpath SourceTreeManager.java
  Log:
  Major fixes for source tree caching, and fix for URL resolution.  Still a work in progress
  
  Revision  Changes    Path
  1.3       +261 -39   xml-xalan/java/src/org/apache/xpath/SourceTreeManager.java
  
  Index: SourceTreeManager.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/SourceTreeManager.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- SourceTreeManager.java	2000/07/30 22:42:19	1.2
  +++ SourceTreeManager.java	2000/08/04 19:33:27	1.3
  @@ -60,29 +60,60 @@
   import java.io.File;
   import java.io.IOException;
   import java.util.StringTokenizer;
  +
   import org.w3c.dom.Node;
   import org.w3c.dom.Document;
  +
   import trax.URIResolver;
   import trax.TransformException;
  +
   import org.xml.sax.InputSource;
   import org.xml.sax.SAXException;
   import org.xml.sax.SAXParseException;
   import org.xml.sax.helpers.XMLReaderFactory;
   import org.xml.sax.XMLReader;
  +import org.xml.sax.ContentHandler;
  +import org.xml.sax.EntityResolver;
  +
   import org.apache.xalan.res.XSLMessages;
  -import org.apache.xpath.res.XPATHErrorResources;
   import org.apache.xalan.stree.SourceTreeHandler;
   import org.apache.xalan.utils.SystemIDResolver;
   
  +import org.apache.xpath.res.XPATHErrorResources;
  +
   /**
    * This class bottlenecks all management of source trees.  The methods
    * in this class should allow easy garbage collection of source 
    * trees, and should centralize parsing for those source trees.
    */
  -public class SourceTreeManager implements URIResolver
  +public class SourceTreeManager
   {
  +  public static int CACHESIZE = 4;
     private int m_size = 0;
  -  private SourceTree m_sourceTree[] = new SourceTree[20];
  +  private SourceTree m_sourceTree[] = new SourceTree[CACHESIZE];
  +  
  +  URIResolver m_uriResolver;
  +  
  +  /**
  +   * Set an object that will be used to resolve URIs used in 
  +   * document(), etc.
  +   * @param resolver An object that implements the URIResolver interface, 
  +   * or null.
  +   */
  +  public void setURIResolver(URIResolver resolver)
  +  {
  +    m_uriResolver = resolver;
  +  }
  +
  +  EntityResolver m_entityResolver;
  +    
  +  /*
  +  * Allow an application to register an entity resolver.
  +  */
  +  public void setEntityResolver (EntityResolver resolver)
  +  {
  +    m_entityResolver = resolver;
  +  }
       
     /**
      * Given a document, find the URL associated with that document.
  @@ -106,8 +137,95 @@
       }
       return url;
     }
  +    
  +  /**
  +   * This will be called by the processor when it encounters 
  +   * an xsl:include, xsl:import, or document() function.
  +   * 
  +   * @param base The base URI that should be used.
  +   * @param uri Value from an xsl:import or xsl:include's href attribute, 
  +   * or a URI specified in the document() function.
  +   * @returns a InputSource that can be used to process the resource.
  +   */
  +  public InputSource resolveURI (String base, String urlString)
  +    throws TransformException, IOException
  +  {
  +    String uri;
  +    try
  +    {
  +      if(urlString.startsWith("../"))
  +       {
  +        // urlString = "file:/"+urlString;
  +      }
  +      // System.out.println("Calling getAbsoluteURI urlString: "+urlString + ", base: "+base);
  +
  +      uri = SystemIDResolver.getAbsoluteURI(urlString, base);
  +      // System.out.println("Returned from getAbsoluteURI: "+uri);
  +    }
  +    catch(SAXException se)
  +    {
  +      // Try and see if the entity resolver can do the job. 
  +      // If not, throw an exception.
  +      if(null != m_entityResolver)
  +      {
  +        try
  +        {
  +          return m_entityResolver.resolveEntity(null, urlString);
  +        }
  +        catch(SAXException se2)
  +        {
  +          throw new TransformException(se2);
  +        }
  +      }
  +      else
  +        throw new TransformException(se);
  +    }
  +    
  +    InputSource source;
  +    try
  +    {
  +      if(null != m_entityResolver)
  +        source = m_entityResolver.resolveEntity(null, urlString);
  +      else
  +        source = new InputSource(uri);
  +    }
  +    catch(SAXException se2)
  +    {
  +      throw new TransformException(se2);
  +    }
  +
  +    return source;
  +  }
     
     /**
  +   * Put the source tree root node in the document cache.
  +   * TODO: This function needs to be a LOT more sophisticated.
  +   */
  +  public void putDocumentInCache(Node n, InputSource source)
  +  {
  +    if(m_size < CACHESIZE)
  +    {
  +      // TODO: What to do if the SystemID isn't specified?
  +      if(null != source.getSystemId())
  +      {
  +        m_sourceTree[m_size] = new SourceTree(n, source.getSystemId());
  +        m_size++;
  +      }
  +    }
  +    else
  +    {
  +      // TODO: Implement a smart cache algorithm (read: pain)
  +      if(null != source.getSystemId())
  +      {
  +        // For now, always cache on the last, on the theory that we're 
  +        // probably in some sort of loop.
  +        m_sourceTree[m_size-1] = new SourceTree(n, source.getSystemId());
  +      }
  +    }
  +    
  +  }
  +  
  +  /**
      * Given a document, find the URL associated with that document.
      * @param owner Document that was previously processed by this liaison.
      */
  @@ -127,69 +245,173 @@
       return node;
     }
     
  +  /**
  +   * Get the source tree from the a base URL and a URL string.
  +   */
  +  public Node getSourceTree (String base, String urlString) 
  +    throws TransformException
  +  {
  +    try
  +    {
  +      InputSource source = this.resolveURI(base, urlString);
  +      // System.out.println("base: "+base+", urlString: "+urlString+", source: "+source.getSystemId());
  +      return getSourceTree(source);
  +    }
  +    catch(IOException ioe)
  +    {
  +      throw new TransformException(ioe);
  +    }
  +  }
  +
     /**
  -   * Return a string suitible for telling the user what parser is being used.
  +   * Get the source tree from the input source.
      */
  -  public String getParserDescription()
  +  public Node getSourceTree (InputSource source) 
  +    throws TransformException
     {
  -    return "(No parser - generic DOM)";
  +    // Try first to see if we have a node cached that matches this 
  +    // systemID.
  +    if(null != source.getSystemId())
  +    {
  +      Node n = findNodeFromURL(source.getSystemId());
  +      if(null != n)
  +        return n;
  +    }
  +    
  +    Node root = null;
  +    
  +    if(null != m_uriResolver)
  +      root = m_uriResolver.getDOMNode(source);
  +    
  +    if(null == root)
  +      root = getDOMNode(source);
  +    
  +    if(null != root)
  +      putDocumentInCache(root, source);
  +    return root;
     }
     
     /**
  -   * This will be called by the processor when it encounters 
  -   * an xsl:include, xsl:import, or document() function.
  -   * 
  -   * @param base The base URI that should be used.
  -   * @param uri Value from an xsl:import or xsl:include's href attribute, 
  -   * or a URI specified in the document() function.
  -   * @returns a InputSource that can be used to process the resource.
  +   * Try to create a DOM source tree from the input source.
      */
  -  public InputSource resolveURI (String base, String urlString)
  -    throws TransformException, IOException
  +  public Node getDOMNode (InputSource source) 
  +    throws TransformException
     {
  -    String uri;
  +    Node doc = null;
  +    String liaisonClassName = System.getProperty("org.apache.xalan.source.liaison");
  +
  +    if(null != liaisonClassName)
  +    {
  +      try 
  +      {
  +        DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
  +        liaison.parse(source);
  +        doc = liaison.getDocument();
  +      } 
  +      catch (SAXException se) 
  +      {
  +        throw new TransformException(se);
  +      } 
  +      catch (ClassNotFoundException e1) 
  +      {
  +        throw new TransformException("XML Liaison class " + liaisonClassName +
  +          " specified but not found", e1);
  +      } 
  +      catch (IllegalAccessException e2) 
  +      {
  +          throw new TransformException("XML Liaison class " + liaisonClassName +
  +            " found but cannot be loaded", e2);
  +      } 
  +      catch (InstantiationException e3) 
  +      {
  +          throw new TransformException("XML Liaison class " + liaisonClassName +
  +            " loaded but cannot be instantiated (no empty public constructor?)",
  +            e3);
  +      } 
  +      catch (ClassCastException e4) 
  +      {
  +          throw new TransformException("XML Liaison class " + liaisonClassName +
  +            " does not implement DOM2Helper", e4);
  +      }
  +    }
  +    else
  +    {
       try
       {
  -      uri = SystemIDResolver.getAbsoluteURI(base, urlString);
  +      XMLReader reader = getXMLReader(source) ;
  +      
  +      // TODO: Need to use factory of some kind to create the ContentHandler
  +      // (Also, try using JAXP if need be...)
  +      ContentHandler handler = new SourceTreeHandler();
  +      if(handler instanceof org.apache.xalan.stree.SourceTreeHandler)
  +      {
  +        // temp hack
  +        ((org.apache.xalan.stree.SourceTreeHandler)handler).m_useMultiThreading = false;
  +      }
  +      reader.setContentHandler(handler);
  +
  +      try
  +      {
  +        reader.setProperty("http://xml.org/sax/properties/lexical-handler", 
  +                           handler);
  +      }
  +      catch(SAXException se){}
  +      
  +      reader.parse(source);
  +
  +      if(handler instanceof org.apache.xalan.stree.SourceTreeHandler)
  +      {
  +        doc = ((org.apache.xalan.stree.SourceTreeHandler)handler).getRoot();
  +      }
       }
  +    catch(IOException ioe)
  +    {
  +      throw new TransformException(ioe);
  +    }
       catch(SAXException se)
       {
         throw new TransformException(se);
       }
  -    InputSource source = new InputSource();
  -    
  -    source.setSystemId(uri);
  -    return source;
  +    }
  +    return doc;
     }
   
     /**
  -   * This will be called by the processor when it encounters 
  -   * an xsl:include, xsl:import, or document() function, if it needs 
  -   * a DOM tree.
  +   * 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().
      * 
  -   * @param base The base URI that should be used.
  -   * @param uri Value from an xsl:import or xsl:include's href attribute, 
  -   * or a URI specified in the document() function.
  -   * @returns a DOM node that represents the resolution of the URI to a tree.
  +   * @param inputSource The value returned from the EntityResolver.
  +   * @returns a SAX2 parser to use with the InputSource.
      */
  -  public Node resolveURIToDOMTree (String base, String uri)
  -    throws TransformException, IOException
  +  public XMLReader getXMLReader(InputSource inputSource) 
  +    throws TransformException
     {
  -    InputSource source = resolveURI (base, uri);
       try
       {
  -      XMLReader reader = XMLReaderFactory.createXMLReader();
  -      SourceTreeHandler handler = new SourceTreeHandler();
  -      reader.setContentHandler(handler);
  -      reader.parse(source);
  -      return handler.getRoot();
  +      XMLReader reader = (null != m_uriResolver) 
  +                         ? m_uriResolver.getXMLReader(inputSource) : null;
  +      if(null == reader)
  +        reader = XMLReaderFactory.createXMLReader();
  +      
  +      try
  +      {
  +        reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
  +      }
  +      catch(SAXException se)
  +      {
  +        // What can we do?
  +        // TODO: User diagnostics.
  +      }
  +
  +      return reader;
       }
       catch(SAXException se)
       {
         throw new TransformException(se);
       }
     }
  -
  -
  -
   }