001: /* OriginSeekInputStream
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: * Alters the origin of some other SeekInputStream. This class allows you
029: * to completely ignore everything in the underlying stream before a specified
030: * position, the origin position.
031: *
032: * <p>With the exception of {@link #position()} and {@link position(long)},
033: * all of the methods in this class simply delegate to the underlying input
034: * stream. The <code>position</code> methods adjust the position of the
035: * underlying stream relative to the origin specified at construction time.
036: *
037: * @author pjack
038: */
039: public class OriginSeekInputStream extends SeekInputStream {
040:
041: /**
042: * The underlying stream.
043: */
044: final private SeekInputStream input;
045:
046: /**
047: * The origin position. In other words, this.position(0)
048: * resolves to input.position(start).
049: */
050: final private long origin;
051:
052: /**
053: * Constructor.
054: *
055: * @param input the underlying stream
056: * @param origin the origin position
057: * @throws IOException if an IO error occurs
058: */
059: public OriginSeekInputStream(SeekInputStream input, long origin)
060: throws IOException {
061: this .input = input;
062: this .origin = origin;
063: input.position(origin);
064: }
065:
066: @Override
067: public int available() throws IOException {
068: return input.available();
069: }
070:
071: @Override
072: public int read() throws IOException {
073: return input.read();
074: }
075:
076: @Override
077: public int read(byte[] buf, int ofs, int len) throws IOException {
078: return input.read(buf, ofs, len);
079: }
080:
081: @Override
082: public int read(byte[] buf) throws IOException {
083: return input.read(buf);
084: }
085:
086: @Override
087: public long skip(long count) throws IOException {
088: return input.skip(count);
089: }
090:
091: /**
092: * Returns the position of the underlying stream relative to the origin.
093: *
094: * @return the relative position
095: * @throws IOException if an IO error occurs
096: */
097: public long position() throws IOException {
098: return input.position() - origin;
099: }
100:
101: /**
102: * Positions the underlying stream relative to the origin.
103: * In other words, this.position(0) resolves to input.position(origin),
104: * where input is underlying stream and origin is the origin specified
105: * at construction time.
106: *
107: * @param p the new position for this stream
108: * @throws IOException if an IO error occurs
109: */
110: public void position(long p) throws IOException {
111: input.position(p + origin);
112: }
113: }
|