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.OutputStream;
008
009import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
010import org.openstreetmap.josm.gui.progress.ProgressMonitor;
011
012/**
013 * An {@link OutputStream} which reports progress to the {@link ProgressMonitor}.
014 *
015 * @since 9185
016 */
017public class ProgressOutputStream extends OutputStream {
018
019    private final StreamProgressUpdater updater;
020    private final OutputStream out;
021    private final boolean finishOnClose;
022
023    /**
024     * Constructs a new {@code ProgressOutputStream}.
025     *
026     * @param out the stream to monitor
027     * @param size the total size which will be sent
028     * @param progressMonitor the monitor to report to
029     * @param finishOnClose whether to call {@link ProgressMonitor#finishTask} when this stream is closed
030     * @since 10302
031     */
032    public ProgressOutputStream(OutputStream out, long size, ProgressMonitor progressMonitor, boolean finishOnClose) {
033        this(out, size, progressMonitor, tr("Uploading data ..."), finishOnClose);
034    }
035
036    /**
037     * Constructs a new {@code ProgressOutputStream}.
038     *
039     * @param out the stream to monitor
040     * @param size the total size which will be sent
041     * @param progressMonitor the monitor to report to
042     * @param message the message that will be displayed by the inner {@link StreamProgressUpdater}
043     * @param finishOnClose whether to call {@link ProgressMonitor#finishTask} when this stream is closed
044     * @since 12711
045     */
046    public ProgressOutputStream(OutputStream out, long size, ProgressMonitor progressMonitor, String message, boolean finishOnClose) {
047        this.updater = new StreamProgressUpdater(size,
048                progressMonitor != null ? progressMonitor : NullProgressMonitor.INSTANCE, message);
049        this.out = out;
050        this.finishOnClose = finishOnClose;
051    }
052
053    @Override
054    public void write(byte[] b, int off, int len) throws IOException {
055        out.write(b, off, len);
056        updater.advanceTicker(len);
057    }
058
059    @Override
060    public void write(int b) throws IOException {
061        out.write(b);
062        updater.advanceTicker(1);
063    }
064
065    @Override
066    public void close() throws IOException {
067        try {
068            out.close();
069        } finally {
070            if (finishOnClose) {
071                updater.finishTask();
072            }
073        }
074    }
075}