14c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
24c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
34c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * or more contributor license agreements. See the NOTICE file
44c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed with this work for additional information
54c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * regarding copyright ownership. The ASF licenses this file
64c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
74c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * you may not use this file except in compliance with the License.
84c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * You may obtain a copy of the License at
94c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * Unless required by applicable law or agreed to in writing, software
134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * See the License for the specific language governing permissions and
164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * limitations under the License.
174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/*
194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * $Id: ProcessorInclude.java 469349 2006-10-31 03:06:50Z minchau $
204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpackage org.apache.xalan.processor;
224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport java.io.IOException;
244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.XMLConstants;
264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.Source;
274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.TransformerException;
284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.URIResolver;
294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.dom.DOMSource;
304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.sax.SAXSource;
314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport javax.xml.transform.stream.StreamSource;
324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.res.XSLMessages;
344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xalan.res.XSLTErrorResources;
354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.SystemIDResolver;
364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.apache.xml.utils.TreeWalker;
374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.w3c.dom.Node;
394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.xml.sax.Attributes;
414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.xml.sax.InputSource;
424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.xml.sax.XMLReader;
434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonimport org.xml.sax.helpers.XMLReaderFactory;
444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson/**
464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * TransformerFactory class for xsl:include markup.
474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see <a href="http://www.w3.org/TR/xslt#dtd">XSLT DTD</a>
484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @see <a href="http://www.w3.org/TR/xslt#include">include in XSLT Specification</a>
494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson *
504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson * @xsl.usage internal
514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson */
524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilsonpublic class ProcessorInclude extends XSLTElementProcessor
534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson{
544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    static final long serialVersionUID = -4570078731972673481L;
554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * The base URL of the XSL document.
584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @serial
594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private String m_href = null;
614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the base identifier with which this stylesheet is associated.
644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return non-null reference to the href attribute string, or
664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *         null if setHref has not been called.
674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public String getHref()
694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return m_href;
714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the base identifier with which this stylesheet is associated.
754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param baseIdent Should be a non-null reference to a valid URL string.
774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void setHref(String baseIdent)
794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    // Validate?
814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    m_href = baseIdent;
824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the stylesheet type associated with an included stylesheet
864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the type of the stylesheet
884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected int getStylesheetType()
904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return StylesheetHandler.STYPE_INCLUDE;
924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the error number associated with this type of stylesheet including itself
964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the appropriate error number
984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected String getStylesheetInclErr()
1004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    return XSLTErrorResources.ER_STYLESHEET_INCLUDES_ITSELF;
1024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Receive notification of the start of an xsl:include element.
1064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param handler The calling StylesheetHandler/TemplatesBuilder.
1084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param uri The Namespace URI, or the empty string if the
1094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        element has no Namespace URI or if Namespace
1104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        processing is not being performed.
1114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param localName The local name (without prefix), or the
1124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        empty string if Namespace processing is not being
1134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        performed.
1144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param rawName The raw XML 1.0 name (with prefix), or the
1154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        empty string if raw names are not available.
1164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param attributes The attributes attached to the element.  If
1174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        there are no attributes, it shall be an empty
1184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *        Attributes object.
1194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws org.xml.sax.SAXException Any SAX exception, possibly
1214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *            wrapping another exception.
1224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  public void startElement(
1244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
1254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throws org.xml.sax.SAXException
1264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    setPropertiesFromAttributes(handler, rawName, attributes, this);
1304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try
1324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // Get the Source from the user's URIResolver (if any).
1354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      Source sourceFromURIResolver = getSourceFromUriResolver(handler);
1364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // Get the system ID of the included/imported stylesheet module
1374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      String hrefUrl = getBaseURIOfIncludedStylesheet(handler, sourceFromURIResolver);
1384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (handler.importStackContains(hrefUrl))
1404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
1414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        throw new org.xml.sax.SAXException(
1424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          XSLMessages.createMessage(
1434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          getStylesheetInclErr(), new Object[]{ hrefUrl }));  //"(StylesheetHandler) "+hrefUrl+" is directly or indirectly importing itself!");
1444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
1454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // Push the system ID and corresponding Source
1474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // on some stacks for later retrieval during parse() time.
1484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.pushImportURL(hrefUrl);
1494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.pushImportSource(sourceFromURIResolver);
1504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      int savedStylesheetType = handler.getStylesheetType();
1524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.setStylesheetType(this.getStylesheetType());
1544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.pushNewNamespaceSupport();
1554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      try
1574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
1584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        parse(handler, uri, localName, rawName, attributes);
1594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
1604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      finally
1614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
1624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        handler.setStylesheetType(savedStylesheetType);
1634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        handler.popImportURL();
1644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        handler.popImportSource();
1654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        handler.popNamespaceSupport();
1664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
1674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch(TransformerException te)
1694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.error(te.getMessage(), te);
1714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
1724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
1734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
1754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Set off a new parse for an included or imported stylesheet.  This will
1764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * set the {@link StylesheetHandler} to a new state, and recurse in with
1774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * a new set of parse events.  Once this function returns, the state of
1784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * the StylesheetHandler should be restored.
1794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param handler non-null reference to current StylesheetHandler that is constructing the Templates.
1814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param uri The Namespace URI, which should be the XSLT namespace.
1824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param localName The local name (without prefix), which should be "include" or "import".
1834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param rawName The qualified name (with prefix).
1844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param attributes The list of attributes on the xsl:include or xsl:import element.
1854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *
1864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @throws org.xml.sax.SAXException Any SAX exception, possibly
1874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   *            wrapping another exception.
1884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
1894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected void parse(
1904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes)
1914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throws org.xml.sax.SAXException
1924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
1934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    TransformerFactoryImpl processor = handler.getStylesheetProcessor();
1944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    URIResolver uriresolver = processor.getURIResolver();
1954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
1964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    try
1974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
1984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      Source source = null;
1994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // The base identifier, an aboslute URI
2014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // that is associated with the included/imported
2024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // stylesheet module is known in this method,
2034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // so this method does the pushing of the
2044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // base ID onto the stack.
2054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null != uriresolver)
2074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
2084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // There is a user provided URI resolver.
2094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // At the startElement() call we would
2104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // have tried to obtain a Source from it
2114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // which we now retrieve
2124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        source = handler.peekSourceFromURIResolver();
2134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (null != source && source instanceof DOMSource)
2154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        {
2164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          Node node = ((DOMSource)source).getNode();
2174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // There is a user provided URI resolver.
2194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // At the startElement() call we would
2204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // have already pushed the system ID, obtained
2214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // from either the source.getSystemId(), if non-null
2224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // or from SystemIDResolver.getAbsoluteURI() as a backup
2234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // which we now retrieve.
2244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          String systemId = handler.peekImportURL();
2254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // Push the absolute URI of the included/imported
2274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          // stylesheet module onto the stack.
2284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          if (systemId != null)
2294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              handler.pushBaseIndentifier(systemId);
2304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          TreeWalker walker = new TreeWalker(handler, new org.apache.xml.utils.DOM2Helper(), systemId);
2324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          try
2344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          {
2354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            walker.traverse(node);
2364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          }
2374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          catch(org.xml.sax.SAXException se)
2384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          {
2394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throw new TransformerException(se);
2404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          }
2414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          if (systemId != null)
2424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            handler.popBaseIndentifier();
2434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          return;
2444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
2454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
2464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(null == source)
2484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
2494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        String absURL = SystemIDResolver.getAbsoluteURI(getHref(),
2504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                          handler.getBaseIdentifier());
2514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        source = new StreamSource(absURL);
2534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
2544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      // possible callback to a class that over-rides this method.
2564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      source = processSource(handler, source);
2574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      XMLReader reader = null;
2594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if(source instanceof SAXSource)
2614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
2624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        SAXSource saxSource = (SAXSource)source;
2634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        reader = saxSource.getXMLReader(); // may be null
2644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
2654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      InputSource inputSource = SAXSource.sourceToInputSource(source);
2674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null == reader)
2694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
2704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // Use JAXP1.1 ( if possible )
2714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        try {
2724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          javax.xml.parsers.SAXParserFactory factory=
2734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                                                     javax.xml.parsers.SAXParserFactory.newInstance();
2744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          factory.setNamespaceAware( true );
2754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          if (handler.getStylesheetProcessor().isSecureProcessing())
2774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          {
2784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            try
2794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            {
2804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson              factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
2814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            }
2824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            catch (org.xml.sax.SAXException se) {}
2834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          }
2844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          javax.xml.parsers.SAXParser jaxpParser=
2864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                                                 factory.newSAXParser();
2874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          reader=jaxpParser.getXMLReader();
2884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
2894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        } catch( javax.xml.parsers.ParserConfigurationException ex ) {
2904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          throw new org.xml.sax.SAXException( ex );
2914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        } catch( javax.xml.parsers.FactoryConfigurationError ex1 ) {
2924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throw new org.xml.sax.SAXException( ex1.toString() );
2934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
2944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        catch( NoSuchMethodError ex2 )
2954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        {
2964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
2974c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        catch (AbstractMethodError ame){}
2984c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
2994c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null == reader)
3004c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        reader = XMLReaderFactory.createXMLReader();
3014c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3024c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      if (null != reader)
3034c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      {
3044c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        reader.setContentHandler(handler);
3054c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3064c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // Push the absolute URI of the included/imported
3074c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        // stylesheet module onto the stack.
3084c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        handler.pushBaseIndentifier(inputSource.getSystemId());
3094c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3104c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        try
3114c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        {
3124c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          reader.parse(inputSource);
3134c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
3144c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        finally
3154c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        {
3164c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson          handler.popBaseIndentifier();
3174c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
3184c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      }
3194c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3204c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch (IOException ioe)
3214c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
3224c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.error(XSLTErrorResources.ER_IOEXCEPTION,
3234c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    new Object[]{ getHref() }, ioe);
3244c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3254c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    catch(TransformerException te)
3264c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    {
3274c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      handler.error(te.getMessage(), te);
3284c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3294c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3304c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3314c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3324c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * This method does nothing, but a class that extends this class could
3334c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * over-ride it and do some processing of the source.
3344c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param handler The calling StylesheetHandler/TemplatesBuilder.
3354c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @param source The source of the included stylesheet.
3364c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * @return the same or an equivalent source to what was passed in.
3374c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3384c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  protected Source processSource(StylesheetHandler handler, Source source)
3394c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  {
3404c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson      return source;
3414c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  }
3424c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3434c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  /**
3444c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * Get the Source object for the included or imported stylesheet module
3454c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * obtained from the user's URIResolver, if there is no user provided
3464c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   * URIResolver null is returned.
3474c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson   */
3484c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson  private Source getSourceFromUriResolver(StylesheetHandler handler)
3494c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throws TransformerException {
3504c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        Source s = null;
3514c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            TransformerFactoryImpl processor = handler.getStylesheetProcessor();
3524c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            URIResolver uriresolver = processor.getURIResolver();
3534c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            if (uriresolver != null) {
3544c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                String href = getHref();
3554c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                String base = handler.getBaseIdentifier();
3564c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                s = uriresolver.resolve(href,base);
3574c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            }
3584c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3594c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return s;
3604c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3614c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3624c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    /**
3634c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * Get the base URI of the included or imported stylesheet,
3644c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * if the user provided a URIResolver, then get the Source
3654c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * object for the stylsheet from it, and get the systemId
3664c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * from that Source object, otherwise try to recover by
3674c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * using the SysteIDResolver to figure out the base URI.
3684c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param handler The handler that processes the stylesheet as SAX events,
3694c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * and maintains state
3704c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * @param s The Source object from a URIResolver, for the included stylesheet module,
3714c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     * so this will be null if there is no URIResolver set.
3724c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson     */
3734c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    private String getBaseURIOfIncludedStylesheet(StylesheetHandler handler, Source s)
3744c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            throws TransformerException {
3754c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3764c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3774c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3784c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        String baseURI;
3794c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        String idFromUriResolverSource;
3804c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        if (s != null && (idFromUriResolverSource = s.getSystemId()) != null) {
3814c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // We have a Source obtained from a users's URIResolver,
3824c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // and the system ID is set on it, so return that as the base URI
3834c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            baseURI = idFromUriResolverSource;
3844c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        } else {
3854c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // The user did not provide a URIResolver, or it did not
3864c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // return a Source for the included stylesheet module, or
3874c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // the Source has no system ID set, so we fall back to using
3884c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // the system ID Resolver to take the href and base
3894c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            // to generate the baseURI of the included stylesheet.
3904c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson            baseURI = SystemIDResolver.getAbsoluteURI(getHref(), handler
3914c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson                    .getBaseIdentifier());
3924c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        }
3934c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson
3944c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson        return baseURI;
3954c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson    }
3964c7a0d97cf2b27790e6236965a1d798d710d7ec7Jesse Wilson}
397