/* * Copyright 2011 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 static com.google.jstestdriver.requesthandlers.HttpMethod.ANY; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; import com.google.jstestdriver.server.gateway.GatewayRequestHandler; import com.google.jstestdriver.server.gateway.MockRequestHandler; import com.google.jstestdriver.server.gateway.MockResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.Map; import javax.servlet.ServletException; /** * An object that maintains a mapping between {@link RequestMatcher}s and * initialized {@link GatewayRequestHandler}s pointing to various hosts so that the * {@link RequestDispatcher} may instantiate {@link GatewayRequestHandler}s on * demand. * * @author rdionne@google.com (Robert Dionne) */ public class GatewayConfiguration { private static final Logger logger = LoggerFactory.getLogger(GatewayConfiguration.class); /** * JSON key identifying the {@link RequestMatcher} pattern. */ public static final String MATCHER = "matcher"; /** * JSON key identifying the host path. */ public static final String SERVER = "server"; private final GatewayRequestHandler.Factory gatewayFactory; private final MockRequestHandler.Factory mockFactory; private JsonArray gatewayConfig = new JsonArray(); private List<RequestMatcher> matchers; private Map<RequestMatcher, MockResponse> mockResponses; private Map<RequestMatcher, String> destinations; /** * Constructs a {@link GatewayConfiguration}. {@link GatewayConfiguration} is * bound to the {@link Singleton} scope. * @param gatewayFactory A Guice {@link Provider} of {@link GatewayRequestHandler}s. */ @Inject public GatewayConfiguration( GatewayRequestHandler.Factory gatewayFactory, MockRequestHandler.Factory mockFactory) { this.gatewayFactory = gatewayFactory; this.mockFactory = mockFactory; clearConfiguration(); } /** * @return A {@link List} of {@link RequestMatcher}s to hand off to the * {@link RequestDispatcher} for gatewaying matching requests to various hosts. */ public synchronized List<RequestMatcher> getMatchers() { return matchers; } /** * Instantiates a {@link GatewayRequestHandler} to gateway the current request * along to the matching host. * @param matcher The {@link RequestMatcher} that matches the current request. * @return A suitable {@link RequestHandler}. */ public synchronized RequestHandler getRequestHandler(RequestMatcher matcher) { MockResponse mockResponse = mockResponses.get(matcher); if (mockResponse != null) { return mockFactory.create(mockResponse); } String destination = destinations.get(matcher); if (destination != null) { return gatewayFactory.create(destination, matcher.getPrefix()); } return new NullRequestHandler(); } public synchronized JsonArray getGatewayConfig() { return gatewayConfig; } /** * Updates this {@link GatewayConfiguration} given the new {@code configuration} * encoded as a {@link JsonObject} by discarding previously initialized * {@link GatewayRequestHandler}s and instantiating new ones with new hosts. * @param configuration A {@link JsonObject} specifying a new configuration. * @throws ServletException If the new servlets fail to initialize. */ public synchronized void updateConfiguration(JsonArray configuration) throws ServletException { gatewayConfig = configuration; ImmutableList.Builder<RequestMatcher> matchersBuilder = ImmutableList.builder(); ImmutableMap.Builder<RequestMatcher, MockResponse> mockResponsesBuilder = ImmutableMap.builder(); ImmutableMap.Builder<RequestMatcher, String> destinationsBuilder = ImmutableMap.builder(); for (JsonElement element : configuration) { JsonObject entry = element.getAsJsonObject(); RequestMatcher matcher = new RequestMatcher(ANY, entry.get(MATCHER).getAsString()); matchersBuilder.add(matcher); if (MockResponse.entryDescribesMockResponse(entry)) { mockResponsesBuilder.put(matcher, MockResponse.buildFromEntry(entry)); } else { destinationsBuilder.put(matcher, entry.get(SERVER).getAsString()); } } this.matchers = matchersBuilder.build(); this.mockResponses = mockResponsesBuilder.build(); this.destinations = destinationsBuilder.build(); } /** * Empties the mapping of {@link RequestMatcher}s to * {@link GatewayRequestHandler}s. */ public synchronized void clearConfiguration() { this.matchers = ImmutableList.of(); this.mockResponses = ImmutableMap.of(); this.destinations = ImmutableMap.of(); } }