1 package de.netseeker.ejoe.io;
2
3 import java.io.FilterOutputStream;
4 import java.io.IOException;
5 import java.io.OutputStream;
6 import java.nio.channels.ClosedChannelException;
7
8 import de.netseeker.ejoe.EJConstants;
9
10 /***
11 * Simple input stream wrapper which overwrites #close to prevent some and is used when output streams are handed over
12 * to serialize adapters to prevent some encoders, eg. Suns XmlEncoder, to close our socket output streams
13 * automatically.
14 *
15 * @author netseeker
16 * @since 0.3.5
17 */
18 public class UncloseableOutputStream extends FilterOutputStream
19 {
20
21 private boolean _customEOF;
22
23 private boolean _isClosed = false;
24
25 private int _written = 0;
26
27 private int _lastFlush = 0;
28
29 /***
30 * @param out
31 */
32 public UncloseableOutputStream(OutputStream out)
33 {
34 this( out, false );
35 }
36
37 /***
38 * @param out
39 * @param customEOF
40 */
41 public UncloseableOutputStream(OutputStream out, boolean customEOF)
42 {
43 super( out );
44 _customEOF = customEOF;
45 }
46
47
48
49
50
51
52 public void write( byte[] b, int off, int len ) throws IOException
53 {
54 if ( _customEOF && len > 0 && b[off + len - 1] == -1 )
55 {
56 len -= 1;
57 }
58
59 super.write( b, off, len );
60 _written += len;
61 }
62
63
64
65
66
67
68 public void write( byte[] b ) throws IOException
69 {
70 write( b, 0, b.length );
71 }
72
73
74
75
76
77
78 public void write( int b ) throws IOException
79 {
80 super.write( b );
81 _written++;
82 }
83
84
85
86
87
88
89 public void flush() throws IOException
90 {
91 try
92 {
93 if ( _written > _lastFlush ) super.flush();
94 }
95 catch ( IOException e )
96 {
97 throw new ClosedChannelException();
98 }
99 finally
100 {
101 _lastFlush = _written;
102 }
103 }
104
105
106
107
108
109
110 public void close() throws IOException
111 {
112 if ( !_isClosed )
113 {
114 try
115 {
116 if ( _written > 0 )
117 {
118 if ( _customEOF )
119 {
120 super.write( EJConstants.EJOE_EOF );
121 }
122
123 flush();
124 }
125 }
126 catch ( IOException e )
127 {
128 throw new ClosedChannelException();
129 }
130 finally
131 {
132 _isClosed = true;
133 _written = 0;
134 }
135 }
136 }
137 }