/*
* 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.webx;
import static com.alibaba.citrus.test.TestEnvStatic.*;
import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.StringUtil.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.requestcontext.RequestContext;
import com.alibaba.citrus.service.requestcontext.RequestContextFactory;
import com.alibaba.citrus.service.requestcontext.rundata.RunData;
import com.alibaba.citrus.service.requestcontext.support.AbstractRequestContextFactory;
import com.alibaba.citrus.util.ServletUtil;
import com.alibaba.citrus.util.internal.Servlet3Util;
import com.alibaba.citrus.util.io.StreamUtil;
import com.alibaba.citrus.webx.handler.RequestHandler;
import com.alibaba.citrus.webx.handler.RequestHandlerContext;
import com.alibaba.citrus.webx.pipeline.TestExceptionValve;
import com.alibaba.citrus.webx.pipeline.TestValve;
import com.alibaba.citrus.webx.pipeline.ValveRunner;
import com.alibaba.citrus.webx.support.AbstractWebxRootController;
import com.alibaba.citrus.webx.util.ErrorHandlerHelper;
import com.meterware.httpunit.WebResponse;
import com.meterware.httpunit.javascript.JavaScript;
import com.meterware.servletunit.InvocationContext;
import com.meterware.servletunit.PatchedServletRunner;
import com.meterware.servletunit.ServletRunner;
import com.meterware.servletunit.ServletUnitClient;
import org.junit.After;
import org.junit.Before;
public abstract class AbstractWebxTests {
// web client
protected ServletUnitClient client;
protected WebResponse clientResponse;
protected int clientResponseCode;
protected String clientResponseContent;
protected static final ThreadLocal<RequestContextFactory> requestContextFactoryHolder = new ThreadLocal<RequestContextFactory>();
static {
Servlet3Util.setDisableServlet3Features(true); // 禁用servlet3,因为httpunit还不支持
}
protected final void prepareWebClient(String webXmlName) throws Exception {
prepareWebClient(webXmlName, "");
}
protected final void prepareWebClient(String webXmlName, String contextPath) throws Exception {
// Servlet container
File webInf = new File(srcdir, "WEB-INF");
File webXml = new File(webInf, defaultIfEmpty(webXmlName, "web.xml"));
ServletRunner servletRunner = new PatchedServletRunner(webXml, contextPath);
// Servlet client
client = servletRunner.newClient();
client.setExceptionsThrownOnErrorStatus(false);
client.getClientProperties().setAutoRedirect(false);
// Ignore script error
JavaScript.setThrowExceptionsOnError(false);
}
/** 调用servlet,取得request/response。 */
protected final void invokeServlet(String uri) throws Exception {
if (uri != null && uri.startsWith("http")) {
uri = URI.create(uri).normalize().toString(); // full uri
} else {
uri = URI.create("http://www.taobao.com/" + trimToEmpty(uri)).normalize().toString(); // partial uri
}
InvocationContext ic = client.newInvocation(uri);
ic.getFilter().doFilter(new MyHttpRequest(ic.getRequest(), uri), ic.getResponse(), ic.getFilterChain());
clientResponse = client.getResponse(ic);
clientResponseCode = clientResponse.getResponseCode();
clientResponseContent = clientResponse.getText();
}
@Before
public final void initPipeline() {
TestValve.runnerHolder.set(new SimpleValveRunner());
TestExceptionValve.runnerHolder.set(new SimpleValveRunner());
}
@After
public void dispose() {
TestValve.runnerHolder.remove();
TestExceptionValve.runnerHolder.remove();
requestContextFactoryHolder.remove();
}
/** 设置<code>WebxDispatcherServlet.internalHandlerMapping.errorHandler</code>。 */
protected void setErrorHandler(AbstractWebxRootController controller, RequestHandler handler) throws Exception {
Object o1 = getFieldValue(controller, "internalHandlerMapping", null);
getAccessibleField(o1.getClass(), "errorHandler").set(o1, handler);
}
/** 简化的error page handler。 */
protected static class SimpleValveRunner implements ValveRunner {
public void run(RunData rundata, PipelineContext pipelineContext) throws Exception {
rundata.setContentType("text/plain");
rundata.getResponse().getWriter().println("hello!");
}
}
/** 简化的error page handler。 */
public static class TestErrorHandler implements RequestHandler {
public void handleRequest(RequestHandlerContext ctx) throws Exception {
HttpServletResponse response = ctx.getResponse();
ErrorHandlerHelper helper = ErrorHandlerHelper.getInstance(ctx.getRequest());
Throwable exception = helper.getException();
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
if (exception != null) {
out.println("<pre>");
exception.printStackTrace(out);
out.println("</pre>");
}
out.flush();
}
}
public static class ResourceServlet extends HttpServlet {
private static final long serialVersionUID = -5288195741719029071L;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String path = ServletUtil.getResourcePath(req);
if ("".equals(path) || "/".equals(path)) {
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
out.print("Homepage");
out.flush();
} else {
URL resource = getServletContext().getResource(path);
URLConnection conn = resource.openConnection();
resp.setContentType(conn.getContentType());
StreamUtil.io(conn.getInputStream(), resp.getOutputStream(), true, false);
}
}
}
/** 由于httpunit getQueryString()实现得有问题, 所以只能将request包装一下。 */
public static class MyHttpRequest extends HttpServletRequestWrapper {
private String overrideQueryString;
public MyHttpRequest(HttpServletRequest request, String uri) {
super(request);
if (uri != null) {
int index = uri.indexOf("?");
if (index >= 0) {
this.overrideQueryString = uri.substring(index + 1);
}
}
}
@Override
public String getQueryString() {
if (overrideQueryString == null) {
return super.getQueryString();
} else {
return overrideQueryString;
}
}
}
public static class JavaScriptFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
if (!((HttpServletRequest) request).getRequestURI().endsWith("scriptaculous.js")) {
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
public static class RequestContextTesterFactory extends AbstractRequestContextFactory<RequestContext> {
public RequestContext getRequestContextWrapper(RequestContext wrappedContext) {
RequestContextFactory<RequestContext> threadLocalFactory = requestContextFactoryHolder.get();
if (threadLocalFactory == null) {
return wrappedContext;
} else {
return threadLocalFactory.getRequestContextWrapper(wrappedContext);
}
}
public String[] getFeatures() {
return null;
}
public FeatureOrder[] featureOrders() {
return null;
}
}
}