001    /* ProgressMonitorInputStream.java --
002       Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing;
040    
041    import java.awt.Component;
042    
043    import java.io.FilterInputStream;
044    import java.io.InputStream;
045    import java.io.InterruptedIOException;
046    import java.io.IOException;
047    
048    /**
049     * An input stream with a {@link ProgressMonitor}.
050     *
051     * @author      Andrew Selkirk
052     * @author  Robert Schuster (robertschuster@fsfe.org)
053     * @status updated to 1.2
054     * @since 1.2
055     */
056    public class ProgressMonitorInputStream extends FilterInputStream
057    {
058    
059      /**
060       * The monitor watching the progress of the input stream.
061       */
062      private ProgressMonitor monitor;
063    
064      /**
065       * read
066       */
067      private int read;
068    
069      /**
070       * Creates a new <code>ProgressMonitorInputStream</code>.
071       *
072       * @param component  the parent component for the progress monitor dialog.
073       * @param message  the task description.
074       * @param stream  the underlying input stream.
075       */
076      public ProgressMonitorInputStream(Component component, Object message,
077                                        InputStream stream)
078      {
079        super(stream);
080    
081        int max = 0;
082    
083        try
084          {
085            max = stream.available();
086          }
087        catch ( IOException ioe )
088          {
089            // Behave like the JDK here.
090          }
091    
092        monitor = new ProgressMonitor(component, message, null, 0, max);
093      }
094    
095      /**
096       * Resets the input stream to the point where {@link #mark(int)} was called.
097       *
098       * @exception IOException TODO
099       */
100      public void reset() throws IOException
101      {
102        super.reset();
103    
104        checkMonitorCanceled();
105    
106        // TODO: The docs says the monitor should be resetted. But to which
107        // value? (mark is not overridden)
108      }
109    
110      /**
111       * Reads an unsigned byte from the input stream and returns it as an
112       * <code>int</code> in the range of 0-255.  Returns -1 if the end of the
113       * stream has been reached.  The progress monitor is updated.
114       *
115       * @return int
116       *
117       * @exception IOException if there is a problem reading the stream.
118       */
119      public int read() throws IOException
120      {
121        int t = super.read();
122    
123        monitor.setProgress(++read);
124    
125        checkMonitorCanceled();
126    
127        return t;
128      }
129    
130      /**
131       * Reads bytes from the input stream and stores them in the supplied array,
132       * and updates the progress monitor (or closes it if the end of the stream
133       * is reached).
134       *
135       * @param data  the data array for returning bytes read from the stream.
136       *
137       * @return The number of bytes read, or -1 if there are no more bytes in the
138       *         stream.
139       *
140       * @throws IOException if there is a problem reading bytes from the stream.
141       */
142      public int read(byte[] data) throws IOException
143      {
144        int t = super.read(data);
145    
146        if ( t > 0 )
147          {
148            read += t;
149            monitor.setProgress(read);
150    
151            checkMonitorCanceled();
152          }
153        else
154          {
155            monitor.close();
156          }
157    
158        return t;
159      }
160    
161      /**
162       * Reads up to <code>length</code> bytes from the input stream and stores
163       * them in the supplied array at the given index, and updates the progress
164       * monitor (or closes it if the end of the stream is reached).
165       *
166       * @param data  the data array for returning bytes read from the stream.
167       * @param offset  the offset into the array where the bytes should be written.
168       * @param length  the maximum number of bytes to read from the stream.
169       *
170       * @return The number of bytes read, or -1 if there are no more bytes in the
171       *         stream.
172       *
173       * @throws IOException if there is a problem reading bytes from the stream.
174       */
175      public int read(byte[] data, int offset, int length) throws IOException
176      {
177        int t = super.read(data, offset, length);
178    
179        if ( t > 0 )
180          {
181            read += t;
182            monitor.setProgress(read);
183    
184            checkMonitorCanceled();
185          }
186        else
187          {
188            monitor.close();
189          }
190    
191        return t;
192      }
193    
194      /**
195       * Skips the specified number of bytes and updates the
196       * {@link ProgressMonitor}.
197       *
198       * @param length the number of bytes to skip.
199       *
200       * @return The actual number of bytes skipped.
201       *
202       * @throws IOException if there is a problem skipping bytes in the stream.
203       */
204      public long skip(long length) throws IOException
205      {
206        long t = super.skip(length);
207    
208        // 'read' may overflow here in rare situations.
209        assert ( (long) read + t <= (long) Integer.MAX_VALUE );
210    
211        read += (int) t;
212    
213        monitor.setProgress(read);
214    
215        checkMonitorCanceled();
216    
217        return t;
218      }
219    
220      /**
221       * Closes the input stream and the associated {@link ProgressMonitor}.
222       *
223       * @throws IOException if there is a problem closing the input stream.
224       */
225      public void close() throws IOException
226      {
227        super.close();
228        monitor.close();
229      }
230    
231      /**
232       * Returns the {@link ProgressMonitor} used by this input stream.
233       *
234       * @return The progress monitor.
235       */
236      public ProgressMonitor getProgressMonitor()
237      {
238        return monitor;
239      }
240    
241      private void checkMonitorCanceled() throws InterruptedIOException
242      {
243        if (monitor.isCanceled())
244          {
245            throw new InterruptedIOException("ProgressMonitor was canceled");
246          }
247      }
248    
249    }