286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 2001-2004 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A/*
286N/A * $Id: LoadDocument.java,v 1.2.4.1 2005/09/06 07:14:12 pvedula Exp $
286N/A */
286N/A
286N/Apackage com.sun.org.apache.xalan.internal.xsltc.dom;
286N/A
559N/Aimport com.sun.org.apache.xalan.internal.XalanConstants;
286N/Aimport java.io.FileNotFoundException;
286N/A
286N/Aimport javax.xml.transform.stream.StreamSource;
286N/A
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOM;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOMCache;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.TransletException;
559N/Aimport com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
286N/Aimport com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
559N/Aimport com.sun.org.apache.xalan.internal.utils.SecuritySupport;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTM;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMManager;
286N/Aimport com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase;
286N/Aimport com.sun.org.apache.xml.internal.dtm.ref.EmptyIterator;
286N/Aimport com.sun.org.apache.xml.internal.utils.SystemIDResolver;
286N/A
286N/Aimport org.xml.sax.InputSource;
286N/Aimport org.xml.sax.XMLReader;
286N/A
286N/A/**
286N/A * @author Morten Jorgensen
286N/A */
286N/Apublic final class LoadDocument {
286N/A
286N/A private static final String NAMESPACE_FEATURE =
286N/A "http://xml.org/sax/features/namespaces";
286N/A
286N/A /**
286N/A * Interprets the arguments passed from the document() function (see
286N/A * com/sun/org/apache/xalan/internal/xsltc/compiler/DocumentCall.java) and returns an
286N/A * iterator containing the requested nodes. Builds a union-iterator if
286N/A * several documents are requested.
286N/A * 2 arguments arg1 and arg2. document(Obj, node-set) call
286N/A */
286N/A public static DTMAxisIterator documentF(Object arg1, DTMAxisIterator arg2,
286N/A String xslURI, AbstractTranslet translet, DOM dom)
286N/A throws TransletException {
286N/A String baseURI = null;
286N/A final int arg2FirstNode = arg2.next();
286N/A if (arg2FirstNode == DTMAxisIterator.END) {
286N/A // the second argument node-set is empty
286N/A return EmptyIterator.getInstance();
286N/A } else {
286N/A //System.err.println("arg2FirstNode name: "
286N/A // + dom.getNodeName(arg2FirstNode )+"["
286N/A // +Integer.toHexString(arg2FirstNode )+"]");
286N/A baseURI = dom.getDocumentURI(arg2FirstNode);
286N/A if (!SystemIDResolver.isAbsoluteURI(baseURI))
286N/A baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
286N/A }
286N/A
286N/A try {
286N/A if (arg1 instanceof String) {
286N/A if (((String)arg1).length() == 0) {
286N/A return document(xslURI, "", translet, dom);
286N/A } else {
286N/A return document((String)arg1, baseURI, translet, dom);
286N/A }
286N/A } else if (arg1 instanceof DTMAxisIterator) {
286N/A return document((DTMAxisIterator)arg1, baseURI, translet, dom);
286N/A } else {
286N/A final String err = "document("+arg1.toString()+")";
286N/A throw new IllegalArgumentException(err);
286N/A }
286N/A } catch (Exception e) {
286N/A throw new TransletException(e);
286N/A }
286N/A }
286N/A /**
286N/A * Interprets the arguments passed from the document() function (see
286N/A * com/sun/org/apache/xalan/internal/xsltc/compiler/DocumentCall.java) and returns an
286N/A * iterator containing the requested nodes. Builds a union-iterator if
286N/A * several documents are requested.
286N/A * 1 arguments arg. document(Obj) call
286N/A */
286N/A public static DTMAxisIterator documentF(Object arg, String xslURI,
286N/A AbstractTranslet translet, DOM dom)
286N/A throws TransletException {
286N/A try {
286N/A if (arg instanceof String) {
286N/A if (xslURI == null )
286N/A xslURI = "";
286N/A
286N/A String baseURI = xslURI;
286N/A if (!SystemIDResolver.isAbsoluteURI(xslURI))
286N/A baseURI = SystemIDResolver.getAbsoluteURIFromRelative(xslURI);
286N/A
286N/A String href = (String)arg;
286N/A if (href.length() == 0) {
286N/A href = "";
286N/A // %OPT% Optimization to cache the stylesheet DOM.
286N/A // The stylesheet DOM is built once and cached
286N/A // in the Templates object.
286N/A TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
286N/A DOM sdom = null;
286N/A if (templates != null) {
286N/A sdom = templates.getStylesheetDOM();
286N/A }
286N/A
286N/A // If the cached dom exists, we need to migrate it
286N/A // to the new DTMManager and create a DTMAxisIterator
286N/A // for the document.
286N/A if (sdom != null) {
286N/A return document(sdom, translet, dom);
286N/A }
286N/A else {
286N/A return document(href, baseURI, translet, dom, true);
286N/A }
286N/A }
286N/A else {
286N/A return document(href, baseURI, translet, dom);
286N/A }
286N/A } else if (arg instanceof DTMAxisIterator) {
286N/A return document((DTMAxisIterator)arg, null, translet, dom);
286N/A } else {
286N/A final String err = "document("+arg.toString()+")";
286N/A throw new IllegalArgumentException(err);
286N/A }
286N/A } catch (Exception e) {
286N/A throw new TransletException(e);
286N/A }
286N/A }
286N/A
286N/A private static DTMAxisIterator document(String uri, String base,
286N/A AbstractTranslet translet, DOM dom)
286N/A throws Exception
286N/A {
286N/A return document(uri, base, translet, dom, false);
286N/A }
286N/A
286N/A private static DTMAxisIterator document(String uri, String base,
286N/A AbstractTranslet translet, DOM dom,
286N/A boolean cacheDOM)
286N/A throws Exception
286N/A {
286N/A try {
286N/A final String originalUri = uri;
286N/A MultiDOM multiplexer = (MultiDOM)dom;
286N/A
286N/A // Prepend URI base to URI (from context)
286N/A if (base != null && !base.equals("")) {
286N/A uri = SystemIDResolver.getAbsoluteURI(uri, base);
286N/A }
286N/A
286N/A // Return an empty iterator if the URI is clearly invalid
286N/A // (to prevent some unncessary MalformedURL exceptions).
286N/A if (uri == null || uri.equals("")) {
286N/A return(EmptyIterator.getInstance());
286N/A }
286N/A
286N/A // Check if this DOM has already been added to the multiplexer
286N/A int mask = multiplexer.getDocumentMask(uri);
286N/A if (mask != -1) {
286N/A DOM newDom = ((DOMAdapter)multiplexer.getDOMAdapter(uri))
286N/A .getDOMImpl();
286N/A if (newDom instanceof DOMEnhancedForDTM) {
286N/A return new SingletonIterator(((DOMEnhancedForDTM)newDom)
286N/A .getDocument(),
286N/A true);
286N/A }
286N/A }
286N/A
286N/A // Check if we can get the DOM from a DOMCache
286N/A DOMCache cache = translet.getDOMCache();
286N/A DOM newdom;
286N/A
286N/A mask = multiplexer.nextMask(); // peek
286N/A
286N/A if (cache != null) {
286N/A newdom = cache.retrieveDocument(base, originalUri, translet);
286N/A if (newdom == null) {
286N/A final Exception e = new FileNotFoundException(originalUri);
286N/A throw new TransletException(e);
286N/A }
286N/A } else {
559N/A String accessError = SecuritySupport.checkAccess(uri, translet.getAllowedProtocols(), XalanConstants.ACCESS_EXTERNAL_ALL);
559N/A if (accessError != null) {
559N/A ErrorMsg msg = new ErrorMsg(ErrorMsg.ACCESSING_XSLT_TARGET_ERR,
559N/A SecuritySupport.sanitizePath(uri), accessError);
559N/A throw new Exception(msg.toString());
559N/A }
559N/A
286N/A // Parse the input document and construct DOM object
286N/A // Trust the DTMManager to pick the right parser and
286N/A // set up the DOM correctly.
286N/A XSLTCDTMManager dtmManager = (XSLTCDTMManager)multiplexer
286N/A .getDTMManager();
286N/A DOMEnhancedForDTM enhancedDOM =
286N/A (DOMEnhancedForDTM) dtmManager.getDTM(new StreamSource(uri),
286N/A false, null, true, false,
286N/A translet.hasIdCall(), cacheDOM);
286N/A newdom = enhancedDOM;
286N/A
286N/A // Cache the stylesheet DOM in the Templates object
286N/A if (cacheDOM) {
286N/A TemplatesImpl templates = (TemplatesImpl)translet.getTemplates();
286N/A if (templates != null) {
286N/A templates.setStylesheetDOM(enhancedDOM);
286N/A }
286N/A }
286N/A
286N/A translet.prepassDocument(enhancedDOM);
286N/A enhancedDOM.setDocumentURI(uri);
286N/A }
286N/A
286N/A // Wrap the DOM object in a DOM adapter and add to multiplexer
286N/A final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
286N/A multiplexer.addDOMAdapter(domAdapter);
286N/A
286N/A // Create index for any key elements
286N/A translet.buildKeys(domAdapter, null, null, newdom.getDocument());
286N/A
286N/A // Return a singleton iterator containing the root node
286N/A return new SingletonIterator(newdom.getDocument(), true);
286N/A } catch (Exception e) {
286N/A throw e;
286N/A }
286N/A }
286N/A
286N/A
286N/A private static DTMAxisIterator document(DTMAxisIterator arg1,
286N/A String baseURI,
286N/A AbstractTranslet translet, DOM dom)
286N/A throws Exception
286N/A {
286N/A UnionIterator union = new UnionIterator(dom);
286N/A int node = DTM.NULL;
286N/A
286N/A while ((node = arg1.next()) != DTM.NULL) {
286N/A String uri = dom.getStringValueX(node);
286N/A //document(node-set) if true; document(node-set,node-set) if false
286N/A if (baseURI == null) {
286N/A baseURI = dom.getDocumentURI(node);
286N/A if (!SystemIDResolver.isAbsoluteURI(baseURI))
286N/A baseURI = SystemIDResolver.getAbsoluteURIFromRelative(baseURI);
286N/A }
286N/A union.addIterator(document(uri, baseURI, translet, dom));
286N/A }
286N/A return(union);
286N/A }
286N/A
286N/A /**
286N/A * Create a DTMAxisIterator for the newdom. This is currently only
286N/A * used to create an iterator for the cached stylesheet DOM.
286N/A *
286N/A * @param newdom the cached stylesheet DOM
286N/A * @param translet the translet
286N/A * @param the main dom (should be a MultiDOM)
286N/A * @return a DTMAxisIterator from the document root
286N/A */
286N/A private static DTMAxisIterator document(DOM newdom,
286N/A AbstractTranslet translet,
286N/A DOM dom)
286N/A throws Exception
286N/A {
286N/A DTMManager dtmManager = ((MultiDOM)dom).getDTMManager();
286N/A // Need to migrate the cached DTM to the new DTMManager
286N/A if (dtmManager != null && newdom instanceof DTM) {
286N/A ((DTM)newdom).migrateTo(dtmManager);
286N/A }
286N/A
286N/A translet.prepassDocument(newdom);
286N/A
286N/A // Wrap the DOM object in a DOM adapter and add to multiplexer
286N/A final DOMAdapter domAdapter = translet.makeDOMAdapter(newdom);
286N/A ((MultiDOM)dom).addDOMAdapter(domAdapter);
286N/A
286N/A // Create index for any key elements
286N/A translet.buildKeys(domAdapter, null, null,
286N/A newdom.getDocument());
286N/A
286N/A // Return a singleton iterator containing the root node
286N/A return new SingletonIterator(newdom.getDocument(), true);
286N/A }
286N/A
286N/A}