001: package net.sf.saxon;
002:
003: import net.sf.saxon.event.ContentHandlerProxy;
004: import org.xml.sax.*;
005: import org.xml.sax.ext.LexicalHandler;
006:
007: import javax.xml.parsers.SAXParserFactory;
008: import javax.xml.transform.Transformer;
009: import javax.xml.transform.TransformerException;
010: import javax.xml.transform.sax.SAXSource;
011: import java.io.IOException;
012:
013: /**
014: * <B>Filter</B> is an XMLFilter (a SAX2 filter) that performs a transformation
015: * taking a SAX stream as input and producing a SAX stream as output.
016: * @author Michael H. Kay
017: */
018:
019: public class Filter implements XMLFilter {
020:
021: private Controller controller;
022: private XMLReader parser;
023: private ContentHandler contentHandler; // destination for output of this filter
024: private LexicalHandler lexicalHandler; // destination for output of this filter
025:
026: /**
027: * Create a Filter and initialise variables. The constructor is protected, because
028: * the Filter should be created using newXMLFilter() in the SAXTransformerFactory
029: * class
030: */
031:
032: protected Filter(Controller controller) {
033: this .controller = controller;
034: }
035:
036: //////////////////////////////////////////////////////////////////
037: // Implement XMLFilter interface methods
038: //////////////////////////////////////////////////////////////////
039:
040: /**
041: * Set the parent reader.
042: *
043: * <p>This method allows the application to link the filter to
044: * a parent reader (which may be another filter). The argument
045: * may not be null.</p>
046: *
047: * @param parent The parent reader (the supplier of SAX events).
048: */
049:
050: public void setParent(XMLReader parent) {
051: parser = parent;
052: }
053:
054: /**
055: * Get the parent reader.
056: *
057: * <p>This method allows the application to query the parent
058: * reader (which may be another filter). It is generally a
059: * bad idea to perform any operations on the parent reader
060: * directly: they should all pass through this filter.</p>
061: *
062: * @return The parent filter, or null if none has been set.
063: */
064:
065: public XMLReader getParent() {
066: return parser;
067: }
068:
069: ///////////////////////////////////////////////////////////////////
070: // implement XMLReader interface methods
071: ///////////////////////////////////////////////////////////////////
072:
073: /**
074: * Look up the value of a feature.
075: *
076: * <p>The feature name is any fully-qualified URI. It is
077: * possible for an XMLReader to recognize a feature name but
078: * to be unable to return its value; this is especially true
079: * in the case of an adapter for a SAX1 Parser, which has
080: * no way of knowing whether the underlying parser is
081: * performing validation or expanding external entities.</p>
082: *
083: * <p>All XMLReaders are required to recognize the
084: * http://xml.org/sax/features/namespaces and the
085: * http://xml.org/sax/features/namespace-prefixes feature names.</p>
086: *
087: * @param name The feature name, which is a fully-qualified URI.
088: * @return The current state of the feature (true or false).
089: * @exception org.xml.sax.SAXNotRecognizedException When the
090: * XMLReader does not recognize the feature name.
091: * @exception org.xml.sax.SAXNotSupportedException When the
092: * XMLReader recognizes the feature name but
093: * cannot determine its value at this time.
094: * @see #setFeature
095: */
096:
097: public boolean getFeature(String name)
098: throws SAXNotRecognizedException, SAXNotSupportedException {
099: if (name.equals("http://xml.org/sax/features/namespaces")) {
100: return true;
101: } else if (name
102: .equals("http://xml.org/sax/features/namespace-prefixes")) {
103: return false;
104: } else {
105: throw new SAXNotRecognizedException(name);
106: }
107: }
108:
109: /**
110: * Set the state of a feature.
111: *
112: * <p>The feature name is any fully-qualified URI. It is
113: * possible for an XMLReader to recognize a feature name but
114: * to be unable to set its value</p>
115: *
116: * <p>All XMLReaders are required to support setting
117: * http://xml.org/sax/features/namespaces to true and
118: * http://xml.org/sax/features/namespace-prefixes to false.</p>
119: *
120: * <p>Some feature values may be immutable or mutable only
121: * in specific contexts, such as before, during, or after
122: * a parse.</p>
123: *
124: * @param name The feature name, which is a fully-qualified URI.
125: * @param value The requested state of the feature (true or false).
126: * @exception org.xml.sax.SAXNotRecognizedException When the
127: * XMLReader does not recognize the feature name.
128: * @exception org.xml.sax.SAXNotSupportedException When the
129: * XMLReader recognizes the feature name but
130: * cannot set the requested value.
131: * @see #getFeature
132: */
133:
134: public void setFeature(String name, boolean value)
135: throws SAXNotRecognizedException, SAXNotSupportedException {
136: if (name.equals("http://xml.org/sax/features/namespaces")) {
137: if (!value) {
138: throw new SAXNotSupportedException(name);
139: }
140: } else if (name
141: .equals("http://xml.org/sax/features/namespace-prefixes")) {
142: if (value) {
143: throw new SAXNotSupportedException(name);
144: }
145: } else {
146: throw new SAXNotRecognizedException(name);
147: }
148: }
149:
150: /**
151: * Look up the value of a property.
152: *
153: * <p>The property name is any fully-qualified URI. It is
154: * possible for an XMLReader to recognize a property name but
155: * to be unable to return its state.</p>
156: *
157: * <p>XMLReaders are not required to recognize any specific
158: * property names, though an initial core set is documented for
159: * SAX2.</p>
160: *
161: * <p>Some property values may be available only in specific
162: * contexts, such as before, during, or after a parse.</p>
163: *
164: * <p>Implementors are free (and encouraged) to invent their own properties,
165: * using names built on their own URIs.</p>
166: *
167: * @param name The property name, which is a fully-qualified URI.
168: * @return The current value of the property.
169: * @exception org.xml.sax.SAXNotRecognizedException When the
170: * XMLReader does not recognize the property name.
171: * @exception org.xml.sax.SAXNotSupportedException When the
172: * XMLReader recognizes the property name but
173: * cannot determine its value at this time.
174: * @see #setProperty
175: */
176:
177: public Object getProperty(String name)
178: throws SAXNotRecognizedException, SAXNotSupportedException {
179: if (name
180: .equals("http://xml.org/sax/properties/lexical-handler")) {
181: return lexicalHandler;
182: } else {
183: throw new SAXNotRecognizedException(name);
184: }
185: }
186:
187: /**
188: * Set the value of a property.
189: *
190: * <p>The property name is any fully-qualified URI. It is
191: * possible for an XMLReader to recognize a property name but
192: * to be unable to set its value.</p>
193: *
194: * <p>XMLReaders are not required to recognize setting
195: * any specific property names, though a core set is provided with
196: * SAX2.</p>
197: *
198: * <p>Some property values may be immutable or mutable only
199: * in specific contexts, such as before, during, or after
200: * a parse.</p>
201: *
202: * <p>This method is also the standard mechanism for setting
203: * extended handlers.</p>
204: *
205: * @param name The property name, which is a fully-qualified URI.
206: * @param value The requested value for the property.
207: * @exception org.xml.sax.SAXNotRecognizedException When the
208: * XMLReader does not recognize the property name.
209: * @exception org.xml.sax.SAXNotSupportedException When the
210: * XMLReader recognizes the property name but
211: * cannot set the requested value.
212: */
213:
214: public void setProperty(String name, Object value)
215: throws SAXNotRecognizedException, SAXNotSupportedException {
216: if (name
217: .equals("http://xml.org/sax/properties/lexical-handler")) {
218: if (value instanceof LexicalHandler) {
219: lexicalHandler = (LexicalHandler) value;
220: } else {
221: throw new SAXNotSupportedException(
222: "Lexical Handler must be instance of org.xml.sax.ext.LexicalHandler");
223: }
224: } else {
225: throw new SAXNotRecognizedException(name);
226: }
227: }
228:
229: /**
230: * Register a content handler to receive the output of the transformation
231: * filter. If the content handler is also a LexicalHandler, and if no LexicalHandler
232: * is separately registered, the ContentHandler will also act as the LexicalHandler
233: */
234:
235: public void setContentHandler(ContentHandler handler) {
236: contentHandler = handler;
237: if (handler instanceof LexicalHandler && lexicalHandler == null) {
238: lexicalHandler = (LexicalHandler) handler;
239: }
240: }
241:
242: /**
243: * Get the ContentHandler registered using setContentHandler()
244: */
245:
246: public ContentHandler getContentHandler() {
247: return contentHandler;
248: }
249:
250: /**
251: * Allow an application to register an entity resolver.
252: *
253: * <p>If the application does not register an entity resolver,
254: * the XMLReader will perform its own default resolution.</p>
255: *
256: * <p>Applications may register a new or different resolver in the
257: * middle of a parse, and the SAX parser must begin using the new
258: * resolver immediately.</p>
259: *
260: * @param resolver The entity resolver.
261: * @exception java.lang.NullPointerException If the resolver
262: * argument is null.
263: * @see #getEntityResolver
264: */
265:
266: public void setEntityResolver(EntityResolver resolver) {
267: // XSLT output does not use entities, so the resolver is never used
268: }
269:
270: /**
271: * Return the current entity resolver.
272: *
273: * @return Always null, since no entity resolver is used even if one
274: * is supplied.
275: * @see #setEntityResolver
276: */
277:
278: public EntityResolver getEntityResolver() {
279: return null;
280: }
281:
282: /**
283: * Allow an application to register a DTD event handler.
284: *
285: * <p>If the application does not register a DTD handler, all DTD
286: * events reported by the SAX parser will be silently ignored.</p>
287: *
288: * <p>Applications may register a new or different handler in the
289: * middle of a parse, and the SAX parser must begin using the new
290: * handler immediately.</p>
291: *
292: * @param handler The DTD handler.
293: * @exception java.lang.NullPointerException If the handler
294: * argument is null.
295: * @see #getDTDHandler
296: */
297:
298: public void setDTDHandler(DTDHandler handler) {
299: // XSLT output does not include a DTD
300: }
301:
302: /**
303: * Return the current DTD handler.
304: *
305: * @return Always null, since no DTD handler is used even if one has been
306: * supplied.
307: * @see #setDTDHandler
308: */
309:
310: public DTDHandler getDTDHandler() {
311: return null;
312: }
313:
314: /**
315: * Allow an application to register an error event handler.
316: *
317: * <p>If the application does not register an error handler, all
318: * error events reported by the SAX parser will be silently
319: * ignored; however, normal processing may not continue. It is
320: * highly recommended that all SAX applications implement an
321: * error handler to avoid unexpected bugs.</p>
322: *
323: * <p>Applications may register a new or different handler in the
324: * middle of a parse, and the SAX parser must begin using the new
325: * handler immediately.</p>
326: *
327: * @param handler The error handler.
328: * @exception java.lang.NullPointerException If the handler
329: * argument is null.
330: * @see #getErrorHandler
331: */
332:
333: public void setErrorHandler(ErrorHandler handler) {
334: // No effect
335: }
336:
337: /**
338: * Return the current error handler.
339: *
340: * @return The current error handler, or null if none
341: * has been registered.
342: * @see #setErrorHandler
343: */
344: public ErrorHandler getErrorHandler() {
345: return null;
346: }
347:
348: /**
349: * Parse an XML document - In the context of a Transformer, this means
350: * perform a transformation. The method is equivalent to transform().
351: *
352: * @param input The input source (the XML document to be transformed)
353: * @exception org.xml.sax.SAXException Any SAX exception, possibly
354: * wrapping another exception.
355: * @exception java.io.IOException An IO exception from the parser,
356: * possibly from a byte stream or character stream
357: * supplied by the application.
358: * @see org.xml.sax.InputSource
359: * @see #parse(java.lang.String)
360: * @see #setEntityResolver
361: * @see #setDTDHandler
362: * @see #setContentHandler
363: * @see #setErrorHandler
364: */
365:
366: public void parse(InputSource input) throws IOException,
367: SAXException {
368: if (parser == null) {
369: try {
370: parser = SAXParserFactory.newInstance().newSAXParser()
371: .getXMLReader();
372: } catch (Exception err) {
373: throw new SAXException(err);
374: }
375: }
376: SAXSource source = new SAXSource();
377: source.setInputSource(input);
378: source.setXMLReader(parser);
379: ContentHandlerProxy result = new ContentHandlerProxy();
380: result.setPipelineConfiguration(controller
381: .makePipelineConfiguration());
382: result.setUnderlyingContentHandler(contentHandler);
383: if (lexicalHandler != null) {
384: result.setLexicalHandler(lexicalHandler);
385: }
386: try {
387: controller.transform(source, result);
388: } catch (TransformerException err) {
389: Throwable cause = err.getException();
390: if (cause != null && cause instanceof SAXException) {
391: throw (SAXException) cause;
392: } else if (cause != null && cause instanceof IOException) {
393: throw (IOException) cause;
394: } else {
395: throw new SAXException(err);
396: }
397: }
398:
399: }
400:
401: /**
402: * Parse (that is, transform) an XML document given a system identifier (URI).
403: *
404: * <p>This method is a shortcut for the common case of reading a
405: * document from a system identifier. It is the exact
406: * equivalent of the following:</p>
407: *
408: * <pre>
409: * parse(new InputSource(systemId));
410: * </pre>
411: *
412: * <p>If the system identifier is a URL, it must be fully resolved
413: * by the application before it is passed to the parser.</p>
414: *
415: * @param systemId The system identifier (URI).
416: * @exception org.xml.sax.SAXException Any SAX exception, possibly
417: * wrapping another exception.
418: * @exception java.io.IOException An IO exception from the parser,
419: * possibly from a byte stream or character stream
420: * supplied by the application.
421: * @see #parse(org.xml.sax.InputSource)
422: */
423:
424: public void parse(String systemId) throws IOException, SAXException {
425: InputSource input = new InputSource(systemId);
426: parse(input);
427: }
428:
429: /**
430: * Get the underlying Transformer. This is a Saxon-specific method that allows the
431: * user to set parameters on the transformation, set a URIResolver or ErrorListener, etc.
432: * New in Saxon 7.2
433: */
434:
435: public Transformer getTransformer() {
436: return controller;
437: }
438:
439: }
440:
441: //
442: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
443: // you may not use this file except in compliance with the License. You may obtain a copy of the
444: // License at http://www.mozilla.org/MPL/
445: //
446: // Software distributed under the License is distributed on an "AS IS" basis,
447: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
448: // See the License for the specific language governing rights and limitations under the License.
449: //
450: // The Original Code is: all this file.
451: //
452: // The Initial Developer of the Original Code is Michael H. Kay.
453: //
454: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
455: //
456: // Contributor(s): None
457: //
|