changeset 796:9e42f29a200d

Assemble WAR for webservice deployment. Reviewed-by: neugens, jerboaa Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-November/004162.html
author Roman Kennke <rkennke@redhat.com>
date Wed, 21 Nov 2012 21:28:09 +0100
parents 9fdbdf22d9d4
children d6145521e208
files distribution/config/commands/webservice.properties distribution/pom.xml pom.xml storage/core/src/main/java/com/redhat/thermostat/storage/core/StorageProviderUtil.java web/cmd/pom.xml web/cmd/src/main/java/com/redhat/thermostat/web/cmd/Activator.java web/cmd/src/main/java/com/redhat/thermostat/web/cmd/WebServiceCommand.java web/cmd/src/main/java/com/redhat/thermostat/web/cmd/WebServiceLauncher.java web/cmd/src/test/java/com/redhat/thermostat/web/cmd/WebServiceCommandTest.java web/cmd/src/test/java/com/redhat/thermostat/web/cmd/WebServiceLauncherTest.java web/common/src/main/java/com/redhat/thermostat/web/common/StorageWrapper.java web/pom.xml web/server/pom.xml web/server/src/main/java/com/redhat/thermostat/web/server/Activator.java web/server/src/main/java/com/redhat/thermostat/web/server/IpPortsParser.java web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceCommand.java web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceLauncher.java web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java web/server/src/main/java/com/redhat/thermostat/web/server/internal/IpPortsParser.java web/server/src/test/java/com/redhat/thermostat/web/server/WebServiceCommandTest.java web/server/src/test/java/com/redhat/thermostat/web/server/WebServiceLauncherTest.java web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java web/server/src/test/java/com/redhat/thermostat/web/server/internal/IpPortsParserTest.java web/war/pom.xml web/war/src/main/webapp/WEB-INF/web.xml
diffstat 25 files changed, 856 insertions(+), 651 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/config/commands/webservice.properties	Mon Nov 19 18:21:20 2012 +0100
+++ b/distribution/config/commands/webservice.properties	Wed Nov 21 21:28:09 2012 +0100
@@ -1,4 +1,5 @@
-bundles = thermostat-web-server-@project.version@.jar, \
+bundles = thermostat-web-cmd-@project.version@.jar, \
+          thermostat-web-server-@project.version@.jar, \
           thermostat-web-common-@project.version@.jar, \
           thermostat-thread-collector-@project.version@.jar, \
           commons-fileupload-@fileupload.version@.jar, \
--- a/distribution/pom.xml	Mon Nov 19 18:21:20 2012 +0100
+++ b/distribution/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -380,7 +380,7 @@
     </dependency>
     <dependency>
         <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-web-server</artifactId>
+        <artifactId>thermostat-web-cmd</artifactId>
         <version>${project.version}</version>
     </dependency>
     <dependency>
--- a/pom.xml	Mon Nov 19 18:21:20 2012 +0100
+++ b/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -88,6 +88,7 @@
     <netty.version>3.2.4.Final</netty.version>
     <httpcomponents.version>4.1.2</httpcomponents.version>
     <fileupload.version>1.2.2</fileupload.version>
+    <jetty.version>8.1.5.v20120716</jetty.version>
   </properties>
 
   <repositories>
