KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > Emitter


1 package net.sf.saxon.event;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.Controller;
4 import net.sf.saxon.charcode.CharacterSet;
5 import net.sf.saxon.charcode.CharacterSetFactory;
6 import net.sf.saxon.charcode.PluggableCharacterSet;
7 import net.sf.saxon.charcode.UnicodeCharacterSet;
8 import net.sf.saxon.om.NamePool;
9 import net.sf.saxon.trans.DynamicError;
10 import net.sf.saxon.trans.XPathException;
11 import org.xml.sax.ContentHandler JavaDoc;
12
13 import javax.xml.transform.OutputKeys JavaDoc;
14 import javax.xml.transform.Result JavaDoc;
15 import javax.xml.transform.TransformerException JavaDoc;
16 import javax.xml.transform.stream.StreamResult JavaDoc;
17 import java.io.*;
18 import java.net.URI JavaDoc;
19 import java.net.URISyntaxException JavaDoc;
20 import java.util.Properties JavaDoc;
21
22
23 /**
24   * Emitter: This abstract class defines methods that must be implemented by
25   * components that format SAXON output. There is one emitter for XML,
26   * one for HTML, and so on. Additional methods are concerned with
27   * setting options and providing a Writer.<p>
28   *
29   * The interface is deliberately designed to be as close as possible to the
30   * standard SAX2 ContentHandler interface, however, it allows additional
31   * information to be made available.
32   *
33   * An Emitter is a Receiver, specifically it is a Receiver that can direct output
34   * to a Writer or OutputStream, using serialization properties defined in a Properties
35   * object.
36   */

