package org.nextprot.api.core.service.export; import java.io.Closeable; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Queue; import java.util.concurrent.Future; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nextprot.api.commons.exception.NextProtException; /** * Helper class to stream data and dealing with exception, like when user cancels a request. * @author dteixeira * */ public class ExportUtils { private static final Log LOGGER = LogFactory.getLog(ExportUtils.class); private static int BYTES_DOWNLOAD = 10 * 1024 * 1024; // 10 MB public static void printOutput(Queue<Future<File>> futuresQueue, HttpServletResponse response) { boolean userHasCanceled = false; OutputStream out = null; Future<File> currentFuture = null; while (!futuresQueue.isEmpty()) { currentFuture = futuresQueue.remove(); InputStream currentInputStream = null; try { if(out == null){ out = response.getOutputStream(); } File f = currentFuture.get(); currentInputStream = new FileInputStream(f); LOGGER.info("Content of " + f.getName() + " is being streamed to the client"); int read = 0; byte[] bytes = new byte[BYTES_DOWNLOAD]; while ((read = currentInputStream.read(bytes)) != -1) { out.write(bytes, 0, read); } currentInputStream.close(); out.flush(); } catch (EOFException e) { LOGGER.info("User has cancelled the request"); cancelFutures(currentFuture, futuresQueue); userHasCanceled = true; } catch (Exception e) { LOGGER.error("Something when wrong when streaming the data" + e.getMessage()); e.printStackTrace(); cancelFutures(currentFuture, futuresQueue); closeStream(out); throw new NextProtException(e.getClass().getName() + ": " + e.getMessage()); } finally { closeStream(currentInputStream); } } //No need to close stream when the user has canceled because it is already closed if(!userHasCanceled){ closeStream(out); } } private static void closeStream(Closeable stream){ // Closes try { if(stream != null){ stream.close(); } } catch (IOException e) { e.printStackTrace(); throw new NextProtException(e.getClass().getName() + ": " + e.getMessage()); } } private static void cancelFutures(Future<File> currentFuture, Queue<Future<File>> futuresQueue) { if(currentFuture != null) currentFuture.cancel(true); if(!futuresQueue.isEmpty()){ System.out.println("Canceling " + futuresQueue.size() + " tasks"); } while (!futuresQueue.isEmpty()) { futuresQueue.remove().cancel(true); } } }