code: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements. See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership. The ASF licenses this file
   * to you 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$
   */
  
  package org.apache.xalan.xsltc.dom;
  
  import java.io.FileNotFoundException;
  
  import javax.xml.transform.stream.StreamSource;
  
  import org.apache.xalan.xsltc.DOM;
  import org.apache.xalan.xsltc.DOMCache;
  import org.apache.xalan.xsltc.DOMEnhancedForDTM;
  import org.apache.xalan.xsltc.TransletException;
  import org.apache.xalan.xsltc.runtime.AbstractTranslet;
  import org.apache.xalan.xsltc.trax.TemplatesImpl;
  import org.apache.xml.dtm.DTM;
  import org.apache.xml.dtm.DTMAxisIterator;
  import org.apache.xml.dtm.DTMManager;
  import org.apache.xml.dtm.ref.EmptyIterator;
  import org.apache.xml.utils.SystemIDResolver;
  
  /**
   * @author Morten Jorgensen
   */
  public final class LoadDocument {
  
      private static final String NAMESPACE_FEATURE =
         "http://xml.org/sax/features/namespaces";
  
      /**
       * Interprets the arguments passed from the document() function (see
       * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
       * iterator containing the requested nodes. Builds a union-iterator if
       * several documents are requested.
       * 2 arguments arg1 and arg2.  document(Obj, node-set) call 
       */
      public static DTMAxisIterator documentF(Object arg1, DTMAxisIterator arg2,
                              String xslURI, AbstractTranslet translet, DOM dom)
      throws TransletException {
          String baseURI = null;
          final int arg2FirstNode = arg2.next();
          if (arg2FirstNode == DTMAxisIterator.END) {
              //  the second argument node-set is empty
              return EmptyIterator.getInstance();
          } else {
              //System.err.println("arg2FirstNode name: "
              //                   + dom.getNodeName(arg2FirstNode )+"["
              //                   +Integer.toHexString(arg2FirstNode )+"]");
              baseURI = dom.getDocumentURI(arg2FirstNode);
              if (!SystemIDResolver.isAbsoluteURI(baseURI))
                 baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
          }
        
          try {
              if (arg1 instanceof String) {
                  if (((String)arg1).length() == 0) {
                      return document(xslURI, "", translet, dom);
                  } else {
                      return document((String)arg1, baseURI, translet, dom);
                  }
              } else if (arg1 instanceof DTMAxisIterator) {
                  return document((DTMAxisIterator)arg1, baseURI, translet, dom);
              } else {
                  final String err = "document("+arg1.toString()+")";
                  throw new IllegalArgumentException(err);
              }      
          } catch (Exception e) {
              throw new TransletException(e);
          }
      }
      /**
       * Interprets the arguments passed from the document() function (see
       * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
       * iterator containing the requested nodes. Builds a union-iterator if
       * several documents are requested.
       * 1 arguments arg.  document(Obj) call
       */
      public static DTMAxisIterator documentF(Object arg, String xslURI,
                      AbstractTranslet translet, DOM dom)
      throws TransletException {
          try {
              if (arg instanceof String) {
                  if (xslURI == null )
                      xslURI = "";
  
                  String baseURI = xslURI;
                  if (!SystemIDResolver.isAbsoluteURI(xslURI))
                     baseURI = SystemIDResolver.getAbsoluteURIFromRelative(xslURI);
                  
                  String href = (String)arg;
                  if (href.length() == 0) {
                      href = "";
                      // %OPT% Optimization to cache the stylesheet DOM.
                      // The stylesheet DOM is built once and cached
                      // in the Templates object.
                      TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
                      DOM sdom = null;
                      if (templates != null) {
                          sdom = templates.getStylesheetDOM();
                      }
                      
                      // If the cached dom exists, we need to migrate it
                      // to the new DTMManager and create a DTMAxisIterator
                      // for the document.
                      if (sdom != null) {
                      	return document(sdom, translet, dom);
                      }
                      else {
                      	return document(href, baseURI, translet, dom, true);
                      } 
                  }
                  else {
                      return document(href, baseURI, translet, dom);
                  }
              } else if (arg instanceof DTMAxisIterator) {
                  return document((DTMAxisIterator)arg, null, translet, dom);
              } else {
                  final String err = "document("+arg.toString()+")";
                  throw new IllegalArgumentException(err);
              }      
          } catch (Exception e) {
              throw new TransletException(e);
          }
      }
   
      private static DTMAxisIterator document(String uri, String base,
                      AbstractTranslet translet, DOM dom)
          throws Exception
      {
          return document(uri, base, translet, dom, false);
      }
   
      private static DTMAxisIterator document(String uri, String base,
                      AbstractTranslet translet, DOM dom,
                      boolean cacheDOM)
      throws Exception 
      {
          try {
          final String originalUri = uri;
          MultiDOM multiplexer = (MultiDOM)dom;
  
          // Prepend URI base to URI (from context)
          if (base != null && base.length() != 0) {
              uri = SystemIDResolver.getAbsoluteURI(uri, base);
          }
  
          // Return an empty iterator if the URI is clearly invalid
          // (to prevent some unncessary MalformedURL exceptions).
          if (uri == null || uri.length() == 0) {
              return(EmptyIterator.getInstance());
          }
          
          // Check if this DOM has already been added to the multiplexer
          int mask = multiplexer.getDocumentMask(uri);
          if (mask != -1) {
              DOM newDom = ((DOMAdapter)multiplexer.getDOMAdapter(uri))
                                         .getDOMImpl();
              if (newDom instanceof DOMEnhancedForDTM) {
                  return new SingletonIterator(((DOMEnhancedForDTM)newDom)
                                                                 .getDocument(),
                                               true);
              } 
          }
  
          // Check if we can get the DOM from a DOMCache
          DOMCache cache = translet.getDOMCache();
          DOM newdom;
  
          mask = multiplexer.nextMask(); // peek
  
          if (cache != null) {
              newdom = cache.retrieveDocument(base, originalUri, translet);
              if (newdom == null) {
                  final Exception e = new FileNotFoundException(originalUri);
                  throw new TransletException(e);
              }
          } else {
              // Parse the input document and construct DOM object
              // Trust the DTMManager to pick the right parser and
              // set up the DOM correctly.
              XSLTCDTMManager dtmManager = (XSLTCDTMManager)multiplexer
                                                                .getDTMManager();
              DOMEnhancedForDTM enhancedDOM =
                      (DOMEnhancedForDTM) dtmManager.getDTM(new StreamSource(uri),
                                              false, null, true, false,
                                              translet.hasIdCall(), cacheDOM);
              newdom = enhancedDOM;
  
              // Cache the stylesheet DOM in the Templates object
              if (cacheDOM) {
                  TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
                  if (templates != null) {
                      templates.setStylesheetDOM(enhancedDOM);
                  }
              }
              
              translet.prepassDocument(enhancedDOM);
              enhancedDOM.setDocumentURI(uri);
          }
  
          // Wrap the DOM object in a DOM adapter and add to multiplexer
          final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
          multiplexer.addDOMAdapter(domAdapter);
  
          // Create index for any key elements
          translet.buildKeys(domAdapter, null, null, newdom.getDocument());
  
          // Return a singleton iterator containing the root node
          return new SingletonIterator(newdom.getDocument(), true);
          } catch (Exception e) {
              throw e;
          }
      }
  
  
      private static DTMAxisIterator document(DTMAxisIterator arg1,
                                              String baseURI,
                                              AbstractTranslet translet, DOM dom)
      throws Exception
      {
          UnionIterator union = new UnionIterator(dom);
          int node = DTM.NULL;
  
          while ((node = arg1.next()) != DTM.NULL) {
              String uri = dom.getStringValueX(node);
              //document(node-set) if true;  document(node-set,node-set) if false
              if (baseURI  == null) {
                 baseURI = dom.getDocumentURI(node);
                 if (!SystemIDResolver.isAbsoluteURI(baseURI))
                      baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
              }
              union.addIterator(document(uri, baseURI, translet, dom));
          }
          return(union);
      }
  
      /**
       * Create a DTMAxisIterator for the newdom. This is currently only
       * used to create an iterator for the cached stylesheet DOM.
       * 
       * @param newdom the cached stylesheet DOM
       * @param translet the translet
       * @param the main dom (should be a MultiDOM)
       * @return a DTMAxisIterator from the document root
       */
      private static DTMAxisIterator document(DOM newdom, 
                                              AbstractTranslet translet,
                                              DOM dom)
          throws Exception
      {
          DTMManager dtmManager = ((MultiDOM)dom).getDTMManager();
          // Need to migrate the cached DTM to the new DTMManager
          if (dtmManager != null && newdom instanceof DTM) {
              ((DTM)newdom).migrateTo(dtmManager);
          }
      	
      	translet.prepassDocument(newdom);
          
          // Wrap the DOM object in a DOM adapter and add to multiplexer
          final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
          ((MultiDOM)dom).addDOMAdapter(domAdapter);
  
          // Create index for any key elements
          translet.buildKeys(domAdapter, null, null,
                             newdom.getDocument());
  
          // Return a singleton iterator containing the root node
          return new SingletonIterator(newdom.getDocument(), true);
      }
   
  }
  