1 18 19 package org.apache.tools.ant.util; 20 21 import java.io.IOException ; 22 import java.io.OutputStream ; 23 24 30 public class OutputStreamFunneler { 31 32 36 public static final long DEFAULT_TIMEOUT_MILLIS = 1000; 37 38 private final class Funnel extends OutputStream { 39 private boolean closed = false; 40 41 private Funnel() { 42 synchronized (OutputStreamFunneler.this) { 43 ++count; 44 } 45 } 46 47 public void flush() throws IOException { 48 synchronized (OutputStreamFunneler.this) { 49 dieIfClosed(); 50 out.flush(); 51 } 52 } 53 54 public void write(int b) throws IOException { 55 synchronized (OutputStreamFunneler.this) { 56 dieIfClosed(); 57 out.write(b); 58 } 59 } 60 61 public void write(byte[] b) throws IOException { 62 synchronized (OutputStreamFunneler.this) { 63 dieIfClosed(); 64 out.write(b); 65 } 66 } 67 68 public void write(byte[] b, int off, int len) throws IOException { 69 synchronized (OutputStreamFunneler.this) { 70 dieIfClosed(); 71 out.write(b, off, len); 72 } 73 } 74 75 public void close() throws IOException { 76 release(this); 77 } 78 } 79 80 private OutputStream out; 81 private int count = 0; 82 private boolean closed; 83 private long timeoutMillis; 84 85 90 public OutputStreamFunneler(OutputStream out) { 91 this(out, DEFAULT_TIMEOUT_MILLIS); 92 } 93 94 102 public OutputStreamFunneler(OutputStream out, long timeoutMillis) { 103 if (out == null) { 104 throw new IllegalArgumentException ( 105 "OutputStreamFunneler.<init>: out == null"); 106 } 107 this.out = out; 108 this.closed = false; setTimeout(timeoutMillis); 110 } 111 112 120 public synchronized void setTimeout(long timeoutMillis) { 121 this.timeoutMillis = timeoutMillis; 122 } 123 124 131 public synchronized OutputStream getFunnelInstance() 132 throws IOException { 133 dieIfClosed(); 134 try { 135 return new Funnel(); 136 } finally { 137 notifyAll(); 138 } 139 } 140 141 private synchronized void release(Funnel funnel) throws IOException { 142 if (!funnel.closed) { 144 try { 145 if (timeoutMillis > 0) { 146 try { 147 wait(timeoutMillis); 148 } catch (InterruptedException eyeEx) { 149 } 151 } 152 if (--count == 0) { 153 close(); 154 } 155 } finally { 156 funnel.closed = true; 157 } 158 } 159 } 160 161 private synchronized void close() throws IOException { 162 try { 163 dieIfClosed(); 164 out.close(); 165 } finally { 166 closed = true; 167 } 168 } 169 170 private synchronized void dieIfClosed() throws IOException { 171 if (closed) { 172 throw new IOException ("The funneled OutputStream has been closed."); 173 } 174 } 175 176 } 177 | Popular Tags |