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