From ecfa747a2c0e7daaca6f9dc472fd1752e1a8ad7d Mon Sep 17 00:00:00 2001 From: bgamard Date: Thu, 23 Nov 2017 15:32:20 +0100 Subject: [PATCH 1/2] Closes #172: smart images caching --- .../main/java/com/sismics/util/HttpUtil.java | 88 +++---------------- .../docs/rest/resource/FileResource.java | 20 +++-- .../docs/rest/resource/ThemeResource.java | 9 +- 3 files changed, 29 insertions(+), 88 deletions(-) diff --git a/docs-core/src/main/java/com/sismics/util/HttpUtil.java b/docs-core/src/main/java/com/sismics/util/HttpUtil.java index 49cb12e4..ed88a770 100644 --- a/docs-core/src/main/java/com/sismics/util/HttpUtil.java +++ b/docs-core/src/main/java/com/sismics/util/HttpUtil.java @@ -1,14 +1,8 @@ package com.sismics.util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.URL; -import java.net.URLConnection; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; /** * HTTP request utilities. @@ -17,77 +11,17 @@ import java.net.URLConnection; */ public class HttpUtil { /** - * Logger. + * Format of the expires header. */ - private static final Logger log = LoggerFactory.getLogger(HttpUtil.class); + private static final SimpleDateFormat EXPIRES_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH); /** - * Loads the content of an URL into a string. - * - * @param url URL to load - * @return Contents of the resource + * Build an Expires HTTP header. + * + * @param futureTime Expire interval + * @return Formatted header value */ - public static String readUrlIntoString(URL url) { - URLConnection connection; - BufferedReader in = null; - try { - connection = url.openConnection(); - in = new BufferedReader(new InputStreamReader(connection.getInputStream())); - StringBuilder sb = new StringBuilder(); - String inputLine; - while ((inputLine = in.readLine()) != null) { - sb.append(inputLine); - } - return sb.toString(); - } catch (IOException e) { - if (log.isErrorEnabled()) { - log.error("Error reading URL", e); - } - return null; - } finally { - if (in != null) { - try { - in.close(); - } catch (Exception e) { - // NOP - } - } - } - } - - public static String postUrl(URL url, String data) throws IOException { - OutputStreamWriter wr = null; - BufferedReader rd = null; - try { - URLConnection conn = url.openConnection(); - conn.setDoOutput(true); - wr = new OutputStreamWriter(conn.getOutputStream()); - wr.write(data); - wr.flush(); - - // Get the response - rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); - StringBuilder sb = new StringBuilder(); - String line = null; - while ((line = rd.readLine()) != null) { - sb.append(line).append("\n"); - } - return sb.toString(); - } finally { - if (wr != null) { - try { - wr.close(); - } catch (IOException e) { - // NOP - } - } - if (rd != null) { - try { - rd.close(); - } catch (IOException e) { - // NOP - } - } - } + public static String buildExpiresHeader(long futureTime) { + return EXPIRES_FORMAT.format(new Date().getTime() + futureTime); } } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index e88491a0..6d99e965 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -14,12 +14,16 @@ import com.sismics.docs.core.event.FileCreatedAsyncEvent; import com.sismics.docs.core.event.FileDeletedAsyncEvent; import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.User; -import com.sismics.docs.core.util.*; +import com.sismics.docs.core.util.DirectoryUtil; +import com.sismics.docs.core.util.EncryptionUtil; +import com.sismics.docs.core.util.FileUtil; +import com.sismics.docs.core.util.PdfUtil; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.HttpUtil; import com.sismics.util.context.ThreadLocalContext; import com.sismics.util.mime.MimeType; import com.sismics.util.mime.MimeTypeUtil; @@ -30,18 +34,19 @@ import javax.json.Json; import javax.json.JsonArrayBuilder; import javax.json.JsonObjectBuilder; import javax.ws.rs.*; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.text.MessageFormat; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -581,9 +586,10 @@ public class FileResource extends BaseResource { } return Response.ok(stream) - .header("Content-Disposition", "inline; filename=" + file.getFullName("data")) - .header("Content-Type", mimeType) - .header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24)) + .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + file.getFullName("data")) + .header(HttpHeaders.CONTENT_TYPE, mimeType) + .header(HttpHeaders.CACHE_CONTROL, "private") + .header(HttpHeaders.EXPIRES, HttpUtil.buildExpiresHeader(3_600_000L * 24L * 365L)) .build(); } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java index 66f2c620..423432ff 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/ThemeResource.java @@ -12,12 +12,14 @@ import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.HttpUtil; import com.sismics.util.css.Selector; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataParam; import javax.json.*; import javax.ws.rs.*; +import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import java.io.IOException; @@ -26,8 +28,6 @@ import java.io.OutputStream; import java.io.StringReader; import java.nio.file.Files; import java.nio.file.StandardCopyOption; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Map; /** @@ -235,8 +235,9 @@ public class ThemeResource extends BaseResource { } } }) - .header("Content-Type", "image/*") - .header("Expires", new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z").format(new Date().getTime() + 3600000 * 24 * 15)) + .header(HttpHeaders.CONTENT_TYPE, "image/*") + .header(HttpHeaders.CACHE_CONTROL, "public") + .header(HttpHeaders.EXPIRES, HttpUtil.buildExpiresHeader(3_600_000L * 24L * 15L)) .build(); } From e883c1e6780a81c8501418c0db450793581a4dbd Mon Sep 17 00:00:00 2001 From: bgamard Date: Thu, 23 Nov 2017 15:40:53 +0100 Subject: [PATCH 2/2] Closes #171: strip alpha channel from png --- .../src/main/java/com/sismics/util/ImageUtil.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs-core/src/main/java/com/sismics/util/ImageUtil.java b/docs-core/src/main/java/com/sismics/util/ImageUtil.java index 21c2a56a..edc4efa2 100644 --- a/docs-core/src/main/java/com/sismics/util/ImageUtil.java +++ b/docs-core/src/main/java/com/sismics/util/ImageUtil.java @@ -9,6 +9,7 @@ import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; +import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.IOException; @@ -40,6 +41,17 @@ public class ImageUtil { iwp.setCompressionQuality(1.f); imageOutputStream = ImageIO.createImageOutputStream(outputStream); writer.setOutput(imageOutputStream); + + if (image.getColorModel().hasAlpha()) { + // Strip alpha channel + BufferedImage noAlphaImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB); + Graphics graphics = noAlphaImage.getGraphics(); + graphics.setColor(Color.WHITE); + graphics.fillRect(0, 0, image.getWidth(), image.getHeight()); + graphics.drawImage(image, 0, 0, null); + image = noAlphaImage; + } + IIOImage iioImage = new IIOImage(image, null, null); writer.write(null, iioImage, iwp); } finally {