Java tutorial
/* * BeanShell Web * Copyright (C) 2012 Stefano Fornari * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License version 3 as published by * the Free Software Foundation with the addition of the following permission * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED * WORK IN WHICH THE COPYRIGHT IS OWNED BY Stefano Fornari, Stefano Fornari * DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program; if not, see http://www.gnu.org/licenses or write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA. */ package ste.web.http.velocity; import java.io.File; import java.net.URI; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.http.HttpStatus; import org.apache.http.HttpVersion; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHttpRequest; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicRequestLine; import org.apache.velocity.exception.ParseErrorException; import static org.assertj.core.api.Assertions.fail; import static org.assertj.core.api.BDDAssertions.then; import org.junit.Test; import org.junit.Before; import static ste.web.beanshell.Constants.*; import ste.web.http.HttpSessionContext; import ste.web.http.HttpUtils; import ste.web.http.QueryString; /** * * @author ste */ public class BugFreeVelocityHandler { public static final String ROOT = "src/test/webroot"; public static final String TEST_URL_PARAM1 = "p_one"; public static final String TEST_URL_PARAM2 = "p_two"; public static final String TEST_URL_PARAM3 = "p_three"; public static final String TEST_REQ_ATTR_NAME1 = "a_one"; public static final String TEST_REQ_ATTR_NAME2 = "a_two"; public static final String TEST_REQ_ATTR_NAME3 = "a_three"; public static final String TEST_VALUE1 = "uno"; public static final String TEST_VALUE2 = "due"; public static final String TEST_VALUE3 = "tre"; public static final String TEST_VALUE4 = "uno/due"; // path separators may cause issues public static final String TEST_VIEW1 = "first.v"; public static final String TEST_VIEW2 = "second.v"; public static final String TEST_VIEW3 = "third.v"; public static final String TEST_VIEW4 = "fourth.v"; public static final String TEST_VIEW5 = "secondlevelview.v"; public static final String TEST_NO_VIEW1 = "notexisting.v"; public static final String TEST_NO_VIEW2 = "invalidview"; public static final String TEST_NO_VIEW3 = "invalidview.a"; public static final String TEST_ERROR_VIEW1 = "witherror.v"; private BasicHttpRequest request; private BasicHttpResponse response; private HttpSessionContext context; private VelocityHandler handler; public BugFreeVelocityHandler() { request = null; response = null; context = null; handler = null; } @Before public void startUp() throws Exception { request = new BasicHttpRequest("GET", String.format("controller.bsh?%s=%s", TEST_URL_PARAM1, TEST_VALUE4)); response = HttpUtils.getBasicResponse(true); context = new HttpSessionContext(); handler = new VelocityHandler(ROOT); } @Test public void constructors() throws Exception { try { new VelocityHandler(null); fail("missing check for null parameters"); } catch (IllegalArgumentException x) { then(x.getMessage()).contains("webroot").contains("not be null"); } VelocityHandler h = new VelocityHandler(new File(ROOT).getAbsolutePath()); then(handler.getViewsFolder()).isEqualTo(DEFAULT_VIEWS_PREFIX); then(handler.getEngine()).isNotNull(); h = new VelocityHandler(new File(ROOT).getAbsolutePath(), "/v"); then(h.getViewsFolder()).isEqualTo("/v"); h = new VelocityHandler(new File(ROOT).getAbsolutePath(), null); then(h.getViewsFolder()).isEqualTo(DEFAULT_VIEWS_PREFIX); h = new VelocityHandler(new File(ROOT).getAbsolutePath(), "/a"); then(h.getViewsFolder()).isEqualTo("/a"); } @Test public void viewDefaultDirs() throws Exception { context.setAttribute(ATTR_VIEW, TEST_VIEW1); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); } @Test public void viewNonDefaultDirs() throws Exception { handler.setViewsFolder("/views"); context.setAttribute(ATTR_VIEW, TEST_VIEW3); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); handler.setViewsFolder("views"); context.setAttribute(ATTR_VIEW, TEST_VIEW4); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); } @Test public void viewInSubDirs() throws Exception { handler.setViewsFolder("/views"); context.setAttribute(ATTR_VIEW, TEST_VIEW5); handler.handle(new BasicHttpRequest("GET", "/first/controller.bsh"), response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); } @Test public void viewNotFound() throws Exception { context.setAttribute(ATTR_VIEW, TEST_NO_VIEW1); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_NOT_FOUND); then(response.getStatusLine().getReasonPhrase()).contains(TEST_NO_VIEW1); } /** * Velocity views are identified by the .v extension. We replace here * <cde>request.isHandled()</vode> available in jetty with a check on * the content length, but we may need to revisit this. * * @throws Exception */ @Test public void velocityViewOnly() throws Exception { context.setAttribute(ATTR_VIEW, TEST_NO_VIEW2); handler.handle(request, response, context); then(response.getEntity().getContentLength()).isEqualTo(-1); context.setAttribute(ATTR_VIEW, TEST_NO_VIEW3); handler.handle(request, response, context); then(response.getEntity().getContentLength()).isEqualTo(-1); } @Test public void viewError() { try { context.setAttribute(ATTR_VIEW, TEST_ERROR_VIEW1); handler.handle(request, response, context); fail(TEST_ERROR_VIEW1 + " error shall throw a HttpException"); } catch (Exception x) { // // OK // then(x.getCause()).isInstanceOf(ParseErrorException.class); } } @Test public void noViewProvided() throws Exception { handler.handle(request, response, context); then(response.getEntity().getContentLength()).isEqualTo(-1); } @Test public void attributes() throws Exception { context.setAttribute(ATTR_VIEW, TEST_VIEW1); context.setAttribute(TEST_REQ_ATTR_NAME1, TEST_VALUE1); context.setAttribute(TEST_REQ_ATTR_NAME2, TEST_VALUE2); context.setAttribute(TEST_REQ_ATTR_NAME3, TEST_VALUE3); handler.handle(request, response, context); ByteArrayOutputStream baos = new ByteArrayOutputStream(); response.getEntity().writeTo(baos); then(baos.toString()) .isEqualTo(String.format("First (%s,%s,%s,%s)", TEST_VIEW1, TEST_VALUE1, TEST_VALUE2, TEST_VALUE3)); } @Test public void parameters() throws Exception { QueryString qs = QueryString.create(); qs.set(TEST_URL_PARAM1, TEST_VALUE1); qs.set(TEST_URL_PARAM2, TEST_VALUE2); qs.set(TEST_URL_PARAM3, TEST_VALUE3); BasicRequestLine req = new BasicRequestLine("GET", qs.apply(new URI("index.v")).toString(), HttpVersion.HTTP_1_1); context.setAttribute(ATTR_VIEW, TEST_VIEW2); handler.setViewsFolder("/views"); handler.handle(new BasicHttpRequest(req), response, context); ByteArrayOutputStream baos = new ByteArrayOutputStream(); response.getEntity().writeTo(baos); then(baos.toString()).isEqualTo(String.format("Second (%s,%s,%s)", TEST_VALUE1, TEST_VALUE2, TEST_VALUE3)); } @Test public void setContentTypeIfNotSetAlready() throws Exception { // // content-type not set yet // context.setAttribute(ATTR_VIEW, TEST_VIEW1); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); then(response.getEntity().getContentType().getValue()).isEqualTo(mime(ContentType.TEXT_HTML)); // // content-type already set // ((BasicHttpEntity) response.getEntity()).setContentType(mime(ContentType.APPLICATION_OCTET_STREAM)); handler.handle(request, response, context); then(response.getStatusLine().getStatusCode()).isEqualTo(HttpStatus.SC_OK); then(response.getEntity().getContentType().getValue()) .isEqualTo(mime(ContentType.APPLICATION_OCTET_STREAM)); } // --------------------------------------------------------- Private methods private String mime(final ContentType type) { return type.getMimeType(); } }