KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > om > Builder


1 package com.icl.saxon.om;
2 import com.icl.saxon.Controller;
3 import com.icl.saxon.expr.*;
4 import com.icl.saxon.ContentEmitter;
5 import com.icl.saxon.PreviewManager;
6 import com.icl.saxon.ExtendedInputSource;
7 import com.icl.saxon.output.Emitter;
8
9 import org.xml.sax.*;
10
11 import javax.xml.parsers.SAXParserFactory JavaDoc;
12 import javax.xml.transform.TransformerException JavaDoc;
13 import javax.xml.transform.SourceLocator JavaDoc;
14 import javax.xml.transform.ErrorListener JavaDoc;
15 import javax.xml.transform.sax.SAXSource JavaDoc;
16
17 import java.util.*;
18 import java.io.*;
19 import java.net.URL JavaDoc;
20
21 /**
22   * The abstract Builder class is responsible for taking a stream of SAX events
23   * and constructing a Document tree. There is one concrete subclass for each
24   * tree implementation.
25   * @author Michael H. Kay (mhkay@iclway.co.uk)
26   */

27   
28 public abstract class Builder extends Emitter
29                     implements ErrorHandler, Locator JavaDoc, SourceLocator JavaDoc
30
31 {
32     public final static int STANDARD_TREE = 0;
33     public final static int TINY_TREE = 1;
34
35     //protected static int nextSequenceNr = 0;
36
protected int estimatedLength; // Estimated size of document in bytes
37
//TODO: currently not used
38
protected Writer errorOutput = new PrintWriter(System.err);
39                                                   // Destination for error messages
40
protected Stripper stripper; // manages list of elements to be stripped
41
protected PreviewManager previewManager = null;
42     protected boolean discardComments; // true if comments and PIs should be ignored
43

44     protected DocumentInfo currentDocument;
45     protected ErrorHandler errorHandler = this; // SAX-compliant XML error handler
46
protected ErrorListener JavaDoc errorListener = null; // JAXP-compliant XSLT error handler
47

48     protected boolean failed = false;
49     protected boolean started = false;
50     protected boolean timing = false;
51
52     protected boolean inDTD = false;
53     protected boolean lineNumbering = false;
54     protected int lineNumber = -1;
55     protected int columnNumber = -1;
56     
57     private long startTime;
58     
59     protected Controller controller;
60     
61     public void setController(Controller c) {
62         controller = c;
63     }
64
65     /**
66     * create a Builder and initialise variables
67     */

68
69     public Builder() {}
70
71     /////////////////////////////////////////////////////////////////////////
72
// Methods setting and getting options for building the tree
73
/////////////////////////////////////////////////////////////////////////
74

75     /**
76     * Set the root (document) node to use. This method is used to support
77     * the JAXP facility to attach transformation output to a supplied Document
78     * node. It must be called before startDocument(), and the type of document
79     * node must be compatible with the type of Builder used.
80     */

81     
82     public void setRootNode(DocumentInfo doc) {
83         currentDocument = doc;
84     }
85         
86
87     /**
88     * Set timing option on or off
89     */

90
91     public void setTiming(boolean on) {
92         timing = on;
93     }
94
95     /**
96     * Get timing option
97     */

98
99     public boolean isTiming() {
100         return timing;
101     }
102
103     /**
104     * Set line numbering on or off
105     */

106
107     public void setLineNumbering(boolean onOrOff) {
108         lineNumbering = onOrOff;
109     }
110
111     /**
112     * Set the Stripper to use
113     */

114
115     public void setStripper(Stripper s) {
116         stripper = s;
117     }
118
119     /**
120     * Get the Stripper in use
121     */

122
123     public Stripper getStripper() {
124         return stripper;
125     }
126
127     /**
128     * Set the PreviewManager to use
129     */

130
131     public void setPreviewManager(PreviewManager pm) {
132         previewManager = pm;
133     }
134
135
136     /**
137     * Indicate whether comments and Processing Instructions should be discarded
138     * @params discard true if comments and PIs are to be discarded, false if
139     * they are to be added to the tree
140     */

141
142     public void setDiscardCommentsAndPIs(boolean discard) {
143         discardComments = discard;
144     }
145
146     /**
147     * Set the SAX error handler to use. If none is specified, SAXON supplies its own,
148     * which writes error messages to the selected error output writer.
149     * @param eh The error handler to use. It must conform to the interface
150     * org.xml.sax.ErrorHandler
151     */

152
153     public void setErrorHandler(ErrorHandler eh) {
154         this.errorHandler = eh;
155     }
156
157     /**
158     * Set the JAXP error listener to use, if no SAX errorHandler has been provided.
159     * @param eh The error listener to use. It must conform to the interface
160     * javax.xml.transform.ErrorListener
161     */

162
163     public void setErrorListener(ErrorListener JavaDoc eh) {
164         this.errorListener = eh;
165     }
166
167     /**
168     * Set output for error messages produced by the default error handler.<BR>
169     * The default error handler does not throw an exception
170     * for parse errors or input I/O errors, rather it returns a result code and
171     * writes diagnostics to a user-specified output writer, which defaults to
172     * System.err<BR>
173     * This call has no effect if setErrorHandler() has been called to supply a
174     * user-defined error handler
175     * @param writer The Writer to use for error messages
176     */

177
178     public void setErrorOutput(Writer writer) {
179         errorOutput = writer;
180     }
181
182     /**
183     * Build the tree from an input source. After building the tree, it can
184     * be walked as often as required using run(Document doc).
185     * @param source The source to use. SAXSource is a SAX-defined class that
186     * allows input from a URL, a byte stream, or a character stream. SAXON also
187     * provides a subclass, ExtendedInputSource, that allows input directly from a File.
188     * @return The DocumentInfo object that results from parsing the input.
189     * @throws TransformerException if the input document could not be read or if it was not parsed
190     * correctly.
191     */

192
193     public DocumentInfo build(SAXSource JavaDoc source) throws TransformerException JavaDoc
194     {
195         InputSource in = source.getInputSource();
196         XMLReader parser = source.getXMLReader();
197
198         // System.err.println("Builder " + this + " build using parser " + parser);
199
if (timing) {
200             System.err.println("Building tree for " + in.getSystemId() + " using " + getClass());
201             startTime = (new Date()).getTime();
202         }
203
204         failed = true; // until startDocument() called
205
started = false;
206         if (source.getSystemId() != null) {
207             setSystemId(source.getSystemId());
208         } else {
209             setSystemId(in.getSystemId());
210         }
211
212         if (in instanceof ExtendedInputSource) {
213             estimatedLength = ((ExtendedInputSource)in).getEstimatedLength();
214             if (estimatedLength < 1) estimatedLength = 4096;
215             if (estimatedLength > 1000000) estimatedLength = 1000000;
216         } else {
217             estimatedLength = 4096;
218         }
219
220         // parse the document
221

222         if (parser==null) {
223             try {
224                 parser = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
225                 // This is a fallback, it shouldn't happen
226
} catch (Exception JavaDoc err) {
227                 throw new TransformerException JavaDoc(err);
228             }
229         }
230
231         ContentEmitter ce = new ContentEmitter();
232         ce.setNamePool(namePool);
233         parser.setContentHandler(ce);
234         parser.setDTDHandler(ce);
235         parser.setErrorHandler(errorHandler);
236
237         if (!discardComments) {
238             try {
239                 parser.setProperty("http://xml.org/sax/properties/lexical-handler", ce);
240             } catch (SAXNotSupportedException err) { // this just means we won't see the comments
241
} catch (SAXNotRecognizedException err) {
242             }
243         }
244
245         if (stripper!=null) {
246             ce.setEmitter(stripper);
247             stripper.setUnderlyingEmitter(this);
248         } else {
249             ce.setEmitter(this);
250         }
251
252         try {
253             parser.setFeature("http://xml.org/sax/features/namespaces", true);
254             parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
255         } catch (SAXNotSupportedException err) { // SAX2 parsers MUST support this feature!
256
throw new TransformerException JavaDoc(
257                 "The SAX2 parser does not recognize a required namespace feature");
258         } catch (SAXNotRecognizedException err) {
259             throw new TransformerException JavaDoc(
260                 "The SAX2 parser does not support a required namespace feature");
261         }
262
263
264         try {
265             parser.parse(in);
266         } catch (java.io.IOException JavaDoc err1) {
267             throw new TransformerException JavaDoc("Failure reading " + in.getSystemId(), err1);
268         } catch (SAXException err2) {
269             Exception JavaDoc wrapped = err2.getException();
270             if (wrapped != null && wrapped instanceof TransformerException JavaDoc) {
271                 throw (TransformerException JavaDoc)wrapped;
272             }
273             throw new TransformerException JavaDoc(err2);
274         }
275             
276
277         if (!started) {
278             // System.err.println("Builder " + this + " failed");
279
throw new TransformerException JavaDoc("Source document not supplied");
280         }
281
282         if (failed) {
283             // System.err.println("Builder " + this + " failed");
284
throw new TransformerException JavaDoc("XML Parsing failed");
285         }
286
287         if (timing) {
288             long endTime = (new Date()).getTime();
289             System.err.println("Tree built in " + (endTime-startTime) + " milliseconds");
290             startTime = endTime;
291         }
292
293         return currentDocument;
294     }
295
296     /**
297     * Get the current document
298     * @return the document that has been most recently built using this builder
299     */

300
301     public DocumentInfo getCurrentDocument() {
302         return currentDocument;
303     }
304
305     ////////////////////////////////////////////////////////////////////////////
306
// Implement the org.xml.sax.ErrorHandler interface.
307
// The user can supply an alternative implementation using setErrorHandler()
308
////////////////////////////////////////////////////////////////////////////
309

310     /**
311     * Callback interface for SAX: not for application use
312     */

313
314     public void warning (SAXParseException e) {
315         if (errorListener != null) {
316             try {
317                 errorListener.warning(new TransformerException JavaDoc(e));
318             } catch (Exception JavaDoc err) {}
319         }
320     }
321
322     /**
323     * Callback interface for SAX: not for application use
324     */

325
326     public void error (SAXParseException e) throws SAXException {
327         reportError(e, false);
328         failed = true;
329     }
330
331     /**
332     * Callback interface for SAX: not for application use
333     */

334     
335     public void fatalError (SAXParseException e) throws SAXException {
336         reportError(e, true);
337         failed = true;
338         throw e;
339     }
340
341     /**
342     * Common routine for errors and fatal errors
343     */

344
345     protected void reportError (SAXParseException e, boolean isFatal) {
346         
347         if (errorListener != null) {
348             try {
349                 systemId = e.getSystemId();
350                 lineNumber = e.getLineNumber();
351                 columnNumber = e.getColumnNumber();
352                 TransformerException JavaDoc err =
353                     new TransformerException JavaDoc("Error reported by XML parser", this, e);
354                 if (isFatal) {
355                     errorListener.fatalError(err);
356                 } else {
357                     errorListener.error(err);
358                 }
359             } catch (Exception JavaDoc err) {}
360         } else {
361             
362             try {
363                 String JavaDoc errcat = (isFatal ? "Fatal error" : "Error");
364                 errorOutput.write(errcat + " reported by XML parser: " + e.getMessage() + "\n");
365                 errorOutput.write(" URL: " + e.getSystemId() + "\n");
366                 errorOutput.write(" Line: " + e.getLineNumber() + "\n");
367                 errorOutput.write(" Column: " + e.getColumnNumber() + "\n");
368                 errorOutput.flush();
369             } catch (Exception JavaDoc e2) {
370                 System.err.println(e);
371                 System.err.println(e2);
372                 e2.printStackTrace();
373             };
374         }
375     }
376
377
378
379     /**
380     * Set the URI for an unparsed entity in the document.
381     * Abstract method to be implemented in each subclass.
382     */

383
384     public abstract void setUnparsedEntity(String JavaDoc name, String JavaDoc uri);
385
386
387     //////////////////////////////////////////////////////////////////////////////
388
// Implement Locator interface (default implementation)
389
//////////////////////////////////////////////////////////////////////////////
390

391     //public void setSystemId(String uri) {
392
// baseURI = uri;
393
//}
394

395     //public String getSystemId() {
396
// return baseURI;
397
//}
398

399     public String JavaDoc getPublicId() {
400         return null;
401     }
402
403     public int getLineNumber() {
404         return lineNumber;
405     }
406
407     public int getColumnNumber() {
408         return columnNumber;
409     }
410
411
412 } // end of outer class Builder
413

414 //
415
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
416
// you may not use this file except in compliance with the License. You may obtain a copy of the
417
// License at http://www.mozilla.org/MPL/
418
//
419
// Software distributed under the License is distributed on an "AS IS" basis,
420
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
421
// See the License for the specific language governing rights and limitations under the License.
422
//
423
// The Original Code is: all this file.
424
//
425
// The Initial Developer of the Original Code is
426
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
427
//
428
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
429
//
430
// Contributor(s): none.
431
//
432
Popular Tags