001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.IOException;
007import java.io.InputStream;
008import java.net.URLConnection;
009
010import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
011import org.openstreetmap.josm.gui.progress.ProgressMonitor;
012import org.openstreetmap.josm.tools.CheckParameterUtil;
013
014/**
015 * Read from an other reader and increment an progress counter while on the way.
016 * @author Imi
017 */
018public class ProgressInputStream extends InputStream {
019
020    private final StreamProgressUpdater updater;
021    private final InputStream in;
022
023    /**
024     * Constructs a new {@code ProgressInputStream}.
025     *
026     * @param in the stream to monitor. Must not be null
027     * @param size the total size which will be sent
028     * @param progressMonitor the monitor to report to
029     * @since 9172
030     */
031    public ProgressInputStream(InputStream in, long size, ProgressMonitor progressMonitor) {
032        CheckParameterUtil.ensureParameterNotNull(in, "in");
033        if (progressMonitor == null) {
034            progressMonitor = NullProgressMonitor.INSTANCE;
035        }
036        this.updater = new StreamProgressUpdater(size, progressMonitor, tr("Downloading data..."));
037        this.in = in;
038    }
039
040    /**
041     * Constructs a new {@code ProgressInputStream}.
042     *
043     * Will call {@link URLConnection#getInputStream()} to obtain the stream to monitor.
044     *
045     * @param con the connection to monitor
046     * @param progressMonitor the monitor to report to
047     * @throws OsmTransferException if any I/O error occurs
048     */
049    public ProgressInputStream(URLConnection con, ProgressMonitor progressMonitor) throws OsmTransferException {
050        if (progressMonitor == null) {
051            progressMonitor = NullProgressMonitor.INSTANCE;
052        }
053        progressMonitor.beginTask(tr("Contacting OSM Server..."), 1);
054        progressMonitor.indeterminateSubTask(null);
055
056        try {
057            this.in = con.getInputStream();
058            this.updater = new StreamProgressUpdater(con.getContentLength(), progressMonitor, tr("Downloading data..."));
059        } catch (IOException e) {
060            progressMonitor.finishTask();
061            if (con.getHeaderField("Error") != null)
062                throw new OsmTransferException(tr(con.getHeaderField("Error")), e);
063            throw new OsmTransferException(e);
064        }
065    }
066
067    @Override
068    public void close() throws IOException {
069        try {
070            in.close();
071        } finally {
072            updater.finishTask();
073        }
074    }
075
076    @Override
077    public int read(byte[] b, int off, int len) throws IOException {
078        int read = in.read(b, off, len);
079        if (read != -1) {
080            updater.advanceTicker(read);
081        } else {
082            updater.finishTask();
083        }
084        return read;
085    }
086
087    @Override
088    public int read() throws IOException {
089        int read = in.read();
090        if (read != -1) {
091            updater.advanceTicker(1);
092        } else {
093            updater.finishTask();
094        }
095        return read;
096    }
097}