From e2fe328d3c5dea94096df17991e26855d937e621 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 6 Jun 2012 10:24:41 +0200 Subject: [PATCH] SONAR-3555 Content type is missing on static files provided by plugins --- .../org/sonar/server/plugins/MimeTypes.java | 76 +++++++++++++++++++ .../plugins/StaticResourcesServlet.java | 10 +++ .../sonar/server/plugins/MimeTypesTest.java | 38 ++++++++++ .../plugins/StaticResourcesServletTest.java | 24 ++++-- 4 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 sonar-server/src/main/java/org/sonar/server/plugins/MimeTypes.java create mode 100644 sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/MimeTypes.java b/sonar-server/src/main/java/org/sonar/server/plugins/MimeTypes.java new file mode 100644 index 00000000000..da607b0d871 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/plugins/MimeTypes.java @@ -0,0 +1,76 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.plugins; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMap; +import org.apache.commons.io.FilenameUtils; + +import java.util.Locale; +import java.util.Map; + +/** + * @since 3.1 + */ +public final class MimeTypes { + private MimeTypes() { + } + + private static final Map MAP = new ImmutableMap.Builder() + .put("json", "application/json") + .put("zip", "application/zip") + .put("tgz", "application/tgz") + .put("ps", "application/postscript") + .put("jnlp", "application/jnlp") + .put("jar", "application/java-archive") + .put("xls", "application/vnd.ms-excel") + .put("ppt", "application/vnd.ms-powerpoint") + .put("tar", "application/x-tar") + .put("xml", "application/xml") + .put("dtd", "application/xml-dtd") + .put("xslt", "application/xslt+xml") + .put("bmp", "image/bmp") + .put("gif", "image/gif") + .put("jpg", "image/jpeg") + .put("jpeg", "image/jpeg") + .put("tiff", "image/tiff") + .put("png", "image/png") + .put("svg", "image/svg+xml") + .put("ico", "image/x-icon") + .put("txt", "text/plain") + .put("csv", "text/csv") + .put("properties", "text/plain") + .put("rtf", "text/rtf") + .put("html", "text/html") + .put("css", "text/css") + .put("tsv", "text/tab-separated-values") + .build(); + + public static final String DEFAULT = "application/octet-stream"; + + public static String getByFilename(String filename) { + String extension = FilenameUtils.getExtension(filename); + String mime = null; + if (!Strings.isNullOrEmpty(extension)) { + mime = MAP.get(extension.toLowerCase(Locale.ENGLISH)); + } + return mime != null ? mime : DEFAULT; + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java b/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java index 6e06c03e0e7..fbc269dc6fb 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java @@ -19,12 +19,14 @@ */ package org.sonar.server.plugins; +import com.google.common.annotations.VisibleForTesting; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.server.platform.Platform; +import javax.activation.MimetypesFileTypeMap; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -37,6 +39,7 @@ public class StaticResourcesServlet extends HttpServlet { private static final Logger LOG = LoggerFactory.getLogger(StaticResourcesServlet.class); private static final long serialVersionUID = -2577454614650178426L; + private static final MimetypesFileTypeMap MIME_TYPES = new MimetypesFileTypeMap(); @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -57,6 +60,8 @@ public class StaticResourcesServlet extends HttpServlet { if (in != null) { out = response.getOutputStream(); IOUtils.copy(in, out); + completeContentType(response, resource); + } else { LOG.error("Unable to find resource '" + resource + "' in plugin '" + pluginKey + "'"); response.sendError(HttpServletResponse.SC_NOT_FOUND); @@ -87,4 +92,9 @@ public class StaticResourcesServlet extends HttpServlet { protected String getResourcePath(HttpServletRequest request) { return "static/" + StringUtils.substringAfter(getPluginKeyAndResourcePath(request), "/"); } + + @VisibleForTesting + void completeContentType(HttpServletResponse response, String filename) { + response.setContentType(MimeTypes.getByFilename(filename)); + } } diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java new file mode 100644 index 00000000000..b955066a141 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java @@ -0,0 +1,38 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.plugins; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class MimeTypesTest { + @Test + public void getByFilename_default_mime_type() { + assertThat(MimeTypes.getByFilename("")).isEqualTo(MimeTypes.DEFAULT); + assertThat(MimeTypes.getByFilename("unknown.extension")).isEqualTo(MimeTypes.DEFAULT); + } + + @Test + public void getByFilename() { + assertThat(MimeTypes.getByFilename("static/sqale/sqale.css")).isEqualTo("text/css"); + assertThat(MimeTypes.getByFilename("sqale.css")).isEqualTo("text/css"); + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/StaticResourcesServletTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/StaticResourcesServletTest.java index 96868ed4a3d..d4d0efce1ba 100644 --- a/sonar-server/src/test/java/org/sonar/server/plugins/StaticResourcesServletTest.java +++ b/sonar-server/src/test/java/org/sonar/server/plugins/StaticResourcesServletTest.java @@ -23,10 +23,11 @@ import org.junit.Before; import org.junit.Test; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class StaticResourcesServletTest { @@ -45,13 +46,13 @@ public class StaticResourcesServletTest { when(request.getContextPath()).thenReturn("/"); when(request.getServletPath()).thenReturn("static"); when(request.getRequestURI()).thenReturn("/static/myplugin/image.png"); - assertThat(servlet.getPluginKey(request), is("myplugin")); + assertThat(servlet.getPluginKey(request)).isEqualTo("myplugin"); when(request.getRequestURI()).thenReturn("/static/myplugin/images/image.png"); - assertThat(servlet.getPluginKey(request), is("myplugin")); + assertThat(servlet.getPluginKey(request)).isEqualTo("myplugin"); when(request.getRequestURI()).thenReturn("/static/myplugin/"); - assertThat(servlet.getPluginKey(request), is("myplugin")); + assertThat(servlet.getPluginKey(request)).isEqualTo("myplugin"); } @Test @@ -59,12 +60,19 @@ public class StaticResourcesServletTest { when(request.getContextPath()).thenReturn("/"); when(request.getServletPath()).thenReturn("static"); when(request.getRequestURI()).thenReturn("/static/myplugin/image.png"); - assertThat(servlet.getResourcePath(request), is("static/image.png")); + assertThat(servlet.getResourcePath(request)).isEqualTo("static/image.png"); when(request.getRequestURI()).thenReturn("/static/myplugin/images/image.png"); - assertThat(servlet.getResourcePath(request), is("static/images/image.png")); + assertThat(servlet.getResourcePath(request)).isEqualTo("static/images/image.png"); when(request.getRequestURI()).thenReturn("/static/myplugin/"); - assertThat(servlet.getResourcePath(request), is("static/")); + assertThat(servlet.getResourcePath(request)).isEqualTo("static/"); + } + + @Test + public void completeMimeType() { + HttpServletResponse response = mock(HttpServletResponse.class); + servlet.completeContentType(response, "static/sqale/sqale.css"); + verify(response).setContentType("text/css"); } } -- 2.39.5