/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed 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: LoadDocument.java,v 1.25 2004/02/16 22:54:59 minchau Exp $ */ package com.sun.org.apache.xalan.internal.xsltc.dom; import java.io.FileNotFoundException; import javax.xml.transform.stream.StreamSource; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.DOMCache; import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM; import com.sun.org.apache.xalan.internal.xsltc.TransletException; import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.DTMManager; import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; import com.sun.org.apache.xml.internal.dtm.ref.EmptyIterator; import com.sun.org.apache.xml.internal.utils.SystemIDResolver; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; /** * @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 * com/sun/org/apache/xalan/internal/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 * com/sun/org/apache/xalan/internal/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.equals("")) { 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.equals("")) { 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); } }