/** * Copyright 2005-2015 Red Hat, Inc. * * Red Hat licenses this file to you 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 io.apiman.gateway.platforms.war.micro; import io.apiman.common.servlet.ApimanCorsFilter; import io.apiman.common.servlet.AuthenticationFilter; import io.apiman.common.servlet.DisableCachingFilter; import io.apiman.common.servlet.LocaleFilter; import io.apiman.common.servlet.RootResourceFilter; import io.apiman.gateway.engine.GatewayConfigProperties; import io.apiman.gateway.engine.components.IBufferFactoryComponent; import io.apiman.gateway.engine.components.ICacheStoreComponent; import io.apiman.gateway.engine.components.IJdbcComponent; import io.apiman.gateway.engine.components.ILdapComponent; import io.apiman.gateway.engine.components.IPolicyFailureFactoryComponent; import io.apiman.gateway.engine.components.IRateLimiterComponent; import io.apiman.gateway.engine.components.ISharedStateComponent; import io.apiman.gateway.engine.es.ESCacheStoreComponent; import io.apiman.gateway.engine.es.ESMetrics; import io.apiman.gateway.engine.es.ESRateLimiterComponent; import io.apiman.gateway.engine.es.ESSharedStateComponent; import io.apiman.gateway.engine.es.PollCachingESRegistry; import io.apiman.gateway.engine.impl.ByteBufferFactoryComponent; import io.apiman.gateway.engine.impl.DefaultJdbcComponent; import io.apiman.gateway.engine.impl.DefaultLdapComponent; import io.apiman.gateway.engine.impl.DefaultPluginRegistry; import io.apiman.gateway.engine.policy.PolicyFactoryImpl; import io.apiman.gateway.platforms.servlet.PolicyFailureFactoryComponent; import io.apiman.gateway.platforms.servlet.connectors.HttpConnectorFactory; import io.apiman.gateway.platforms.war.filters.HttpRequestThreadLocalFilter; import io.apiman.gateway.platforms.war.listeners.WarGatewayBootstrapper; import io.apiman.gateway.platforms.war.servlets.WarGatewayServlet; import java.util.EnumSet; import javax.servlet.DispatcherType; import org.eclipse.jetty.security.ConstraintSecurityHandler; import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.security.Credential; import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher; import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; /** * This class starts up an embedded Jetty test server so that integration tests * can be performed. * * @author eric.wittmann@redhat.com */ @SuppressWarnings("nls") public class GatewayMicroService { private Server server; /** * Constructor. */ public GatewayMicroService() { configure(); } /** * Configure the gateway options. */ protected void configure() { configureGlobalVars(); configurePluginRegistry(); configureRegistry(); configureConnectorFactory(); configurePolicyFactory(); configureMetrics(); // Register test components registerComponents(); } /** * Configure some global variables in the system properties. */ protected void configureGlobalVars() { setConfigProperty("apiman.es.protocol", "http"); setConfigProperty("apiman.es.host", "localhost"); setConfigProperty("apiman.es.port", "9200"); setConfigProperty("apiman.es.username", ""); setConfigProperty("apiman.es.password", ""); } /** * Register the components. */ protected void registerComponents() { registerBufferFactoryComponent(); registerSharedStateComponent(); registerRateLimiterComponent(); registerPolicyFailureFactoryComponent(); registerCacheStoreComponent(); registerJdbcComponent(); registerLdapComponent(); } /** * The buffer factory component. */ private void registerBufferFactoryComponent() { setConfigProperty(GatewayConfigProperties.COMPONENT_PREFIX + IBufferFactoryComponent.class.getSimpleName(), ByteBufferFactoryComponent.class.getName()); } /** * The policy failure factory component. */ protected void registerPolicyFailureFactoryComponent() { setConfigProperty(GatewayConfigProperties.COMPONENT_PREFIX + IPolicyFailureFactoryComponent.class.getSimpleName(), PolicyFailureFactoryComponent.class.getName()); } /** * The rate limiter component. */ protected void registerRateLimiterComponent() { String componentPropName = GatewayConfigProperties.COMPONENT_PREFIX + IRateLimiterComponent.class.getSimpleName(); setConfigProperty(componentPropName, ESRateLimiterComponent.class.getName()); setConfigProperty(componentPropName + ".client.type", "jest"); setConfigProperty(componentPropName + ".client.protocol", "${apiman.es.protocol}"); setConfigProperty(componentPropName + ".client.host", "${apiman.es.host}"); setConfigProperty(componentPropName + ".client.port", "${apiman.es.port}"); setConfigProperty(componentPropName + ".client.username", "${apiman.es.username}"); setConfigProperty(componentPropName + ".client.password", "${apiman.es.password}"); } /** * The shared state component. */ protected void registerSharedStateComponent() { String componentPropName = GatewayConfigProperties.COMPONENT_PREFIX + ISharedStateComponent.class.getSimpleName(); setConfigProperty(componentPropName, ESSharedStateComponent.class.getName()); setConfigProperty(componentPropName + ".client.type", "jest"); setConfigProperty(componentPropName + ".client.protocol", "${apiman.es.protocol}"); setConfigProperty(componentPropName + ".client.host", "${apiman.es.host}"); setConfigProperty(componentPropName + ".client.port", "${apiman.es.port}"); setConfigProperty(componentPropName + ".client.username", "${apiman.es.username}"); setConfigProperty(componentPropName + ".client.password", "${apiman.es.password}"); } /** * The cache store component. */ protected void registerCacheStoreComponent() { String componentPropName = GatewayConfigProperties.COMPONENT_PREFIX + ICacheStoreComponent.class.getSimpleName(); setConfigProperty(componentPropName, ESCacheStoreComponent.class.getName()); setConfigProperty(componentPropName + ".client.type", "jest"); setConfigProperty(componentPropName + ".client.protocol", "${apiman.es.protocol}"); setConfigProperty(componentPropName + ".client.host", "${apiman.es.host}"); setConfigProperty(componentPropName + ".client.port", "${apiman.es.port}"); setConfigProperty(componentPropName + ".client.index", "apiman_cache"); setConfigProperty(componentPropName + ".client.username", "${apiman.es.username}"); setConfigProperty(componentPropName + ".client.password", "${apiman.es.password}"); } /** * The jdbc component. */ protected void registerJdbcComponent() { String componentPropName = GatewayConfigProperties.COMPONENT_PREFIX + IJdbcComponent.class.getSimpleName(); setConfigProperty(componentPropName, DefaultJdbcComponent.class.getName()); } /** * The ldap component. */ protected void registerLdapComponent() { String componentPropName = GatewayConfigProperties.COMPONENT_PREFIX + ILdapComponent.class.getSimpleName(); setConfigProperty(componentPropName, DefaultLdapComponent.class.getName()); } /** * The policy factory component. */ protected void configurePolicyFactory() { setConfigProperty(GatewayConfigProperties.POLICY_FACTORY_CLASS, PolicyFactoryImpl.class.getName()); } /** * The connector factory. */ protected void configureConnectorFactory() { setConfigProperty(GatewayConfigProperties.CONNECTOR_FACTORY_CLASS, HttpConnectorFactory.class.getName()); setConfigProperty(GatewayConfigProperties.CONNECTOR_FACTORY_CLASS + ".http.timeouts.read", "25"); setConfigProperty(GatewayConfigProperties.CONNECTOR_FACTORY_CLASS + ".http.timeouts.write", "25"); setConfigProperty(GatewayConfigProperties.CONNECTOR_FACTORY_CLASS + ".http.timeouts.connect", "10"); setConfigProperty(GatewayConfigProperties.CONNECTOR_FACTORY_CLASS + ".http.followRedirects", "true"); } /** * The plugin registry. */ protected void configurePluginRegistry() { setConfigProperty(GatewayConfigProperties.PLUGIN_REGISTRY_CLASS, DefaultPluginRegistry.class.getName()); } /** * The registry. */ protected void configureRegistry() { setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS, PollCachingESRegistry.class.getName()); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.type", "jest"); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.protocol", "${apiman.es.protocol}"); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.host", "${apiman.es.host}"); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.port", "${apiman.es.port}"); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.username", "${apiman.es.username}"); setConfigProperty(GatewayConfigProperties.REGISTRY_CLASS + ".client.password", "${apiman.es.password}"); } /** * Configure the metrics system. */ protected void configureMetrics() { setConfigProperty(GatewayConfigProperties.METRICS_CLASS, ESMetrics.class.getName()); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.type", "jest"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.protocol", "${apiman.es.protocol}"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.host", "${apiman.es.host}"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.port", "${apiman.es.port}"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.username", "${apiman.es.username}"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.password", "${apiman.es.password}"); setConfigProperty(GatewayConfigProperties.METRICS_CLASS + ".client.index", "apiman_metrics"); } /** * Sets a system property if it's not already set. * @param propName * @param propValue */ protected void setConfigProperty(String propName, String propValue) { if (System.getProperty(propName) == null) { System.setProperty(propName, propValue); } } /** * Start/run the server. * @throws Exception when any exception occurs */ public void start() throws Exception { long startTime = System.currentTimeMillis(); ContextHandlerCollection handlers = new ContextHandlerCollection(); addModulesToJetty(handlers); // Create the server. int serverPort = serverPort(); System.out.println("**** Starting Gateway (" + getClass().getSimpleName() + ") on port: " + serverPort); server = new Server(serverPort); server.setHandler(handlers); server.start(); long endTime = System.currentTimeMillis(); System.out.println("******* Started in " + (endTime - startTime) + "ms"); } /** * Stop the server. * @throws Exception when any exception occurs */ public void stop() throws Exception { server.stop(); } /** * @return the server port. */ public int serverPort() { return Integer.parseInt(System.getProperty("apiman.micro.gateway.port", "7777")); } /** * Configure the web application(s). * @param handlers * @throws Exception */ protected void addModulesToJetty(ContextHandlerCollection handlers) throws Exception { /* ************* * Gateway API * ************* */ ServletContextHandler gatewayApiServer = new ServletContextHandler(ServletContextHandler.SESSIONS); addSecurityHandler(gatewayApiServer); gatewayApiServer.setContextPath("/api"); gatewayApiServer.addEventListener(new ResteasyBootstrap()); gatewayApiServer.addEventListener(new WarGatewayBootstrapper()); gatewayApiServer.addFilter(HttpRequestThreadLocalFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); gatewayApiServer.addFilter(LocaleFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); gatewayApiServer.addFilter(ApimanCorsFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); gatewayApiServer.addFilter(DisableCachingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); addApiAuthFilter(gatewayApiServer); gatewayApiServer.addFilter(RootResourceFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); ServletHolder resteasyServlet = new ServletHolder(new HttpServletDispatcher()); resteasyServlet.setInitParameter("javax.ws.rs.Application", GatewayMicroServiceApplication.class.getName()); gatewayApiServer.addServlet(resteasyServlet, "/*"); gatewayApiServer.setInitParameter("resteasy.servlet.mapping.prefix", ""); handlers.addHandler(gatewayApiServer); /* ************* * Gateway * ************* */ ServletContextHandler gatewayServer = new ServletContextHandler(ServletContextHandler.SESSIONS); addSecurityHandler(gatewayServer); gatewayServer.setContextPath("/gateway"); ServletHolder servlet = new ServletHolder(new WarGatewayServlet()); gatewayServer.addServlet(servlet, "/*"); handlers.addHandler(gatewayServer); } /** * @param apiManServer * @throws Exception */ protected void addSecurityHandler(ServletContextHandler apiManServer) throws Exception { apiManServer.setSecurityHandler(createSecurityHandler()); } /** * @param apiManServer */ protected void addApiAuthFilter(ServletContextHandler apiManServer) { apiManServer.addFilter(AuthenticationFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); } /** * Creates a basic auth security handler. */ protected SecurityHandler createSecurityHandler() throws Exception { HashLoginService l = new HashLoginService(); for (User user : Users.getUsers()) { l.putUser(user.getId(), Credential.getCredential(user.getPassword()), user.getRolesAsArray()); } l.setName("apimanrealm"); ConstraintSecurityHandler csh = new ConstraintSecurityHandler(); csh.setAuthenticator(new BasicAuthenticator()); csh.setRealmName("apimanrealm"); csh.setLoginService(l); return csh; } /** * @throws InterruptedException when interrupted */ public void join() throws InterruptedException { server.join(); } }