changeset 158:c0199757fe20

Add static resource handler for web-client. Reviewed-by: jkang Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/023164.html
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 17 May 2017 19:39:08 +0200
parents e34d462cc342
children e0c80817fd11
files common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/GlobalConfiguration.java distribution/src/etc/global-config.properties server/src/main/java/com/redhat/thermostat/gateway/server/CoreServerBuilder.java server/src/main/java/com/redhat/thermostat/gateway/server/webclient/StaticAssetsHandler.java server/src/test/java/com/redhat/thermostat/gateway/server/CoreServerBuilderTest.java server/src/test/java/com/redhat/thermostat/gateway/server/webclient/StaticAssetsHandlerFactory.java services/commands/src/test/java/com/redhat/thermostat/service/commands/http/handlers/AuthBasicCoreServerTest.java
diffstat 7 files changed, 273 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/GlobalConfiguration.java	Tue May 23 14:46:14 2017 +0200
+++ b/common/core/src/main/java/com/redhat/thermostat/gateway/common/core/config/GlobalConfiguration.java	Wed May 17 19:39:08 2017 +0200
@@ -70,6 +70,17 @@
          *
          */
         SERVICES,
+        /**
+         * Specifies whether or not the swagger UI handler should get
+         * created under context path /doc
+         */
+        WITH_SWAGGER_UI,
+        /**
+         * Specifies whether or not a static resource handler, at
+         * context path /web-client, for built web-client assets
+         * should get created.
+         */
+        WITH_WEB_CLIENT
     }
 
 }
--- a/distribution/src/etc/global-config.properties	Tue May 23 14:46:14 2017 +0200
+++ b/distribution/src/etc/global-config.properties	Wed May 17 19:39:08 2017 +0200
@@ -5,3 +5,14 @@
 # The file specifying which services to deploy in the
 # servlet container.
 properties|SERVICES=services.properties
+#
+# Specifies whether or not the swagger UI handler should get
+# created under context path /doc
+#
+WITH_SWAGGER_UI=true
+#
+# Specifies whether or not a static resource handler, at
+# context path /web-client, for built web-client assets
+# should get created.
+#
+WITH_WEB_CLIENT=true
--- a/server/src/main/java/com/redhat/thermostat/gateway/server/CoreServerBuilder.java	Tue May 23 14:46:14 2017 +0200
+++ b/server/src/main/java/com/redhat/thermostat/gateway/server/CoreServerBuilder.java	Wed May 17 19:39:08 2017 +0200
@@ -52,16 +52,30 @@
 
 import com.redhat.thermostat.gateway.common.core.config.Configuration;
 import com.redhat.thermostat.gateway.common.core.config.GlobalConfiguration;
+import com.redhat.thermostat.gateway.common.core.config.GlobalConfiguration.ConfigurationKey;
 import com.redhat.thermostat.gateway.server.apidoc.SwaggerUiHandler;
 import com.redhat.thermostat.gateway.server.services.CoreService;
 import com.redhat.thermostat.gateway.server.services.CoreServiceBuilder;
+import com.redhat.thermostat.gateway.server.webclient.StaticAssetsHandler;
 
 public class CoreServerBuilder {
 
-    private Server server = new Server();
+    private final SwaggerUiHandler swaggerHandler;
+    private final StaticAssetsHandler staticAssetsHandler;
+    private final Server server = new Server();
     private CoreServiceBuilder coreServiceBuilder;
     private Configuration serverConfig;
 
+    public CoreServerBuilder() {
+        this(new SwaggerUiHandler(), new StaticAssetsHandler());
+    }
+
+    // package-private for test-overrides
+    CoreServerBuilder(SwaggerUiHandler swaggerHandler, StaticAssetsHandler staticHandler) {
+        this.staticAssetsHandler = staticHandler;
+        this.swaggerHandler = swaggerHandler;
+    }
+
     public CoreServerBuilder setServiceBuilder(CoreServiceBuilder builder) {
         this.coreServiceBuilder = builder;
         return this;
@@ -94,16 +108,31 @@
             }
         }
 
