1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.internal.storage.io;
12
13 import org.eclipse.jgit.lib.Constants;
14 import org.eclipse.jgit.lib.ProgressMonitor;
15
16 import java.io.IOException;
17 import java.io.InterruptedIOException;
18 import java.io.OutputStream;
19 import java.security.MessageDigest;
20
21
22
23
24
25 public class CancellableDigestOutputStream extends OutputStream {
26
27
28 public static final int BYTES_TO_WRITE_BEFORE_CANCEL_CHECK = 128 * 1024;
29
30 private final ProgressMonitor writeMonitor;
31
32 private final OutputStream out;
33
34 private final MessageDigest md = Constants.newMessageDigest();
35
36 private long count;
37
38 private long checkCancelAt;
39
40
41
42
43
44
45
46
47
48 public CancellableDigestOutputStream(ProgressMonitor writeMonitor,
49 OutputStream out) {
50 this.writeMonitor = writeMonitor;
51 this.out = out;
52 this.checkCancelAt = BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
53 }
54
55
56
57
58
59
60
61 public final ProgressMonitor getWriteMonitor() {
62 return writeMonitor;
63 }
64
65
66
67
68
69
70 public final byte[] getDigest() {
71 return md.digest();
72 }
73
74
75
76
77
78
79 public final long length() {
80 return count;
81 }
82
83
84 @Override
85 public final void write(int b) throws IOException {
86 if (checkCancelAt <= count) {
87 if (writeMonitor.isCancelled()) {
88 throw new InterruptedIOException();
89 }
90 checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
91 }
92
93 out.write(b);
94 md.update((byte) b);
95 count++;
96 }
97
98
99 @Override
100 public final void write(byte[] b, int off, int len) throws IOException {
101 while (0 < len) {
102 if (checkCancelAt <= count) {
103 if (writeMonitor.isCancelled()) {
104 throw new InterruptedIOException();
105 }
106 checkCancelAt = count + BYTES_TO_WRITE_BEFORE_CANCEL_CHECK;
107 }
108
109 int n = Math.min(len, BYTES_TO_WRITE_BEFORE_CANCEL_CHECK);
110 out.write(b, off, n);
111 md.update(b, off, n);
112 count += n;
113
114 off += n;
115 len -= n;
116 }
117 }
118
119
120 @Override
121 public void flush() throws IOException {
122 out.flush();
123 }
124 }