1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.util.io;
12
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.InterruptedIOException;
16 import java.io.OutputStream;
17
18
19
20
21 public class StreamCopyThread extends Thread {
22 private static final int BUFFER_SIZE = 1024;
23
24 private final InputStream src;
25
26 private final OutputStream dst;
27
28 private volatile boolean done;
29
30
31 private final Object writeLock;
32
33
34
35
36
37
38
39
40
41
42
43 public StreamCopyThread(InputStream i, OutputStream o) {
44 setName(Thread.currentThread().getName() + "-StreamCopy");
45 src = i;
46 dst = o;
47 writeLock = new Object();
48 }
49
50
51
52
53
54
55
56
57
58
59 public void halt() throws InterruptedException {
60 for (;;) {
61 join(250 );
62 if (isAlive()) {
63 done = true;
64 interrupt();
65 } else
66 break;
67 }
68 }
69
70
71 @Override
72 public void run() {
73 try {
74 final byte[] buf = new byte[BUFFER_SIZE];
75 boolean readInterrupted = false;
76 for (;;) {
77 try {
78 if (readInterrupted) {
79 synchronized (writeLock) {
80 boolean interruptedAgain = Thread.interrupted();
81 dst.flush();
82 if (interruptedAgain) {
83 interrupt();
84 }
85 }
86 readInterrupted = false;
87 }
88
89 if (done)
90 break;
91
92 final int n;
93 try {
94 n = src.read(buf);
95 } catch (InterruptedIOException wakey) {
96 readInterrupted = true;
97 continue;
98 }
99 if (n < 0)
100 break;
101
102 synchronized (writeLock) {
103 boolean writeInterrupted = Thread.interrupted();
104 dst.write(buf, 0, n);
105 if (writeInterrupted) {
106 interrupt();
107 }
108 }
109 } catch (IOException e) {
110 break;
111 }
112 }
113 } finally {
114 try {
115 src.close();
116 } catch (IOException e) {
117
118 }
119 try {
120 dst.close();
121 } catch (IOException e) {
122
123 }
124 }
125 }
126 }