001    // License: GPL. Copyright 2007 by Immanuel Scholz and others
002    package org.openstreetmap.josm.io;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.io.IOException;
007    import java.io.InputStream;
008    import java.net.URLConnection;
009    
010    import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
011    import org.openstreetmap.josm.gui.progress.ProgressMonitor;
012    
013    /**
014     * Read from an other reader and increment an progress counter while on the way.
015     * @author Imi
016     */
017    public class ProgressInputStream extends InputStream {
018    
019        private final InputStream in;
020        private int readSoFar = 0;
021        private int lastDialogUpdate = 0;
022        private boolean sizeKnown;
023        private final URLConnection connection;
024        private final ProgressMonitor progressMonitor;
025    
026        public ProgressInputStream(URLConnection con, ProgressMonitor progressMonitor) throws OsmTransferException {
027            this.connection = con;
028            if (progressMonitor == null) {
029                progressMonitor = NullProgressMonitor.INSTANCE;
030            }
031            this.progressMonitor = progressMonitor;
032            progressMonitor.beginTask(tr("Contacting OSM Server..."), 1);
033            progressMonitor.indeterminateSubTask(null);
034    
035            try {
036                this.in = con.getInputStream();
037            } catch (IOException e) {
038                progressMonitor.finishTask();
039                if (con.getHeaderField("Error") != null)
040                    throw new OsmTransferException(tr(con.getHeaderField("Error")));
041                throw new OsmTransferException(e);
042            }
043    
044            updateSize();
045            if (!sizeKnown) {
046                progressMonitor.indeterminateSubTask(tr("Downloading OSM data..."));
047            }
048        }
049    
050        @Override public void close() throws IOException {
051            in.close();
052            progressMonitor.finishTask();
053        }
054    
055        @Override public int read(byte[] b, int off, int len) throws IOException {
056            int read = in.read(b, off, len);
057            if (read != -1) {
058                advanceTicker(read);
059            } else {
060                progressMonitor.finishTask();
061            }
062            return read;
063        }
064    
065        @Override public int read() throws IOException {
066            int read = in.read();
067            if (read != -1) {
068                advanceTicker(1);
069            } else {
070                progressMonitor.finishTask();
071            }
072            return read;
073        }
074    
075        /**
076         * Increase ticker (progress counter and displayed text) by the given amount.
077         * @param amount
078         */
079        private void advanceTicker(int amount) {
080            readSoFar += amount;
081            updateSize();
082    
083            if (readSoFar / 1024 != lastDialogUpdate) {
084                lastDialogUpdate++;
085                if (sizeKnown) {
086                    progressMonitor.setTicks(readSoFar);
087                }
088                progressMonitor.setExtraText(readSoFar/1024 + " KB");
089            }
090        }
091    
092        private void updateSize() {
093            if (!sizeKnown && connection.getContentLength() > 0) {
094                sizeKnown = true;
095                progressMonitor.subTask(tr("Downloading OSM data..."));
096                progressMonitor.setTicksCount(connection.getContentLength());
097            }
098        }
099    }