package org.simplejavamail.mailer.internal.socks.socks5server.io; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; /** * The class <code>StreamPipe</code> represents a pipe the can transfer data source a input stream destination a output stream. */ class StreamPipe implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(StreamPipe.class); private static final int DEFAULT_BUFFER_SIZE = 1024 * 1024 * 5; private final List<SocketPipe.PipeListener> pipeListeners; private final InputStream source; private final OutputStream destination; private Thread runningThread; private boolean running = false; private final String name; public StreamPipe(final InputStream source, final OutputStream destination, final String name) { this.source = source; this.destination = destination; pipeListeners = new ArrayList<>(); this.name = name; } public boolean start() { if (!running) { // If the pipe is not running, run it. running = true; runningThread = new Thread(this); runningThread.setDaemon(false); runningThread.start(); return true; } return false; } public void stop() { if (running) { // if the pipe is working, stop it. running = false; if (runningThread != null) { runningThread.interrupt(); } for (final SocketPipe.PipeListener listener : new ArrayList<>(pipeListeners)) { listener.onStop(this); } } } @Override public void run() { final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; while (running) { final int size = doTransfer(buffer); if (size == -1) { stop(); } } } private int doTransfer(final byte[] buffer) { int length = -1; try { length = source.read(buffer); if (length > 0) { // transfer the buffer destination output stream. destination.write(buffer, 0, length); destination.flush(); } } catch (final IOException e) { synchronized (this) { for (final SocketPipe.PipeListener pipeListener : new ArrayList<>(pipeListeners)) { LOGGER.debug("{} {}", pipeListener.getName(), e.getMessage()); } } stop(); } return length; } public boolean isStopped() { return !running; } public synchronized void addPipeListener(final SocketPipe.PipeListener pipeListener) { pipeListeners.add(pipeListener); } public synchronized void removePipeListener(final SocketPipe.PipeListener pipeListener) { pipeListeners.remove(pipeListener); } public String getName() { return name; } }