From 4d79dd707676d80fe85c1672b47930191e08f7e6 Mon Sep 17 00:00:00 2001 From: jendib Date: Sun, 8 May 2016 17:25:21 +0200 Subject: [PATCH] #79: Change background and logo image --- .../docs/core/model/context/AppContext.java | 2 +- .../sismics/docs/core/util/DirectoryUtil.java | 9 +++ .../com/sismics/util/mime/MimeTypeUtil.java | 7 +- .../docs/rest/resource/FileResource.java | 2 +- .../docs/rest/resource/ThemeResource.java | 74 +++++++++++++++++- .../img => resources/image}/background.jpg | Bin .../favicon.png => resources/image/logo.png} | Bin docs-web/src/main/webapp/Gruntfile.js | 2 +- docs-web/src/main/webapp/src/index.html | 4 +- docs-web/src/main/webapp/src/share.html | 2 +- docs-web/src/main/webapp/src/style/main.less | 6 +- .../sismics/docs/rest/TestFileResource.java | 26 +++--- .../sismics/docs/rest/TestThemeResource.java | 51 +++++++++++- 13 files changed, 153 insertions(+), 32 deletions(-) rename docs-web/src/main/{webapp/src/img => resources/image}/background.jpg (100%) rename docs-web/src/main/{webapp/src/favicon.png => resources/image/logo.png} (100%) diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java b/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java index 2d2ab739..526371e7 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java +++ b/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java @@ -72,7 +72,7 @@ public class AppContext { eventBus = new EventBus(); eventBus.register(new DeadEventListener()); - asyncExecutorList = new ArrayList(); + asyncExecutorList = new ArrayList<>(); asyncEventBus = newAsyncEventBus(); asyncEventBus.register(new FileCreatedAsyncListener()); diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java index 7f947157..6f0973ba 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/DirectoryUtil.java @@ -86,6 +86,15 @@ public class DirectoryUtil { return getDataSubDirectory("log"); } + /** + * Returns the theme directory. + * + * @return Theme directory. + */ + public static Path getThemeDirectory() { + return getDataSubDirectory("theme"); + } + /** * Returns a subdirectory of the base data directory * diff --git a/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java b/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java index fcb3d2ec..2eb5f079 100644 --- a/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java +++ b/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java @@ -1,5 +1,6 @@ package com.sismics.util.mime; +import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; @@ -21,16 +22,16 @@ public class MimeTypeUtil { * * @param is Stream to inspect * @return MIME type - * @throws Exception + * @throws IOException */ - public static String guessMimeType(InputStream is) throws Exception { + public static String guessMimeType(InputStream is) throws IOException { byte[] headerBytes = new byte[64]; is.mark(headerBytes.length); int readCount = is.read(headerBytes); is.reset(); if (readCount <= 0) { - throw new Exception("Cannot read input file"); + throw new IOException("Cannot read input file"); } return guessMimeType(headerBytes); 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 b692ed4e..35520179 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 @@ -107,7 +107,7 @@ public class FileResource extends BaseResource { String mimeType; try { mimeType = MimeTypeUtil.guessMimeType(fileInputStream); - } catch (Exception e) { + } catch (IOException e) { throw new ServerException("ErrorGuessMime", "Error guessing mime type", e); } if (mimeType == null) { 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 6e3f96a1..672b8e0c 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 @@ -1,22 +1,31 @@ package com.sismics.docs.rest.resource; -import javax.json.*; -import javax.ws.rs.*; -import javax.ws.rs.core.Response; - import com.google.common.base.Strings; +import com.google.common.io.ByteStreams; import com.sismics.docs.core.constant.ConfigType; import com.sismics.docs.core.dao.jpa.ConfigDao; import com.sismics.docs.core.model.jpa.Config; +import com.sismics.docs.core.util.DirectoryUtil; import com.sismics.docs.rest.constant.BaseFunction; +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.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.Response; +import javax.ws.rs.core.StreamingOutput; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.io.StringReader; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Map; /** @@ -26,6 +35,10 @@ import java.util.Map; */ @Path("/theme") public class ThemeResource extends BaseResource { + // Filenames for images in theme directory + private static final String LOGO_IMAGE = "logo"; + private static final String BACKGROUND_IMAGE = "background"; + /** * Returns custom CSS stylesheet. * @@ -116,10 +129,63 @@ public class ThemeResource extends BaseResource { throw new ForbiddenClientException(); } checkBaseFunction(BaseFunction.ADMIN); + if (logoBodyPart == null && backgrounBodyPart == null) { + throw new ClientException("NoImageProvided", "logo or background is required"); + } + + // Only a background or a logo is handled + FormDataBodyPart bodyPart = logoBodyPart == null ? backgrounBodyPart : logoBodyPart; + String type = logoBodyPart == null ? BACKGROUND_IMAGE : LOGO_IMAGE; + java.nio.file.Path filePath = DirectoryUtil.getThemeDirectory().resolve(type); + + // Copy the image to the theme directory + try (InputStream inputStream = bodyPart.getValueAs(InputStream.class)) { + Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + throw new ServerException("CopyError", "Error copying the image to the theme directory", e); + } return Response.ok().build(); } + @GET + @Produces("image/*") + @Path("image/{type: logo|background}") + public Response getImage(@PathParam("type") final String type) { + if (!LOGO_IMAGE.equals(type) && !BACKGROUND_IMAGE.equals(type)) { + throw new ClientException("InvalidType", "Type must be logo or background"); + } + + final java.nio.file.Path filePath = DirectoryUtil.getThemeDirectory().resolve(type); + + // Copy the image to the response output + return Response.ok(new StreamingOutput() { + @Override + public void write(OutputStream outputStream) throws IOException, WebApplicationException { + InputStream inputStream = null; + try { + if (Files.exists(filePath)) { + inputStream = Files.newInputStream(filePath); + } else { + inputStream = getClass().getResource("/image/" + (type.equals(LOGO_IMAGE) ? "logo.png" : "background.jpg")).openStream(); + } + ByteStreams.copy(inputStream, outputStream); + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + outputStream.close(); + } catch (IOException e) { + // Ignore + } + } + } + }) + .header("Content-Type", "image/*") + .build(); + } + /** * Returns the theme configuration object. * diff --git a/docs-web/src/main/webapp/src/img/background.jpg b/docs-web/src/main/resources/image/background.jpg similarity index 100% rename from docs-web/src/main/webapp/src/img/background.jpg rename to docs-web/src/main/resources/image/background.jpg diff --git a/docs-web/src/main/webapp/src/favicon.png b/docs-web/src/main/resources/image/logo.png similarity index 100% rename from docs-web/src/main/webapp/src/favicon.png rename to docs-web/src/main/resources/image/logo.png diff --git a/docs-web/src/main/webapp/Gruntfile.js b/docs-web/src/main/webapp/Gruntfile.js index cb4ad357..5dba6d2d 100644 --- a/docs-web/src/main/webapp/Gruntfile.js +++ b/docs-web/src/main/webapp/Gruntfile.js @@ -93,7 +93,7 @@ module.exports = function(grunt) { }, replace: { dist: { - src: ['dist/docs.min.js', 'dist/share.min.js', 'dist/**/*.html'], + src: ['dist/docs.min.js', 'dist/share.min.js', 'dist/**/*.html', 'dist/style/style.min.css'], overwrite: true, replacements: [{ from: '../api', diff --git a/docs-web/src/main/webapp/src/index.html b/docs-web/src/main/webapp/src/index.html index d4cce917..c7760315 100644 --- a/docs-web/src/main/webapp/src/index.html +++ b/docs-web/src/main/webapp/src/index.html @@ -4,7 +4,7 @@ Sismics Docs - + @@ -100,7 +100,7 @@ {{ appName }} diff --git a/docs-web/src/main/webapp/src/share.html b/docs-web/src/main/webapp/src/share.html index a9a7ddf8..ab67af4a 100644 --- a/docs-web/src/main/webapp/src/share.html +++ b/docs-web/src/main/webapp/src/share.html @@ -46,7 +46,7 @@