1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.ifs;
20
21 import java.io.FilterInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.security.DigestInputStream;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27
28 import org.mycore.common.MCRException;
29 import org.mycore.common.config.MCRConfigurationException;
30 import org.mycore.common.content.streams.MCRBlockingInputStream;
31
32
33
34
35
36
37
38
39
40
41
42 public class MCRContentInputStream extends FilterInputStream {
43
44 protected static final int HEADER_SIZE = 65536;
45
46
47 protected byte[] md5 = null;
48
49
50 protected MessageDigest digest = null;
51
52
53 protected long length;
54
55
56 protected byte[] header;
57
58
59
60
61
62
63
64
65
66 public MCRContentInputStream(InputStream in) throws MCRException {
67 super(null);
68
69 digest = buildMD5Digest();
70
71 DigestInputStream dis = new DigestInputStream(in, digest);
72 MCRBlockingInputStream bis = new MCRBlockingInputStream(dis, HEADER_SIZE);
73
74 byte[] buffer = new byte[HEADER_SIZE];
75
76 try {
77 int num = bis.read(buffer, 0, buffer.length);
78 header = new byte[Math.max(0, num)];
79
80 if (num > 0) {
81 System.arraycopy(buffer, 0, header, 0, num);
82 }
83 } catch (IOException ex) {
84 String msg = "Error while reading content input stream header";
85 throw new MCRException(msg, ex);
86 }
87
88 this.in = bis;
89 }
90
91 public int consume() throws IOException {
92 byte[] buffer = new byte[4096];
93 int numRead, totalRead = 0;
94 do {
95 numRead = read(buffer);
96 if (numRead > 0) {
97 totalRead += numRead;
98 }
99 } while (numRead != -1);
100 return totalRead;
101 }
102
103 @Override
104 public int read() throws IOException {
105 int b;
106
107
108 if (header.length > 0 && length < header.length) {
109 b = header[(int) length];
110 length++;
111 } else {
112 b = super.read();
113 if (b != -1) {
114 length++;
115 }
116 }
117
118 return b;
119 }
120
121 @Override
122 public int read(byte[] buf, int off, int len) throws IOException {
123
124 if (header.length > 0 && length < header.length) {
125 int numAvail = header.length - (int) length;
126 len = Math.min(len, numAvail);
127 System.arraycopy(header, (int) length, buf, off, len);
128 length += len;
129 return len;
130 } else {
131 len = super.read(buf, off, len);
132 if (len != -1) {
133 length += len;
134 }
135 return len;
136 }
137 }
138
139
140
141
142
143
144
145 public byte[] getHeader() {
146 return header;
147 }
148
149
150
151
152
153
154 public long getLength() {
155 return length;
156 }
157
158
159
160
161
162
163
164 public byte[] getMD5() {
165 if (md5 == null) {
166 md5 = digest.digest();
167 }
168 return md5;
169 }
170
171
172
173
174
175
176 public String getMD5String() {
177 return getMD5String(getMD5());
178 }
179
180
181
182
183
184
185 public static String getMD5String(byte[] digest) {
186 StringBuilder md5SumBuilder = new StringBuilder();
187 for (byte b : digest) {
188 md5SumBuilder.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
189 }
190 return md5SumBuilder.toString();
191 }
192
193
194
195
196
197
198
199 private static MessageDigest buildMD5Digest() {
200 try {
201 return MessageDigest.getInstance("MD5");
202 } catch (NoSuchAlgorithmException exc) {
203 String msg = "Could not find java classes that support MD5 checksum algorithm";
204 throw new MCRConfigurationException(msg, exc);
205 }
206 }
207 }