package com.denimgroup.threadfix.webapp.controller; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.denimgroup.threadfix.service.SanitizedLogger; @Controller @RequestMapping("/jasperimage") @PreAuthorize("hasRole('ROLE_CAN_GENERATE_REPORTS')") public class ReportImageController { private final SanitizedLogger log = new SanitizedLogger(ReportImageController.class); /** * This method is used to push report images to the browser from session memory. * It currently erases images as they are retrieved, but could modified to cache them. * A better map naming scheme would be necessary in that case. */ @RequestMapping(value="/{mapKey}/{imageKey}", method = RequestMethod.GET) public String getImage(@PathVariable String mapKey, @PathVariable String imageKey, HttpServletRequest request, HttpServletResponse response) { InputStream imageStream = null; if (request.getSession().getAttribute(mapKey) != null) { Object value = request.getSession().getAttribute(mapKey); if (value instanceof Map<?,?>) { Map<?, ?> map = (Map<?, ?>) value; if (map.containsKey(imageKey)) { Object image = map.get(imageKey); if (image instanceof byte[]) { byte[] imageBytes = (byte[]) image; imageStream = new ByteArrayInputStream(imageBytes); } map.remove(imageKey); if (map.size() == 0) { request.getSession().removeAttribute(mapKey); } } } } if (imageStream != null) { // Java 7 try-with-resources try (ServletOutputStream out = response.getOutputStream()) { byte[] outputByteBuffer = new byte[65535]; int remainingSize; remainingSize = imageStream.read(outputByteBuffer, 0, 65535); // copy binary content to output stream while (remainingSize != -1) { out.write(outputByteBuffer, 0, remainingSize); remainingSize = imageStream.read(outputByteBuffer, 0, 65535); } out.flush(); return null; } catch (IOException e) { log.error("IOException encountered while trying to export an image.", e); } finally { try { imageStream.close(); } catch (IOException e) { log.error("IOException encountered while trying to close the image stream.", e); } } } log.error("Unable to find report image."); return null; } }