--- a/storage/core/src/main/java/com/redhat/thermostat/storage/core/StorageProviderUtil.java	Mon Nov 19 18:21:20 2012 +0100
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/StorageProviderUtil.java	Wed Nov 21 21:28:09 2012 +0100
@@ -1,5 +1,6 @@
 package com.redhat.thermostat.storage.core;
 
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
@@ -14,7 +15,8 @@
     // specify isStorageRequired() == true and the launcher handles the rest
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public static StorageProvider getStorageProvider(StartupConfiguration config) {
-        BundleContext ctxt = FrameworkUtil.getBundle(StorageProviderUtil.class).getBundleContext();
+        Bundle bundle = FrameworkUtil.getBundle(StorageProviderUtil.class);
+        BundleContext ctxt = bundle.getBundleContext();
         try {
             ServiceReference[] refs = ctxt.getServiceReferences(StorageProvider.class.getName(), null);
             for (int i = 0; i < refs.length; i++) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-web</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-web-cmd</artifactId>
+  <packaging>bundle</packaging>
+
+  <name>Thermostat Web Service Command</name>
+
+  <dependencies>
+  
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-server</artifactId>
+      <version>${jetty.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-webapp</artifactId>
+      <version>${jetty.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-web-server</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>com.redhat.thermostat.web.cmd</Bundle-SymbolicName>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Bundle-Activator>com.redhat.thermostat.web.cmd.Activator</Bundle-Activator>
+            <Export-Package>com.redhat.thermostat.web.cmd</Export-Package>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/src/main/java/com/redhat/thermostat/web/cmd/Activator.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 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.web.cmd;
+
+import java.util.Arrays;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.cli.CommandRegistry;
+import com.redhat.thermostat.common.cli.CommandRegistryImpl;
+
+public class Activator implements BundleActivator {
+
+    private CommandRegistry reg;
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        reg = new CommandRegistryImpl(context);
+        reg.registerCommands(Arrays.asList(new WebServiceCommand()));
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        reg.unregisterCommands();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/src/main/java/com/redhat/thermostat/web/cmd/WebServiceCommand.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2012 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.web.cmd;
+
+import java.util.List;
+
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleCommand;
+import com.redhat.thermostat.web.server.IpPortPair;
+import com.redhat.thermostat.web.server.IpPortsParser;
+
+public class WebServiceCommand extends SimpleCommand {
+
+    private WebServiceLauncher serviceLauncher;
+    
+    public WebServiceCommand() {
+        this.serviceLauncher = new WebServiceLauncher();
+    }
+    
+    // Constructor for testing
+    WebServiceCommand(WebServiceLauncher launcher) {
+        this.serviceLauncher = launcher;
+    }
+
+    @Override
+    public void run(CommandContext ctx) throws CommandException {
+        String storageURL = ctx.getArguments().getArgument("storageURL");
+        serviceLauncher.setIpAddresses(parseIPsPorts(ctx.getArguments().getArgument("bindAddrs")));
+        serviceLauncher.setStorageURL(storageURL);
+        try {
+            // this blocks
+            serviceLauncher.start();
+        } catch (InterruptedException e) {
+            // just shut down cleanly
+            try {
+                serviceLauncher.stop();
+            } catch (Exception ex) {
+                ex.printStackTrace(ctx.getConsole().getError());
+                throw new CommandException(ex);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace(ctx.getConsole().getError());
+            throw new CommandException(ex);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "webservice";
+    }
+
+    @Override
+    public boolean isStorageRequired() {
+        return false;
+    }
+
+    private List<IpPortPair> parseIPsPorts(String rawIpsPorts) throws CommandException {
+        IpPortsParser parser = new IpPortsParser(rawIpsPorts);
+        try {
+           parser.parse(); 
+        } catch (IllegalArgumentException e) {
+            throw new CommandException(e);
+        }
+        return parser.getIpsPorts();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/src/main/java/com/redhat/thermostat/web/cmd/WebServiceLauncher.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2012 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.web.cmd;
+
+import java.util.List;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.web.server.WebStorageEndPoint;
+import com.redhat.thermostat.web.server.IpPortPair;
+
+class WebServiceLauncher {
+
+    private Server server;
+    private String storageURL;
+    // IP/Port pairs, keyed by IP
+    private List<IpPortPair> ipsPorts;
+    
+    WebServiceLauncher() {
+        server = new Server();
+    }
+    
+    // Constructor for testing
+    WebServiceLauncher(Server server) {
+        this.server = server;
+    }
+
+    void start() throws Exception {
+        checkConfig();
+        Connector[] connectors = new Connector[ipsPorts.size()];
+        for (int i = 0; i < ipsPorts.size(); i++) {
+            IpPortPair pair = ipsPorts.get(i);
+            connectors[i] = new SelectChannelConnector();
+            connectors[i].setPort(pair.getPort());
+            connectors[i].setHost(pair.getIp());
+        }
+        server.setConnectors( connectors );
+        ServletHandler handler = new ServletHandler();
+        ServletHolder servletHolder = new ServletHolder("rest-storage-end-point", new WebStorageEndPoint());
+        servletHolder.setInitParameter(WebStorageEndPoint.STORAGE_ENDPOINT, storageURL);
+        handler.setServlets(new ServletHolder[] { servletHolder });
+        ServletMapping mapping = new ServletMapping();
+        mapping.setPathSpec("/");
+        mapping.setServletName("rest-storage-end-point");
+        handler.setServletMappings(new ServletMapping[] { mapping });
+        server.setHandler(handler);
+        server.start();
+        server.join();
+    }
+
+    void stop() throws Exception {
+        server.stop();
+        server.join();
+    }
+
+    public void setStorageURL(String storageURL) {
+        this.storageURL = storageURL;
+    }
+
+    public void setIpAddresses(List<IpPortPair> ipsPorts) {
+        this.ipsPorts = ipsPorts;
+    }
+
+    /*
+     * StorageURL, port must have been set
+     */
+    private void checkConfig() throws InvalidConfigurationException {
+        if (storageURL == null) {
+            throw new InvalidConfigurationException("Storage URL must be set");
+        }
+        if (ipsPorts == null) {
+            throw new InvalidConfigurationException("IP adresses to bind to must be set");
+        }
+        for (IpPortPair pair: ipsPorts) {
+            if (pair.getPort() <= 0) {
+                throw new InvalidConfigurationException("Invalid port number " + pair.getPort());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/src/test/java/com/redhat/thermostat/web/cmd/WebServiceCommandTest.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 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.web.cmd;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.any;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.SimpleArguments;
+import com.redhat.thermostat.test.TestCommandContextFactory;
+
+public class WebServiceCommandTest {
+
+    private TestCommandContextFactory cmdCtxFactory;
+    private BundleContext bundleContext;
+    private WebServiceLauncher launcher;
+    private WebServiceCommand cmd;
+    
+    @Before
+    public void setUp() {
+        Bundle sysBundle = mock(Bundle.class);
+        bundleContext = mock(BundleContext.class);
+        when(bundleContext.getBundle(0)).thenReturn(sysBundle);
+        cmdCtxFactory = new TestCommandContextFactory(bundleContext);
+        launcher = mock(WebServiceLauncher.class);
+        cmd = new WebServiceCommand(launcher);
+    }
+    
+    @After
+    public void tearDown() {
+        cmdCtxFactory = null;
+        cmd = null;
+        launcher = null;
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public void verifyLauncherStart() throws Exception {
+        SimpleArguments args = new SimpleArguments();
+        String storageUrl = "mongodb://127.0.0.1:27518";
+        args.addArgument("storageURL", storageUrl);
+        args.addArgument("bindAddrs", "127.0.0.1:8888,127.0.0.2:9999");
+        try {
+            cmd.run(cmdCtxFactory.createContext(args));
+        } catch (CommandException e) {
+            fail("should not throw exception");
+        }
+        verify(launcher).setStorageURL(storageUrl);
+        verify(launcher).setIpAddresses(any(List.class));
+        verify(launcher).start();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/cmd/src/test/java/com/redhat/thermostat/web/cmd/WebServiceLauncherTest.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012 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.web.cmd;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.server.Server;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.web.server.IpPortPair;
+
+public class WebServiceLauncherTest {
+    
+    private WebServiceLauncher launcher;
+    private List<IpPortPair> dummyIp;
+    
+    @Before
+    public void setUp() {
+        dummyIp = new ArrayList<IpPortPair>();
+        dummyIp.add(new IpPortPair("127.0.0.1", 8889));
+    }
+    
+    @After
+    public void tearDown() {
+        launcher = null;
+        dummyIp = null;
+    }
+    
+    @Test( expected=InvalidConfigurationException.class )
+    public void unsetStorageURLThrowsException() throws Exception {
+        launcher = new WebServiceLauncher();
+        launcher.setIpAddresses(dummyIp);
+        launcher.start();
+    }
+    
+    @Test( expected=InvalidConfigurationException.class )
+    public void unsetIpAddressesThrowsException() throws Exception {
+        launcher = new WebServiceLauncher();
+        launcher.setStorageURL("something not null");
+        launcher.setIpAddresses(null);
+        launcher.start();
+    }
+    
+    @Test
+    public void invalidPortThrowsException() throws Exception {
+        int excptnsThrown = 0;
+        int excptnsExpected = 2;
+        launcher = new WebServiceLauncher();
+        List<IpPortPair> ips = new ArrayList<>();
+        ips.add(new IpPortPair("127.0.0.1", -10));
+        try {
+            launcher.setIpAddresses(ips);
+            launcher.start();
+        } catch (InvalidConfigurationException e) {
+            excptnsThrown++;
+        }
+        ips = new ArrayList<>();
+        ips.add(new IpPortPair("127.0.0.1", 0));
+        try {
+            launcher.setIpAddresses(ips);
+            launcher.start();
+        } catch (InvalidConfigurationException e) {
+            excptnsThrown++;
+        }
+        assertEquals(excptnsExpected, excptnsThrown);
+    }
+    
+    @Test
+    @Ignore("server.start() throws NPE for some reason")
+    public void verifyStartDoesStartServer() throws Exception {
+        Server server = mock(Server.class);
+        WebServiceLauncher launcher = new WebServiceLauncher(server);
+        launcher.setIpAddresses(dummyIp);
+        launcher.setStorageURL("mongodb://test.example.org/db");
+        launcher.start();
+        verify(server).start();
+        launcher.stop();
+    }
+
+}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/StorageWrapper.java	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/common/src/main/java/com/redhat/thermostat/web/common/StorageWrapper.java	Wed Nov 21 21:28:09 2012 +0100
@@ -39,13 +39,14 @@
 
 import com.redhat.thermostat.storage.config.StartupConfiguration;
 import com.redhat.thermostat.storage.core.Storage;
+import com.redhat.thermostat.storage.core.StorageException;
 import com.redhat.thermostat.storage.core.StorageProvider;
-import com.redhat.thermostat.storage.core.StorageProviderUtil;
 
 public class StorageWrapper {
 
     private static Storage storage;
-    public static Storage getStorage() {
+
+    public static Storage getStorage(String storageClass, final String storageEndpoint) {
         if (storage != null) {
             return storage;
         }
@@ -53,13 +54,18 @@
             
             @Override
             public String getDBConnectionString() {
-                return "mongodb://127.0.0.1:27518";
+                return storageEndpoint;
             }
         };
-        StorageProvider provider = StorageProviderUtil.getStorageProvider(conf);
-        storage = provider.createStorage();
-        storage.getConnection().connect();
-        return storage;
+        try {
+            StorageProvider provider = (StorageProvider) Class.forName(storageClass).newInstance();
+            provider.setConfig(conf);
+            storage = provider.createStorage();
+            storage.getConnection().connect();
+            return storage;
+        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+            throw new StorageException (e);
+        }
     }
     public static void setStorage(Storage storage) {
         StorageWrapper.storage = storage;
--- a/web/pom.xml	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -54,6 +54,8 @@
     <module>common</module>
     <module>server</module>
     <module>client</module>
+    <module>cmd</module>
+    <module>war</module>
   </modules>
 
 </project>
--- a/web/server/pom.xml	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/server/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -63,22 +63,16 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-web-client</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-
-
-    <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
-      <version>8.1.5.v20120716</version>
+      <version>${jetty.version}</version>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-webapp</artifactId>
-      <version>8.1.5.v20120716</version>
+      <version>${jetty.version}</version>
+      <scope>test</scope>
     </dependency>
 
 
@@ -118,11 +112,6 @@
       <artifactId>org.osgi.core</artifactId>
       <scope>provided</scope>
     </dependency>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.compendium</artifactId>
-      <scope>provided</scope>
-    </dependency>
 
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
@@ -130,12 +119,6 @@
       <version>${project.version}</version>
     </dependency>
 
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-thread-collector</artifactId>
-      <version>${project.version}</version>
-      <scope>compile</scope>
-    </dependency>
   </dependencies>
 
   <build>
@@ -148,13 +131,13 @@
           <instructions>
             <Bundle-SymbolicName>com.redhat.thermostat.web.server</Bundle-SymbolicName>
             <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.web.server.Activator</Bundle-Activator>
             <Export-Package>
               com.redhat.thermostat.web.server
             </Export-Package>
             <!-- TODO: For the thread tab (i.e. thread plug-in) the web server
                  bundle requires model classes provided by said bundle. Since
-                 no explicit imports (in the Java import sense) are in our code,                 the maven bundle plugin seems to fail on us. Therefore we need
+                 no explicit imports (in the Java import sense) are in our code,
+                 the maven bundle plugin seems to fail on us. Therefore we need
                  these explicit Import-Package instructions. If not there, this
                  results in class not found exceptions. This may be a problem
                  for user-provided bundles which contribute DAOs/models in the
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/Activator.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012 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.web.server;
-
-import java.util.Arrays;
-
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlet.ServletMapping;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.common.cli.CommandRegistry;
-import com.redhat.thermostat.common.cli.CommandRegistryImpl;
-
-public class Activator implements BundleActivator {
-
-    private CommandRegistry reg;
-
-    @Override
-    public void start(BundleContext context) throws Exception {
-        reg = new CommandRegistryImpl(context);
-        reg.registerCommands(Arrays.asList(new WebServiceCommand()));
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        reg.unregisterCommands();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/IpPortsParser.java	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 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.web.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parses IP/Port pairs from a raw string of the form:
+ * 
+ * IPv4:
+ *      127.0.0.1:9999,127.0.0.2:8888
+ *      
+ * or
+ * 
+ * IPv6:
+ *      [1fff:0:a88:85a3::ac1f]:8001,[1fff:0:a88:85a3::ac2f]:8001
+ *
+ */
+public class IpPortsParser {
+
+    private final String rawString;
+    private List<IpPortPair> ipPorts;
+    private final IllegalArgumentException formatException; 
+    
+    public IpPortsParser(String parseString) {
+        this.rawString = parseString;
+        this.formatException = new IllegalArgumentException("Invalid format of IP/port argument " + rawString);
+    }
+    
+    public void parse() throws IllegalArgumentException {
+        ipPorts = new ArrayList<>();
+        for (String ipPortPair: rawString.split(",")) {
+            // if we have a '[' in the ip:port pair string we likely have an IPv6
+            int idxRparen = ipPortPair.indexOf(']');
+            int idxLParen = ipPortPair.indexOf('[');
+            if (idxLParen == -1) {
+                // IPv4
+                if (idxRparen != -1 || ipPortPair.indexOf(':') == -1) {
+                   throw formatException; 
+                }
+                String[] ipPort = ipPortPair.split(":");
+                int port = -1;
+                try {
+                    port = Integer.parseInt(ipPort[1]);
+                } catch (NumberFormatException e) {
+                    throw formatException;
+                }
+                ipPorts.add(new IpPortPair(ipPort[0], port));
+            } else {
+                // IPv6
+                if (idxRparen == -1) {
+                    throw formatException;
+                }
+                int port = -1;
+                try {
+                    port = Integer.parseInt(ipPortPair.substring(idxRparen + 2));
+                } catch (NumberFormatException e) {
+                    throw formatException;
+                }
+                ipPorts.add(new IpPortPair(ipPortPair.substring(idxLParen + 1, idxRparen), port));
+            }
+        }
+    }
+    
+    public List<IpPortPair> getIpsPorts() {
+        if (ipPorts == null) {
+            throw new IllegalStateException("Must call parse() before getting map!");
+        }
+        return ipPorts;
+    }
+}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceCommand.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright 2012 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.web.server;
-
-import java.util.List;
-
-import com.redhat.thermostat.common.cli.CommandContext;
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleCommand;
-import com.redhat.thermostat.web.server.internal.IpPortsParser;
-
-public class WebServiceCommand extends SimpleCommand {
-
-    private WebServiceLauncher serviceLauncher;
-    
-    public WebServiceCommand() {
-        this.serviceLauncher = new WebServiceLauncher();
-    }
-    
-    // Constructor for testing
-    WebServiceCommand(WebServiceLauncher launcher) {
-        this.serviceLauncher = launcher;
-    }
-
-    @Override
-    public void run(CommandContext ctx) throws CommandException {
-        String storageURL = ctx.getArguments().getArgument("storageURL");
-        serviceLauncher.setIpAddresses(parseIPsPorts(ctx.getArguments().getArgument("bindAddrs")));
-        serviceLauncher.setStorageURL(storageURL);
-        try {
-            // this blocks
-            serviceLauncher.start();
-        } catch (InterruptedException e) {
-            // just shut down cleanly
-            try {
-                serviceLauncher.stop();
-            } catch (Exception ex) {
-                ex.printStackTrace(ctx.getConsole().getError());
-                throw new CommandException(ex);
-            }
-        } catch (Exception ex) {
-            ex.printStackTrace(ctx.getConsole().getError());
-            throw new CommandException(ex);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return "webservice";
-    }
-
-    @Override
-    public boolean isStorageRequired() {
-        return false;
-    }
-
-    private List<IpPortPair> parseIPsPorts(String rawIpsPorts) throws CommandException {
-        IpPortsParser parser = new IpPortsParser(rawIpsPorts);
-        try {
-           parser.parse(); 
-        } catch (IllegalArgumentException e) {
-            throw new CommandException(e);
-        }
-        return parser.getIpsPorts();
-    }
-
-}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebServiceLauncher.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright 2012 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.web.server;
-
-import java.util.List;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlet.ServletMapping;
-
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-class WebServiceLauncher {
-
-    private Server server;
-    private String storageURL;
-    // IP/Port pairs, keyed by IP
-    private List<IpPortPair> ipsPorts;
-    
-    WebServiceLauncher() {
-        server = new Server();
-    }
-    
-    // Constructor for testing
-    WebServiceLauncher(Server server) {
-        this.server = server;
-    }
-
-    void start() throws Exception {
-        checkConfig();
-        Connector[] connectors = new Connector[ipsPorts.size()];
-        for (int i = 0; i < ipsPorts.size(); i++) {
-            IpPortPair pair = ipsPorts.get(i);
-            connectors[i] = new SelectChannelConnector();
-            connectors[i].setPort(pair.getPort());
-            connectors[i].setHost(pair.getIp());
-        }
-        server.setConnectors( connectors );
-        ServletHandler handler = new ServletHandler();
-        ServletHolder servletHolder = new ServletHolder("rest-storage-end-point", new WebStorageEndPoint());
-        servletHolder.setInitParameter(WebStorageEndPoint.STORAGE_ENDPOINT, storageURL);
-        handler.setServlets(new ServletHolder[] { servletHolder });
-        ServletMapping mapping = new ServletMapping();
-        mapping.setPathSpec("/");
-        mapping.setServletName("rest-storage-end-point");
-        handler.setServletMappings(new ServletMapping[] { mapping });
-        server.setHandler(handler);
-        server.start();
-        server.join();
-    }
-
-    void stop() throws Exception {
-        server.stop();
-        server.join();
-    }
-
-    public void setStorageURL(String storageURL) {
-        this.storageURL = storageURL;
-    }
-
-    public void setIpAddresses(List<IpPortPair> ipsPorts) {
-        this.ipsPorts = ipsPorts;
-    }
-
-    /*
-     * StorageURL, port must have been set
-     */
-    private void checkConfig() throws InvalidConfigurationException {
-        if (storageURL == null) {
-            throw new InvalidConfigurationException("Storage URL must be set");
-        }
-        if (ipsPorts == null) {
-            throw new InvalidConfigurationException("IP adresses to bind to must be set");
-        }
-        for (IpPortPair pair: ipsPorts) {
-            if (pair.getPort() <= 0) {
-                throw new InvalidConfigurationException("Invalid port number " + pair.getPort());
-            }
-        }
-    }
-}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Wed Nov 21 21:28:09 2012 +0100
@@ -85,7 +85,8 @@
     private Storage storage;
     private Gson gson;
 
-    static final String STORAGE_ENDPOINT = "storageEndpoint";
+    public static final String STORAGE_ENDPOINT = "storage.endpoint";
+    public static final String STORAGE_CLASS = "storage.class";
     
     private int currentCategoryId;
 
@@ -101,7 +102,9 @@
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
         if (storage == null) {
-            storage = StorageWrapper.getStorage();
+            String storageClass = getServletConfig().getInitParameter(STORAGE_CLASS);
+            String storageEndpoint = getServletConfig().getInitParameter(STORAGE_ENDPOINT);
+            storage = StorageWrapper.getStorage(storageClass, storageEndpoint);
         }
         String uri = req.getRequestURI();
         int lastPartIdx = uri.lastIndexOf("/");
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/internal/IpPortsParser.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright 2012 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.web.server.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.redhat.thermostat.web.server.IpPortPair;
-
-/**
- * Parses IP/Port pairs from a raw string of the form:
- * 
- * IPv4:
- *      127.0.0.1:9999,127.0.0.2:8888
- *      
- * or
- * 
- * IPv6:
- *      [1fff:0:a88:85a3::ac1f]:8001,[1fff:0:a88:85a3::ac2f]:8001
- *
- */
-public class IpPortsParser {
-
-    private final String rawString;
-    private List<IpPortPair> ipPorts;
-    private final IllegalArgumentException formatException; 
-    
-    public IpPortsParser(String parseString) {
-        this.rawString = parseString;
-        this.formatException = new IllegalArgumentException("Invalid format of IP/port argument " + rawString);
-    }
-    
-    public void parse() throws IllegalArgumentException {
-        ipPorts = new ArrayList<>();
-        for (String ipPortPair: rawString.split(",")) {
-            // if we have a '[' in the ip:port pair string we likely have an IPv6
-            int idxRparen = ipPortPair.indexOf(']');
-            int idxLParen = ipPortPair.indexOf('[');
-            if (idxLParen == -1) {
-                // IPv4
-                if (idxRparen != -1 || ipPortPair.indexOf(':') == -1) {
-                   throw formatException; 
-                }
-                String[] ipPort = ipPortPair.split(":");
-                int port = -1;
-                try {
-                    port = Integer.parseInt(ipPort[1]);
-                } catch (NumberFormatException e) {
-                    throw formatException;
-                }
-                ipPorts.add(new IpPortPair(ipPort[0], port));
-            } else {
-                // IPv6
-                if (idxRparen == -1) {
-                    throw formatException;
-                }
-                int port = -1;
-                try {
-                    port = Integer.parseInt(ipPortPair.substring(idxRparen + 2));
-                } catch (NumberFormatException e) {
-                    throw formatException;
-                }
-                ipPorts.add(new IpPortPair(ipPortPair.substring(idxLParen + 1, idxRparen), port));
-            }
-        }
-    }
-    
-    public List<IpPortPair> getIpsPorts() {
-        if (ipPorts == null) {
-            throw new IllegalStateException("Must call parse() before getting map!");
-        }
-        return ipPorts;
-    }
-}
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebServiceCommandTest.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 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.web.server;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.mockito.Matchers.any;
-
-import java.util.List;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.common.cli.SimpleArguments;
-import com.redhat.thermostat.test.TestCommandContextFactory;
-
-public class WebServiceCommandTest {
-
-    private TestCommandContextFactory cmdCtxFactory;
-    private BundleContext bundleContext;
-    private WebServiceLauncher launcher;
-    private WebServiceCommand cmd;
-    
-    @Before
-    public void setUp() {
-        Bundle sysBundle = mock(Bundle.class);
-        bundleContext = mock(BundleContext.class);
-        when(bundleContext.getBundle(0)).thenReturn(sysBundle);
-        cmdCtxFactory = new TestCommandContextFactory(bundleContext);
-        launcher = mock(WebServiceLauncher.class);
-        cmd = new WebServiceCommand(launcher);
-    }
-    
-    @After
-    public void tearDown() {
-        cmdCtxFactory = null;
-        cmd = null;
-        launcher = null;
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Test
-    public void verifyLauncherStart() throws Exception {
-        SimpleArguments args = new SimpleArguments();
-        String storageUrl = "mongodb://127.0.0.1:27518";
-        args.addArgument("storageURL", storageUrl);
-        args.addArgument("bindAddrs", "127.0.0.1:8888,127.0.0.2:9999");
-        try {
-            cmd.run(cmdCtxFactory.createContext(args));
-        } catch (CommandException e) {
-            fail("should not throw exception");
-        }
-        verify(launcher).setStorageURL(storageUrl);
-        verify(launcher).setIpAddresses(any(List.class));
-        verify(launcher).start();
-    }
-}
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebServiceLauncherTest.java	Mon Nov 19 18:21:20 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright 2012 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.web.server;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.jetty.server.Server;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.redhat.thermostat.common.config.InvalidConfigurationException;
-
-public class WebServiceLauncherTest {
-    
-    private WebServiceLauncher launcher;
-    private List<IpPortPair> dummyIp;
-    
-    @Before
-    public void setUp() {
-        dummyIp = new ArrayList<IpPortPair>();
-        dummyIp.add(new IpPortPair("127.0.0.1", 8889));
-    }
-    
-    @After
-    public void tearDown() {
-        launcher = null;
-        dummyIp = null;
-    }
-    
-    @Test( expected=InvalidConfigurationException.class )
-    public void unsetStorageURLThrowsException() throws Exception {
-        launcher = new WebServiceLauncher();
-        launcher.setIpAddresses(dummyIp);
-        launcher.start();
-    }
-    
-    @Test( expected=InvalidConfigurationException.class )
-    public void unsetIpAddressesThrowsException() throws Exception {
-        launcher = new WebServiceLauncher();
-        launcher.setStorageURL("something not null");
-        launcher.setIpAddresses(null);
-        launcher.start();
-    }
-    
-    @Test
-    public void invalidPortThrowsException() throws Exception {
-        int excptnsThrown = 0;
-        int excptnsExpected = 2;
-        launcher = new WebServiceLauncher();
-        List<IpPortPair> ips = new ArrayList<>();
-        ips.add(new IpPortPair("127.0.0.1", -10));
-        try {
-            launcher.setIpAddresses(ips);
-            launcher.start();
-        } catch (InvalidConfigurationException e) {
-            excptnsThrown++;
-        }
-        ips = new ArrayList<>();
-        ips.add(new IpPortPair("127.0.0.1", 0));
-        try {
-            launcher.setIpAddresses(ips);
-            launcher.start();
-        } catch (InvalidConfigurationException e) {
-            excptnsThrown++;
-        }
-        assertEquals(excptnsExpected, excptnsThrown);
-    }
-    
-    @Test
-    @Ignore("server.start() throws NPE for some reason")
-    public void verifyStartDoesStartServer() throws Exception {
-        Server server = mock(Server.class);
-        WebServiceLauncher launcher = new WebServiceLauncher(server);
-        launcher.setIpAddresses(dummyIp);
-        launcher.setStorageURL("mongodb://test.example.org/db");
-        launcher.start();
-        verify(server).start();
-        launcher.stop();
-    }
-
-}
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Wed Nov 21 21:28:09 2012 +0100
@@ -88,7 +88,6 @@
 import com.redhat.thermostat.test.FreePortFinder;
 import com.redhat.thermostat.test.FreePortFinder.TryPort;
 import com.redhat.thermostat.test.MockQuery;
-import com.redhat.thermostat.web.client.WebStorage;
 import com.redhat.thermostat.web.common.WebQuery;
 import com.redhat.thermostat.web.common.StorageWrapper;
 import com.redhat.thermostat.web.common.WebInsert;
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/internal/IpPortsParserTest.java	Mon Nov 19 18:21:20 2012 +0100
+++ b/web/server/src/test/java/com/redhat/thermostat/web/server/internal/IpPortsParserTest.java	Wed Nov 21 21:28:09 2012 +0100
@@ -43,6 +43,7 @@
 import org.junit.Test;
 
 import com.redhat.thermostat.web.server.IpPortPair;
+import com.redhat.thermostat.web.server.IpPortsParser;
 
 public class IpPortsParserTest {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/war/pom.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat-web</artifactId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>thermostat-web-war</artifactId>
+  <packaging>war</packaging>
+
+  <name>Thermostat Web WAR package</name>
+
+  <dependencies>
+  
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-web-server</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/war/src/main/webapp/WEB-INF/web.xml	Wed Nov 21 21:28:09 2012 +0100
@@ -0,0 +1,26 @@
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd" >
+
+<web-app>
+
+  <display-name>Thermostat Web Service</display-name>
+  <description>Thermostat Web Service</description> 
+  <servlet>
+    <init-param>
+      <param-name>storage.class</param-name>
+      <param-value>com.redhat.thermostat.common.storage.MongoStorageProvider</param-value>
+    </init-param>
+    <init-param>
+      <param-name>storage.endpoint</param-name>
+      <param-value>mongodb://127.0.0.1:27518</param-value>
+    </init-param>
+    <servlet-name>reststorage-servlet</servlet-name>
+    <servlet-class>com.redhat.thermostat.web.server.WebStorageEndPoint</servlet-class>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>reststorage-servlet</servlet-name>
+    <url-pattern>/storage/*</url-pattern>
+  </servlet-mapping>
+</web-app>