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