/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.service.jsp; import static com.alibaba.citrus.test.TestUtil.*; import static org.easymock.EasyMock.*; import static org.junit.Assert.*; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.alibaba.citrus.service.jsp.impl.JspEngineImpl; import com.alibaba.citrus.service.requestcontext.RequestContext; import com.alibaba.citrus.service.requestcontext.RequestContextChainingService; import com.alibaba.citrus.service.template.TemplateContext; import com.alibaba.citrus.service.template.TemplateNotFoundException; import com.alibaba.citrus.service.template.support.MappedTemplateContext; import com.alibaba.citrus.springext.util.ProxyTargetFactory; import com.meterware.httpunit.WebResponse; import org.junit.Test; import org.springframework.beans.FatalBeanException; import org.springframework.core.io.ResourceLoader; public class JspEngineTests extends AbstractJspEngineTests { @Test public void createEngineDirectly() throws Exception { initServlet("webapp/WEB-INF/web.xml"); // no servletContext try { new JspEngineImpl(null, null, null); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("servletContext")); } // no request try { new JspEngineImpl(servletContext, null, null); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("request")); } // no response try { new JspEngineImpl(servletContext, createMock(MockRequestProxy.class), null); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("response")); } // request not a proxy try { new JspEngineImpl(servletContext, request, response); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("expects a proxy delegating to a real object, but got an object of type " + request.getClass().getName())); } // response not a proxy try { new JspEngineImpl(servletContext, createMock(MockRequestProxy.class), response); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("expects a proxy delegating to a real object, but got an object of type " + response.getClass().getName())); } // no resource loader JspEngineImpl engine = new JspEngineImpl(servletContext, createMock(MockRequestProxy.class), createMock(MockResponseProxy.class)); try { engine.afterPropertiesSet(); fail(); } catch (IllegalArgumentException e) { assertThat(e, exception("resourceLoader")); } // ok engine = new JspEngineImpl(servletContext, createMock(MockRequestProxy.class), createMock(MockResponseProxy.class)); engine.setResourceLoader(createMock(ResourceLoader.class)); // not inited yet try { engine.getPathWithinServletContext("/test"); fail(); } catch (IllegalStateException e) { assertThat(e, exception("has not been initialized yet")); } engine.afterPropertiesSet(); } @Test public void contextRoot_getResourceOfRoot() throws Exception { // getResource("/")存在 initServlet("webapp1/WEB-INF/web.xml"); initFactory(); assertEquals("/mytemplates/mytemplate.jsp", engine.getPathWithinServletContext("/mytemplate.jsp")); try { engine.getPathWithinServletContext("/not/exist.jsp"); fail(); } catch (TemplateNotFoundException e) { assertThat(e, exception("Template", "/not/exist.jsp", "not found")); } } @Test public void contextRoot_getResourceOfWebXml() throws Exception { // getResource("/")不存在,"WEB-INF/web.xml"存在 initServlet("webapp1/WEB-INF/web.xml"); servletContext = createServletContextWrapper(false); // 使getResource("/")返回null initFactory(); assertEquals("/mytemplates/mytemplate.jsp", engine.getPathWithinServletContext("/mytemplate.jsp")); try { engine.getPathWithinServletContext("/not/exist.jsp"); fail(); } catch (TemplateNotFoundException e) { assertThat(e, exception("Template", "/not/exist.jsp", "not found")); } } @Test public void contextRoot_failed() throws Exception { // getResource("/")不存在,WEB-INF/web.xml也不存在 initServlet("webapp2/WEB-INF-2/web.xml"); servletContext = createServletContextWrapper(false); // 使getResource("/")返回null try { initFactory(); fail(); } catch (FatalBeanException e) { assertThat(e, exception(IllegalArgumentException.class, "Could not find WEBROOT")); } } @Test public void exists() throws Exception { // with default path initServlet("webapp/WEB-INF/web.xml"); initFactory(); assertEquals(true, engine.exists("/test.jsp")); assertEquals(true, engine.exists("/test.jspx")); assertEquals(false, engine.exists("/not/exist.jsp")); assertEquals(true, templateService.exists("/test.jsp")); assertEquals(true, templateService.exists("/test.jspx")); assertEquals(false, templateService.exists("/not/exist.jsp")); } @Test public void render_getText() throws Exception { render(1, false); render(1, true); } @Test public void render_writeToStream() throws Exception { render(2, false); render(2, true); } @Test public void render_writeToWriter() throws Exception { render(3, false); render(3, true); } private void render(int type, boolean jspx) throws Exception { initServlet("webapp/WEB-INF/web.xml"); initFactory(); RequestContextChainingService requestContexts = (RequestContextChainingService) factory .getBean("requestContexts"); RequestContext rc = null; try { // 预备request, response rc = requestContexts.getRequestContext(servletContext, request, response); // 设置contentType和charset,和jsp中的设置不同,以此为准 rc.getResponse().setContentType("text/plain; charset=GBK"); // JSP: text/html; charset=UTF-8 // 预备template context TemplateContext context = new MappedTemplateContext(); context.put("hello", "中国"); String jsp = jspx ? "/test.jspx" : "/test.jsp"; // 渲染 switch (type) { case 1: assertEquals("", templateService.getText(jsp, context)); break; case 2: templateService.writeTo(jsp, context, (OutputStream) null); break; case 3: templateService.writeTo(jsp, context, (Writer) null); break; default: fail(); break; } } finally { // 结束并提交response requestContexts.commitRequestContext(rc); } WebResponse webResponse = client.getResponse(ic); assertEquals("text/plain", webResponse.getContentType()); assertEquals("GBK", webResponse.getCharacterSet()); assertEquals("hello, 中国!", webResponse.getText().trim()); } public static interface MockRequestProxy extends HttpServletRequest, ProxyTargetFactory { } public static interface MockResponseProxy extends HttpServletResponse, ProxyTargetFactory { } public static class MyServlet extends HttpServlet { private static final long serialVersionUID = -4881126944249115409L; } /** 由于jasper不支持jspx,故做一个假的servlet仅用于测试。在新版的tomcat中,将自动支持jspx。 */ public static class FakeJspxServlet extends HttpServlet { private static final long serialVersionUID = 780039704847320821L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String jspx = (String) request.getAttribute("javax.servlet.include.servlet_path"); if (jspx.endsWith(".jspx")) { jspx = jspx.substring(0, jspx.length() - ".jspx".length()) + ".jsp"; } RequestDispatcher rd = getServletContext().getRequestDispatcher(jspx); rd.include(request, response); } } }