001: /* SafeSeekInputStream
002: *
003: * Created on September 14, 2006
004: *
005: * Copyright (C) 2006 Internet Archive.
006: *
007: * This file is part of the Heritrix web crawler (crawler.archive.org).
008: *
009: * Heritrix is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU Lesser Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * any later version.
013: *
014: * Heritrix is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU Lesser Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser Public License
020: * along with Heritrix; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: package org.archive.io;
024:
025: import java.io.IOException;
026:
027: /**
028: * Enables multiple concurrent streams based on the same underlying stream.
029: *
030: * @author pjack
031: */
032: public class SafeSeekInputStream extends SeekInputStream {
033:
034: /**
035: * The underlying stream.
036: */
037: private SeekInputStream input;
038:
039: /**
040: * The expected position of the underlying stream.
041: */
042: private long expected;
043:
044: /**
045: * Constructor. The given stream will be positioned to 0 so that an
046: * accurate position can be tracked.
047: *
048: * @param input the underlying input stream
049: * @throws IOException if an IO error occurs
050: */
051: public SafeSeekInputStream(SeekInputStream input)
052: throws IOException {
053: this .input = input;
054: this .expected = input.position();
055: }
056:
057: /**
058: * Ensures that the underlying stream's position is what we expect to be.
059: *
060: * @throws IOException if an IO error occurs
061: */
062: private void ensure() throws IOException {
063: if (expected != input.position()) {
064: input.position(expected);
065: }
066: }
067:
068: @Override
069: public int read() throws IOException {
070: ensure();
071: int c = input.read();
072: if (c >= 0) {
073: expected++;
074: }
075: return c;
076: }
077:
078: @Override
079: public int read(byte[] buf, int ofs, int len) throws IOException {
080: ensure();
081: int r = input.read(buf, ofs, len);
082: if (r > 0) {
083: expected += r;
084: }
085: return r;
086: }
087:
088: @Override
089: public int read(byte[] buf) throws IOException {
090: ensure();
091: int r = input.read(buf);
092: if (r > 0) {
093: expected += r;
094: }
095: return r;
096: }
097:
098: @Override
099: public long skip(long c) throws IOException {
100: ensure();
101: long r = input.skip(c);
102: if (r > 0) {
103: expected += r;
104: }
105: return r;
106: }
107:
108: public void position(long p) throws IOException {
109: input.position(p);
110: expected = p;
111: }
112:
113: public long position() throws IOException {
114: return expected;
115: }
116:
117: }
|