-        // Set up Swagger UI-based API doc handler together with the service handlers.
-        // It'll be able to generate API docs based on any URL accessible
-        // swagger spec (swagger.json/swagger.yaml). Hence, we set this up
-        // once in the deploying server and make the swagger spec available
-        // in the services themselves
-        ContextHandler swaggerHandler = new SwaggerUiHandler().createSwaggerResourceHandler();
-        contextHandlerCollection.addHandler(swaggerHandler);
+        Map<String, Object> config = serverConfig.asMap();
+        if (isEnabled(config, ConfigurationKey.WITH_SWAGGER_UI)) {
+            // Set up Swagger UI-based API doc handler together with the service handlers.
+            // It'll be able to generate API docs based on any URL accessible
+            // swagger spec (swagger.json/swagger.yaml). Hence, we set this up
+            // once in the deploying server and make the swagger spec available
+            // in the services themselves
+            ContextHandler swHandler = swaggerHandler.createSwaggerResourceHandler();
+            contextHandlerCollection.addHandler(swHandler);
+        }
+
+        if (isEnabled(config, ConfigurationKey.WITH_WEB_CLIENT)) {
+            // Set up a static resource handler which serves static assets
+            // via /web-client context path
+            ContextHandler webClientHandler = staticAssetsHandler.create();
+            contextHandlerCollection.addHandler(webClientHandler);
+        }
+
         server.setHandler(contextHandlerCollection);
     }
 
