/*
* @(#)$Id$
*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2001, Sun
* Microsystems., http://www.sun.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* @author Morten Jorgensen
*
*/
package org.apache.xalan.xsltc.dom;
import java.io.File;
import java.net.URL;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.apache.xalan.xsltc.DOM;
import org.apache.xalan.xsltc.DOMCache;
import org.apache.xalan.xsltc.Translet;
import org.apache.xalan.xsltc.NodeIterator;
import org.apache.xalan.xsltc.TransletException;
import org.apache.xalan.xsltc.runtime.AbstractTranslet;
public final class LoadDocument {
/**
* Returns an iterator containing a set of nodes from an XML document
* loaded by the document() function. Loads the
*/
public static NodeIterator document(String uri,
String base,
AbstractTranslet translet,
MultiDOM multiplexer)
throws Exception {
// Check if this is a local file name
final File file = new File(uri);
if (file.exists())
uri = "file:" + file.getAbsolutePath();
// Return an empty iterator if the URI is clearly invalid
// (to prevent some unncessary MalformedURL exceptions).
if ((uri == null) || (uri.equals("")))
return(new SingletonIterator(DOM.NULL,true));
if ((base != null) && (!base.equals(""))) {
if (!uri.startsWith(base))
uri = base+uri;
}
// Check if this DOM has already been added to the multiplexer
int mask = multiplexer.getDocumentMask(uri);
if (mask != -1) {
return new SingletonIterator(DOM.ROOTNODE | mask, true);
}
// Check if we can get the DOM from a DOMCache
DOMCache cache = translet.getDOMCache();
DOMImpl dom;
mask = multiplexer.nextMask(); // peek
if (cache != null) {
dom = cache.retrieveDocument(uri, mask, translet);
}
else {
// Parse the input document and construct DOM object
// Create a SAX parser and get the XMLReader object it uses
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SAXParser parser = factory.newSAXParser();
final XMLReader reader = parser.getXMLReader();
// Set the DOM's DOM builder as the XMLReader's SAX2 content handler
dom = new DOMImpl();
reader.setContentHandler(dom.getBuilder());
// Create a DTD monitor and pass it to the XMLReader object
DTDMonitor dtdMonitor = new DTDMonitor();
dtdMonitor.handleDTD(reader);
dom.setDocumentURI(uri);
reader.parse(uri);
// Set size of key/id indices
translet.setIndexSize(dom.getSize());
// Create index for any ID attributes defined in the document DTD
dtdMonitor.buildIdIndex(dom, mask, translet);
// Pass any unparsed URI elements to the translet
translet.setUnparsedEntityURIs(dtdMonitor.getUnparsedEntityURIs());
}
// Wrap the DOM object in a DOM adapter and add to multiplexer
final DOMAdapter domAdapter = translet.makeDOMAdapter(dom);
mask = multiplexer.addDOMAdapter(domAdapter);
// Create index for any key elements
translet.buildKeys((DOM)multiplexer, null, null, DOM.ROOTNODE | mask);
// Return a singleton iterator containing the root node
return new SingletonIterator(DOM.ROOTNODE | mask, true);
}
/**
* Interprets the arguments passed from the document() function (see
* org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an iterator
* containing the requested nodes. Builds a union-iterator if several
* documents are requested.
*/
public static NodeIterator document(Object arg,
NodeIterator nodeset,
AbstractTranslet translet,
MultiDOM multiplexer)
throws TransletException {
try {
String baseURI = "";
// Get the base of the URI (if any)
if (nodeset != null) {
final int node = nodeset.next();
if (node != DOM.NULL) {
baseURI = multiplexer.getNodeURI(node);
if (baseURI == null) baseURI = "";
final int sep = baseURI.lastIndexOf('/');
if (sep > 0)
baseURI = baseURI.substring(0,sep);
else
baseURI = "";
}
}
// If the argument is just a single string (an URI) we just return
// the nodes from the one document this URI points to.
if (arg instanceof String) {
return document((String)arg, baseURI, translet, multiplexer);
}
// Otherwise we must create a union iterator, add the nodes from
// all the DOMs to this iterator, and return the union in the end.
else {
UnionIterator union = new UnionIterator(multiplexer);
NodeIterator iterator = (NodeIterator)arg;
int node;
while ((node = iterator.next()) != DOM.NULL) {
String uri = multiplexer.getNodeValue(node);
union.addIterator(document(uri, baseURI,
translet, multiplexer));
}
return(union);
}
}
catch (Exception e) {
throw new TransletException(e);
}
}
}