/*
* Copyright 2010 Google Inc.
*
* 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.google.jstestdriver.requesthandlers;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.servlet.RequestParameters;
import com.google.inject.servlet.RequestScoped;
import com.google.jstestdriver.annotations.RequestProtocol;
import com.google.jstestdriver.annotations.ResponseWriter;
import com.google.jstestdriver.server.gateway.GatewayRequestHandler;
import com.google.jstestdriver.server.gateway.MockRequestHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* An abstract {@link Guice} module providing an EDSL for binding {@link RequestHandler}s
* to ({@link HttpMethod}, {@link RequestMatcher}}) pairs. Also, exposes the
* {@link HttpServletRequest}, {@link HttpServletResponse} and interesting
* properties of these in the request scope.
*
* @author rdionne@google.com (Robert Dionne)
*/
public abstract class RequestHandlersModule extends AbstractModule {
private static final Logger logger = LoggerFactory.getLogger(RequestHandlersModule.class);
private final ImmutableList.Builder<RequestMatcher> matchers;
private final RequestScope requestScope;
public RequestHandlersModule() {
matchers = ImmutableList.builder();
requestScope = new RequestScope();
}
/**
* Override this method to specify ({@link HttpMethod}, {@link RequestMatcher})
* pairs associated with {@link RequestHandler}s. Also provide any further
* bindings for your handlers here.
*
* The {@link RequestDispatcher} will dispatch requests to the {@link RequestHandler}
* associated with the first matching {@link RequestMatcher}.
*
* Specify the order via:
*
* serve(GET, "/first/*", FirstHandler.class);
* serve(GET, "/first/second", SecondHandler.class);
* ...
* etc.
*/
protected abstract void configureHandlers();
@Override
protected void configure() {
configureHandlers();
bindScope(RequestScoped.class, requestScope);
bind(RequestScope.class).toInstance(requestScope);
bind(new Key<List<RequestMatcher>>() {}).toInstance(matchers.build());
bind(Servlet.class).to(RequestHandlerServlet.class).in(Singleton.class);
bind(GatewayRequestHandler.Factory.class).toProvider(
FactoryProvider.newFactory(
GatewayRequestHandler.Factory.class, GatewayRequestHandler.class));
bind(MockRequestHandler.Factory.class).toProvider(
FactoryProvider.newFactory(
MockRequestHandler.Factory.class, MockRequestHandler.class));
bind(GatewayConfiguration.class).in(Singleton.class);
}
@Provides @Singleton HttpClient provideHttpClient() {
Protocol.registerProtocol("https",
new Protocol("https", (ProtocolSocketFactory) new EasySSLProtocolSocketFactory(), 443));
MultiThreadedHttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
manager.getParams().setDefaultMaxConnectionsPerHost(20);
manager.getParams().setMaxTotalConnections(200);
HttpClient client = new HttpClient(manager);
client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
return client;
}
@Provides @Singleton ServletContext provideServletContext(Servlet servlet) {
return ((GenericServlet) servlet).getServletContext();
}
@Provides @RequestScoped HttpServletRequest provideRequest() {
return RequestHandlerServlet.getRequest();
}
@Provides @RequestScoped HttpMethod provideRequestMethod() {
return HttpMethod.valueOf(RequestHandlerServlet.getRequest().getMethod());
}
@Provides @RequestScoped @RequestProtocol String provideRequestProtocol() {
return RequestHandlerServlet.getRequest().getProtocol();
}
@SuppressWarnings("unchecked")
@Provides @RequestScoped @RequestParameters Map<String, String[]> provideRequestParameters() {
return RequestHandlerServlet.getRequest().getParameterMap();
}
@Provides @RequestScoped HttpServletResponse provideResponse() {
return RequestHandlerServlet.getResponse();
}
@Provides @RequestScoped @ResponseWriter PrintWriter provideResponseWriter() throws IOException {
return RequestHandlerServlet.getResponse().getWriter();
}
protected void serve(HttpMethod method, String pattern, Class<? extends RequestHandler> withHttpHandler) {
logger.debug("Registering {} on {} to {}", new Object[]{method, pattern, withHttpHandler});
RequestMatcher matcher = new RequestMatcher(method, pattern);
matchers.add(matcher);
MapBinder.newMapBinder(binder(), RequestMatcher.class, RequestHandler.class)
.addBinding(matcher).to(withHttpHandler).in(RequestScoped.class);
}
}