View Javadoc

    1   /* SafeSeekInputStream
    2   *
    3   * Created on September 14, 2006
    4   *
    5   * Copyright (C) 2006 Internet Archive.
    6   *
    7   * This file is part of the Heritrix web crawler (crawler.archive.org).
    8   *
    9   * Heritrix is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU Lesser Public License as published by
    11  * the Free Software Foundation; either version 2.1 of the License, or
    12  * any later version.
    13  *
    14  * Heritrix is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU Lesser Public License for more details.
    18  *
    19  * You should have received a copy of the GNU Lesser Public License
    20  * along with Heritrix; if not, write to the Free Software
    21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    22  */
    23  package org.archive.io;
    24
    25
    26  import java.io.IOException;
    27
    28
    29  /***
    30   * Enables multiple concurrent streams based on the same underlying stream.
    31   *
    32   * @author pjack
    33   */
    34  public class SafeSeekInputStream extends SeekInputStream {
    35
    36
    37      /***
    38       * The underlying stream.
    39       */
    40      private SeekInputStream input;
    41
    42
    43      /***
    44       * The expected position of the underlying stream.
    45       */
    46      private long expected;
    47
    48
    49      /***
    50       * Constructor.  The given stream will be positioned to 0 so that an
    51       * accurate position can be tracked.
    52       *
    53       * @param input  the underlying input stream
    54       * @throws IOException   if an IO error occurs
    55       */
    56      public SafeSeekInputStream(SeekInputStream input) throws IOException {
    57          this.input = input;
    58          this.expected = input.position();
    59      }
    60
    61
    62      /***
    63       * Ensures that the underlying stream's position is what we expect to be.
    64       *
    65       * @throws IOException  if an IO error occurs
    66       */
    67      private void ensure() throws IOException {
    68          if (expected != input.position()) {
    69              input.position(expected);
    70          }
    71      }
    72
    73
    74      @Override
    75      public int read() throws IOException {
    76          ensure();
    77          int c = input.read();
    78          if (c >= 0) {
    79              expected++;
    80          }
    81          return c;
    82      }
    83
    84
    85      @Override
    86      public int read(byte[] buf, int ofs, int len) throws IOException {
    87          ensure();
    88          int r = input.read(buf, ofs, len);
    89          if (r > 0) {
    90              expected += r;
    91          }
    92          return r;
    93      }
    94
    95
    96      @Override
    97      public int read(byte[] buf) throws IOException {
    98          ensure();
    99          int r = input.read(buf);
    100         if (r > 0) {
    101             expected += r;
    102         }
    103         return r;
    104     }
    105
    106
    107     @Override
    108     public long skip(long c) throws IOException {
    109         ensure();
    110         long r = input.skip(c);
    111         if (r > 0) {
    112             expected += r;
    113         }
    114         return r;
    115     }
    116
    117
    118     public void position(long p) throws IOException {
    119         input.position(p);
    120         expected = p;
    121     }
    122
    123
    124     public long position() throws IOException {
    125         return expected;
    126     }
    127
    128 }