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 }