+    private boolean isEnabled(Map<String, Object> config, ConfigurationKey configKey) {
+        return Boolean.parseBoolean((String)config.get(configKey.name()));
+    }
+
     private void setupConnector() {
         ServerConnector httpConnector = new ServerConnector(server);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/com/redhat/thermostat/gateway/server/webclient/StaticAssetsHandler.java	Wed May 17 19:39:08 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.server.webclient;
+
+import java.io.File;
+
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+
+import com.redhat.thermostat.gateway.common.core.servlet.GlobalConstants;
+
+public class StaticAssetsHandler {
+
+    private static final String WEB_CLIENT_ASSETS_FOLDER = "web-client";
+    private static final String WEB_CLIENT_CONTEXT_PATH = "/" + WEB_CLIENT_ASSETS_FOLDER;
+
+    private final EnvHelper envHelper;
+
+    public StaticAssetsHandler() {
+        this(new EnvHelper());
+    }
+
+    // package-private for test-overrides
+    StaticAssetsHandler(EnvHelper helper) {
+        this.envHelper = helper;
+    }
+
+    public ContextHandler create() {
+        ContextHandler apiContext = new ContextHandler();
+        apiContext.setContextPath(WEB_CLIENT_CONTEXT_PATH);
+        ResourceHandler resourceHandler = new ResourceHandler();
+        resourceHandler.setDirectoriesListed(false);
+        resourceHandler.setWelcomeFiles(new String[]{ "index.html" });
+        File webClientDir = getWebClientAssetsDir();
+        resourceHandler.setResourceBase(webClientDir.getAbsolutePath());
+        apiContext.setHandler(resourceHandler);
+        return apiContext;
+    }
+
+    private File getWebClientAssetsDir() {
+        String gatewayHome = envHelper.getEnv(GlobalConstants.GATEWAY_HOME_ENV);
+        if (gatewayHome == null) {
+            throw new RuntimeException("THERMOSTAT_GATEWAY_HOME environment variable not set");
+        }
+        return new File(gatewayHome, WEB_CLIENT_ASSETS_FOLDER);
+    }
+
+    public static class EnvHelper {
+        public String getEnv(String var) {
+            return System.getenv(var);
+        }
+    }
+}
--- a/server/src/test/java/com/redhat/thermostat/gateway/server/CoreServerBuilderTest.java	Tue May 23 14:46:14 2017 +0200
+++ b/server/src/test/java/com/redhat/thermostat/gateway/server/CoreServerBuilderTest.java	Wed May 17 19:39:08 2017 +0200
@@ -54,13 +54,86 @@
 
 import com.redhat.thermostat.gateway.common.core.config.Configuration;
 import com.redhat.thermostat.gateway.common.core.config.GlobalConfiguration;
+import com.redhat.thermostat.gateway.server.apidoc.SwaggerUiHandler;
 import com.redhat.thermostat.gateway.server.services.CoreService;
 import com.redhat.thermostat.gateway.server.services.CoreServiceBuilder;
+import com.redhat.thermostat.gateway.server.webclient.StaticAssetsHandler;
+import com.redhat.thermostat.gateway.server.webclient.StaticAssetsHandler.EnvHelper;
+import com.redhat.thermostat.gateway.server.webclient.StaticAssetsHandlerFactory;
 
 public class CoreServerBuilderTest {
 
+    /**
+     * Tests building without optional handlers, like swagger-ui or web-client
+     * static resources.
+     */
     @Test
-    public void testBuild() {
+    public void testBuildNoDefaultHandlers() {
+        CoreServiceBuilder serviceBuilder = getMockServiceBuilder();
+
+        Map<String, Object> configMap = new HashMap<>();
+        String ip = "127.0.0.1";
+        String port = "8080";
+        configMap.put(GlobalConfiguration.ConfigurationKey.IP.name(), ip);
+        configMap.put(GlobalConfiguration.ConfigurationKey.PORT.name(), port);
+        configMap.put(GlobalConfiguration.ConfigurationKey.WITH_SWAGGER_UI.name(), Boolean.FALSE.toString());
+        configMap.put(GlobalConfiguration.ConfigurationKey.WITH_WEB_CLIENT.name(), Boolean.FALSE.toString());
+        Configuration configuration = getMockConfiguration(configMap);
+
+        CoreServerBuilder builder = new CoreServerBuilder();
+        builder.setServerConfiguration(configuration);
+        builder.setServiceBuilder(serviceBuilder);
+
+        Server server = builder.build();
+
+        ContextHandlerCollection handler = (ContextHandlerCollection) server.getHandler();
+        // Expects 1 handlers, 1 service mocked. Others disabled by config
+        assertEquals(1, handler.getHandlers().length);
+
+        ServerConnector connector = (ServerConnector) server.getConnectors()[0];
+        assertEquals(connector.getPort(), Integer.parseInt(port));
+        assertEquals(connector.getHost(), ip);
+    }
+
+    /**
+     * Tests building *with* optional handlers, like swagger-ui or web-client
+     * static resources.
+     */
+    @Test
+    public void testBuildWithDefaultHandlers() {
+        CoreServiceBuilder serviceBuilder = getMockServiceBuilder();
+
+        Map<String, Object> configMap = new HashMap<>();
+        String ip = "127.0.0.1";
+        String port = "8080";
+        configMap.put(GlobalConfiguration.ConfigurationKey.IP.name(), ip);
+        configMap.put(GlobalConfiguration.ConfigurationKey.PORT.name(), port);
+        configMap.put(GlobalConfiguration.ConfigurationKey.WITH_SWAGGER_UI.name(), Boolean.TRUE.toString());
+        configMap.put(GlobalConfiguration.ConfigurationKey.WITH_WEB_CLIENT.name(), Boolean.TRUE.toString());
+        Configuration configuration = getMockConfiguration(configMap);
+
+        SwaggerUiHandler swaggerHandler = new SwaggerUiHandler();
+        EnvHelper envHelper = mock(EnvHelper.class);
+        when(envHelper.getEnv(any(String.class))).thenReturn("/fake-gw-home");
+        StaticAssetsHandler staticAssetsHandler = new StaticAssetsHandlerFactory().create(envHelper);
+        CoreServerBuilder builder = new CoreServerBuilder(swaggerHandler, staticAssetsHandler);
+        builder.setServerConfiguration(configuration);
+        builder.setServiceBuilder(serviceBuilder);
+
+        Server server = builder.build();
+
+        ContextHandlerCollection handler = (ContextHandlerCollection) server.getHandler();
+        // Expects 3 handlers, 1 service mocked above, 1 swagger ui handler, 1 static resource handler
+        assertEquals(3, handler.getHandlers().length);
+    }
+
+    private Configuration getMockConfiguration(Map<String, Object> configMap) {
+        Configuration configuration = mock(Configuration.class);
+        when(configuration.asMap()).thenReturn(configMap);
+        return configuration;
+    }
+
+    private CoreServiceBuilder getMockServiceBuilder() {
         CoreServiceBuilder serviceBuilder = mock(CoreServiceBuilder.class);
         List<CoreService> serviceList = new ArrayList<>();
         CoreService service = mock(CoreService.class);
@@ -69,28 +142,6 @@
         when(service.createServletContextHandler(any(Server.class))).thenReturn(servletContextHandler);
         serviceList.add(service);
         when(serviceBuilder.build()).thenReturn(serviceList);
-
-        Map<String, Object> configMap = new HashMap<>();
-        String ip = "127.0.0.1";
-        String port = "8080";
-        configMap.put(GlobalConfiguration.ConfigurationKey.IP.name(), ip);
-        configMap.put(GlobalConfiguration.ConfigurationKey.PORT.name(), port);
-        Configuration configuration = mock(Configuration.class);
-        when(configuration.asMap()).thenReturn(configMap);
-
-
-        CoreServerBuilder builder = new CoreServerBuilder();
-        builder.setServerConfiguration(configuration);
-        builder.setServiceBuilder(serviceBuilder);
-
-        Server server = builder.build();
-
-        ContextHandlerCollection handler = (ContextHandlerCollection) server.getHandler();
-        // Expects 2 handlers, 1 service mocked above and 1 swagger ui handler
-        assertEquals(2, handler.getHandlers().length);
-
-        ServerConnector connector = (ServerConnector) server.getConnectors()[0];
-        assertEquals(connector.getPort(), Integer.parseInt(port));
-        assertEquals(connector.getHost(), ip);
+        return serviceBuilder;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/test/java/com/redhat/thermostat/gateway/server/webclient/StaticAssetsHandlerFactory.java	Wed May 17 19:39:08 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-2017 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.gateway.server.webclient;
+
+import com.redhat.thermostat.gateway.server.webclient.StaticAssetsHandler.EnvHelper;
+
+/**
+ * Test artifact to create a handler with a mock env helper
+ *
+ */
+public class StaticAssetsHandlerFactory {
+
+    public StaticAssetsHandler create(EnvHelper helper) {
+        return new StaticAssetsHandler(helper);
+    }
+}
--- a/services/commands/src/test/java/com/redhat/thermostat/service/commands/http/handlers/AuthBasicCoreServerTest.java	Tue May 23 14:46:14 2017 +0200
+++ b/services/commands/src/test/java/com/redhat/thermostat/service/commands/http/handlers/AuthBasicCoreServerTest.java	Wed May 17 19:39:08 2017 +0200
@@ -107,6 +107,8 @@
                 Map<String, Object> config = new HashMap<>();
                 config.put(GlobalConfiguration.ConfigurationKey.IP.name(), TEST_ADDRESS);
                 config.put(GlobalConfiguration.ConfigurationKey.PORT.name(), Integer.toString(TEST_PORT));
+                config.put(GlobalConfiguration.ConfigurationKey.WITH_SWAGGER_UI.name(), Boolean.FALSE.toString());
+                config.put(GlobalConfiguration.ConfigurationKey.WITH_WEB_CLIENT.name(), Boolean.FALSE.toString());
                 return config;
             }
         });