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