KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > core > streams > PollingInputStream


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.core.streams;
12
13 import java.io.FilterInputStream JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.io.InterruptedIOException JavaDoc;
17
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.core.runtime.OperationCanceledException;
21 import org.eclipse.team.internal.core.*;
22 import org.eclipse.team.internal.core.Policy;
23 import org.eclipse.team.internal.core.TeamPlugin;
24
25 /**
26  * Polls a progress monitor periodically and handles timeouts over extended durations.
27  * For this class to be effective, a high numAttempts should be specified, and the
28  * underlying stream should time out frequently on reads (every second or so).
29  *
30  * Supports resuming partially completed operations after an InterruptedIOException
31  * if the underlying stream does. Check the bytesTransferred field to determine how
32  * much of the operation completed; conversely, at what point to resume.
33  */

34 public class PollingInputStream extends FilterInputStream JavaDoc {
35     private static final boolean DEBUG = Policy.DEBUG_STREAMS;
36     private int numAttempts;
37     private IProgressMonitor monitor;
38     private boolean cancellable;
39     
40     /**
41      * Creates a new polling input stream.
42      * @param in the underlying input stream
43      * @param numAttempts the number of attempts before issuing an InterruptedIOException,
44      * if 0, retries indefinitely until canceled
45      * @param monitor the progress monitor to be polled for cancellation
46      */

47     public PollingInputStream(InputStream JavaDoc in, int numAttempts, IProgressMonitor monitor) {
48         super(in);
49         this.numAttempts = numAttempts;
50         this.monitor = monitor;
51         this.cancellable = true;
52     }
53     
54     /**
55      * Wraps the underlying stream's method.
56      * It may be important to wait for an input stream to be closed because it
57      * holds an implicit lock on a system resoure (such as a file) while it is
58      * open. Closing a stream may take time if the underlying stream is still
59      * servicing a previous request.
60      * @throws OperationCanceledException if the progress monitor is canceled
61      * @throws InterruptedIOException if the underlying operation times out numAttempts times
62      * @throws IOException if an i/o error occurs
63      */

64     public void close() throws IOException JavaDoc {
65         int attempts = 0;
66         try {
67             readPendingInput();
68         } catch (IOException JavaDoc e) {
69             // We shouldn't get an exception when we're getting the available input.
70
// If we do, just log it so we can close.
71
TeamPlugin.log(IStatus.ERROR, e.getMessage(), e);
72         } finally {
73             boolean stop = false;
74             while (!stop) {
75                 try {
76                     in.close();
77                     stop = true;
78                 } catch (InterruptedIOException JavaDoc e) {
79                     if (checkCancellation()) throw new OperationCanceledException();
80                     if (++attempts == numAttempts)
81                         throw new InterruptedIOException JavaDoc(Messages.PollingInputStream_closeTimeout);
82                     if (DEBUG) System.out.println("close retry=" + attempts); //$NON-NLS-1$
83
}
84             }
85         }
86     }
87     
88     /**
89      * Wraps the underlying stream's method.
90      * @throws OperationCanceledException if the progress monitor is canceled
91      * @throws InterruptedIOException if the underlying operation times out numAttempts times
92      * and no data was received, bytesTransferred will be zero
93      * @throws IOException if an i/o error occurs
94      */

95     public int read() throws IOException JavaDoc {
96         int attempts = 0;
97         for (;;) {
98             if (checkCancellation()) throw new OperationCanceledException();
99             try {
100                 return in.read();
101             } catch (InterruptedIOException JavaDoc e) {
102                 if (++attempts == numAttempts)
103                     throw new InterruptedIOException JavaDoc(Messages.PollingInputStream_readTimeout);
104                 if (DEBUG) System.out.println("read retry=" + attempts); //$NON-NLS-1$
105
}
106         }
107     }
108     
109     /**
110      * Wraps the underlying stream's method.
111      * @throws OperationCanceledException if the progress monitor is canceled
112      * @throws InterruptedIOException if the underlying operation times out numAttempts times
113      * and no data was received, bytesTransferred will be zero
114      * @throws IOException if an i/o error occurs
115      */

116     public int read(byte[] buffer, int off, int len) throws IOException JavaDoc {
117         int attempts = 0;
118         for (;;) {
119             if (checkCancellation()) throw new OperationCanceledException();
120             try {
121                 return in.read(buffer, off, len);
122             } catch (InterruptedIOException JavaDoc e) {
123                 if (e.bytesTransferred != 0) return e.bytesTransferred; // keep partial transfer
124
if (++attempts == numAttempts)
125                     throw new InterruptedIOException JavaDoc(Messages.PollingInputStream_readTimeout);
126                 if (DEBUG) System.out.println("read retry=" + attempts); //$NON-NLS-1$
127
}
128         }
129     }
130     
131     /**
132      * Wraps the underlying stream's method.
133      * @throws OperationCanceledException if the progress monitor is canceled
134      * @throws InterruptedIOException if the underlying operation times out numAttempts times
135      * and no data was received, bytesTransferred will be zero
136      * @throws IOException if an i/o error occurs
137      */

138     public long skip(long count) throws IOException JavaDoc {
139         int attempts = 0;
140         for (;;) {
141             if (checkCancellation()) throw new OperationCanceledException();
142             try {
143                 return in.skip(count);
144             } catch (InterruptedIOException JavaDoc e) {
145                 if (e.bytesTransferred != 0) return e.bytesTransferred; // keep partial transfer
146
if (++attempts == numAttempts)
147                     throw new InterruptedIOException JavaDoc(Messages.PollingInputStream_readTimeout);
148                 if (DEBUG) System.out.println("read retry=" + attempts); //$NON-NLS-1$
149
}
150         }
151     }
152     
153     /**
154      * Reads any pending input from the input stream so that
155      * the stream can savely be closed.
156      */

157     protected void readPendingInput() throws IOException JavaDoc {
158         byte[] buffer= new byte[2048];
159         while (true) {
160             int available = in.available();
161             if (available < 1) break;
162             if (available > buffer.length) available = buffer.length;
163             if (in.read(buffer, 0, available) < 1) break;
164         }
165     }
166         
167     /**
168      * Called to set whether cancellation will be checked by this stream. Turning cancellation checking
169      * off can be very useful for protecting critical portions of a protocol that shouldn't be interrupted.
170      * For example, it is often necessary to protect login sequences.
171      * @param cancellable a flag controlling whether this stream will check for cancellation.
172      */

173     public void setIsCancellable(boolean cancellable) {
174         this.cancellable = cancellable;
175     }
176
177     /**
178      * Checked whether the monitor for this stream has been cancelled. If the cancellable
179      * flag is <code>false</code> then the monitor is never cancelled.
180      * @return <code>true</code> if the monitor has been cancelled and <code>false</code>
181      * otherwise.
182      */

183     private boolean checkCancellation() {
184         if(cancellable) {
185             return monitor.isCanceled();
186         } else {
187             return false;
188         }
189     }
190 }
191
Popular Tags