1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: TrAXFilter.java 468645 2006-10-28 06:57:24Z minchau $
20 */
21package org.apache.xalan.transformer;
22
23import java.io.IOException;
24
25import javax.xml.XMLConstants;
26import javax.xml.transform.ErrorListener;
27import javax.xml.transform.Templates;
28import javax.xml.transform.TransformerConfigurationException;
29
30import org.apache.xalan.res.XSLMessages;
31import org.apache.xalan.res.XSLTErrorResources;
32
33import org.xml.sax.ContentHandler;
34import org.xml.sax.DTDHandler;
35import org.xml.sax.EntityResolver;
36import org.xml.sax.InputSource;
37import org.xml.sax.XMLReader;
38import org.xml.sax.helpers.XMLFilterImpl;
39import org.xml.sax.helpers.XMLReaderFactory;
40
41
42public class TrAXFilter extends XMLFilterImpl
43{
44  private Templates m_templates;
45  private TransformerImpl m_transformer;
46
47  /**
48   * Construct an empty XML filter, with no parent.
49   *
50   * <p>This filter will have no parent: you must assign a parent
51   * before you start a parse or do any configuration with
52   * setFeature or setProperty.</p>
53   *
54   * @see org.xml.sax.XMLReader#setFeature
55   * @see org.xml.sax.XMLReader#setProperty
56   */
57  public TrAXFilter (Templates templates)
58    throws TransformerConfigurationException
59  {
60    m_templates = templates;
61    m_transformer = (TransformerImpl)templates.newTransformer();
62  }
63
64  /**
65   * Return the Transformer object used for this XML filter.
66   */
67  public TransformerImpl getTransformer()
68  {
69    return m_transformer;
70  }
71
72  /** Set the parent reader.
73   *
74   * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which
75   * this filter will obtain its events and to which it will pass its
76   * configuration requests.  The parent may itself be another filter.</p>
77   *
78   * <p>If there is no parent reader set, any attempt to parse
79   * or to set or get a feature or property will fail.</p>
80   *
81   * @param parent The parent XML reader.
82   * @throws java.lang.NullPointerException If the parent is null.
83   */
84  public void setParent (XMLReader parent)
85  {
86    super.setParent(parent);
87
88    if(null != parent.getContentHandler())
89      this.setContentHandler(parent.getContentHandler());
90
91    // Not really sure if we should do this here, but
92    // it seems safer in case someone calls parse() on
93    // the parent.
94    setupParse ();
95  }
96
97  /**
98   * Parse a document.
99   *
100   * @param input The input source for the document entity.
101   * @throws org.xml.sax.SAXException Any SAX exception, possibly
102   *            wrapping another exception.
103   * @throws java.io.IOException An IO exception from the parser,
104   *            possibly from a byte stream or character stream
105   *            supplied by the application.
106   * @see org.xml.sax.XMLReader#parse(org.xml.sax.InputSource)
107   */
108  public void parse (InputSource input)
109    throws org.xml.sax.SAXException, IOException
110  {
111    if(null == getParent())
112    {
113      XMLReader reader=null;
114
115      // Use JAXP1.1 ( if possible )
116      try {
117          javax.xml.parsers.SAXParserFactory factory=
118              javax.xml.parsers.SAXParserFactory.newInstance();
119          factory.setNamespaceAware( true );
120
121          if (m_transformer.getStylesheet().isSecureProcessing()) {
122              try {
123                  factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
124              }
125              catch (org.xml.sax.SAXException se) {}
126          }
127
128          javax.xml.parsers.SAXParser jaxpParser=
129              factory.newSAXParser();
130          reader=jaxpParser.getXMLReader();
131
132      } catch( javax.xml.parsers.ParserConfigurationException ex ) {
133          throw new org.xml.sax.SAXException( ex );
134      } catch( javax.xml.parsers.FactoryConfigurationError ex1 ) {
135          throw new org.xml.sax.SAXException( ex1.toString() );
136      } catch( NoSuchMethodError ex2 ) {
137      }
138      catch (AbstractMethodError ame){}
139
140      XMLReader parent;
141      if( reader==null )
142          parent= XMLReaderFactory.createXMLReader();
143      else
144          parent=reader;
145      try
146      {
147        parent.setFeature("http://xml.org/sax/features/namespace-prefixes",
148                          true);
149      }
150      catch (org.xml.sax.SAXException se){}
151      // setParent calls setupParse...
152      setParent(parent);
153    }
154    else
155    {
156      // Make sure everything is set up.
157      setupParse ();
158    }
159    if(null == m_transformer.getContentHandler())
160    {
161      throw new org.xml.sax.SAXException(XSLMessages.createMessage(XSLTErrorResources.ER_CANNOT_CALL_PARSE, null)); //"parse can not be called if the ContentHandler has not been set!");
162    }
163
164    getParent().parse(input);
165    Exception e = m_transformer.getExceptionThrown();
166    if(null != e)
167    {
168      if(e instanceof org.xml.sax.SAXException)
169        throw (org.xml.sax.SAXException)e;
170      else
171        throw new org.xml.sax.SAXException(e);
172    }
173  }
174
175  /**
176   * Parse a document.
177   *
178   * @param systemId The system identifier as a fully-qualified URI.
179   * @throws org.xml.sax.SAXException Any SAX exception, possibly
180   *            wrapping another exception.
181   * @throws java.io.IOException An IO exception from the parser,
182   *            possibly from a byte stream or character stream
183   *            supplied by the application.
184   * @see org.xml.sax.XMLReader#parse(java.lang.String)
185   */
186  public void parse (String systemId)
187    throws org.xml.sax.SAXException, IOException
188  {
189    parse(new InputSource(systemId));
190  }
191
192
193  /**
194   * Set up before a parse.
195   *
196   * <p>Before every parse, check whether the parent is
197   * non-null, and re-register the filter for all of the
198   * events.</p>
199   */
200  private void setupParse ()
201  {
202    XMLReader p = getParent();
203    if (p == null) {
204      throw new NullPointerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_PARENT_FOR_FILTER, null)); //"No parent for filter");
205    }
206
207    ContentHandler ch = m_transformer.getInputContentHandler();
208//    if(ch instanceof SourceTreeHandler)
209//      ((SourceTreeHandler)ch).setUseMultiThreading(true);
210    p.setContentHandler(ch);
211    p.setEntityResolver(this);
212    p.setDTDHandler(this);
213    p.setErrorHandler(this);
214  }
215
216  /**
217   * Set the content event handler.
218   *
219   * @param handler The new content handler.
220   * @throws java.lang.NullPointerException If the handler
221   *            is null.
222   * @see org.xml.sax.XMLReader#setContentHandler
223   */
224  public void setContentHandler (ContentHandler handler)
225  {
226    m_transformer.setContentHandler(handler);
227    // super.setContentHandler(m_transformer.getResultTreeHandler());
228  }
229
230  public void setErrorListener (ErrorListener handler)
231  {
232    m_transformer.setErrorListener(handler);
233  }
234
235}
236