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 }