diff --git a/servlet/src/main/java/com/twelvemonkeys/servlet/StaticContentServlet.java b/servlet/src/main/java/com/twelvemonkeys/servlet/StaticContentServlet.java deleted file mode 100644 index 3a5c4601..00000000 --- a/servlet/src/main/java/com/twelvemonkeys/servlet/StaticContentServlet.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2011, Harald Kuhr - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.twelvemonkeys.servlet; - -import com.twelvemonkeys.io.FileUtil; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * A minimal servlet that can serve static files. Also from outside the web application. - * - * @author Harald Kuhr - * @author last modified by $Author: haraldk$ - * @version $Id: StaticContentServlet.java,v 1.0 12.12.11 15:09 haraldk Exp$ - * - * @see #setRoot(java.io.File) - */ -public final class StaticContentServlet extends HttpServlet { - - private File root; - - /** - * Configures the file system {@code root} for this servlet. - * If {@code root} is a directory, files will be served relative to the directory. - * If {@code root} is a file, only this file may be served - * - * @param root the file system root. - */ - @InitParam(name = "root") - public void setRoot(final File root) { - this.root = root; - } - - @Override - public void init() throws ServletException { - if (root == null) { - throw new ServletConfigException("File system root not configured, check 'root' init-param"); - } - else if (!root.exists()) { - throw new ServletConfigException( - String.format("File system root '%s' does not exist, check 'root' init-param", root.getAbsolutePath()) - ); - } - - log(String.format("Serving %s '%s'", root.isDirectory() ? "files from directory" : "single file", root.getAbsolutePath())); - } - - @Override - protected long getLastModified(final HttpServletRequest request) { - File file = findFileForRequest(request); - - return file.exists() ? file.lastModified() : -1L; - } - - @Override - protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException { - File file = findFileForRequest(request); - - if (file.isFile() && file.canRead()) { - // Normal file, all ok - response.setStatus(HttpServletResponse.SC_OK); - String contentType = getServletContext().getMimeType(file.getName()); - response.setContentType(contentType != null ? contentType : "application/octet-stream"); - if (file.length() <= Integer.MAX_VALUE) { - response.setContentLength((int) file.length()); - } - else { - response.setHeader("Content-Length", String.valueOf(file.length())); - } - response.setDateHeader("Last-Modified", file.lastModified()); - - InputStream in = new FileInputStream(file); - - try { - FileUtil.copy(in, response.getOutputStream()); - } - finally { - in.close(); - } - } - else { - if (file.exists()) { - // Attempted directory listing or non-readable file - response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI()); - } - else { - // No such file - response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI()); - } - } - } - - private File findFileForRequest(final HttpServletRequest request) { - String relativePath = request.getPathInfo(); - - return relativePath != null ? new File(root, relativePath) : root; - } -} diff --git a/servlet/src/test/java/com/twelvemonkeys/servlet/StaticContentServletTest.java b/servlet/src/test/java/com/twelvemonkeys/servlet/StaticContentServletTest.java deleted file mode 100644 index a3361102..00000000 --- a/servlet/src/test/java/com/twelvemonkeys/servlet/StaticContentServletTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2011, Harald Kuhr - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.twelvemonkeys.servlet; - -import org.junit.Test; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Arrays; -import java.util.Collections; - -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; - - -/** - * StaticContentServletTest - * - * @author Harald Kuhr - * @author last modified by $Author: haraldk$ - * @version $Id: StaticContentServletTest.java,v 1.0 12.12.11 15:10 haraldk Exp$ - */ -public class StaticContentServletTest { - - private static final String IMAGE_RESOURCE = "/12monkeys-splash.png"; - - private static String getFileSystemRoot() { - File root = getResourceAsFile(IMAGE_RESOURCE).getParentFile(); - return root.getAbsolutePath(); - } - - private static File getResourceAsFile(String resourceName) { - URL resource = StaticContentServletTest.class.getResource("/com/twelvemonkeys/servlet/image" + resourceName); - - try { - return new File(resource.toURI()); - } - catch (URISyntaxException e) { - throw new RuntimeException(e); - } - } - - @Test(expected = ServletException.class) - public void testBadInitNoRoot() throws ServletException { - StaticContentServlet servlet = new StaticContentServlet(); - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Collections.emptyList())); - - servlet.init(config); - } - - @Test(expected = ServletException.class) - public void testBadInit() throws ServletException { - StaticContentServlet servlet = new StaticContentServlet(); - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn("foo/bar"); - - servlet.init(config); - } - - @Test - public void testNotFound() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("image/jpeg"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot()); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("GET"); - when(request.getPathInfo()).thenReturn("/missing.jpg"); - when(request.getRequestURI()).thenReturn("/foo/missing.jpg"); - when(request.getContextPath()).thenReturn("/foo"); - - HttpServletResponse response = mock(HttpServletResponse.class); - - servlet.service(request, response); - - verify(response).sendError(HttpServletResponse.SC_NOT_FOUND, "/foo/missing.jpg"); - } - - @Test - public void testDirectoryListingForbidden() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("image/png"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot()); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("GET"); - when(request.getPathInfo()).thenReturn("/"); // Attempt directory listing - when(request.getRequestURI()).thenReturn("/foo/"); // Attempt directory listing - when(request.getContextPath()).thenReturn("/foo"); - - ServletOutputStream stream = mock(ServletOutputStream.class); - - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getOutputStream()).thenReturn(stream); - - servlet.service(request, response); - - verify(response).sendError(HttpServletResponse.SC_FORBIDDEN, "/foo/"); - } - - @Test - public void testGet() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("image/png"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot()); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("GET"); - when(request.getPathInfo()).thenReturn(IMAGE_RESOURCE); - when(request.getRequestURI()).thenReturn("/foo" + IMAGE_RESOURCE); - when(request.getContextPath()).thenReturn("/foo"); - - ServletOutputStream stream = mock(ServletOutputStream.class); - - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getOutputStream()).thenReturn(stream); - - servlet.service(request, response); - - verify(response).setStatus(HttpServletResponse.SC_OK); -// verify(stream, atLeastOnce()).write((byte[]) any(), anyInt(), anyInt()); // Mockito bug? - verify(stream, times(51)).write((byte[]) any(), anyInt(), anyInt()); // This test is fragile, but the above throws exception..? - verify(stream, atLeastOnce()).flush(); - } - - @Test - public void testGetConfiguredForSingleFile() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("text/plain"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot() + "/foo.txt"); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("GET"); - when(request.getPathInfo()).thenReturn(null); - when(request.getRequestURI()).thenReturn("/foo"); - when(request.getContextPath()).thenReturn("/foo"); - - ServletOutputStream stream = mock(ServletOutputStream.class); - - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getOutputStream()).thenReturn(stream); - - servlet.service(request, response); - - verify(response).setStatus(HttpServletResponse.SC_OK); -// verify(stream, atLeastOnce()).write((byte[]) any(), anyInt(), anyInt()); // Mockito bug? - verify(stream, times(1)).write((byte[]) any(), anyInt(), anyInt()); // This test is fragile, but the above throws exception..? - verify(stream, atLeastOnce()).flush(); - } - - @Test - public void testGetNotModified() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("image/png"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot()); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("GET"); - when(request.getPathInfo()).thenReturn(IMAGE_RESOURCE); - when(request.getRequestURI()).thenReturn("/foo" + IMAGE_RESOURCE); - when(request.getContextPath()).thenReturn("/foo"); - when(request.getDateHeader("If-Modified-Since")).thenReturn(getResourceAsFile(IMAGE_RESOURCE).lastModified()); - - ServletOutputStream stream = mock(ServletOutputStream.class); - - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getOutputStream()).thenReturn(stream); - - servlet.service(request, response); - - verify(response).setStatus(HttpServletResponse.SC_NOT_MODIFIED); - verifyZeroInteractions(stream); - } - - @Test - public void testHead() throws ServletException, IOException { - StaticContentServlet servlet = new StaticContentServlet(); - - ServletContext context = mock(ServletContext.class); - when(context.getServletContextName()).thenReturn("foo"); - when(context.getMimeType(anyString())).thenReturn("image/png"); - - ServletConfig config = mock(ServletConfig.class); - when(config.getInitParameterNames()).thenReturn(Collections.enumeration(Arrays.asList("root"))); - when(config.getInitParameter("root")).thenReturn(getFileSystemRoot()); - when(config.getServletContext()).thenReturn(context); - - servlet.init(config); - - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn("HEAD"); - when(request.getPathInfo()).thenReturn(IMAGE_RESOURCE); - when(request.getRequestURI()).thenReturn("/foo" + IMAGE_RESOURCE); - when(request.getContextPath()).thenReturn("/foo"); - - ServletOutputStream stream = mock(ServletOutputStream.class); - - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getOutputStream()).thenReturn(stream); - - servlet.service(request, response); - - verify(response).setStatus(HttpServletResponse.SC_OK); - verifyZeroInteractions(stream); - } -}