1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package org.apache.commons.httpclient.server;
33
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37
38 /***
39 * Pipes all data of an input stream through to an output stream asynchronously.
40 * Instances of this class are thread safe.
41 *
42 * @author Ortwin Glueck
43 */
44 class StreamProxy {
45 private InputStream in;
46 private OutputStream out;
47 private Pump pump = new Pump();
48 private Thread pumpThread = new Thread(pump, "Stream copier");
49 private int state = 0;
50
51 public StreamProxy(InputStream in, OutputStream out) {
52 this.in = in;
53 this.out = out;
54 }
55
56 public synchronized void start() {
57 if (state != 0) throw new IllegalStateException("Can not start again.");
58 state = 1;
59 pumpThread.start();
60 }
61
62 /***
63 * Returns immediately. The object must not be used again.
64 */
65 public void abort() {
66 if (state != 1) return;
67 state = 2;
68 pumpThread.interrupt();
69 dispose();
70 }
71
72 /***
73 * Blocks until all data has been copied. Basically calls the
74 * join method on the pump thread.
75 * @throws InterruptedException
76 */
77 public void block() throws InterruptedException {
78 if (state != 1) throw new IllegalStateException("Can not block before started");
79 pumpThread.join();
80 }
81
82 private void dispose() {
83 pumpThread = null;
84 pump = null;
85 in = null;
86 out = null;
87 }
88
89 private class Pump implements Runnable {
90
91 public void run() {
92 byte[] buffer = new byte[10000];
93 try {
94 while (!Thread.interrupted()) {
95 int len;
96 while ((len = in.read(buffer)) != -1) {
97 out.write(buffer, 0, len);
98 out.flush();
99 }
100 }
101 } catch(IOException e) {
102
103 e.printStackTrace();
104 } finally {
105 dispose();
106 }
107 }
108
109 }
110 }