37
38 public abstract class Emitter implements Result JavaDoc, Receiver
39 {
40     protected PipelineConfiguration pipelineConfig;
41     protected NamePool namePool;
42     protected String JavaDoc systemId;
43     protected StreamResult JavaDoc streamResult;
44     protected Writer writer;
45     protected OutputStream outputStream;
46     protected Properties JavaDoc outputProperties;
47     protected CharacterSet characterSet = null;
48
49     /**
50     * Set the namePool in which all name codes can be found
51     */

52
53     public void setPipelineConfiguration(PipelineConfiguration config) {
54         this.pipelineConfig = config;
55         this.namePool = config.getConfiguration().getNamePool();
56     }
57
58     /**
59     * Get the pipeline configuration used for this document
60     */

61
62     public PipelineConfiguration getPipelineConfiguration() {
63         return pipelineConfig;
64     }
65
66     /**
67     * Get the configuration used for this document
68     */

69
70     public Configuration getConfiguration() {
71         return pipelineConfig.getConfiguration();
72     }
73
74     /**
75     * Set the System ID
76     */

77
78     public void setSystemId(String JavaDoc systemId) {
79         this.systemId = systemId;
80     }
81
82     /**
83     * Get the System ID
84     */

85
86     public String JavaDoc getSystemId() {
87         return systemId;
88     }
89
90     /**
91     * Set output properties
92     */

93
94     public void setOutputProperties(Properties JavaDoc details) throws XPathException {
95         if (characterSet==null) {
96             characterSet = CharacterSetFactory.getCharacterSet(details, getPipelineConfiguration().getController());
97         }
98         outputProperties = details;
99     }
100
101     /**
102     * Get the output properties
103     */

104
105     public Properties JavaDoc getOutputProperties() {
106         return outputProperties;
107     }
108
109     /**
110      * Set the StreamResult acting as the output destination of the Emitter
111      */

112
113     public void setStreamResult(StreamResult JavaDoc result) throws XPathException {
114         this.streamResult = result;
115     }
116
117     /**
118      * Make a Writer for this Emitter to use, given a StreamResult
119      */

120
121     protected void makeWriter() throws XPathException {
122         if (writer != null) {
123             return;
124         }
125         if (streamResult == null) {
126             throw new IllegalStateException JavaDoc("Emitter must have either a Writer or a StreamResult to write to");
127         }
128         writer = streamResult.getWriter();
129         if (writer == null) {
130             OutputStream os = streamResult.getOutputStream();
131             if (os != null) {
132                 setOutputStream(os);
133             }
134         }
135         if (writer == null) {
136             String JavaDoc uri = streamResult.getSystemId();
137             try {
138                 File file = new File(new URI JavaDoc(uri));
139                 setOutputStream(new FileOutputStream(file));
140                 // Set the outputstream in the StreamResult object so that the
141
// call on OutputURIResolver.close() can close it
142
streamResult.setOutputStream(outputStream);
143             } catch (FileNotFoundException fnf) {
144                 throw new DynamicError(fnf);
145             } catch (URISyntaxException JavaDoc use) {
146                 throw new DynamicError(use);
147             }
148         }
149     }
150     /**
151     * Determine whether the Emitter wants a Writer for character output or
152     * an OutputStream for binary output. The standard Emitters all use a Writer, so
153     * this returns true; but a subclass can override this if it wants to use an OutputStream
154     */

155
156     public boolean usesWriter() {
157         return true;
158     }
159
160     /**
161     * Set the output destination as a character stream
162     */

163
164     public void setWriter(Writer writer) {
165         this.writer = writer;
166
167         // If the writer uses a known encoding, change the encoding in the XML declaration
168
// to match. Any encoding actually specified in xsl:output is ignored, because encoding
169
// is being done by the user-supplied Writer, and not by Saxon itself.
170

171         if (writer instanceof OutputStreamWriter && outputProperties != null) {
172             String JavaDoc enc = ((OutputStreamWriter)writer).getEncoding();
173             outputProperties.put(OutputKeys.ENCODING, enc);
174         }
175     }
176
177     /**
178     * Get the output writer
179     */

180
181     public Writer getWriter() {
182         return writer;
183     }
184
185     /**
186     * Set the output destination as a byte stream
187     */

188
189     public void setOutputStream(OutputStream stream) throws XPathException {
190         this.outputStream = stream;
191
192         // If the user supplied an OutputStream, but the Emitter is written to
193
// use a Writer (this is the most common case), then we create a Writer
194
// to wrap the supplied OutputStream; the complications are to ensure that
195
// the character encoding is correct.
196

197         if (usesWriter()) {
198
199             //CharacterSet charSet = CharacterSetFactory.getCharacterSet(outputProperties);
200

201             String JavaDoc encoding = outputProperties.getProperty(OutputKeys.ENCODING);
202             if (encoding==null) encoding = "UTF8";
203             if (encoding.equalsIgnoreCase("UTF-8")) encoding = "UTF8";
204                  // needed for Microsoft Java VM
205

206             if (characterSet instanceof PluggableCharacterSet) {
207                 encoding = ((PluggableCharacterSet)characterSet).getEncodingName();
208             }
209
210             while (true) {
211                 try {
212                     String JavaDoc javaEncoding = encoding;
213                     if (encoding.equalsIgnoreCase("iso-646") || encoding.equalsIgnoreCase("iso646")) {
214                         javaEncoding = "US-ASCII";
215                     }
216                     writer = new BufferedWriter(
217                                     new OutputStreamWriter(
218                                         outputStream, javaEncoding));
219                     break;
220                 } catch (Exception JavaDoc err) {
221                     if (encoding.equalsIgnoreCase("UTF8")) {
222                         throw new DynamicError("Failed to create a UTF8 output writer");
223                     }
224                     DynamicError de = new DynamicError("Encoding " + encoding + " is not supported: using UTF8");
225                     de.setErrorCode("SESU0007");
226                     try {
227                         getPipelineConfiguration().getErrorListener().error(de);
228                     } catch (TransformerException JavaDoc e) {
229                         throw DynamicError.makeDynamicError(e);
230                     }
231                     encoding = "UTF8";
232                     characterSet = UnicodeCharacterSet.getInstance();
233                     outputProperties.put(OutputKeys.ENCODING, "UTF-8");
234                 }
235             }
236         }
237
238     }
239
240     /**
241     * Get the output stream
242     */

243
244     public OutputStream getOutputStream() {
245         return outputStream;
246     }
247
248     /**
249     * Set unparsed entity URI. Needed to satisfy the Receiver interface, but not used,
250     * because unparsed entities can occur only in input documents, not in output documents.
251     */

252
253     public void setUnparsedEntity(String JavaDoc name, String JavaDoc uri, String JavaDoc publicId) throws XPathException {}
254
255     /**
256     * Load a named output emitter or SAX2 ContentHandler and check it is OK.
257     */

258
259     public static Receiver makeEmitter (String JavaDoc className, Controller controller) throws XPathException
260     {
261         Object JavaDoc handler;
262         try {
263             handler = controller.getConfiguration().getInstance(className, controller.getClassLoader());
264         } catch (XPathException e) {
265             throw new DynamicError("Cannot load user-supplied output method " + className);
266         }
267
268         if (handler instanceof Receiver) {
269             return (Receiver)handler;
270         } else if (handler instanceof ContentHandler JavaDoc) {
271             ContentHandlerProxy emitter = new ContentHandlerProxy();
272             emitter.setUnderlyingContentHandler((ContentHandler JavaDoc)handler);
273             return emitter;
274         } else {
275             throw new DynamicError("Failed to load " + className +
276                         ": it is neither a Receiver nor a SAX2 ContentHandler");
277         }
278
279     }
280
281     /**
282     * Close output stream or writer. Called by subclasses at endDocument time
283     */

284 /*
285     public void close() {
286         if (closeAfterUse) {
287             try {
288                 if (usesWriter) {
289                     writer.close();
290                 } else {
291                     outputStream.close();
292                 }
293             } catch (Exception err) {}
294         }
295     }
296 */

297 }
298
299 //
300
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
301
// you may not use this file except in compliance with the License. You may obtain a copy of the
302
// License at http://www.mozilla.org/MPL/
303
//
304
// Software distributed under the License is distributed on an "AS IS" basis,
305
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
306
// See the License for the specific language governing rights and limitations under the License.
307
//
308
// The Original Code is: all this file.
309
//
310
// The Initial Developer of the Original Code is Michael H. Kay.
311
//
312
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
313
//
314
// Contributor(s): none.
315
//
316
Popular Tags