1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.backsource.utils.io;
21
22 import java.io.FileInputStream;
23 import java.io.PipedInputStream;
24 import java.io.PipedOutputStream;
25 import java.io.IOException;
26
27 import org.w3c.dom.Document;
28
29 import org.backsource.utils.io.IOHelper;
30 import org.backsource.utils.xml.DocumentUtil;
31 /***
32 * Write to a DOM Document.
33 *
34 * <p>Much like a FileOutputStream writes the stream to a File this class writes the stream directly to a DOM tree. This is however done with the use of two threads; so this class should probably not be used in EJB:s. When the writing is finished it is possible to get the Document with {@link #getDocument()}.</p>
35 *
36 * @author <a href="mailto:pra@tim.se">Peter Antman</a>
37 * @version $Revision: 1.1.1.1 $
38 */
39
40 public class DOMOutputStream extends PipedOutputStream {
41 private Document doc;
42 private PipedInputStream pis;
43 private boolean started = false;
44 private Exception domEx;
45 private Thread domThread;
46 private boolean closed =false;
47
48 public DOMOutputStream (){
49
50 }
51
52 /***
53 * Write to the DOM tree, if its the first write start the DOM reader.
54 */
55 public void write(int b) throws IOException {
56 if ( !started) {
57 startDOMReader();
58 started = true;
59 }
60
61 if ( domEx != null) {
62 throw new IOException("Could not read from DOM: " +domEx);
63 }
64 super.write(b);
65 }
66 /***
67 * Write to the DOM tree, if its the first write start the DOM reader.
68 */
69 public void write(byte b[], int off, int len) throws IOException {
70 if ( !started) {
71 startDOMReader();
72 started = true;
73 }
74 if ( domEx != null) {
75 throw new IOException("Could not read from DOM: " +domEx);
76 }
77
78 super.write(b,off,len);
79 }
80
81 /***
82 * Start the DOM reader thread.
83 */
84 protected void startDOMReader() throws IOException {
85 pis = new PipedInputStream();
86 connect(pis);
87 domThread = new Thread( new Runnable() {
88 public void run() {
89 try {
90 doc = DocumentUtil.getDocument(pis);
91 } catch (Exception e) {
92 domEx = e;
93 } finally {
94 try {
95 pis.close();
96 } catch (Exception e) {
97 domEx = e;
98 }
99
100 }
101
102 }
103 });
104 domThread.start();
105 }
106
107 /***
108 * Get the document written to, if the stream was not closed before this methods was called it will be closed by it.
109 */
110 public Document getDocument() throws IOException {
111 close();
112
113 return doc;
114 }
115 /***
116 * Close the stream.
117 * <p>The stream will be flushed and the wait for the DOM reader to finish. Any exceptions thrown in the reader thread will also be reported.</p>
118 */
119 public void close() throws IOException {
120 if ( ! closed) {
121 flush();
122 }
123 super.close();
124 if ( domThread == null) {
125 throw new IOException("The stream was never written to: did you use it through a buffered stream without flush or close?");
126 }
127
128 if ( ! closed ) {
129 try {
130 domThread.join();
131 } catch ( InterruptedException e) {
132 ;
133 }
134
135 if (domEx != null) {
136 throw new IOException("Could not get document: " +domEx);
137 }
138
139 }
140 closed = true;
141 }
142 }