KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > archive > io > ReplayInputStream


1 /* ReplayInputStream
2  *
3  * $Id: ReplayInputStream.java,v 1.7.18.1 2007/01/13 01:31:34 stack-sf Exp $
4  *
5  * Created on Sep 24, 2003
6  *
7  * Copyright (C) 2003 Internet Archive.
8  *
9  * This file is part of the Heritrix web crawler (crawler.archive.org).
10  *
11  * Heritrix is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * any later version.
15  *
16  * Heritrix is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser Public License
22  * along with Heritrix; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */

25 package org.archive.io;
26
27 import java.io.File JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.OutputStream JavaDoc;
30
31
32 /**
33  * Replays the bytes recorded from a RecordingInputStream or
34  * RecordingOutputStream.
35  *
36  * This InputStream supports mark and reset.
37  *
38  * @author gojomo
39  */

40 public class ReplayInputStream extends SeekInputStream
41 {
42     private BufferedSeekInputStream diskStream;
43     private byte[] buffer;
44     private long position;
45
46     /**
47      * Total size of stream content.
48      *
49      * Size of data to replay.
50      */

51     private long size = -1;
52
53     /**
54      * Where the response body starts, if marked
55      */

56     protected long responseBodyStart = -1;
57
58
59     /**
60      * Constructor.
61      *
62      * @param buffer Buffer to read from.
63      * @param size Size of data to replay.
64      * @param responseBodyStart Start of the response body.
65      * @param backingFilename Backing file that sits behind the buffer. If
66      * <code>size<code> > than buffer then we go to backing file to read
67      * data that is beyond buffer.length.
68      *
69      * @throws IOException If we fail to open an input stream on
70      * backing file.
71      */

72     public ReplayInputStream(byte[] buffer, long size, long responseBodyStart,
73             String JavaDoc backingFilename)
74         throws IOException JavaDoc
75     {
76         this(buffer, size, backingFilename);
77         this.responseBodyStart = responseBodyStart;
78     }
79
80     /**
81      * Constructor.
82      *
83      * @param buffer Buffer to read from.
84      * @param size Size of data to replay.
85      * @param backingFilename Backing file that sits behind the buffer. If
86      * <code>size<code> > than buffer then we go to backing file to read
87      * data that is beyond buffer.length.
88      * @throws IOException If we fail to open an input stream on
89      * backing file.
90      */

91     public ReplayInputStream(byte[] buffer, long size, String JavaDoc backingFilename)
92         throws IOException JavaDoc
93     {
94         this.buffer = buffer;
95         this.size = size;
96         if (size > buffer.length) {
97             RandomAccessInputStream rais = new RandomAccessInputStream(
98                     new File JavaDoc(backingFilename));
99             diskStream = new BufferedSeekInputStream(rais, 4096);
100         }
101     }
102
103     public long setToResponseBodyStart() throws IOException JavaDoc {
104         position(responseBodyStart);
105         return this.position;
106     }
107     
108
109     /* (non-Javadoc)
110      * @see java.io.InputStream#read()
111      */

112     public int read() throws IOException JavaDoc {
113         if (position == size) {
114             return -1; // EOF
115
}
116         if (position < buffer.length) {
117             // Convert to unsigned int.
118
int c = buffer[(int) position] & 0xFF;
119             position++;
120             return c;
121         }
122         int c = diskStream.read();
123         if (c >= 0) {
124             position++;
125         }
126         return c;
127     }
128
129     /*
130      * (non-Javadoc)
131      *
132      * @see java.io.InputStream#read(byte[], int, int)
133      */

134     public int read(byte[] b, int off, int len) throws IOException JavaDoc {
135         if (position == size) {
136             return -1; // EOF
137
}
138         if (position < buffer.length) {
139             int toCopy = (int)Math.min(size - position,
140                 Math.min(len, buffer.length - position));
141             System.arraycopy(buffer, (int)position, b, off, toCopy);
142             if (toCopy > 0) {
143                 position += toCopy;
144             }
145             return toCopy;
146         }
147         // into disk zone
148
int read = diskStream.read(b,off,len);
149         if(read>0) {
150             position += read;
151         }
152         return read;
153     }
154
155     public void readFullyTo(OutputStream JavaDoc os) throws IOException JavaDoc {
156         byte[] buf = new byte[4096];
157         int c = read(buf);
158         while (c != -1) {
159             os.write(buf,0,c);
160             c = read(buf);
161         }
162     }
163
164     /* (non-Javadoc)
165      * @see java.io.InputStream#close()
166      */

167     public void close() throws IOException JavaDoc {
168         super.close();
169         if(diskStream != null) {
170             diskStream.close();
171         }
172     }
173
174     /**
175      * Total size of stream content.
176      * @return Returns the size.
177      */

178     public long getSize()
179     {
180         return size;
181     }
182
183     /**
184      * @return Amount THEORETICALLY remaining (TODO: Its not theoretical
185      * seemingly. The class implemetentation depends on it being exact).
186      */

187     public long remaining() {
188         return size - position;
189     }
190     
191
192     /**
193      * Reposition the stream.
194      *
195      * @param p the new position for this stream
196      * @throws IOException if an IO error occurs
197      */

198     public void position(long p) throws IOException JavaDoc {
199         if (p < 0) {
200             throw new IOException JavaDoc("Negative seek offset.");
201         }
202         if (p >= size) {
203             throw new IOException JavaDoc("Desired position exceeds size.");
204         }
205         if (p < buffer.length) {
206             // Only seek file if necessary
207
if (position > buffer.length) {
208                 diskStream.position(0);
209             }
210         } else {
211             diskStream.position(p - buffer.length);
212         }
213         this.position = p;
214     }
215     
216     
217     public long position() throws IOException JavaDoc {
218         return position;
219     }
220 }
221
Popular Tags