TimeoutInputStream.java

  1. /*
  2.  * Copyright (C) 2009, 2013 Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.util.io;

  11. import java.io.FilterInputStream;
  12. import java.io.IOException;
  13. import java.io.InputStream;
  14. import java.io.InterruptedIOException;
  15. import java.text.MessageFormat;

  16. import org.eclipse.jgit.internal.JGitText;

  17. /**
  18.  * InputStream with a configurable timeout.
  19.  */
  20. public class TimeoutInputStream extends FilterInputStream {
  21.     private final InterruptTimer myTimer;

  22.     private int timeout;

  23.     /**
  24.      * Wrap an input stream with a timeout on all read operations.
  25.      *
  26.      * @param src
  27.      *            base input stream (to read from). The stream must be
  28.      *            interruptible (most socket streams are).
  29.      * @param timer
  30.      *            timer to manage the timeouts during reads.
  31.      */
  32.     public TimeoutInputStream(final InputStream src,
  33.             final InterruptTimer timer) {
  34.         super(src);
  35.         myTimer = timer;
  36.     }

  37.     /**
  38.      * Get number of milliseconds before aborting a read.
  39.      *
  40.      * @return number of milliseconds before aborting a read.
  41.      */
  42.     public int getTimeout() {
  43.         return timeout;
  44.     }

  45.     /**
  46.      * Set number of milliseconds before aborting a read.
  47.      *
  48.      * @param millis
  49.      *            number of milliseconds before aborting a read. Must be > 0.
  50.      */
  51.     public void setTimeout(int millis) {
  52.         if (millis < 0)
  53.             throw new IllegalArgumentException(MessageFormat.format(
  54.                     JGitText.get().invalidTimeout, Integer.valueOf(millis)));
  55.         timeout = millis;
  56.     }

  57.     /** {@inheritDoc} */
  58.     @Override
  59.     public int read() throws IOException {
  60.         try {
  61.             beginRead();
  62.             return super.read();
  63.         } catch (InterruptedIOException e) {
  64.             throw readTimedOut(e);
  65.         } finally {
  66.             endRead();
  67.         }
  68.     }

  69.     /** {@inheritDoc} */
  70.     @Override
  71.     public int read(byte[] buf) throws IOException {
  72.         return read(buf, 0, buf.length);
  73.     }

  74.     /** {@inheritDoc} */
  75.     @Override
  76.     public int read(byte[] buf, int off, int cnt) throws IOException {
  77.         try {
  78.             beginRead();
  79.             return super.read(buf, off, cnt);
  80.         } catch (InterruptedIOException e) {
  81.             throw readTimedOut(e);
  82.         } finally {
  83.             endRead();
  84.         }
  85.     }

  86.     /** {@inheritDoc} */
  87.     @Override
  88.     public long skip(long cnt) throws IOException {
  89.         try {
  90.             beginRead();
  91.             return super.skip(cnt);
  92.         } catch (InterruptedIOException e) {
  93.             throw readTimedOut(e);
  94.         } finally {
  95.             endRead();
  96.         }
  97.     }

  98.     private void beginRead() {
  99.         myTimer.begin(timeout);
  100.     }

  101.     private void endRead() {
  102.         myTimer.end();
  103.     }

  104.     private InterruptedIOException readTimedOut(InterruptedIOException e) {
  105.         InterruptedIOException interrupted = new InterruptedIOException(
  106.                 MessageFormat.format(JGitText.get().readTimedOut,
  107.                         Integer.valueOf(timeout)));
  108.         interrupted.initCause(e);
  109.         return interrupted;
  110.     }
  111. }