View Javadoc

1   /*
2    * Copyright (c) 2003 Peter Antman, Teknik i Media  <peter.antman@tim.se>
3    *
4    * $Id: DOMOutputStream.java,v 1.1.1.1 2004/05/19 12:07:30 pra Exp $
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version
10   * 
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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();//This works because the fact that also the byte version calles read() first
58           started = true;
59        } // end of if ()
60        
61        if ( domEx != null) {
62           throw new IOException("Could not read from DOM: " +domEx);
63        } // end of if ()
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        } // end of if ()
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                    } // end of try-catch
99                    
100                } // end of finally
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       } // end of if ()
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       } // end of if ()
127       
128       if ( ! closed ) {
129          try {
130             domThread.join();
131          } catch ( InterruptedException e) {
132             ;//Ignore I hope
133          } // end of try-catch
134          
135          if (domEx != null) {
136          throw new IOException("Could not get document: " +domEx); 
137       } // end of if ()
138 
139       } // end of if ()
140       closed = true;
141    }
142 } // DOMOutputStream