View Javadoc
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  
11  package org.eclipse.jgit.util.io;
12  
13  import java.io.FilterInputStream;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.io.InterruptedIOException;
17  import java.text.MessageFormat;
18  
19  import org.eclipse.jgit.internal.JGitText;
20  
21  /**
22   * InputStream with a configurable timeout.
23   */
24  public class TimeoutInputStream extends FilterInputStream {
25  	private final InterruptTimer myTimer;
26  
27  	private int timeout;
28  
29  	/**
30  	 * Wrap an input stream with a timeout on all read operations.
31  	 *
32  	 * @param src
33  	 *            base input stream (to read from). The stream must be
34  	 *            interruptible (most socket streams are).
35  	 * @param timer
36  	 *            timer to manage the timeouts during reads.
37  	 */
38  	public TimeoutInputStream(final InputStream src,
39  			final InterruptTimer timer) {
40  		super(src);
41  		myTimer = timer;
42  	}
43  
44  	/**
45  	 * Get number of milliseconds before aborting a read.
46  	 *
47  	 * @return number of milliseconds before aborting a read.
48  	 */
49  	public int getTimeout() {
50  		return timeout;
51  	}
52  
53  	/**
54  	 * Set number of milliseconds before aborting a read.
55  	 *
56  	 * @param millis
57  	 *            number of milliseconds before aborting a read. Must be > 0.
58  	 */
59  	public void setTimeout(int millis) {
60  		if (millis < 0)
61  			throw new IllegalArgumentException(MessageFormat.format(
62  					JGitText.get().invalidTimeout, Integer.valueOf(millis)));
63  		timeout = millis;
64  	}
65  
66  	/** {@inheritDoc} */
67  	@Override
68  	public int read() throws IOException {
69  		try {
70  			beginRead();
71  			return super.read();
72  		} catch (InterruptedIOException e) {
73  			throw readTimedOut(e);
74  		} finally {
75  			endRead();
76  		}
77  	}
78  
79  	/** {@inheritDoc} */
80  	@Override
81  	public int read(byte[] buf) throws IOException {
82  		return read(buf, 0, buf.length);
83  	}
84  
85  	/** {@inheritDoc} */
86  	@Override
87  	public int read(byte[] buf, int off, int cnt) throws IOException {
88  		try {
89  			beginRead();
90  			return super.read(buf, off, cnt);
91  		} catch (InterruptedIOException e) {
92  			throw readTimedOut(e);
93  		} finally {
94  			endRead();
95  		}
96  	}
97  
98  	/** {@inheritDoc} */
99  	@Override
100 	public long skip(long cnt) throws IOException {
101 		try {
102 			beginRead();
103 			return super.skip(cnt);
104 		} catch (InterruptedIOException e) {
105 			throw readTimedOut(e);
106 		} finally {
107 			endRead();
108 		}
109 	}
110 
111 	private void beginRead() {
112 		myTimer.begin(timeout);
113 	}
114 
115 	private void endRead() {
116 		myTimer.end();
117 	}
118 
119 	private InterruptedIOException readTimedOut(InterruptedIOException e) {
120 		InterruptedIOException interrupted = new InterruptedIOException(
121 				MessageFormat.format(JGitText.get().readTimedOut,
122 						Integer.valueOf(timeout)));
123 		interrupted.initCause(e);
124 		return interrupted;
125 	}
126 }