package com.skcraft.playblock.installer.tasks; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import com.sk89q.task.Task; public class StreamCopy extends Task { private String format = "%s"; private final InputStream in; private final OutputStream out; private final long totalLength; private long totalRead = 0; private int bufferSize = 1024 * 8; public StreamCopy(InputStream in, OutputStream out) { this.in = in; this.out = out; this.totalLength = -1; } public StreamCopy(InputStream in, OutputStream out, long totalLength) { this.in = in; this.out = out; this.totalLength = totalLength; } public StreamCopy(InputStream in, OutputStream out, long totalLength, String format) { this.in = in; this.out = out; this.totalLength = totalLength; this.format = format; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public int getBufferSize() { return bufferSize; } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } @Override public void execute() throws IOException, InterruptedException { fireProgressChange(0); Thread thread = new Thread(new ProgressTracker(), ProgressTracker.class.getCanonicalName()); if (totalLength <= 0) { fireProgressChange(-1); } try { thread.start(); byte[] data = new byte[bufferSize]; int len = 0; while ((len = in.read(data, 0, bufferSize)) >= 0) { if (Thread.interrupted()) { throw new InterruptedException(); } out.write(data, 0, len); totalRead += len; } } finally { thread.interrupt(); } } /** * Fires progress events periodically. */ private class ProgressTracker implements Runnable { @Override public void run() { try { while (true) { update(); Thread.sleep(200); } } catch (InterruptedException e) { } } private void update() { double readKBytes = Math.round(totalRead / 1024.0 * 100) / 100; if (totalLength <= 0) { // Fire status message String status = String.format("%,.2f kB", readKBytes); fireStatusChange(String.format(format, status)); } else { double totalKBytes = Math.round(totalLength / 1024.0 * 100) / 100; // Fire progress percent double progress = Math.min(1, totalRead / (double) totalLength); fireProgressChange(progress); // Fire status message String status = String.format("%.0f%% (%,.0f kB)", progress * 100, readKBytes); fireStatusChange(String.format(format, status)); } } } }