KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > internal > verifier > DigestedInputStream


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.internal.verifier;
13
14 import java.io.*;
15 import java.security.MessageDigest JavaDoc;
16
17 /**
18  * This InputStream will calculate the digest of bytes as they are read. At the
19  * end of the InputStream, it will calculate the digests and throw an exception
20  * if the calculated digest do not match the expected digests.
21  */

22 class DigestedInputStream extends FilterInputStream {
23     MessageDigest JavaDoc digest;
24     byte result[];
25     long remaining;
26
27     /**
28      * Constructs an InputStream that uses another InputStream as a source and
29      * calculates the digest. At the end of the stream an exception will be
30      * thrown if the calculated digest doesn't match the passed digest.
31      *
32      * @param in the stream to use as an input source.
33      * @param digestAlgorithm the MessageDigest algorithm to use.
34      * @param result the expected digest.
35      */

36     DigestedInputStream(InputStream in, String JavaDoc digestAlgorithm, byte result[], long size) {
37         super(in);
38         this.remaining = size;
39         this.digest = SignedBundleFile.getMessageDigest(digestAlgorithm);
40         this.result = result;
41     }
42
43     /**
44      * Not supported.
45      */

46     public synchronized void mark(int readlimit) {
47         // Noop, we don't want to support this
48
}
49
50     /**
51      * Always returns false.
52      */

53     public boolean markSupported() {
54         return false;
55     }
56
57     /**
58      * Read a byte from the InputStream. Digests are calculated on reads. At the
59      * end of the stream the calculated digests must match the expected digests.
60      *
61      * @return the character read or -1 at end of stream.
62      * @throws IOException if there was an problem reading the byte or at the
63      * end of the stream the calculated digests do not match the
64      * expected digests.
65      * @see java.io.InputStream#read()
66      */

67     public int read() throws IOException {
68         if (remaining <= 0)
69             return -1;
70         int c = super.read();
71         if (c != -1) {
72             digest.update((byte) c);
73             remaining--;
74         } else {
75             // We hit eof so set remaining to zero
76
remaining = 0;
77         }
78         if (remaining == 0)
79             verifyDigests();
80         return c;
81     }
82
83     private void verifyDigests() throws IOException {
84         // Check the digest at end of file
85
byte rc[] = digest.digest();
86         if (!MessageDigest.isEqual(result, rc))
87             throw new IOException("Corrupted file: the digest is valid for " + digest.getAlgorithm()); //$NON-NLS-1$
88
}
89
90     /**
91      * Read bytes from the InputStream. Digests are calculated on reads. At the
92      * end of the stream the calculated digests must match the expected digests.
93      *
94      * @return the number of characters read or -1 at end of stream.
95      * @throws IOException if there was an problem reading or at the
96      * end of the stream the calculated digests do not match the
97      * expected digests.
98      * @see java.io.InputStream#read()
99      */

100     public int read(byte[] b, int off, int len) throws IOException {
101         if (remaining <= 0)
102             return -1;
103         int rc = super.read(b, off, len);
104         if (rc != -1) {
105             digest.update(b, off, rc);
106             remaining -= rc;
107         } else {
108             // We hit eof so set remaining to zero
109
remaining = 0;
110         }
111         if (remaining <= 0)
112             verifyDigests();
113         return rc;
114     }
115
116     /**
117      * Not supported.
118      *
119      * @throws IOException always thrown if this method is called since mark/reset is not supported.
120      * @see java.io.InputStream#reset()
121      */

122     public synchronized void reset() throws IOException {
123         // Throw IOException, we don't want to support this
124
throw new IOException("Reset not supported"); //$NON-NLS-1$
125
}
126
127     /**
128      * This method is implemented as a read into a bitbucket.
129      */

130     public long skip(long n) throws IOException {
131         byte buffer[] = new byte[4096];
132         long count = 0;
133         while (n - count > 0) {
134             int rc = (n - count) > buffer.length ? buffer.length : (int) (n - count);
135             rc = read(buffer, 0, rc);
136             if (rc == -1)
137                 break;
138             count += rc;
139             n -= rc;
140         }
141         return count;
142     }
143 }
Popular Tags