1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/server/StreamProxy.java,v 1.1.2.2 2004/02/22 18:21:18 olegk Exp $
3 * $Revision: 1.1.2.2 $
4 * $Date: 2004/02/22 18:21:18 $
5 *
6 * ====================================================================
7 *
8 * Copyright 1999-2004 The Apache Software Foundation
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ====================================================================
22 *
23 * This software consists of voluntary contributions made by many
24 * individuals on behalf of the Apache Software Foundation. For more
25 * information on the Apache Software Foundation, please see
26 * <http://www.apache.org/>.
27 *
28 * [Additional notices, if required by prior licensing conditions]
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 /* expected if parties close connection */
103 e.printStackTrace();
104 } finally {
105 dispose();
106 }
107 }
108
109 }
110 }