KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > hudson > remoting > ProxyOutputStream


1 package hudson.remoting;
2
3 import java.io.ByteArrayOutputStream JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.OutputStream JavaDoc;
6
7 /**
8  * {@link OutputStream} that sends bits to an exported
9  * {@link OutputStream} on a remote machine.
10  */

11 final class ProxyOutputStream extends OutputStream JavaDoc {
12     private Channel channel;
13     private int oid;
14
15     /**
16      * If bytes are written to this stream before it's connected
17      * to a remote object, bytes will be stored in this buffer.
18      */

19     private ByteArrayOutputStream JavaDoc tmp;
20
21     /**
22      * Set to true if the stream is closed.
23      */

24     private boolean closed;
25
26     /**
27      * Creates unconnected {@link ProxyOutputStream}.
28      * The returned stream accepts data right away, and
29      * when it's {@link #connect(Channel,int) connected} later,
30      * the data will be sent at once to the remote stream.
31      */

32     public ProxyOutputStream() {
33     }
34
35     /**
36      * Creates an already connected {@link ProxyOutputStream}.
37      *
38      * @param oid
39      * The object id of the exported {@link OutputStream}.
40      */

41     public ProxyOutputStream(Channel channel, int oid) throws IOException JavaDoc {
42         connect(channel,oid);
43     }
44
45     /**
46      * Connects this stream to the specified remote object.
47      */

48     synchronized void connect(Channel channel, int oid) throws IOException JavaDoc {
49         if(this.channel!=null)
50             throw new IllegalStateException JavaDoc("Cannot connect twice");
51         this.channel = channel;
52         this.oid = oid;
53
54         // if we already have bytes to write, do so now.
55
if(tmp!=null) {
56             channel.send(new Chunk(oid,tmp.toByteArray()));
57             tmp = null;
58         }
59         if(closed) // already marked closed?
60
close();
61     }
62
63     public void write(int b) throws IOException JavaDoc {
64         write(new byte[]{(byte)b},0,1);
65     }
66
67     public void write(byte b[], int off, int len) throws IOException JavaDoc {
68         if(closed)
69             throw new IOException JavaDoc("stream is already closed");
70         if(off==0 && len==b.length)
71             write(b);
72         else {
73             byte[] buf = new byte[len];
74             System.arraycopy(b,off,buf,0,len);
75             write(buf);
76         }
77     }
78
79     public synchronized void write(byte b[]) throws IOException JavaDoc {
80         if(closed)
81             throw new IOException JavaDoc("stream is already closed");
82         if(channel==null) {
83             if(tmp==null)
84                 tmp = new ByteArrayOutputStream JavaDoc();
85             tmp.write(b);
86         } else {
87             channel.send(new Chunk(oid,b));
88         }
89     }
90
91
92     public void flush() throws IOException JavaDoc {
93         if(channel!=null)
94             channel.send(new Flush(oid));
95     }
96
97     public synchronized void close() throws IOException JavaDoc {
98         closed = true;
99         if(channel!=null) {
100             channel.send(new EOF(oid));
101             channel = null;
102             oid = -1;
103         }
104     }
105
106     protected void finalize() throws Throwable JavaDoc {
107         super.finalize();
108         close();
109     }
110     
111     /**
112      * {@link Command} for sending bytes.
113      */

114     private static final class Chunk extends Command {
115         private final int oid;
116         private final byte[] buf;
117
118         public Chunk(int oid, byte[] buf) {
119             this.oid = oid;
120             this.buf = buf;
121         }
122
123         protected void execute(Channel channel) {
124             OutputStream JavaDoc os = (OutputStream JavaDoc) channel.getExportedObject(oid);
125             try {
126                 os.write(buf);
127             } catch (IOException JavaDoc e) {
128                 // ignore errors
129
}
130         }
131
132         public String JavaDoc toString() {
133             return "Pipe.Chunk("+oid+","+buf.length+")";
134         }
135
136         private static final long serialVersionUID = 1L;
137     }
138
139     /**
140      * {@link Command} for flushing.
141      */

142     private static final class Flush extends Command {
143         private final int oid;
144
145         public Flush(int oid) {
146             this.oid = oid;
147         }
148
149         protected void execute(Channel channel) {
150             OutputStream JavaDoc os = (OutputStream JavaDoc) channel.getExportedObject(oid);
151             try {
152                 os.flush();
153             } catch (IOException JavaDoc e) {
154                 // ignore errors
155
}
156         }
157
158         public String JavaDoc toString() {
159             return "Pipe.Flush("+oid+")";
160         }
161
162         private static final long serialVersionUID = 1L;
163     }
164
165     /**
166      * {@link Command} for sending EOF.
167      */

168     private static final class EOF extends Command {
169         private final int oid;
170
171         public EOF(int oid) {
172             this.oid = oid;
173         }
174
175
176         protected void execute(Channel channel) {
177             OutputStream JavaDoc os = (OutputStream JavaDoc) channel.getExportedObject(oid);
178             channel.unexport(oid);
179             try {
180                 os.close();
181             } catch (IOException JavaDoc e) {
182                 // ignore errors
183
}
184         }
185
186         public String JavaDoc toString() {
187             return "Pipe.EOF("+oid+")";
188         }
189
190         private static final long serialVersionUID = 1L;
191     }
192 }
193
Popular Tags