1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *     http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 /*
  21  * $Id: LoadDocument.java,v 1.2.4.1 2005/09/06 07:14:12 pvedula Exp $
  22  */
  23 
  24 package com.sun.org.apache.xalan.internal.xsltc.dom;
  25 
  26 import com.sun.org.apache.xalan.internal.XalanConstants;
  27 import java.io.FileNotFoundException;
  28 
  29 import javax.xml.transform.stream.StreamSource;
  30 
  31 import com.sun.org.apache.xalan.internal.xsltc.DOM;
  32 import com.sun.org.apache.xalan.internal.xsltc.DOMCache;
  33 import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
  34 import com.sun.org.apache.xalan.internal.xsltc.TransletException;
  35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  36 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  37 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  38 import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
  39 import com.sun.org.apache.xml.internal.dtm.DTM;
  40 import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  41 import com.sun.org.apache.xml.internal.dtm.DTMManager;
  42 import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase;
  43 import com.sun.org.apache.xml.internal.dtm.ref.EmptyIterator;
  44 import com.sun.org.apache.xml.internal.utils.SystemIDResolver;
  45 
  46 import org.xml.sax.InputSource;
  47 import org.xml.sax.XMLReader;
  48 
  49 /**
  50  * @author Morten Jorgensen
  51  */
  52 public final class LoadDocument {
  53 
  54     private static final String NAMESPACE_FEATURE =
  55        "http://xml.org/sax/features/namespaces";
  56 
  57     /**
  58      * Interprets the arguments passed from the document() function (see
  59      * com/sun/org/apache/xalan/internal/xsltc/compiler/DocumentCall.java) and returns an
  60      * iterator containing the requested nodes. Builds a union-iterator if
  61      * several documents are requested.
  62      * 2 arguments arg1 and arg2.  document(Obj, node-set) call
  63      */
  64     public static DTMAxisIterator documentF(Object arg1, DTMAxisIterator arg2,
  65                             String xslURI, AbstractTranslet translet, DOM dom)
  66     throws TransletException {
  67         String baseURI = null;
  68         final int arg2FirstNode = arg2.next();
  69         if (arg2FirstNode == DTMAxisIterator.END) {
  70             //  the second argument node-set is empty
  71             return EmptyIterator.getInstance();
  72         } else {
  73             //System.err.println("arg2FirstNode name: "
  74             //                   + dom.getNodeName(arg2FirstNode )+"["
  75             //                   +Integer.toHexString(arg2FirstNode )+"]");
  76             baseURI = dom.getDocumentURI(arg2FirstNode);
  77             if (!SystemIDResolver.isAbsoluteURI(baseURI))
  78                baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
  79         }
  80 
  81         try {
  82             if (arg1 instanceof String) {
  83                 if (((String)arg1).length() == 0) {
  84                     return document(xslURI, "", translet, dom);
  85                 } else {
  86                     return document((String)arg1, baseURI, translet, dom);
  87                 }
  88             } else if (arg1 instanceof DTMAxisIterator) {
  89                 return document((DTMAxisIterator)arg1, baseURI, translet, dom);
  90             } else {
  91                 final String err = "document("+arg1.toString()+")";
  92                 throw new IllegalArgumentException(err);
  93             }
  94         } catch (Exception e) {
  95             throw new TransletException(e);
  96         }
  97     }
  98     /**
  99      * Interprets the arguments passed from the document() function (see
 100      * com/sun/org/apache/xalan/internal/xsltc/compiler/DocumentCall.java) and returns an
 101      * iterator containing the requested nodes. Builds a union-iterator if
 102      * several documents are requested.
 103      * 1 arguments arg.  document(Obj) call
 104      */
 105     public static DTMAxisIterator documentF(Object arg, String xslURI,
 106                     AbstractTranslet translet, DOM dom)
 107     throws TransletException {
 108         try {
 109             if (arg instanceof String) {
 110                 if (xslURI == null )
 111                     xslURI = "";
 112 
 113                 String baseURI = xslURI;
 114                 if (!SystemIDResolver.isAbsoluteURI(xslURI))
 115                    baseURI = SystemIDResolver.getAbsoluteURIFromRelative(xslURI);
 116 
 117                 String href = (String)arg;
 118                 if (href.length() == 0) {
 119                     href = "";
 120                     // %OPT% Optimization to cache the stylesheet DOM.
 121                     // The stylesheet DOM is built once and cached
 122                     // in the Templates object.
 123                     TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
 124                     DOM sdom = null;
 125                     if (templates != null) {
 126                         sdom = templates.getStylesheetDOM();
 127                     }
 128 
 129                     // If the cached dom exists, we need to migrate it
 130                     // to the new DTMManager and create a DTMAxisIterator
 131                     // for the document.
 132                     if (sdom != null) {
 133                         return document(sdom, translet, dom);
 134                     }
 135                     else {
 136                         return document(href, baseURI, translet, dom, true);
 137                     }
 138                 }
 139                 else {
 140                     return document(href, baseURI, translet, dom);
 141                 }
 142             } else if (arg instanceof DTMAxisIterator) {
 143                 return document((DTMAxisIterator)arg, null, translet, dom);
 144             } else {
 145                 final String err = "document("+arg.toString()+")";
 146                 throw new IllegalArgumentException(err);
 147             }
 148         } catch (Exception e) {
 149             throw new TransletException(e);
 150         }
 151     }
 152 
 153     private static DTMAxisIterator document(String uri, String base,
 154                     AbstractTranslet translet, DOM dom)
 155         throws Exception
 156     {
 157         return document(uri, base, translet, dom, false);
 158     }
 159 
 160     private static DTMAxisIterator document(String uri, String base,
 161                     AbstractTranslet translet, DOM dom,
 162                     boolean cacheDOM)
 163     throws Exception
 164     {
 165         try {
 166         final String originalUri = uri;
 167         MultiDOM multiplexer = (MultiDOM)dom;
 168 
 169         // Prepend URI base to URI (from context)
 170         if (base != null && !base.equals("")) {
 171             uri = SystemIDResolver.getAbsoluteURI(uri, base);
 172         }
 173 
 174         // Return an empty iterator if the URI is clearly invalid
 175         // (to prevent some unncessary MalformedURL exceptions).
 176         if (uri == null || uri.equals("")) {
 177             return(EmptyIterator.getInstance());
 178         }
 179 
 180         // Check if this DOM has already been added to the multiplexer
 181         int mask = multiplexer.getDocumentMask(uri);
 182         if (mask != -1) {
 183             DOM newDom = ((DOMAdapter)multiplexer.getDOMAdapter(uri))
 184                                        .getDOMImpl();
 185             if (newDom instanceof DOMEnhancedForDTM) {
 186                 return new SingletonIterator(((DOMEnhancedForDTM)newDom)
 187                                                                .getDocument(),
 188                                              true);
 189             }
 190         }
 191 
 192         // Check if we can get the DOM from a DOMCache
 193         DOMCache cache = translet.getDOMCache();
 194         DOM newdom;
 195 
 196         mask = multiplexer.nextMask(); // peek
 197 
 198         if (cache != null) {
 199             newdom = cache.retrieveDocument(base, originalUri, translet);
 200             if (newdom == null) {
 201                 final Exception e = new FileNotFoundException(originalUri);
 202                 throw new TransletException(e);
 203             }
 204         } else {
 205             String accessError = SecuritySupport.checkAccess(uri, translet.getAllowedProtocols(), XalanConstants.ACCESS_EXTERNAL_ALL);
 206             if (accessError != null) {
 207                 ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
 208                         SecuritySupport.sanitizePath(uri), accessError);
 209                 throw new Exception(msg.toString());
 210             }
 211 
 212             // Parse the input document and construct DOM object
 213             // Trust the DTMManager to pick the right parser and
 214             // set up the DOM correctly.
 215             XSLTCDTMManager dtmManager = (XSLTCDTMManager)multiplexer
 216                                                               .getDTMManager();
 217             DOMEnhancedForDTM enhancedDOM =
 218                     (DOMEnhancedForDTM) dtmManager.getDTM(new StreamSource(uri),
 219                                             false, null, true, false,
 220                                             translet.hasIdCall(), cacheDOM);
 221             newdom = enhancedDOM;
 222 
 223             // Cache the stylesheet DOM in the Templates object
 224             if (cacheDOM) {
 225                 TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
 226                 if (templates != null) {
 227                     templates.setStylesheetDOM(enhancedDOM);
 228                 }
 229             }
 230 
 231             translet.prepassDocument(enhancedDOM);
 232             enhancedDOM.setDocumentURI(uri);
 233         }
 234 
 235         // Wrap the DOM object in a DOM adapter and add to multiplexer
 236         final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
 237         multiplexer.addDOMAdapter(domAdapter);
 238 
 239         // Create index for any key elements
 240         translet.buildKeys(domAdapter, null, null, newdom.getDocument());
 241 
 242         // Return a singleton iterator containing the root node
 243         return new SingletonIterator(newdom.getDocument(), true);
 244         } catch (Exception e) {
 245             throw e;
 246         }
 247     }
 248 
 249 
 250     private static DTMAxisIterator document(DTMAxisIterator arg1,
 251                                             String baseURI,
 252                                             AbstractTranslet translet, DOM dom)
 253     throws Exception
 254     {
 255         UnionIterator union = new UnionIterator(dom);
 256         int node = DTM.NULL;
 257 
 258         while ((node = arg1.next()) != DTM.NULL) {
 259             String uri = dom.getStringValueX(node);
 260             //document(node-set) if true;  document(node-set,node-set) if false
 261             if (baseURI  == null) {
 262                baseURI = dom.getDocumentURI(node);
 263                if (!SystemIDResolver.isAbsoluteURI(baseURI))
 264                     baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
 265             }
 266             union.addIterator(document(uri, baseURI, translet, dom));
 267         }
 268         return(union);
 269     }
 270 
 271     /**
 272      * Create a DTMAxisIterator for the newdom. This is currently only
 273      * used to create an iterator for the cached stylesheet DOM.
 274      *
 275      * @param newdom the cached stylesheet DOM
 276      * @param translet the translet
 277      * @param the main dom (should be a MultiDOM)
 278      * @return a DTMAxisIterator from the document root
 279      */
 280     private static DTMAxisIterator document(DOM newdom,
 281                                             AbstractTranslet translet,
 282                                             DOM dom)
 283         throws Exception
 284     {
 285         DTMManager dtmManager = ((MultiDOM)dom).getDTMManager();
 286         // Need to migrate the cached DTM to the new DTMManager
 287         if (dtmManager != null && newdom instanceof DTM) {
 288             ((DTM)newdom).migrateTo(dtmManager);
 289         }
 290 
 291         translet.prepassDocument(newdom);
 292 
 293         // Wrap the DOM object in a DOM adapter and add to multiplexer
 294         final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
 295         ((MultiDOM)dom).addDOMAdapter(domAdapter);
 296 
 297         // Create index for any key elements
 298         translet.buildKeys(domAdapter, null, null,
 299                            newdom.getDocument());
 300 
 301         // Return a singleton iterator containing the root node
 302         return new SingletonIterator(newdom.getDocument(), true);
 303     }
 304 
 305 }