changeset 2645:d58c740a1a0b

Remove remaining web storage implementation Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/023015.html
author Elliott Baron <ebaron@redhat.com>
date Wed, 10 May 2017 16:02:18 -0400
parents 13807543d358
children 91412a25d6ec
files distribution/assembly/core-assembly-macosx.xml distribution/assembly/core-assembly-windows.xml distribution/assembly/core-assembly.xml distribution/config/commands/agent.properties distribution/pom.xml plugins/vm-byteman/common/pom.xml plugins/vm-byteman/common/src/test/java/com/redhat/thermostat/vm/byteman/common/BytemanMetricTest.java pom.xml web/client/pom.xml web/client/src/main/java/com/redhat/thermostat/web/client/internal/Activator.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/EntityConsumingIOException.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/ExpirableWebPreparedStatementCache.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebCursor.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementCache.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementHolder.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorageProvider.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/EntityConsumingIOExceptionTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/ExpirableWebPreparedStatementCacheTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/TestObj.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebCursorTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementCacheTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageProviderTest.java web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java web/common/pom.xml web/common/src/main/java/com/redhat/thermostat/web/common/PreparedStatementResponseCode.java web/common/src/main/java/com/redhat/thermostat/web/common/SharedStateId.java web/common/src/main/java/com/redhat/thermostat/web/common/WebPreparedStatement.java web/common/src/main/java/com/redhat/thermostat/web/common/WebPreparedStatementResponse.java web/common/src/main/java/com/redhat/thermostat/web/common/WebQueryResponse.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapterFactory.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapter.java web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapterFactory.java web/common/src/test/java/com/redhat/thermostat/web/common/CategorySerializationTest.java web/common/src/test/java/com/redhat/thermostat/web/common/SharedStateIdTest.java web/common/src/test/java/com/redhat/thermostat/web/common/WebQueryResponseTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/JsonPerformanceTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyGSONConverter.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyPreparedParameterSerializer.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyWebPreparedStatementSerializer.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyWebQueryResponseSerializer.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterJSONPerformanceTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersJSONPerformanceTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementJSONPerformanceTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseJSONPerformanceTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapterTest.java web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapterTest.java web/pom.xml
diffstat 64 files changed, 1 insertions(+), 9524 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/assembly/core-assembly-macosx.xml	Wed May 10 16:01:45 2017 -0400
+++ b/distribution/assembly/core-assembly-macosx.xml	Wed May 10 16:02:18 2017 -0400
@@ -65,7 +65,6 @@
         <include>com.redhat.thermostat:thermostat-common-portability</include>
         <include>com.redhat.thermostat:thermostat-process-handler</include>
         <include>com.redhat.thermostat:thermostat-storage-core</include>
-        <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
         <include>org.apache:org.apache.felix.scr</include>
--- a/distribution/assembly/core-assembly-windows.xml	Wed May 10 16:01:45 2017 -0400
+++ b/distribution/assembly/core-assembly-windows.xml	Wed May 10 16:02:18 2017 -0400
@@ -65,7 +65,6 @@
         <include>com.redhat.thermostat:thermostat-common-portability</include>
         <include>com.redhat.thermostat:thermostat-process-handler</include>
         <include>com.redhat.thermostat:thermostat-storage-core</include>
-        <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
         <include>org.apache:org.apache.felix.scr</include>
--- a/distribution/assembly/core-assembly.xml	Wed May 10 16:01:45 2017 -0400
+++ b/distribution/assembly/core-assembly.xml	Wed May 10 16:02:18 2017 -0400
@@ -65,7 +65,6 @@
         <include>com.redhat.thermostat:thermostat-common-portability</include>
         <include>com.redhat.thermostat:thermostat-process-handler</include>
         <include>com.redhat.thermostat:thermostat-storage-core</include>
-        <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
         <include>org.apache:org.apache.felix.scr</include>
--- a/distribution/config/commands/agent.properties	Wed May 10 16:01:45 2017 -0400
+++ b/distribution/config/commands/agent.properties	Wed May 10 16:02:18 2017 -0400
@@ -1,5 +1,4 @@
-bundles = com.redhat.thermostat.web.client=@project.version@, \
-          com.redhat.thermostat.agent.cli=@project.version@, \
+bundles = com.redhat.thermostat.agent.cli=@project.version@, \
           com.redhat.thermostat.backend.system=@project.version@, \
           com.redhat.thermostat.agent.ipc.tcpsocket.server=@project.version@, \
           com.redhat.thermostat.process=@project.version@ \
--- a/distribution/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ b/distribution/pom.xml	Wed May 10 16:02:18 2017 -0400
@@ -483,11 +483,6 @@
     </dependency>
     <dependency>
         <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-web-client</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
         <artifactId>thermostat-system-backend</artifactId>
         <version>${project.version}</version>
     </dependency>
--- a/plugins/vm-byteman/common/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ b/plugins/vm-byteman/common/pom.xml	Wed May 10 16:02:18 2017 -0400
@@ -139,12 +139,6 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-web-common</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-storage-testutils</artifactId>
       <version>${project.version}</version>
       <scope>test</scope>
--- a/plugins/vm-byteman/common/src/test/java/com/redhat/thermostat/vm/byteman/common/BytemanMetricTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * 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.vm.byteman.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParameterTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParametersTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.SharedStateIdTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementResponseTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebQueryResponseTypeAdapterFactory;
-
-public class BytemanMetricTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParametersTypeAdapterFactory())
-                .create();
-    }
-    
-    @Test
-    public void isTransformablefromPojo() {
-        BytemanMetric metric = new BytemanMetric();
-        metric.setAgentId("foo-agent");
-        metric.setData("{ \"key\": \"value\" }");
-        metric.setMarker("foo-marker");
-        metric.setTimeStamp(1L);
-        metric.setVmId("someVmId");
-        String json = gson.toJson(metric, BytemanMetric.class);
-        String expectedJson = "{\"agentId\":\"foo-agent\"," +
-                "\"data\":\"{ \\\"key\\\": \\\"value\\\" }\"," + 
-                "\"marker\":\"foo-marker\"," +
-                "\"timeStamp\":1," +
-                "\"vmId\":\"someVmId\"}";
-        assertEquals(expectedJson, json);
-    }
-    
-    @Test
-    public void isTransformableToPojo() {
-        String json = "{ \"agentId\":\"foo-agent\"," +
-                        "\"data\": \"{ \\\"key\\\": \\\"value\\\" }\"," + 
-                        "\"marker\": \"foo-marker\"," +
-                        "\"timeStamp\":1," +
-                        "\"vmId\":\"someVmId\"}";
-        BytemanMetric metric = gson.fromJson(json, BytemanMetric.class);
-        assertNotNull(metric);
-        assertEquals("foo-agent", metric.getAgentId());
-        assertEquals("foo-marker", metric.getMarker());
-        assertEquals(1L, metric.getTimeStamp());
-        String expectedData = "{ \"key\": \"value\" }";
-        assertEquals(expectedData, metric.getData());
-        assertEquals(expectedData, metric.getDataAsJson());
-        assertEquals("someVmId", metric.getVmId());
-    }
-}
--- a/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ b/pom.xml	Wed May 10 16:02:18 2017 -0400
@@ -340,7 +340,6 @@
     <module>common</module>
     <module>agent</module>
     <module>process-handler</module>
-    <module>web</module>
     <module>system-backend</module>
     <module>storage</module>
     <module>thermostat-plugin-validator</module>
--- a/web/client/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<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>1.99.12-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>thermostat-web-client</artifactId>
-  <packaging>bundle</packaging>
-
-  <name>Thermostat Web Client</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.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-server</artifactId>
-      <version>${jetty.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-webapp</artifactId>
-      <version>${jetty.version}</version>
-      <scope>test</scope>
-    </dependency>
-
-    <dependency>
-      <groupId>com.google.code.gson</groupId>
-      <artifactId>gson</artifactId>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.httpcomponents</groupId>
-      <artifactId>httpclient-osgi</artifactId>
-      <version>${httpcomponents.client.version}</version>
-    </dependency>
-    <!-- httpclient 4.3 needs this bundle, but does only
-         specify it's dep on it with scope provided -->
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.compendium</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.httpcomponents</groupId>
-      <artifactId>httpcore-osgi</artifactId>
-      <version>${httpcomponents.core.version}</version>
-    </dependency>
-
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-web-common</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.client</Bundle-SymbolicName>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.web.client.internal.Activator</Bundle-Activator>
-            <Private-Package>
-              com.redhat.thermostat.web.client.internal
-            </Private-Package>
-            <!-- Do not autogenerate uses clauses in Manifests -->
-            <_nouses>true</_nouses>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
-
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/Activator.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.storage.core.StorageProvider;
-
-public class Activator implements BundleActivator {
-
-    private ServiceRegistration reg;
-    
-    @Override
-    public void start(BundleContext context) throws Exception {
-        WebStorageProvider storage = new WebStorageProvider();
-        this.reg = context.registerService(StorageProvider.class.getName(), storage, null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        reg.unregister();
-    }
-
-}
-
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/EntityConsumingIOException.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.io.IOException;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.util.EntityUtils;
-
-/**
- * Should be used for to-be-thrown IOExceptions which need to consume an
- * {@link HttpEntity} prior to getting thrown. This avoids resource leaks.
- *
- */
-class EntityConsumingIOException extends IOException {
-
-    private static final long serialVersionUID = 6822662292793556315L;
-    
-    EntityConsumingIOException(HttpEntity entity, String msg) {
-        super(msg);
-        consumeEntity(entity);
-    }
-    
-    private void consumeEntity(HttpEntity entity) {
-        try {
-            EntityUtils.consume(entity);
-        } catch (IOException e) {
-            // ignore, consuming failure since we are about to
-            // throw an IOException anyway.
-        }
-    }
-
-}
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/ExpirableWebPreparedStatementCache.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-/**
- * A {@link WebPreparedStatementCache} with an expiration time. When that time
- * has passed it will return null for all cache entries. Used as a read-only
- * transition cache in {@link WebStorage} in order to recover from server
- * component reloads.
- *
- */
-class ExpirableWebPreparedStatementCache extends WebPreparedStatementCache {
-
-    private final long timeExpires;
-    private final WebPreparedStatementCache cache;
-    
-    ExpirableWebPreparedStatementCache(WebPreparedStatementCache cache, long timeExpires) {
-        this.timeExpires = timeExpires;
-        this.cache = cache;
-    }
-    
-    @Override
-    synchronized <T extends Pojo> WebPreparedStatementHolder get(StatementDescriptor<T> desc) {
-        WebPreparedStatementHolder holder = cache.get(desc);
-        if (holder == null) {
-            return null;
-        }
-        // check if corresponding cache entry has expired
-        long now = System.nanoTime();
-        if (now > timeExpires) {
-            // remove cache entry and return null
-            SharedStateId id = holder.getStatementId();
-            cache.remove(id);
-            return null;
-        }
-        return holder;
-    }
-    
-    @Override
-    synchronized <T extends Pojo> StatementDescriptor<T> get(SharedStateId id) {
-        StatementDescriptor<T> desc = cache.get(id);
-        if (desc == null) {
-            return null;
-        }
-        long now = System.nanoTime();
-        if (now > timeExpires) {
-            // remove cache entry and return null
-            cache.remove(id);
-            return null;
-        }
-        return desc;
-    }
-    
-    boolean isExpired() {
-        return System.nanoTime() > timeExpires;
-    }
-    
-}
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebCursor.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.lang.reflect.Type;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.BasicBatchCursor;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-import java.util.NoSuchElementException;
-
-class WebCursor<T extends Pojo> extends BasicBatchCursor<T> {
-    
-    private static final Logger logger = LoggingUtils.getLogger(WebCursor.class);
-
-    private final Type parametrizedTypeToken;
-    private final WebStorage storage;
-    private final int cursorId;
-    private final WebPreparedStatement<T> stmt;
-    private int batchIndex;
-    private T[] dataBatch;
-    private boolean hasMoreBatches;
-
-    // Main constructor called from doQueryExecute()
-    WebCursor(WebStorage storage, T[] dataBatch, boolean hasMoreBatches, int cursorId, Type parametrizedTypeToken, WebPreparedStatement<T> stmt) {
-        this.storage = storage;
-        this.cursorId = cursorId;
-        this.parametrizedTypeToken = parametrizedTypeToken;
-        this.stmt = stmt;
-        this.hasMoreBatches = hasMoreBatches;
-        this.dataBatch = dataBatch;
-        this.batchIndex = 0;
-    }
-
-    @Override
-    public boolean hasNext() {
-        return batchIndex < dataBatch.length || hasMoreBatches;
-    }
-
-    @Override
-    public T next() {
-        if (batchIndex >= dataBatch.length && !hasMoreBatches) {
-            throw new NoSuchElementException();
-        }
-        T result = null;
-        // Check if we have still results left in batch,
-        // if not fetch a new batch.
-        if (batchIndex >= dataBatch.length) {
-            assert(hasMoreBatches);
-            // This updates batchIndex, dataBatch and
-            // hasMoreBatches
-            fetchBatchFromStorage();
-            assert(batchIndex == 0);
-            assert(dataBatch.length > 0);
-        }
-        result = dataBatch[batchIndex];
-        batchIndex++;
-        return result;
-    }
-
-    private void fetchBatchFromStorage() throws StorageException {
-        logger.log(Level.FINEST, "Getting more results for cursorId: " + cursorId);
-        WebQueryResponse<T> nextBatchResponse = storage.getMore(cursorId, parametrizedTypeToken, getBatchSize(), stmt);
-        switch(nextBatchResponse.getResponseCode()) {
-        case PreparedStatementResponseCode.QUERY_SUCCESS: 
-            this.batchIndex = 0;
-            this.hasMoreBatches = nextBatchResponse.hasMoreBatches();
-            this.dataBatch = nextBatchResponse.getResultList();
-            break;
-        case PreparedStatementResponseCode.GET_MORE_NULL_CURSOR:
-            // Advise user about potentially timed-out cursor
-            String msg = "[get-more] Failed to get more results for cursorId: " + cursorId +
-                         " This may be caused because the cursor timed out." +
-                         " Resubmitting the original query might be an approach to fix it." +
-                         " See server logs for more details.";
-            throw new StorageException(msg);
-        default:
-            msg = "[get-more] Failed to get more results for cursorId: " + cursorId +
-            ". See server logs for details.";
-            throw new StorageException(msg);
-        }
-    }
-
-}
-
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementCache.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-
-/**
- * A simple implementation of a cache for {@link WebPreparedStatement}
- * in order to avoid unnecessary network round-trips if a statement
- * has already been prepared and it's not out-of-sync with the server.
- */
-class WebPreparedStatementCache {
-    
-    private final Map<StatementDescriptor<?>, WebPreparedStatementHolder> stmtCache;
-    private final Map<SharedStateId, StatementDescriptor<?>> reverseLookup;
-    
-    WebPreparedStatementCache() {
-        stmtCache = new WeakHashMap<>();
-        reverseLookup = new WeakHashMap<>();
-    }
-
-    synchronized <T extends Pojo> void put(StatementDescriptor<T> desc, WebPreparedStatementHolder holder) {
-        SharedStateId id = holder.getStatementId();
-        stmtCache.put(desc, holder);
-        reverseLookup.put(id, desc);
-    }
-    
-    synchronized <T extends Pojo> WebPreparedStatementHolder get(StatementDescriptor<T> desc) {
-        return stmtCache.get(desc);
-    }
-    
-    @SuppressWarnings("unchecked")
-    synchronized <T extends Pojo> StatementDescriptor<T> get(SharedStateId id) {
-        return (StatementDescriptor<T>)reverseLookup.get(id);
-    }
-    
-    synchronized void remove(SharedStateId id) {
-        StatementDescriptor<?> desc = reverseLookup.get(id);
-        if (desc != null) {
-            stmtCache.remove(desc);
-        }
-        reverseLookup.remove(id);
-    }
-    
-    /**
-     * Creates a snapshot of the current state of this cache.
-     * 
-     * @return A copied snapshot of this cache.
-     */
-    synchronized WebPreparedStatementCache createSnapshot() {
-        WebPreparedStatementCache copy = new WebPreparedStatementCache();
-        for (StatementDescriptor<?> desc: stmtCache.keySet()) {
-            copy.put(desc, stmtCache.get(desc));
-        }
-        return copy;
-    }
-
-}
\ No newline at end of file
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementHolder.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.lang.reflect.Type;
-
-import com.redhat.thermostat.web.common.SharedStateId;
-
-/**
- * Container used for parameter caching in order to avoid unneccessary
- * network overhead.
- *
- * @see {@link WebStorage}
- * @see {@link WebPreparedStatementCache}
- *
- */
-class WebPreparedStatementHolder {
-    
-    private final Type typeToken;
-    private final int numParams;
-    private final SharedStateId statementId;
-    
-    WebPreparedStatementHolder(Type typeToken, int numParams, SharedStateId statementId) {
-        this.typeToken = typeToken;
-        this.numParams = numParams;
-        this.statementId = statementId;
-    }
-
-    Type getTypeToken() {
-        return typeToken;
-    }
-
-    int getNumParams() {
-        return numParams;
-    }
-
-    SharedStateId getStatementId() {
-        return statementId;
-    }
-}
\ No newline at end of file
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorage.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1032 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.lang.reflect.Type;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.SecureRandom;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.net.ssl.SSLContext;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.StatusLine;
-import org.apache.http.auth.AuthSchemeProvider;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.config.AuthSchemes;
-import org.apache.http.client.config.RequestConfig;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.config.Lookup;
-import org.apache.http.config.Registry;
-import org.apache.http.config.RegistryBuilder;
-import org.apache.http.conn.socket.ConnectionSocketFactory;
-import org.apache.http.conn.socket.PlainConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
-import org.apache.http.entity.mime.content.InputStreamBody;
-import org.apache.http.impl.auth.BasicSchemeFactory;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.util.EntityUtils;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.common.ssl.SSLContextFactory;
-import com.redhat.thermostat.common.ssl.SslInitException;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.AuthToken;
-import com.redhat.thermostat.storage.core.Categories;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.Connection;
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.DescriptorParsingException;
-import com.redhat.thermostat.storage.core.IllegalDescriptorException;
-import com.redhat.thermostat.storage.core.IllegalPatchException;
-import com.redhat.thermostat.storage.core.PreparedStatement;
-import com.redhat.thermostat.storage.core.SaveFileListener;
-import com.redhat.thermostat.storage.core.SecureStorage;
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.core.StatementExecutionException;
-import com.redhat.thermostat.storage.core.Storage;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.core.SaveFileListener.EventType;
-import com.redhat.thermostat.storage.model.AggregateResult;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParameterTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParametersTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.SharedStateIdTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementResponseTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebQueryResponseTypeAdapterFactory;
-
-public class WebStorage implements Storage, SecureStorage {
-
-    private static final int STATUS_OK = 200;
-    private static final int STATUS_NO_CONTENT = 204;
-
-    private static final String HTTP_PREFIX = "http";
-    private static final String HTTPS_PREFIX = "https";
-    
-    // Transition cache is valid for 30 seconds starting from the current time.
-    private static final long TRANSITION_CACHE_OFFSET = TimeUnit.NANOSECONDS.convert(30, TimeUnit.SECONDS);
-    
-    static final Logger logger = LoggingUtils.getLogger(WebStorage.class);
-    
-    private static class CloseableHttpEntity implements Closeable, HttpEntity {
-
-        private HttpEntity entity;
-        private int responseCode;
-
-        CloseableHttpEntity(HttpEntity entity, int responseCode) {
-            this.entity = entity;
-            this.responseCode = responseCode;
-        }
-
-        @Override
-        public void consumeContent() throws IOException {
-            EntityUtils.consume(entity);
-        }
-
-        @Override
-        public InputStream getContent() throws IOException,
-                IllegalStateException {
-            return entity.getContent();
-        }
-
-        @Override
-        public Header getContentEncoding() {
-            return entity.getContentEncoding();
-        }
-
-        @Override
-        public long getContentLength() {
-            return entity.getContentLength();
-        }
-
-        @Override
-        public Header getContentType() {
-            return entity.getContentType();
-        }
-
-        @Override
-        public boolean isChunked() {
-            return entity.isChunked();
-        }
-
-        @Override
-        public boolean isRepeatable() {
-            return entity.isRepeatable();
-        }
-
-        @Override
-        public boolean isStreaming() {
-            return entity.isStreaming();
-        }
-
-        @Override
-        public void writeTo(OutputStream out) throws IOException {
-            entity.writeTo(out);
-        }
-
-        @Override
-        public void close() {
-            try {
-                EntityUtils.consume(entity);
-            } catch (IOException ex) {
-                throw new StorageException(ex);
-            }
-        }
-
-        int getResponseCode() {
-            return responseCode;
-        }
-    }
-
-    private final class WebConnection extends Connection {
-        WebConnection() {
-            connected = true;
-        }
-
-        @Override
-        public void disconnect() {
-            connected = false;
-            setUsername(Connection.UNSET_USERNAME);
-            fireChanged(ConnectionStatus.DISCONNECTED);
-        }
-
-        @Override
-        public void connect() {
-            try {
-                initAuthentication();
-                ping();
-                connected = true;
-                logger.fine("Connected to storage");
-                fireChanged(ConnectionStatus.CONNECTED);
-            } catch (Exception ex) {
-                logger.log(Level.WARNING, "Could not connect to storage!", ex);
-                setUsername(Connection.UNSET_USERNAME);
-                fireChanged(ConnectionStatus.FAILED_TO_CONNECT);
-            }
-        }
-        
-        private void initAuthentication()
-                throws MalformedURLException {
-            String username = creds.getUsername();
-            setUsername(username);
-            char[] password = creds.getPassword();
-            if (username != null && password != null) {
-                URL endpointURL = new URL(endpoint);
-                BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-                // FIXME Password as string?  BAD.  Limited by apache API here however.
-                Credentials creds = new UsernamePasswordCredentials(username,
-                        new String(password));
-                Arrays.fill(password, '\0');
-                AuthScope scope = new AuthScope(endpointURL.getHost(),
-                        endpointURL.getPort(), "Thermostat Realm");
-                credsProvider.setCredentials(scope, creds);
-                synchronized (httpClientContextLock) {
-                    httpClientContext.setCredentialsProvider(credsProvider);
-                }
-            }
-        }
-
-        @Override
-        public void setUrl(String url) {
-            super.setUrl(url);
-            endpoint = url;
-        }
-
-        @Override
-        public String getUrl() {
-            return endpoint;
-        }
-    }
-
-    private static class WebDataStream extends InputStream {
-
-        private CloseableHttpEntity entity;
-        private InputStream content;
-
-        WebDataStream(CloseableHttpEntity entity) {
-            this.entity = entity;
-            try {
-                content = entity.getContent();
-            } catch (IllegalStateException | IOException e) {
-                throw new StorageException(e);
-            }
-        }
-
-        @Override
-        public void close() throws IOException {
-            content.close();
-            entity.close();
-        }
-
-        @Override
-        public int read() throws IOException {
-            return content.read();
-        }
-
-        @Override
-        public int available() throws IOException {
-            return content.available();
-        }
-
-        @Override
-        public void mark(int readlimit) {
-            content.mark(readlimit);
-        }
-
-        @Override
-        public boolean markSupported() {
-            return content.markSupported();
-        }
-
-        @Override
-        public int read(byte[] b) throws IOException {
-            return content.read(b);
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-            return content.read(b, off, len);
-        }
-
-        @Override
-        public void reset() throws IOException {
-            content.reset();
-        }
-
-        @Override
-        public long skip(long n) throws IOException {
-            return content.skip(n);
-        }
-
-    }
-
-    private class WebPreparedStatementImpl<T extends Pojo> extends WebPreparedStatement<T> {
-
-        // The type of the query result objects we'd get back upon
-        // statement execution
-        private final transient Type parametrizedTypeToken;
-        
-        public WebPreparedStatementImpl(Type parametrizedTypeToken, int numParams, SharedStateId statementId) {
-            super(numParams, statementId);
-            this.parametrizedTypeToken = parametrizedTypeToken;
-        }
-        
-        @Override
-        public int execute() throws StatementExecutionException {
-            return doWriteExecute(this, 0);
-        }
-
-        @Override
-        public Cursor<T> executeQuery()
-                throws StatementExecutionException {
-            return doExecuteQuery(this, parametrizedTypeToken, 0);
-        }
-        
-    }
-
-    private String endpoint;
-
-    private Map<Category<?>, SharedStateId> categoryIds;
-    private Gson gson;
-    // The shared http client we use for execution (uses the context below)
-    private HttpClient httpClient;
-    private Object httpClientContextLock = new Object();
-    // Http client execution context. Protected via clientContext lock.
-    private HttpClientContext httpClientContext;
-    private StorageCredentials creds;
-    private SecureRandom random;
-    private WebConnection conn;
-    private WebPreparedStatementCache stmtCache;
-    // Temporary cache used for recovering after a server endpoint re-deployment.
-    // Will only be valid for 30 seconds for any server endpoint re-deployment.
-    private ExpirableWebPreparedStatementCache transitionStmtCache;
-    
-    // for testing
-    WebStorage(String url, StorageCredentials creds, HttpClient client) {
-        init(url, creds, client);
-    }
-    
-    // for testing
-    WebStorage(WebPreparedStatementCache stmtCache, ExpirableWebPreparedStatementCache transitionCache) {
-        this.stmtCache = stmtCache;
-        this.transitionStmtCache = transitionCache;
-    }
-    
-    // for testing
-    WebStorage(Map<Category<?>, SharedStateId> categoryIds) {
-        this.categoryIds = categoryIds;
-    }
-
-    public WebStorage(String url, StorageCredentials creds, SSLConfiguration sslConf) throws StorageException {
-        PoolingHttpClientConnectionManager connManager = getPoolingHttpClientConnManager(sslConf, url);
-        HttpClientBuilder builder = HttpClients.custom();
-        Lookup<AuthSchemeProvider> authProviders = RegistryBuilder.<AuthSchemeProvider>create()
-                .register(AuthSchemes.BASIC, new BasicSchemeFactory())
-                .build();
-        // Set up client with default basic-auth scheme and pooled
-        // connection manager.
-        HttpClient client = builder.setConnectionManager(connManager)
-                .setDefaultAuthSchemeRegistry(authProviders)
-                .build();
-        init(url, creds, client);
-    }
-    
-    private void init(String url, StorageCredentials creds, HttpClient client) {
-        categoryIds = new HashMap<>();
-        gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParametersTypeAdapterFactory())
-                .create();
-        httpClient = client;
-        synchronized (httpClientContextLock) {
-            httpClientContext = HttpClientContext.create();
-        }
-        random = new SecureRandom();
-        conn = new WebConnection();
-        
-        this.endpoint = url;
-        this.creds = creds;
-        this.stmtCache = new WebPreparedStatementCache();
-    }
-
-    // package private for testing
-    PoolingHttpClientConnectionManager getPoolingHttpClientConnManager(SSLConfiguration sslConf, String url)
-            throws StorageException {
-        ConnectionSocketFactory plainsf = new PlainConnectionSocketFactory();
-        RegistryBuilder<ConnectionSocketFactory> regBuilder = RegistryBuilder.<ConnectionSocketFactory>create()
-                .register(HTTP_PREFIX, plainsf);
-        try {
-            // setup SSL if necessary
-            if (url.startsWith(HTTPS_PREFIX)) {
-                SSLContext sc = SSLContextFactory.getClientContext(sslConf);
-                SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sc);
-                regBuilder = regBuilder.register(HTTPS_PREFIX, socketFactory);
-            }
-        } catch ( SslInitException e) {
-            throw new StorageException(e);
-        }
-        Registry<ConnectionSocketFactory> r = regBuilder.build();
-        return new PoolingHttpClientConnectionManager(r);
-    }
-
-    private void ping() throws StorageException {
-        post(endpoint + "/ping", (HttpEntity) null).close();
-    }
-
-    private CloseableHttpEntity post(String url, List<NameValuePair> formparams)
-            throws StorageException {
-        try {
-            return postImpl(url, formparams);
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    private CloseableHttpEntity postImpl(String url,
-            List<NameValuePair> formparams) throws IOException {
-        HttpEntity entity;
-        if (formparams != null) {
-            entity = new UrlEncodedFormEntity(formparams, "UTF-8");
-        } else {
-            entity = null;
-        }
-        return postImpl(url, entity);
-    }
-
-    private CloseableHttpEntity post(String url, HttpEntity entity)
-            throws StorageException {
-        try {
-            return postImpl(url, entity, null);
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-    
-    private CloseableHttpEntity post(String url, HttpEntity entity, RequestConfig config)
-            throws StorageException {
-        try {
-            return postImpl(url, entity, config);
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-    
-    private CloseableHttpEntity postImpl(String url, HttpEntity entity, RequestConfig config)
-            throws IOException {
-        HttpPost httpPost = new HttpPost(url);
-        if (entity != null) {
-            httpPost.setEntity(entity);
-        }
-        HttpResponse response = null;
-        // The client context is not thread-safe. Thus protect execution
-        // via the client context lock.
-        synchronized(httpClientContextLock) {
-            RequestConfig oldConfig = httpClientContext.getRequestConfig();
-            if (config != null) {
-                httpClientContext.setRequestConfig(config);
-            }
-            try {
-                response = httpClient.execute(httpPost, httpClientContext);
-            } catch (Throwable e) {
-                throw e;
-            } finally {
-                if (config != null) {
-                    httpClientContext.setRequestConfig(oldConfig);
-                }
-            }
-        }
-        StatusLine status = response.getStatusLine();
-        int responseCode = status.getStatusCode();
-        switch (responseCode) {
-        case (STATUS_NO_CONTENT):
-            // Let calling code handle STATUS_NO_CONTENT
-            break;
-        case (STATUS_OK):
-            // Let calling code handle STATUS_OK
-            break;
-        default:
-            // Properly consume the entity, thus closing the content stream,
-            // by throwing this IOException sub-class. This is important for the
-            // 403 and 500 status code cases. See:
-            // http://hc.apache.org/httpcomponents-core-4.3.x/httpcore/apidocs/org/apache/http/util/EntityUtils.html#consume%28org.apache.http.HttpEntity%29
-            throw new EntityConsumingIOException(response.getEntity(), 
-                    "Server returned status: " + status);
-        }
-        
-        return new CloseableHttpEntity(response.getEntity(), responseCode);
-    }
-
-    private CloseableHttpEntity postImpl(String url, HttpEntity entity)
-            throws StorageException {
-        try {
-            return postImpl(url, entity, null);
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    private static InputStream getContent(HttpEntity entity) {
-        try {
-            return entity.getContent();
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    private static Reader getContentAsReader(HttpEntity entity) {
-        InputStream in = getContent(entity);
-        return new InputStreamReader(in);
-    }
-
-    @Override
-    public void registerCategory(Category<?> category) throws StorageException {
-        NameValuePair nameParam = new BasicNameValuePair("name",
-                category.getName());
-        NameValuePair dataClassParam = new BasicNameValuePair("data-class",
-                category.getDataClass().getName());
-        
-        NameValuePair categoryParam = new BasicNameValuePair("category",
-                gson.toJson(category));
-        List<NameValuePair> formparams = Arrays
-                .asList(nameParam, categoryParam, dataClassParam);
-        try (CloseableHttpEntity entity = post(endpoint + "/register-category",
-                formparams)) {
-            Reader reader = getContentAsReader(entity);
-            SharedStateId id = gson.fromJson(reader, SharedStateId.class);
-            categoryIds.put(category, id);
-        }
-    }
-
-    /**
-     * Executes a prepared query
-     * 
-     * @param stmt
-     *            The prepared statement to execute
-     * @param parametrizedTypeToken
-     *            The parametrized type token to use for deserialization.
-     *            Example as to how this was created:
-     *            <pre>
-     *            Type parametrizedTypeToken = new
-     *            TypeToken&lt;WebQueryResponse&lt;AgentInformation&gt;&gt;().getType();
-     *            </pre>
-     * @param invocationCount The number of recursive invocations performed so far.
-     * @return A cursor for the generic type.
-     * @throws StatementExecutionException
-     *             If execution of the statement failed. In particular, if
-     *             the state got out of sync, it tried to recover and then
-     *             failed again.
-     */
-    <T extends Pojo> Cursor<T> doExecuteQuery(final WebPreparedStatement<T> stmt, Type parametrizedTypeToken, final int invocationCount) throws StatementExecutionException {
-        checkRecursiveInvocationCount(invocationCount);
-        NameValuePair queryParam = new BasicNameValuePair("prepared-stmt", gson.toJson(stmt, WebPreparedStatement.class));
-        List<NameValuePair> formparams = Arrays.asList(queryParam);
-        WebQueryResponse<T> qResp = null;
-        try (CloseableHttpEntity entity = post(endpoint + "/query-execute", formparams)) {
-            Reader reader = getContentAsReader(entity);
-            qResp = gson.fromJson(reader, parametrizedTypeToken);
-        } catch (Exception e) {
-            throw new StatementExecutionException(e);
-        }
-        switch(qResp.getResponseCode()) {
-        case PreparedStatementResponseCode.QUERY_SUCCESS:
-            return new WebCursor<T>(this, qResp.getResultList(),
-                    qResp.hasMoreBatches(),
-                    qResp.getCursorId(), parametrizedTypeToken, stmt);
-        case PreparedStatementResponseCode.ILLEGAL_PATCH: {
-            String msg = "Illegal statement argument. See server logs for details.";
-            IllegalArgumentException iae = new IllegalArgumentException(msg);
-            IllegalPatchException e = new IllegalPatchException(iae);
-            throw new StatementExecutionException(e);
-        }
-        case PreparedStatementResponseCode.PREP_STMT_BAD_STOKEN: {
-            // Try to recover from this situation. If this path is
-            // entered more than once than we'll fail on method entry.
-            try {
-                WebPreparedStatement<T> newStmt = handlePreparedStmtStateOutOfSync(stmt);
-                return doExecuteQuery(newStmt, parametrizedTypeToken, invocationCount + 1);
-            } catch (DescriptorParsingException e) {
-                throw new StatementExecutionException(e);
-            }
-        }
-        default: {
-            String msg = "[query-execute] Unknown response from storage endpoint!";
-            IllegalStateException ise = new IllegalStateException(msg);
-            throw new StatementExecutionException(ise);
-        }
-        }
-    }
-    
-    private void checkRecursiveInvocationCount(int invocationCount) throws StatementExecutionException {
-        if (invocationCount > 1) {
-            // Initial invokation == 0, potential recovery-invocation == 1
-            String msg = "Failed to recover from out-of-sync state with server";
-            logger.log(Level.WARNING, msg);
-            throw new StatementExecutionException(new IllegalStateException(msg));
-        }
-    }
-    
-    /**
-     * This method gets called from WebCursor in order to fetch more results
-     * or refresh the result set since parameters like limit or skip have
-     * changed since the original result set was fetched.
-     * 
-     * @param cursorId
-     * @param parametrizedTypeToken The type token for the data class (Pojo).
-     * @param batchSize The desired batchSize or null. null means that the user
-     *                  did not set an explicit batch size.
-     * @param limit The desired limit for this cursor or null. null means that
-     *              a user did not set an explicit limit.
-     * @param skip The desired skip value or null. null means no skip value has
-     *             been specified by the user.
-     * @return
-     */
-    <T extends Pojo> WebQueryResponse<T> getMore(int cursorId, Type parametrizedTypeToken, Integer batchSize, WebPreparedStatement<T> stmt) {
-        String stmtId = gson.toJson(stmt.getStatementId());
-        NameValuePair preparedStmtIdParam = new BasicNameValuePair("prepared-stmt-id", stmtId);
-        NameValuePair cursorIdParam = new BasicNameValuePair("cursor-id", Integer.toString(cursorId));
-        NameValuePair batchSizeParam = new BasicNameValuePair("batch-size", batchSize.toString());
-        
-        List<NameValuePair> formparams = Arrays.asList(preparedStmtIdParam,
-                                                       cursorIdParam,
-                                                       batchSizeParam);
-        WebQueryResponse<T> qResp = null;
-        try (CloseableHttpEntity entity = post(endpoint + "/get-more", formparams)) {
-            Reader reader = getContentAsReader(entity);
-            qResp = gson.fromJson(reader, parametrizedTypeToken);
-        } catch (Exception e) {
-            throw new StorageException(e);
-        }
-        return qResp;
-    }
-    
-    /**
-     * Executes a prepared write
-     * 
-     * @param stmt
-     *            The prepared statement to execute
-     * @param invocationCount
-     *            The number of times this method has been recursively called,
-     *            starting at 0.
-     * @return The response code of executing the underlying data modifying
-     *         statement.
-     * @throws StatementExecutionException
-     *             If execution of the statement failed. For example if the
-     *             values set as prepared parameters did not work or were
-     *             partially missing for the prepared statement.
-     */
-    <T extends Pojo> int doWriteExecute(final WebPreparedStatement<T> stmt, final int invocationCount)
-            throws StatementExecutionException {
-        checkRecursiveInvocationCount(invocationCount);
-        NameValuePair queryParam = new BasicNameValuePair("prepared-stmt", gson.toJson(stmt, WebPreparedStatement.class));
-        List<NameValuePair> formparams = Arrays.asList(queryParam);
-        int responseCode = PreparedStatementResponseCode.WRITE_GENERIC_FAILURE;
-        try (CloseableHttpEntity entity = post(endpoint + "/write-execute", formparams)) {
-            Reader reader = getContentAsReader(entity);
-            responseCode = gson.fromJson(reader, int.class);
-        } catch (Exception e) {
-            throw new StatementExecutionException(e);
-        }
-        if (responseCode == PreparedStatementResponseCode.ILLEGAL_PATCH) {
-            String msg = "Illegal statement argument. See server logs for details. Invokation count: " + invocationCount;
-            IllegalArgumentException iae = new IllegalArgumentException(msg);
-            IllegalPatchException e = new IllegalPatchException(iae);
-            throw new StatementExecutionException(e);
-        } else if (responseCode == PreparedStatementResponseCode.PREP_STMT_BAD_STOKEN) {
-            // Try to recover from this situation. If this path is
-            // entered more than once than we'll fail on method entry.
-            try {
-                WebPreparedStatement<T> newStmt = handlePreparedStmtStateOutOfSync(stmt);
-                return doWriteExecute(newStmt, invocationCount + 1);
-            } catch (DescriptorParsingException e) {
-                throw new StatementExecutionException(e);
-            }
-        }
-        return responseCode;
-    }
-
-    @Override
-    public Connection getConnection() {
-        return conn;
-    }
-
-    @Override
-    public InputStream loadFile(String name) throws StorageException {
-        NameValuePair fileParam = new BasicNameValuePair("file", name);
-        List<NameValuePair> formparams = Arrays.asList(fileParam);
-        CloseableHttpEntity entity = post(endpoint + "/load-file", formparams);
-        if (entity.getResponseCode() == STATUS_NO_CONTENT) {
-            return null;
-        }
-        return new WebDataStream(entity);
-    }
-
-    @Override
-    public void saveFile(String filename, InputStream data, SaveFileListener listener) {
-        Objects.requireNonNull(listener);
-        StorageException exceptionIfAny = null;
-
-        try {
-            doSave(filename, data);
-        } catch (StorageException e) {
-            exceptionIfAny = e;
-        }
-
-        if (exceptionIfAny != null) {
-            listener.notify(EventType.EXCEPTION_OCCURRED, exceptionIfAny);
-        } else {
-            listener.notify(EventType.SAVE_COMPLETE, null);
-        }
-    }
-
-    private void doSave(String name, InputStream in) throws StorageException {
-        InputStreamBody body = new InputStreamBody(in, name);
-        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
-        HttpEntity mpEntity = builder.addPart("file", body).build();
-        // See IcedTea bug #1314. For safe-file we need to do this:
-        // setExcpectContinueEnabled. However,
-        // doing this for other actions messes up authentication when using
-        // jetty (and possibly others). Hence, do this expect-continue thingy
-        // only for save-file. We achieve this via a single request configuration.
-        RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(true).build();
-        post(endpoint + "/save-file", mpEntity, config).close();
-    }
-
-    @Override
-    public void purge(String agentId) throws StorageException {
-        NameValuePair agentIdParam = new BasicNameValuePair("agentId", agentId);
-        List<NameValuePair> agentIdParams = Arrays.asList(agentIdParam);
-        post(endpoint + "/purge", agentIdParams).close();
-    }
-
-    @Override
-    public AuthToken generateToken(String actionName) throws StorageException {
-        byte[] clientToken = new byte[256];
-        random.nextBytes(clientToken);
-        NameValuePair clientTokenParam = new BasicNameValuePair("client-token", Base64.encodeBase64String(clientToken));
-        NameValuePair actionNameParam = new BasicNameValuePair("action-name",
-                Objects.requireNonNull(actionName));
-        List<NameValuePair> formparams = Arrays.asList(clientTokenParam, actionNameParam);
-        try (CloseableHttpEntity entity = post(endpoint + "/generate-token", formparams)) {
-            byte[] authToken = EntityUtils.toByteArray(entity);
-            return new AuthToken(authToken, clientToken);
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    @Override
-    public boolean verifyToken(AuthToken authToken, String actionName) {
-        byte[] clientToken = authToken.getClientToken();
-        byte[] token = authToken.getToken();
-        NameValuePair clientTokenParam = new BasicNameValuePair("client-token", Base64.encodeBase64String(clientToken));
-        NameValuePair tokenParam = new BasicNameValuePair("token", Base64.encodeBase64String(token));
-        NameValuePair actionNameParam = new BasicNameValuePair("action-name",
-                Objects.requireNonNull(actionName));
-        List<NameValuePair> formparams = Arrays.asList(clientTokenParam,
-                tokenParam, actionNameParam);
-        HttpResponse response = null;
-        try {
-            HttpEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
-            HttpPost httpPost = new HttpPost(endpoint + "/verify-token");
-            httpPost.setEntity(entity);
-            synchronized (httpClientContextLock) {
-                response = httpClient.execute(httpPost, httpClientContext);
-            }
-            StatusLine status = response.getStatusLine();
-            return status.getStatusCode() == STATUS_OK;
-        } catch (IOException ex) {
-            throw new StorageException(ex);
-        } finally {
-            if (response != null) {
-                try {
-                    EntityUtils.consume(response.getEntity());
-                } catch (IOException ex) {
-                    throw new StorageException(ex);
-                }
-            }
-        }
-    }
-
-    @Override
-    public void shutdown() {
-        // Nothing to do here.
-    }
-
-    SharedStateId getCategoryId(Category<?> category) {
-        return categoryIds.get(category);
-    }
-    
-    /**
-     * Package private for testing
-     * 
-     * This method handles the recovery mechanism which needs to be done before
-     * an already failed {@link WebPreparedStatement} can be re-submitted
-     * because some state maintained in the client (here) and on the server
-     * need to be in agreement.
-     * 
-     * Here is how the recovery mechanism works:
-     * 
-     * Pre: client and server agree on an ID for every statement. Any single
-     *      statement is uniquely identifiable via the (server-token, int-id)
-     *      pair. When this method is called we already know that when we first
-     *      tried to execute the statement we had an out-dated server-token in
-     *      record. Thus, we need to refresh the local cache with updated
-     *      statement IDs.
-     * 
-     * Getting the local cache back in sync can be done by:
-     * 1. Removing the old values from the current statement cache and 
-     * 2. Re-registering the underlying category and re-preparing the statement
-     *  
-     * The above two steps will be done once per statement descriptor. This will
-     * update the statement cache accordingly. However, since there may be other
-     * statements in the local queue waiting to be executed. Those pending
-     * statements still have old statement IDs in record. This is where the
-     * transition cache comes into play. There is no need to re-register categories
-     * and re-prepare statements for the same descriptor. It was already done
-     * once and the main statement cache updated accordingly. The transition cache is then used
-     * to get the descriptor from an old statement ID. I.e. whenever the transition
-     * cache is used it is no longer equal to the main statement cache. In a way
-     * the transition cache is a tool to get a descriptor for an now out-dated
-     * statement ID. Once we have the descriptor again we can look it up in the
-     * regular statement cache in (which has been updated previously) in order
-     * to get the updated values for the statement ID.
-     *  
-     * @param origStmt The original statement that failed to execute.
-     * @return A fixed-up statement which should succeed to execute if tried
-     *         again.
-     * @throws DescriptorParsingException If re-preparing a statement failed.
-     */
-    synchronized <T extends Pojo> WebPreparedStatement<T> handlePreparedStmtStateOutOfSync(final WebPreparedStatement<T> origStmt) throws DescriptorParsingException {
-        SharedStateId id = origStmt.getStatementId();
-        String msg = "Prepared statement failed to execute. Server changed token. Trying to recover stmt with id: " + id;
-        logger.log(Level.FINE, msg);
-        // Transition stmt cache needs to be created in 2 cases:
-        // 1. It might be null if it was the first time the server
-        //    re-deployed.
-        // 2. The server did re-deploy at least once and the time it happened
-        //    is more than TRANSITION_CACHE_OFFSET in the past. Case for
-        //    multiple re-deployments of the server parts.
-        if (transitionStmtCache == null || transitionStmtCache.isExpired()) {
-            // Create a transition cache which expires soon in the future
-            // in order to allow successful executions of queued statements which
-            // did not yet run and have old statement IDs in record.
-            logger.log(Level.FINE, "Re-creating transition cache");
-            WebPreparedStatementCache cacheSnapshot = stmtCache.createSnapshot();
-            long timeExpires = System.nanoTime() + TRANSITION_CACHE_OFFSET;
-            transitionStmtCache = new ExpirableWebPreparedStatementCache(cacheSnapshot, timeExpires);
-        }
-        StatementDescriptor<T> desc = stmtCache.get(id);
-        // If the above returned null we most likely tried to execute a statement
-        // with an old server token. Attempt to use the transition cache in order
-        // to still be able to execute it successfully.
-        if (desc == null) {
-            desc = transitionStmtCache.get(id);
-            if (desc == null) {
-                throw new IllegalStateException("Irrecoverable error. GC happened or transition cache expired.");
-            }
-            WebPreparedStatementHolder transCacheHolder = transitionStmtCache.get(desc);
-            WebPreparedStatementHolder cacheHolder = stmtCache.get(desc);
-            if (transCacheHolder.getStatementId().equals(cacheHolder.getStatementId())) {
-                throw new IllegalStateException("Should not happen!");
-            }
-            // Transition case:
-            //
-            // Fetch the new mapping from the stmt cache since the statement id
-            // must have changed but category-registration and preparing the
-            // updated statement was done already.
-            SharedStateId stmtId = cacheHolder.getStatementId();
-            logger.log(Level.FINE, "Returning fixed-up statement using updated statement id: " + stmtId);
-            origStmt.setStatementId(stmtId);
-            return origStmt;
-        }
-        // Base case: re-register category and re-prepare statement. This will
-        //            be done *once* for every statement.
-        logger.log(Level.FINE, "Re-register category + prepareStatement + setting params: " + desc);
-        sendCategoryReRegistrationRequest(desc.getCategory());
-        stmtCache.remove(id);
-        // prepareStatement() will return a raw statement (no parameters will be
-        // set in this new datastructure). In order to make it executable right
-        // away we need to set the params via the params we have in record in the
-        // original stmt.
-        WebPreparedStatement<T> newStmt = (WebPreparedStatement<T>)prepareStatement(desc);
-        newStmt.setParams(origStmt.getParams());
-        return newStmt;
-    }
-
-    @Override
-    public <T extends Pojo> PreparedStatement<T> prepareStatement(StatementDescriptor<T> desc)
-            throws DescriptorParsingException {
-        /*
-         * Avoid two network round-trips for statements which have already
-         * been prepared. Note that this makes preparing statements not entirely
-         * stateless, since the prepared statement ID might change if the
-         * web endpoint reloads. If those IDs get out-of-sync we do our best
-         * to correct this situation by clearing the relevant cache entry and
-         * preparing the statement again.
-         */
-        WebPreparedStatementHolder holder = stmtCache.get(desc);
-        // note this is a WeakHashMap-backed cache and may return null
-        if (holder == null) {
-            // Cache-miss, send request over the wire and cache result.
-            holder = sendPrepareStmtRequest(desc, 0);
-            stmtCache.put(desc, holder);
-        }
-        return new WebPreparedStatementImpl<>(holder.getTypeToken(), holder.getNumParams(), holder.getStatementId());
-    }
-    
-    // package-private for testing
-    <T extends Pojo> WebPreparedStatementHolder sendPrepareStmtRequest(StatementDescriptor<T> desc, final int invokationCount)
-            throws DescriptorParsingException {
-        if (invokationCount > 1) {
-            // Initial invokation == 0, potential recovery-invocation == 1
-            String msg = "Failed to recover from out-of-sync state with server";
-            logger.log(Level.WARNING, msg);
-            throw new DescriptorParsingException(msg);
-        }
-        String strDesc = desc.getDescriptor();
-        SharedStateId categoryId = getCategoryId(desc.getCategory());
-        NameValuePair nameParam = new BasicNameValuePair("query-descriptor",
-                strDesc);
-        NameValuePair categoryParam = new BasicNameValuePair("category-id",
-                gson.toJson(categoryId, SharedStateId.class));
-        List<NameValuePair> formparams = Arrays
-                .asList(nameParam, categoryParam);
-        try (CloseableHttpEntity entity = post(endpoint + "/prepare-statement",
-                formparams)) {
-            Reader reader = getContentAsReader(entity);
-            WebPreparedStatementResponse result = gson.fromJson(reader, WebPreparedStatementResponse.class);
-            int numParams = result.getNumFreeVariables();
-            SharedStateId statementId = result.getStatementId();
-            int stmtId = statementId.getId();
-            switch (stmtId) {
-                case WebPreparedStatementResponse.ILLEGAL_STATEMENT: {
-                    // we've got a descriptor the endpoint doesn't know about or
-                    // refuses to accept for security reasons.
-                    String msg = "Unknown query descriptor which endpoint of " + WebStorage.class.getName() + " refused to accept!";
-                    throw new IllegalDescriptorException(msg, desc.getDescriptor());
-                }
-                case WebPreparedStatementResponse.DESCRIPTOR_PARSE_FAILED: {
-                    String msg = "Statement descriptor failed to parse. " +
-                            "Please check server logs for details!";
-                    throw new DescriptorParsingException(msg);
-                }
-                case WebPreparedStatementResponse.CATEGORY_OUT_OF_SYNC: {
-                    // We tried to prepare a statement and the server's
-                    // representation of category IDs changed. Thus, be sure to
-                    // clear the category state and get their new IDs.
-                    String msg = "Preparing statement failed. Server changed category state. Clearing category ID for statement: " +
-                                    desc.getDescriptor() + " and trying to recover.";
-                    logger.log(Level.FINE, msg);
-                    sendCategoryReRegistrationRequest(desc.getCategory());
-                    return sendPrepareStmtRequest(desc, invokationCount + 1);
-                }
-                default: {
-                    // Common case where stmtId is the actual ID of the statement
-                    // and not an error code.
-                    assert(stmtId >= 0); // negative values are error codes
-                    // We need this ugly trick in order for WebQueryResponse
-                    // deserialization to work properly. I.e. GSON needs this type
-                    // info hint.
-                    Class<T> dataClass = desc.getCategory().getDataClass();
-                    Type typeToken = new WebQueryResponse<T>().getRuntimeParametrizedType(dataClass);
-                    return new WebPreparedStatementHolder(typeToken, numParams, statementId);
-                }
-            }
-        }
-    }
-    
-    // package private for testing
-    synchronized <T extends Pojo> void sendCategoryReRegistrationRequest(Category<T> category) {
-        // There are two possible cases. Category is an aggregate category or
-        // it is not. For aggregate categories we need to re-register the
-        // original first and then the aggregate category.
-        Class<T> dataClass = category.getDataClass();
-        if (AggregateResult.class.isAssignableFrom(dataClass)) {
-            Category<?> nonAggregateCategory = Categories.getByName(category.getName());
-            categoryIds.remove(nonAggregateCategory);
-            registerCategory(nonAggregateCategory);
-        }
-        categoryIds.remove(category);
-        registerCategory(category);
-    }
-
-
-}
-
--- a/web/client/src/main/java/com/redhat/thermostat/web/client/internal/WebStorageProvider.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.util.concurrent.TimeUnit;
-
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.shared.perflog.PerformanceLogFormatter;
-import com.redhat.thermostat.shared.perflog.PerformanceLogFormatterBuilder;
-import com.redhat.thermostat.storage.core.SecureQueuedStorage;
-import com.redhat.thermostat.storage.core.Storage;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.StorageProvider;
-
-public class WebStorageProvider implements StorageProvider {
-
-    private String url;
-    private StorageCredentials creds;
-    private SSLConfiguration sslConf;
-    
-    @Override
-    public Storage createStorage() {
-        WebStorage storage = new WebStorage(url, creds, sslConf);
-        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(WebStorageProvider.class)).intValue() <= LoggingUtils.LogLevel.PERFLOG.getLevel().intValue()) {
-            PerformanceLogFormatterBuilder builder = PerformanceLogFormatterBuilder.create();
-            PerformanceLogFormatter lf = builder.setLoggedTimeUnit(TimeUnit.MICROSECONDS)
-                                              .build();
-            return new SecureQueuedStorage(storage, lf); 
-        }
-        return new SecureQueuedStorage(storage);
-    }
-
-    @Override
-    public void setConfig(String connectionURL, StorageCredentials creds, SSLConfiguration sslConf) {
-        this.url = connectionURL;
-        this.creds = creds;
-        this.sslConf = sslConf;
-    }
-
-    @Override
-    public boolean canHandleProtocol() {
-        // use http since this might be https at some point
-        return url.startsWith("http");
-    }
-
-}
-
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/EntityConsumingIOExceptionTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.http.HttpEntity;
-import org.junit.Test;
-
-public class EntityConsumingIOExceptionTest {
-
-    @Test
-    public void verifyEntityIsConsumed() throws IllegalStateException, IOException {
-        HttpEntity entity = mock(HttpEntity.class);
-        InputStream stream = mock(InputStream.class);
-        when(entity.getContent()).thenReturn(stream);
-        when(entity.isStreaming()).thenReturn(true);
-        
-        // this should trigger consumption of entity
-        new EntityConsumingIOException(entity, "testing-consume");
-        verify(stream).close();
-    }
-}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/ExpirableWebPreparedStatementCacheTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-public class ExpirableWebPreparedStatementCacheTest {
-    
-    private static final UUID SERVER_TOKEN = UUID.randomUUID();
-    private static final SharedStateId STMT_ID = new SharedStateId(3, SERVER_TOKEN);
-    private WebPreparedStatementCache cache;
-    private StatementDescriptor<?> desc;
-    
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setup() {
-        cache = new WebPreparedStatementCache();
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        when(holder.getStatementId()).thenReturn(STMT_ID);
-        desc = new StatementDescriptor<>(mock(Category.class), "test-desc");
-        cache.put(desc, holder);
-    }
-
-    @Test
-    public void testGetByDesc() {
-        long expires = System.nanoTime() + TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS);
-        ExpirableWebPreparedStatementCache expCache = new ExpirableWebPreparedStatementCache(cache, expires);
-        assertNotNull("should not yet be expired", expCache.get(desc));
-        @SuppressWarnings("unchecked")
-        StatementDescriptor<?> notExisting = new StatementDescriptor<>(mock(Category.class), "testing");
-        assertNull("entry does not exist", expCache.get(notExisting));
-        
-        expires = System.nanoTime() - TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS);
-        expCache = new ExpirableWebPreparedStatementCache(cache, expires);
-        assertNull("should have expired", expCache.get(desc));
-    }
-    
-    @Test
-    public void testGetById() {
-        long expires = System.nanoTime() + TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS);
-        ExpirableWebPreparedStatementCache expCache = new ExpirableWebPreparedStatementCache(cache, expires);
-        assertNotNull("should not yet be expired", expCache.get(STMT_ID));
-        assertNull("entry does not exist", expCache.get(new SharedStateId(3, UUID.randomUUID())));
-        
-        expires = System.nanoTime() - TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS);
-        expCache = new ExpirableWebPreparedStatementCache(cache, expires);
-        assertNull("should have expired", expCache.get(STMT_ID));
-    }
-    
-    @Test
-    public void testIsExpired() {
-        long expires = System.nanoTime() - TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
-        ExpirableWebPreparedStatementCache cache = new ExpirableWebPreparedStatementCache(null, expires);
-        assertTrue(cache.isExpired());
-        
-        expires = System.nanoTime() + TimeUnit.NANOSECONDS.convert(100, TimeUnit.MILLISECONDS);
-        cache = new ExpirableWebPreparedStatementCache(null, expires);
-        assertFalse(cache.isExpired());
-    }
-
-}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/TestObj.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.model.BasePojo;
-
-@Entity
-public class TestObj extends BasePojo {
-
-    public TestObj() {
-        super(null);
-    }
-    
-    private String property1;
-
-    @Persist
-    public void setProperty1(String property1) {
-        this.property1 = property1;
-    }
-
-    @Persist
-    public String getProperty1() {
-        return property1;
-    }
-
-    public boolean equals(Object o) {
-        if (! (o instanceof TestObj)) {
-            return false;
-        }
-        TestObj other = (TestObj) o;
-        return property1.equals(other.property1);
-    }
-}
-
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebCursorTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-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 java.lang.reflect.Type;
-import java.util.NoSuchElementException;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-public class WebCursorTest {
-
-    private WebStorage storage;
-    private int cursorId;
-    private Type fakeType;
-    private WebPreparedStatement<TestObj> stmt;
-    
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setup() {
-        storage = mock(WebStorage.class);
-        cursorId = 4441;
-        fakeType = mock(Type.class);
-        stmt = mock(WebPreparedStatement.class);
-    }
-    
-    @Test
-    public void testHasNext() {
-        boolean hasMoreBatches = false;
-        TestObj[] dataBatch = new TestObj[] { };
-        WebCursor<TestObj> cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        assertFalse("no results and no more batches", cursor.hasNext());
-        hasMoreBatches = true;
-        cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        assertTrue("no results, but more batches", cursor.hasNext());
-        TestObj o1 = new TestObj();
-        dataBatch = new TestObj[] { o1 };
-        hasMoreBatches = false;
-        cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        assertTrue("one result, no more batches", cursor.hasNext());
-    }
-    
-    @Test
-    public void testNext() {
-        // test empty results and no more batches
-        boolean hasMoreBatches = false;
-        TestObj[] dataBatch = new TestObj[] { };
-        WebCursor<TestObj> cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        try {
-            cursor.next();
-            fail("Cursor should throw a NoSuchElementException!");
-        } catch (NoSuchElementException e) {
-            // pass
-        }
-        
-        // test empty results but more batches
-        hasMoreBatches = true;
-        cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        WebQueryResponse<TestObj> response = new WebQueryResponse<>();
-        response.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        response.setCursorId(cursorId);
-        response.setHasMoreBatches(false);
-        TestObj o1 = new TestObj();
-        o1.setProperty1("next-test");
-        response.setResultList(new TestObj[] { o1 } );
-        WebQueryResponse<TestObj> second = new WebQueryResponse<>();
-        assertNull(second.getResultList());
-        // be sure to return a bad result should storage.getMore() be called
-        // more than once
-        when(storage.getMore(cursorId, fakeType, Cursor.DEFAULT_BATCH_SIZE, stmt)).thenReturn(response).thenReturn(second);
-        TestObj actual = cursor.next();
-        assertEquals("next-test", actual.getProperty1());
-        
-        // test non-empty results and no more batches
-        hasMoreBatches = false;
-        o1.setAgentId("foo-agent-123");
-        dataBatch = new TestObj[] { o1 };
-        cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        actual = cursor.next();
-        assertEquals("foo-agent-123", actual.getAgentId());
-    }
-    
-    /**
-     * Tests next() calls where get-more fails due to an expired or missing
-     * cursor on the web endpoint.
-     */
-    @Test
-    public void testNextGetMoreBadCursorFailure() {
-        boolean hasMoreBatches = true;
-        TestObj[] dataBatch = new TestObj[] { };
-        WebCursor<TestObj> cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        WebQueryResponse<TestObj> response = new WebQueryResponse<>();
-        response.setResponseCode(PreparedStatementResponseCode.GET_MORE_NULL_CURSOR);
-        response.setCursorId(cursorId);
-        response.setHasMoreBatches(false);
-        when(storage.getMore(cursorId, fakeType, Cursor.DEFAULT_BATCH_SIZE, stmt)).thenReturn(response);
-        try {
-            cursor.next();
-            fail("Expected StorageException to be thrown");
-        } catch (StorageException e) {
-            assertEquals("[get-more] Failed to get more results for cursorId: 4441" +
-                         " This may be caused because the cursor timed out. " +
-                         "Resubmitting the original query might be an approach to fix it. " +
-                         "See server logs for more details.",
-                         e.getMessage());
-        }
-    }
-    
-    /**
-     * Tests next() calls where get-more fails due to some unknown reason.
-     */
-    @Test
-    public void testNextGenericGetMoreFailure() {
-        boolean hasMoreBatches = true;
-        TestObj[] dataBatch = new TestObj[] { };
-        WebCursor<TestObj> cursor = new WebCursor<>(storage, dataBatch, hasMoreBatches, cursorId, fakeType, stmt);
-        WebQueryResponse<TestObj> response = new WebQueryResponse<>();
-        response.setResponseCode(PreparedStatementResponseCode.QUERY_FAILURE);
-        response.setCursorId(cursorId);
-        response.setHasMoreBatches(false);
-        when(storage.getMore(cursorId, fakeType, Cursor.DEFAULT_BATCH_SIZE, stmt)).thenReturn(response);
-        try {
-            cursor.next();
-            fail("Expected StorageException to be thrown");
-        } catch (StorageException e) {
-            assertEquals("[get-more] Failed to get more results for cursorId: " + 
-                         "4441. See server logs for details.",
-                         e.getMessage());
-        }
-    }
-    
-    /**
-     * Verify that if a batch size is explicitly set it gets passed on to
-     * web storage on the next call to getMore. Default batch size is accounted
-     * for in other tests (e.g. testNext()).
-     */
-    @Test
-    public void testSetBatchSize() {
-        boolean hasMoreBatches = true;
-        TestObj[] empty = new TestObj[] {};
-        WebCursor<TestObj> cursor = new WebCursor<>(storage, empty, hasMoreBatches, cursorId, fakeType, stmt);
-        try {
-            cursor.setBatchSize(-1);
-            fail("expected IAE for batch size of -1");
-        } catch (IllegalArgumentException e) {
-            // pass
-            assertEquals("Batch size must be > 0", e.getMessage());
-        }
-        try {
-            cursor.setBatchSize(0);
-            fail("expected IAE for batch size of 0");
-        } catch (IllegalArgumentException e) {
-            // pass
-            assertEquals("Batch size must be > 0", e.getMessage());
-        }
-        cursor = new WebCursor<>(storage, empty, hasMoreBatches, cursorId, fakeType, stmt);
-        cursor.setBatchSize(128);
-        TestObj o1 = new TestObj();
-        WebQueryResponse<TestObj> response = new WebQueryResponse<>();
-        response.setResultList(new TestObj[] { o1 });
-        response.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        when(storage.getMore(cursorId, fakeType, 128, stmt)).thenReturn(response);
-        cursor.next();
-        verify(storage).getMore(cursorId, fakeType, 128, stmt);
-        Mockito.verifyNoMoreInteractions(storage);
-    }
-    
-}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebPreparedStatementCacheTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-public class WebPreparedStatementCacheTest {
-
-    private WebPreparedStatementCache cache;
-
-    @Before
-    public void setup() {
-        cache = new WebPreparedStatementCache();
-    }
-
-    @Test
-    public void testPut() {
-        SharedStateId id = new SharedStateId(3, UUID.randomUUID());
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        when(holder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<TestPojo> cat = mock(Category.class);
-        StatementDescriptor<TestPojo> foo = new StatementDescriptor<>(cat,
-                "something");
-        cache.put(foo, holder);
-        assertSame(holder, cache.get(foo));
-        assertSame(foo, cache.get(id));
-        WebPreparedStatementHolder holder2 = mock(WebPreparedStatementHolder.class);
-        when(holder2.getStatementId()).thenReturn(id);
-        cache.put(foo, holder2);
-        assertNotSame(holder, cache.get(foo));
-        assertSame(holder2, cache.get(foo));
-        assertSame(foo, cache.get(id));
-        
-        // Different server token should not result in an look-up-by-id clash.
-        SharedStateId id2 = new SharedStateId(3, UUID.randomUUID());
-        assertNull(cache.get(id2));
-    }
-
-    @Test
-    public void testGetByDesc() {
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = mock(SharedStateId.class);
-        when(holder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<TestPojo> cat = mock(Category.class);
-        StatementDescriptor<TestPojo> foo = new StatementDescriptor<>(cat,
-                "something");
-        cache.put(foo, holder);
-        assertEquals(holder, cache.get(foo));
-        StatementDescriptor<TestPojo> other = new StatementDescriptor<>(cat,
-                "something-else");
-        assertNull(cache.get(other));
-    }
-
-    @Test
-    public void testGetById() {
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = mock(SharedStateId.class);
-        when(holder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<TestPojo> cat = mock(Category.class);
-        StatementDescriptor<TestPojo> foo = new StatementDescriptor<>(cat,
-                "something");
-        cache.put(foo, holder);
-        assertEquals(foo, cache.get(id));
-        assertNull(cache.get(mock(SharedStateId.class)));
-    }
-
-    @Test
-    public void testRemove() {
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = mock(SharedStateId.class);
-        when(holder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<TestPojo> cat = mock(Category.class);
-        StatementDescriptor<TestPojo> foo = new StatementDescriptor<>(cat,
-                "something");
-        cache.put(foo, holder);
-        assertEquals(holder, cache.get(foo));
-
-        cache.remove(id);
-        assertNull(cache.get(foo));
-        assertNull(cache.get(id));
-    }
-
-    /**
-     * Verify that we are able to create a snapshot of a cache in order to be
-     * able to look up old ID mappings.
-     */
-    @Test
-    public void verifyCreateSnapshot() {
-        WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = mock(SharedStateId.class);
-        when(holder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<TestPojo> cat = mock(Category.class);
-        StatementDescriptor<TestPojo> foo = new StatementDescriptor<>(cat,
-                "something");
-        cache.put(foo, holder);
-        assertEquals(holder, cache.get(foo));
-        assertNotNull(cache.get(id));
-        
-        WebPreparedStatementCache copy = cache.createSnapshot();
-
-        cache.remove(id);
-        
-        assertNull(cache.get(foo));
-        assertNull(cache.get(id));
-        
-        assertNotNull(copy.get(foo));
-        assertNotNull(copy.get(id));
-    }
-
-    private static class TestPojo implements Pojo {
-        // nothing
-    }
-}
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageProviderTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.BackingStorage;
-import com.redhat.thermostat.storage.core.QueuedStorage;
-import com.redhat.thermostat.storage.core.SecureStorage;
-import com.redhat.thermostat.storage.core.Storage;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-
-public class WebStorageProviderTest {
-
-    @Test
-    public void createStorageCreatesSecureStorage() {
-        WebStorageProvider provider = new WebStorageProvider();
-        SSLConfiguration sslConf = mock(SSLConfiguration.class);
-        StorageCredentials creds = mock(StorageCredentials.class);
-        provider.setConfig("http://something", creds, sslConf);
-        Storage storage = provider.createStorage();
-        assertTrue(storage instanceof SecureStorage);
-        assertTrue(storage instanceof QueuedStorage);
-        assertFalse(storage instanceof BackingStorage);
-    }
-
-    @Test
-    public void canHandleHttpProtocol() {
-        WebStorageProvider provider = new WebStorageProvider();
-        provider.setConfig("http://something.com", null, null);
-        assertTrue(provider.canHandleProtocol());
-    }
-
-    @Test
-    public void canHandleHttpsProtocol() {
-        WebStorageProvider provider = new WebStorageProvider();
-        provider.setConfig("https://something.com", null, null);
-        assertTrue(provider.canHandleProtocol());
-    }
-
-    @Test
-    public void cannotHandleNotWebProtocol() {
-        WebStorageProvider provider = new WebStorageProvider();
-        provider.setConfig("ftp://something.com", null, null);
-        assertFalse(provider.canHandleProtocol());
-    }
-}
-
--- a/web/client/src/test/java/com/redhat/thermostat/web/client/internal/WebStorageTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1321 +0,0 @@
-/*
- * 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.web.client.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.UUID;
-import java.util.concurrent.CountDownLatch;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.protocol.HttpContext;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.common.internal.test.FreePortFinder;
-import com.redhat.thermostat.common.internal.test.FreePortFinder.TryPort;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.AuthToken;
-import com.redhat.thermostat.storage.core.BackingStorage;
-import com.redhat.thermostat.storage.core.Categories;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.CategoryAdapter;
-import com.redhat.thermostat.storage.core.Connection;
-import com.redhat.thermostat.storage.core.Connection.ConnectionListener;
-import com.redhat.thermostat.storage.core.Connection.ConnectionStatus;
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.DescriptorParsingException;
-import com.redhat.thermostat.storage.core.IllegalDescriptorException;
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.storage.core.PreparedStatement;
-import com.redhat.thermostat.storage.core.SaveFileListener;
-import com.redhat.thermostat.storage.core.SaveFileListener.EventType;
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.core.StatementExecutionException;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.model.AggregateResult;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParameterTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.SharedStateIdTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementResponseTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebQueryResponseTypeAdapterFactory;
-
-public class WebStorageTest {
-
-    private Server server;
-
-    private int port;
-
-    // Set these in prepareServer() to determine server behaviour
-    private int responseStatus = HttpServletResponse.SC_OK;
-    private String responseBody;
-
-    // These get set by test server handler (anonymous class in startServer())
-    // Check them after WebStorage method call that should interact with server.
-    private String requestBody;
-    private Map<String,String> headers;
-    private String method;
-    private String requestURI;
-    private UUID serverNonce;
-
-    private static Category<TestObj> category;
-    private static Key<String> key1;
-
-    private WebStorage storage;
-
-
-    @BeforeClass
-    public static void setupCategory() {
-        key1 = new Key<>("property1");
-        category = new Category<>("test", TestObj.class, key1);
-    }
-
-    @AfterClass
-    public static void cleanupCategory() {
-        Categories.remove(category);
-        category = null;
-        key1 = null;
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        serverNonce = UUID.randomUUID();
-        port = FreePortFinder.findFreePort(new TryPort() {
-            @Override
-            public void tryPort(int port) throws Exception {
-                startServer(port);
-            }
-        });
-
-        SSLConfiguration sslConf = mock(SSLConfiguration.class);
-        storage = new WebStorage("http://localhost:" + port + "/", 
-                new TrivialStorageCredentials(null, null), sslConf);
-        headers = new HashMap<>();
-        registerCategory();
-    }
-
-    private void startServer(int port) throws Exception {
-        server = new Server(port);
-        server.setHandler(new AbstractHandler() {
-            
-            @Override
-            public void handle(String target, Request baseRequest,
-                    HttpServletRequest request, HttpServletResponse response)
-                    throws IOException, ServletException {
-                Enumeration<String> headerNames = request.getHeaderNames();
-                while (headerNames.hasMoreElements()) {
-                    String headerName = headerNames.nextElement();
-                    headers.put(headerName, request.getHeader(headerName));
-                }
-
-                method = request.getMethod();
-                requestURI = request.getRequestURI();
-
-                // Read request body.
-                StringBuilder body = new StringBuilder();
-                Reader reader = request.getReader();
-                while (true) {
-                    int read = reader.read();
-                    if (read == -1) {
-                        break;
-                    }
-                    body.append((char) read);
-                }
-                requestBody = body.toString();
-                // Send response body.
-                response.setStatus(responseStatus);
-                if (responseBody != null) {
-                    response.getWriter().write(responseBody);
-                }
-                baseRequest.setHandled(true);
-            }
-        });
-        server.start();
-    }
-
-    // Specified status and response body.
-    private void prepareServer(int responseStatus, String responseBody) {
-        this.responseStatus = responseStatus;
-        this.responseBody = responseBody;
-
-        requestBody = null;
-        requestURI = null;
-        method = null;
-        headers.clear();
-    }
-
-    // Specified status and null response body.
-    private void prepareServer(int responseStatus) {
-        prepareServer(responseStatus, null);
-    }
-
-    // OK status and specified response body.
-    private void prepareServer(String responseBody) {
-        prepareServer(HttpServletResponse.SC_OK, responseBody);
-    }
-
-    // OK status and null response body.
-    private void prepareServer() {
-        prepareServer(HttpServletResponse.SC_OK);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-
-        headers = null;
-        requestURI = null;
-        method = null;
-        storage = null;
-
-        server.stop();
-        server.join();
-    }
-
-    private void registerCategory() {
-
-        // Return 42 for categoryId.
-        Gson gson = new GsonBuilder().registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory()).create();
-        responseBody = gson.toJson(new SharedStateId(42, serverNonce));
-
-        storage.registerCategory(category);
-    }
-    
-    // WebStorage is a proxy storage, no backing storage
-    @Test
-    public void isNoBackingStorage() {
-        assertFalse(storage instanceof BackingStorage);
-    }
-    
-    @Test
-    public void preparingFaultyDescriptorThrowsException() throws UnsupportedEncodingException, IOException {
-        Gson gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                .create();
-
-        // missing quotes for LHS key
-        String strDesc = "QUERY test WHERE a = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        SharedStateId id = new SharedStateId(WebPreparedStatementResponse.DESCRIPTOR_PARSE_FAILED, UUID.randomUUID());
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            storage.prepareStatement(desc);
-            fail("Should have refused to prepare the statement");
-        } catch (IllegalDescriptorException e) {
-            // should have thrown superclass DescriptorParsingException
-            fail(e.getMessage());
-        } catch (DescriptorParsingException e) {
-            // pass
-        }
-    }
-    
-    @Test
-    public void preparingUnknownDescriptorThrowsException() throws UnsupportedEncodingException, IOException {
-        Gson gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                .create();
-
-        String strDesc = "QUERY test WHERE 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        SharedStateId id = new SharedStateId(WebPreparedStatementResponse.ILLEGAL_STATEMENT, UUID.randomUUID());
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            storage.prepareStatement(desc);
-            fail("Should have refused to prepare the statement");
-        } catch (IllegalDescriptorException e) {
-            // pass
-            assertEquals(strDesc, e.getFailedDescriptor());
-        } catch (DescriptorParsingException e) {
-            // should have thrown IllegalDescriptorException
-            fail(e.getMessage());
-        }
-    }
-    
-    @Test
-    public void forbiddenExecuteQueryThrowsConsumingExcptn() throws UnsupportedEncodingException, IOException {
-        Gson gson = new GsonBuilder()
-                            .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                            .create();
-
-        String strDesc = "QUERY test WHERE 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        PreparedStatement<TestObj> stmt = null;
-        
-        int fakePrepStmtId = 5;
-        SharedStateId id = new SharedStateId(fakePrepStmtId, UUID.randomUUID());
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        fakeResponse.setNumFreeVariables(1);
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            stmt = storage.prepareStatement(desc);
-        } catch (DescriptorParsingException e) {
-            // descriptor should parse fine and is trusted
-            fail(e.getMessage());
-        }
-        assertTrue(stmt instanceof WebPreparedStatement);
-        WebPreparedStatement<TestObj> webStmt = (WebPreparedStatement<TestObj>)stmt;
-        assertEquals(id, webStmt.getStatementId());
-        PreparedParameters params = webStmt.getParams();
-        assertEquals(1, params.getParams().length);
-        assertNull(params.getParams()[0]);
-        
-        // now set a parameter
-        stmt.setString(0, "fluff");
-        assertEquals("fluff", params.getParams()[0].getValue());
-        assertEquals(String.class, params.getParams()[0].getType());
-        
-        prepareServer(HttpServletResponse.SC_FORBIDDEN);
-        try {
-            stmt.executeQuery();
-            fail("Forbidden should have thrown an exception!");
-        } catch (StatementExecutionException e) {
-            Throwable t = e.getCause();
-            assertTrue(t instanceof StorageException);
-            t = t.getCause();
-            assertTrue("Wanted EntityConsumingIOException as root cause", t instanceof EntityConsumingIOException);
-        }
-    }
-    
-    @Test
-    public void prepareStatementCachesStatements() throws DescriptorParsingException {
-        String strDesc = "QUERY test WHERE 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        PrepareStatementWebStorage testStorage = new PrepareStatementWebStorage("foo", mock(StorageCredentials.class), mock(SSLConfiguration.class));
-        // should fill the cache
-        WebPreparedStatement<TestObj> stmt = (WebPreparedStatement<TestObj>)testStorage.prepareStatement(desc);
-        int numParams = stmt.getParams().getParams().length;
-        SharedStateId stmtId = stmt.getStatementId();
-        assertEquals(0, numParams);
-        assertEquals(1, stmtId.getId());
-        // this one should be cached, same stmtId and numParams as previous
-        // one.
-        stmt = (WebPreparedStatement<TestObj>)testStorage.prepareStatement(desc);
-        numParams = stmt.getParams().getParams().length;
-        stmtId = stmt.getStatementId();
-        assertEquals("PreparedStatementWebStorge increments a counter" +
-                     " if it wasn't cached. Was it 2? Bad!",
-                     0, numParams);
-        assertEquals("PreparedStatementWebStorge increments a counter" +
-                     " if it wasn't cached. Was it 3? Bad!", 1, stmtId.getId());
-        // preparing a different descriptor should not be cached.
-        strDesc = "QUERY test WHERE 'foo' = ?l";
-        desc = new StatementDescriptor<>(category, strDesc);
-        stmt = (WebPreparedStatement<TestObj>)testStorage.prepareStatement(desc);
-        numParams = stmt.getParams().getParams().length;
-        stmtId = stmt.getStatementId();
-        assertEquals("PreparedStatementWebStorge increments a counter" +
-                     " if it wasn't cached. Triggers e.g. if it was erronously cached!",
-                     2, numParams);
-        assertEquals("PreparedStatementWebStorge increments a counter" +
-                     " if it wasn't cached. Triggers e.g. if it was erronously cached!",
-                     3, stmtId.getId());
-    }
-    
-    @Test
-    public void prepareStatementCachesStatements2() throws DescriptorParsingException {
-        WebPreparedStatementCache cache = mock(WebPreparedStatementCache.class);
-        final WebPreparedStatementHolder holder = mock(WebPreparedStatementHolder.class);
-        WebStorage testStorage = new WebStorage(cache, null) {
-            <T extends Pojo> WebPreparedStatementHolder sendPrepareStmtRequest(StatementDescriptor<T> desc, final int invokationCount)
-                    throws DescriptorParsingException {
-                if (invokationCount != 0) {
-                    throw new AssertionError("expected invokation count 0 but was: " + invokationCount);
-                }
-                return holder;
-            }
-        };
-        String strDesc = "QUERY test WHERE 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        testStorage.prepareStatement(desc);
-        verify(cache).get(desc);
-        verify(cache).put(desc, holder);
-    }
-    
-    @Test
-    public void verifySendCategoryReRegistrationRequest() {
-        @SuppressWarnings("unchecked")
-        Map<Category<?>, SharedStateId> categoryMap = mock(Map.class);
-        final List<Category<?>> interceptedCategories = new ArrayList<>();
-        WebStorage testStorage = new WebStorage(categoryMap) {
-            @Override
-            public void registerCategory(Category<?> category) throws StorageException {
-                interceptedCategories.add(category);
-            }
-        };
-        // verify aggregate categories
-        Category<TestAggregate> aggregateCategory = new CategoryAdapter<TestObj, TestAggregate>(category).getAdapted(TestAggregate.class);
-        testStorage.sendCategoryReRegistrationRequest(aggregateCategory);
-        verify(categoryMap).remove(aggregateCategory);
-        verify(categoryMap).remove(category);
-        assertEquals(2, interceptedCategories.size());
-        assertEquals("Expected actual category to be re-registered first", category, interceptedCategories.get(0));
-        assertEquals("Expected aggregate category to be re-registered second", aggregateCategory, interceptedCategories.get(1));
-        
-        interceptedCategories.clear();
-        
-        // verify regular categories
-        testStorage.sendCategoryReRegistrationRequest(category);
-        // earlier test above did invoke it already once
-        verify(categoryMap, times(2)).remove(category);
-        assertEquals(1, interceptedCategories.size());
-        assertEquals(category, interceptedCategories.get(0));
-        verifyNoMoreInteractions(categoryMap);
-    }
-    
-    /**
-     * Tests a query which returns results in a single batch.
-     * 
-     * By setting hasMoreBatches to false in WebQueryResponse we signal that
-     * there are no more batches available via getMore().
-     * 
-     * @see {@link #canPrepareAndExecuteQueryMultiBatchFailure()}
-     * @see {@link #canPrepareAndExecuteQueryMultiBatchSuccess()}
-     */
-    @Test
-    public void canPrepareAndExecuteQuerySingleBatch() {
-        WebQueryResponse<TestObj> fakeQueryResponse = new WebQueryResponse<>();
-        fakeQueryResponse.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        fakeQueryResponse.setResultList(getTwoTestObjects());
-        fakeQueryResponse.setCursorId(444);
-        // Setting this to false makes Cursor.hasNext() return false after the
-        // current result list is exhausted.
-        fakeQueryResponse.setHasMoreBatches(false);
-        Cursor<TestObj> results = doBasicPrepareAndExecuteQueryTest(fakeQueryResponse);
-        assertFalse(results.hasNext());
-        try {
-            results.next();
-            fail("Cursor should throw a NoSuchElementException!");
-        } catch (NoSuchElementException e) {
-            // pass
-        }
-    }
-    
-    /**
-     * Tests a query which returns results in multiple batches. The get-more
-     * call is successful in this test.
-     * 
-     * By setting hasMoreBatches to true in WebQueryResponse we signal that
-     * there are more batches available via getMore().
-     * @throws IOException 
-     * @throws UnsupportedEncodingException 
-     * 
-     * @see {@link #canPrepareAndExecuteQueryMultiBatchFailure()}
-     */
-    @Test
-    public void canPrepareAndExecuteQueryMultiBatchSuccess() throws UnsupportedEncodingException, IOException {
-        WebQueryResponse<TestObj> fakeQueryResponse = new WebQueryResponse<>();
-        fakeQueryResponse.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        fakeQueryResponse.setResultList(getTwoTestObjects());
-        fakeQueryResponse.setCursorId(444);
-        // Setting this to true makes Cursor.hasNext() return true after the
-        // current result list is exhausted.
-        fakeQueryResponse.setHasMoreBatches(true);
-        // doBasicPrepareAndExecuteQueryTest performs two hasNext() and
-        // next() calls on the cursor.
-        Cursor<TestObj> results = doBasicPrepareAndExecuteQueryTest(fakeQueryResponse);
-        assertTrue("Expected cursor to return true, since there are more batches", results.hasNext());
-        assertEquals("POST", method);
-        String path = requestURI.substring(requestURI.lastIndexOf('/'));
-        assertEquals("/query-execute", path);
-
-        TestObj more = new TestObj();
-        more.setProperty1("get-more-result");
-        WebQueryResponse<TestObj> getMoreResults = new WebQueryResponse<>();
-        getMoreResults.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        getMoreResults.setCursorId(444);
-        getMoreResults.setHasMoreBatches(true); // one more batch
-        getMoreResults.setResultList(new TestObj[] {more});
-        final Gson gson = getQueryGson();
-        prepareServer(gson.toJson(getMoreResults));
-        // the following next() call performs the get-more request
-        // for which we had to prepare the server
-        TestObj returnedGetMore = results.next();
-        assertEquals("POST", method);
-        path = requestURI.substring(requestURI.lastIndexOf('/'));
-        assertEquals("/get-more", path);
-        // Verify correctly passed parameters
-        StringReader reader = new StringReader(requestBody);
-        BufferedReader bufRead = new BufferedReader(reader);
-        String line = URLDecoder.decode(bufRead.readLine(), "UTF-8");
-        String[] requestParams = line.split("&");
-        String prepStmtIdParam = requestParams[0];
-        String cursorIdParam = requestParams[1];
-        String batchSizeParam = requestParams[2];
-        String[] prStmtArray = prepStmtIdParam.split("=");
-        String[] cursorIdArray = cursorIdParam.split("=");
-        String[] batchSizeArray = batchSizeParam.split("=");
-        assertEquals("prepared-stmt-id", prStmtArray[0]);
-        SharedStateId prStmtId = gson.fromJson(prStmtArray[1], SharedStateId.class);
-        assertEquals(5, prStmtId.getId());
-        assertEquals("cursor-id", cursorIdArray[0]);
-        assertEquals("444", cursorIdArray[1]);
-        assertEquals("batch-size", batchSizeArray[0]);
-        assertEquals(Integer.toString(Cursor.DEFAULT_BATCH_SIZE), batchSizeArray[1]);
-
-        assertEquals("get-more-result", returnedGetMore.getProperty1());
-        
-        
-        // Do it again, this time with a non-default batch size: 5
-        
-        results.setBatchSize(5);
-        
-        WebQueryResponse<TestObj> getMoreResults2 = new WebQueryResponse<>();
-        getMoreResults2.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        getMoreResults2.setCursorId(444);
-        getMoreResults2.setHasMoreBatches(false); // no more batches this time
-        getMoreResults2.setResultList(new TestObj[] { more });
-        prepareServer(gson.toJson(getMoreResults2));
-        results.next();
-        
-        path = requestURI.substring(requestURI.lastIndexOf('/'));
-        assertEquals("/get-more", path);
-        
-        String[] batchSizeParamPair = requestBody.split("&")[2].split("=");
-        assertEquals("batch-size", batchSizeParamPair[0]);
-        assertEquals("5", batchSizeParamPair[1]);
-    }
-    
-    /**
-     * Tests a query which returns results in multiple batches. The get-more
-     * call fails on the server side, though.
-     *
-     * @see {@link #canPrepareAndExecuteQueryMultiBatchSuccess()}
-     */
-    @Test
-    public void canPrepareAndExecuteQueryMultiBatchFailure() {
-        WebQueryResponse<TestObj> fakeQueryResponse = new WebQueryResponse<>();
-        fakeQueryResponse.setResponseCode(PreparedStatementResponseCode.QUERY_SUCCESS);
-        fakeQueryResponse.setResultList(getTwoTestObjects());
-        fakeQueryResponse.setCursorId(444);
-        fakeQueryResponse.setHasMoreBatches(true);
-        Cursor<TestObj> results = doBasicPrepareAndExecuteQueryTest(fakeQueryResponse);
-        assertTrue("Expected cursor to return true, since there are more batches", results.hasNext());
-        
-        WebQueryResponse<TestObj> getMoreResults = new WebQueryResponse<>();
-        getMoreResults.setResponseCode(PreparedStatementResponseCode.QUERY_FAILURE);
-        final Gson gson = getQueryGson();
-        prepareServer(gson.toJson(getMoreResults));
-        try {
-            results.next();
-            fail(); // Expected storage exception
-        } catch (StorageException e) {
-            assertEquals("[get-more] Failed to get more results for cursorId: 444. See server logs for details.", e.getMessage());
-        }
-        // Do it again with a generic failure code
-        getMoreResults.setResponseCode(-0xcafeBabe); // this should be unknown
-        prepareServer(gson.toJson(getMoreResults));
-        try {
-            results.next();
-            fail(); // Expected storage exception
-        } catch (StorageException e) {
-            assertEquals("[get-more] Failed to get more results for cursorId: 444. See server logs for details.", e.getMessage());
-        }
-    }
-    
-    private TestObj[] getTwoTestObjects() {
-        TestObj obj1 = new TestObj();
-        obj1.setProperty1("fluffor1");
-        TestObj obj2 = new TestObj();
-        obj2.setProperty1("fluffor2");
-        return new TestObj[] { obj1, obj2 };
-    }
-
-    private Cursor<TestObj> doBasicPrepareAndExecuteQueryTest(WebQueryResponse<TestObj> fakeQueryResponse) {
-        Gson gson = getQueryGson();
-
-        String strDesc = "QUERY test WHERE 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        PreparedStatement<TestObj> stmt = null;
-        
-        int fakePrepStmtId = 5;
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        fakeResponse.setNumFreeVariables(1);
-        SharedStateId id = new SharedStateId(fakePrepStmtId, UUID.randomUUID());
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            stmt = storage.prepareStatement(desc);
-        } catch (DescriptorParsingException e) {
-            // descriptor should parse fine and is trusted
-            fail(e.getMessage());
-        }
-        assertTrue(stmt instanceof WebPreparedStatement);
-        WebPreparedStatement<TestObj> webStmt = (WebPreparedStatement<TestObj>)stmt;
-        assertEquals(fakePrepStmtId, webStmt.getStatementId().getId());
-        PreparedParameters params = webStmt.getParams();
-        assertEquals(1, params.getParams().length);
-        assertNull(params.getParams()[0]);
-        
-        // now set a parameter
-        stmt.setString(0, "fluff");
-        assertEquals("fluff", params.getParams()[0].getValue());
-        assertEquals(String.class, params.getParams()[0].getType());
-        
-        prepareServer(gson.toJson(fakeQueryResponse));
-        Cursor<TestObj> results = null;
-        try {
-            results = stmt.executeQuery();
-        } catch (StatementExecutionException e) {
-            // should execute fine
-            e.printStackTrace();
-            fail(e.getMessage());
-        }
-        assertNotNull(results);
-        assertTrue(results instanceof WebCursor);
-        assertTrue(results.hasNext());
-        assertEquals("fluffor1", results.next().getProperty1());
-        assertTrue(results.hasNext());
-        assertEquals("fluffor2", results.next().getProperty1());
-        return results;
-    }
-    
-    private Gson getQueryGson() {
-        return new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                    .create();
-    }
-    
-    @Test
-    public void canPrepareAndExecuteWrite() {
-        TestObj obj1 = new TestObj();
-        obj1.setProperty1("fluffor1");
-        TestObj obj2 = new TestObj();
-        obj2.setProperty1("fluffor2");
-        Gson gson = new GsonBuilder()
-                            .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                            .create();
-
-        String strDesc = "ADD test SET 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        PreparedStatement<TestObj> stmt = null;
-        
-        int fakePrepStmtId = 3;
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        fakeResponse.setNumFreeVariables(1);
-        SharedStateId id = new SharedStateId(fakePrepStmtId, UUID.randomUUID());
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            stmt = storage.prepareStatement(desc);
-        } catch (DescriptorParsingException e) {
-            // descriptor should parse fine and is trusted
-            fail(e.getMessage());
-        }
-        assertTrue(stmt instanceof WebPreparedStatement);
-        WebPreparedStatement<TestObj> webStmt = (WebPreparedStatement<TestObj>)stmt;
-        assertEquals(fakePrepStmtId, webStmt.getStatementId().getId());
-        PreparedParameters params = webStmt.getParams();
-        assertEquals(1, params.getParams().length);
-        assertNull(params.getParams()[0]);
-        
-        // now set a parameter
-        stmt.setString(0, "fluff");
-        assertEquals("fluff", params.getParams()[0].getValue());
-        assertEquals(String.class, params.getParams()[0].getType());
-        
-        prepareServer(gson.toJson(PreparedStatementResponseCode.WRITE_GENERIC_FAILURE));
-        
-        int response = Integer.MAX_VALUE;
-        try {
-            response = stmt.execute();
-        } catch (StatementExecutionException e) {
-            // should execute fine
-            e.printStackTrace();
-            fail(e.getMessage());
-        }
-        
-        assertEquals(PreparedStatementResponseCode.WRITE_GENERIC_FAILURE, response);
-    }
-    
-    @Test
-    public void forbiddenExecuteWriteReturnsGenericWriteFailure() {
-        Gson gson = new GsonBuilder()
-                            .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                            .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                            .create();
-
-        String strDesc = "ADD test SET 'property1' = ?s";
-        StatementDescriptor<TestObj> desc = new StatementDescriptor<>(category, strDesc);
-        PreparedStatement<TestObj> stmt = null;
-        
-        int fakePrepStmtId = 3;
-        WebPreparedStatementResponse fakeResponse = new WebPreparedStatementResponse();
-        fakeResponse.setNumFreeVariables(1);
-        SharedStateId id = new SharedStateId(fakePrepStmtId, UUID.randomUUID());
-        fakeResponse.setStatementId(id);
-        prepareServer(gson.toJson(fakeResponse));
-        try {
-            stmt = storage.prepareStatement(desc);
-        } catch (DescriptorParsingException e) {
-            // descriptor should parse fine and is trusted
-            fail(e.getMessage());
-        }
-        assertTrue(stmt instanceof WebPreparedStatement);
-        WebPreparedStatement<TestObj> webStmt = (WebPreparedStatement<TestObj>)stmt;
-        assertEquals(fakePrepStmtId, webStmt.getStatementId().getId());
-        PreparedParameters params = webStmt.getParams();
-        assertEquals(1, params.getParams().length);
-        assertNull(params.getParams()[0]);
-        
-        // now set a parameter
-        stmt.setString(0, "fluff");
-        assertEquals("fluff", params.getParams()[0].getValue());
-        assertEquals(String.class, params.getParams()[0].getType());
-        
-        prepareServer(HttpServletResponse.SC_FORBIDDEN);
-        try {
-            stmt.execute();
-            fail("Forbidden should have thrown an exception!");
-        } catch (StatementExecutionException e) {
-            Throwable t = e.getCause();
-            assertTrue(t instanceof StorageException);
-            t = t.getCause();
-            assertTrue("Wanted EntityConsumingIOException as root cause", t instanceof EntityConsumingIOException);
-        }
-    }
-
-    @Test (expected=NullPointerException.class)
-    public void testSaveFileThrowsExceptionOnNullListener() throws Exception {
-        String data = "Hello World";
-        ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
-
-        storage.saveFile("fluff", in, null);
-    }
-
-    @Test
-    public void testSaveFile() {
-        String data = "Hello World";
-        ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes());
-
-        SaveFileListener saveListener = mock(SaveFileListener.class);
-        prepareServer();
-        storage.saveFile("fluff", in, saveListener);
-
-        assertEquals("chunked", headers.get("Transfer-Encoding"));
-        String contentType = headers.get("Content-Type");
-        assertTrue(contentType.startsWith("multipart/form-data; boundary="));
-        String boundary = contentType.split("boundary=")[1];
-        String[] lines = requestBody.split("\n");
-        assertEquals("--" + boundary, lines[0].trim());
-        assertEquals("Content-Disposition: form-data; name=\"file\"; filename=\"fluff\"", lines[1].trim());
-        assertEquals("Content-Type: application/octet-stream", lines[2].trim());
-        assertEquals("Content-Transfer-Encoding: binary", lines[3].trim());
-        assertEquals("", lines[4].trim());
-        assertEquals("Hello World", lines[5].trim());
-        assertEquals("--" + boundary + "--", lines[6].trim());
-
-        verify(saveListener).notify(EventType.SAVE_COMPLETE, null);
-    }
-
-    @Test
-    public void testLoadFile() throws IOException {
-        prepareServer(HttpServletResponse.SC_NO_CONTENT);
-        InputStream in = storage.loadFile("no_file_here");
-        assertNull(in);
-
-        prepareServer("Hello World");
-        in = storage.loadFile("fluff");
-        assertEquals("file=fluff", requestBody.trim());
-        byte[] data = new byte[11];
-        int totalRead = 0;
-        while (totalRead < 11) {
-            int read = in.read(data, totalRead, 11 - totalRead);
-            if (read < 0) {
-                fail();
-            }
-            totalRead += read;
-        }
-        assertEquals("Hello World", new String(data));
-
-    }
-
-    @Test
-    public void testPurge() throws UnsupportedEncodingException, IOException {
-
-        prepareServer();
-        storage.purge("fluff");
-
-        assertEquals("POST", method);
-        assertTrue(requestURI.endsWith("/purge"));
-        StringReader reader = new StringReader(requestBody);
-        BufferedReader bufRead = new BufferedReader(reader);
-        String line = URLDecoder.decode(bufRead.readLine(), "UTF-8");
-        String[] parts = line.split("=");
-        assertEquals("agentId", parts[0]);
-        assertEquals("fluff", parts[1]);
-    }
-
-    @Test
-    public void testGenerateToken() throws UnsupportedEncodingException {
-
-        final String actionName = "some action";
-
-        prepareServer("flufftoken");
-        AuthToken authToken = storage.generateToken(actionName);
-
-        assertTrue(requestURI.endsWith("/generate-token"));
-        assertEquals("POST", method);
-
-        String[] requestParts = requestBody.split("=");
-        assertEquals("client-token", requestParts[0]);
-        String clientTokenParam = URLDecoder.decode(requestParts[1], "UTF-8");
-        byte[] clientToken = Base64.decodeBase64(clientTokenParam);
-        assertEquals(256, clientToken.length);
-
-        byte[] tokenBytes = authToken.getToken();
-        assertEquals("flufftoken", new String(tokenBytes));
-
-        assertTrue(Arrays.equals(clientToken, authToken.getClientToken()));
-
-        // Send another request and verify that we send a different client-token every time.
-        prepareServer("flufftoken");
-        storage.generateToken(actionName);
-
-        requestParts = requestBody.split("=");
-        assertEquals("client-token", requestParts[0]);
-        clientTokenParam = URLDecoder.decode(requestParts[1], "UTF-8");
-        byte[] clientToken2 = Base64.decodeBase64(clientTokenParam);
-        assertFalse(Arrays.equals(clientToken, clientToken2));
-
-    }
-
-    @Test
-    public void enablesTLSforHttps() {
-        SSLConfiguration sslConf = mock(SSLConfiguration.class);
-        String httpsUrl = "https://onlyHttpsPrefixUsed.example.com";
-        new WebStorage(httpsUrl,
-                new TrivialStorageCredentials(null, null), sslConf);
-        // should get called for HTTPS URLs
-        verify(sslConf).getKeystoreFile();
-        verify(sslConf).getKeyStorePassword();
-    }
-    
-    @Test
-    public void doesnotEnableTLSForHttp() {
-        SSLConfiguration sslConf = mock(SSLConfiguration.class);
-        String httpsUrl = "http://foo.example.com";
-        new WebStorage(httpsUrl,
-                new TrivialStorageCredentials(null, null), sslConf);
-        verifyNoMoreInteractions(sslConf);
-    }
-
-    @Test
-    public void testVerifyToken() throws UnsupportedEncodingException, NoSuchAlgorithmException {
-        byte[] token = "stuff".getBytes();
-        String clientToken = "fluff";
-        String someAction = "someAction";
-        byte[] tokenDigest = getShaBytes(clientToken, someAction);
-        
-        AuthToken authToken = new AuthToken(token, tokenDigest);
-
-        prepareServer();
-        boolean ok = storage.verifyToken(authToken, someAction);
-
-        assertTrue(ok);
-        assertTrue(requestURI.endsWith("/verify-token"));
-        assertEquals("POST", method);
-        String[] requestParts = requestBody.split("&");
-        assertEquals(3, requestParts.length);
-        String[] clientTokenParts = requestParts[0].split("=");
-        assertEquals(2, clientTokenParts.length);
-        assertEquals("client-token", clientTokenParts[0]);
-        String urlDecoded = URLDecoder.decode(clientTokenParts[1], "UTF-8");
-        assertTrue(Arrays.equals(tokenDigest, Base64.decodeBase64(urlDecoded)));
-        String[] authTokenParts = requestParts[1].split("=");
-        assertEquals(2, authTokenParts.length);
-        assertEquals("token", authTokenParts[0]);
-        String[] actionParts = requestParts[2].split("=");
-        assertEquals(2, actionParts.length);
-        assertEquals("action-name", actionParts[0]);
-        urlDecoded = URLDecoder.decode(authTokenParts[1], "UTF-8");
-        String base64decoded = new String(Base64.decodeBase64(urlDecoded));
-        assertEquals("stuff", base64decoded);
-
-        // Try another one in which verification fails.
-        prepareServer(HttpServletResponse.SC_UNAUTHORIZED);
-        ok = storage.verifyToken(authToken, someAction);
-        assertFalse(ok);
-        
-    }
-
-    private byte[] getShaBytes(String clientToken, String someAction)
-            throws NoSuchAlgorithmException, UnsupportedEncodingException {
-        MessageDigest digest = MessageDigest.getInstance("SHA-256");
-        digest.update(clientToken.getBytes());
-        digest.update(someAction.getBytes("UTF-8"));
-        byte[] tokenDigest = digest.digest();
-        return tokenDigest;
-    }
-    
-    @Test
-    public void verifyConnectFiresEventOnConnectionFailure() throws Exception {
-        HttpClient client = mock(HttpClient.class);
-        // Execution of ping() will fail
-        Mockito.doThrow(RuntimeException.class).when(client).execute(any(HttpUriRequest.class), any(HttpContext.class));
-        storage = new WebStorage("http://localhost:" + port + "/", new TrivialStorageCredentials(null, null),
-                client);
-        
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-        storage.getConnection().connect();
-        // wait for connection to fail
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        assertFalse(listener.connectEvent);
-        assertTrue(listener.failedToConnectEvent);
-    }
-    
-    @Test
-    public void verifyConnectFiresEventOnSuccessfulConnect() {
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-        storage.getConnection().connect();
-        // wait for connection to happen
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        assertTrue(listener.connectEvent);
-        assertFalse(listener.failedToConnectEvent);
-    }
-    
-    @Test
-    public void verifyDisconnectFiresDisconnectEvent() {
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-        storage.getConnection().disconnect();
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        assertFalse(listener.connectEvent);
-        assertFalse(listener.failedToConnectEvent);
-        assertTrue(listener.disconnectEvent);
-    }
-    
-    @Test
-    public void verifyDoWriteExecuteMorethanOne() {
-        try {
-            storage.doWriteExecute(null, 2);
-            fail("Expected excecution exception since invoked count > 1");
-        } catch (StatementExecutionException e) {
-            Throwable cause = e.getCause();
-            // pass
-            assertEquals("Failed to recover from out-of-sync state with server", cause.getMessage());
-        }
-    }
-    
-    @Test
-    public void verifyDoExecuteQueryMorethanOne() {
-        try {
-            storage.doExecuteQuery(null, null, 2);
-            fail("Expected descriptor parsing exception since invoked count > 1");
-        } catch (StatementExecutionException e) {
-            Throwable cause = e.getCause();
-            // pass
-            assertEquals("Failed to recover from out-of-sync state with server", cause.getMessage());
-        }
-    }
-    
-    @Test
-    public void verifySendPreparedStatementRequestMoreThanOne() {
-        try {
-            storage.sendPrepareStmtRequest(null, 2);
-            fail("Expected descriptor parsing exception since invoked count > 1");
-        } catch (DescriptorParsingException e) {
-            // pass
-            assertEquals("Failed to recover from out-of-sync state with server", e.getMessage());
-        }
-    }
-    
-    /**
-     * Test the base case in {@link WebStorage#handlePreparedStmtStateOutOfSync(WebPreparedStatement)}.
-     * with null transition cache and non-null statement cache. This simulates the
-     * case where state got out of sync and handlePreparedStmtStateOutOfSync() is
-     * called the first time after that out-of-sync-event happened. In that case
-     * it is expected for prepareStatement() and sendCategoryReRegistrationRequest()
-     * to be called.
-     * 
-     * @throws DescriptorParsingException 
-     * 
-     */
-    @Test
-    public void testHandleStatementStateOutOfSyncBaseCase() throws DescriptorParsingException {
-        WebPreparedStatementHolder mockHolder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = new SharedStateId(300, UUID.randomUUID());
-        when(mockHolder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<Pojo> foo = mock(Category.class);
-        StatementDescriptor<Pojo> desc = new StatementDescriptor<>(foo, "testing");
-        WebPreparedStatementCache stmtCache = mock(WebPreparedStatementCache.class);
-        // this is called twice. Once for creating the snapshot and another time
-        // for getting the descriptor.
-        when(stmtCache.get(id)).thenReturn(desc).thenReturn(desc);
-        final boolean[] sendCategoryReRegistrationRequest = new boolean[1];
-        final boolean[] prepareStatement = new boolean[1];
-        final WebPreparedStatement<?> newStmt = mock(WebPreparedStatement.class);
-        WebStorage webStorage = new WebStorage(stmtCache, null) {
-            
-            @Override
-            protected synchronized <T extends Pojo> void sendCategoryReRegistrationRequest(Category<T> category) {
-                sendCategoryReRegistrationRequest[0] = true;
-            }
-            
-            @SuppressWarnings("unchecked")
-            @Override
-            public <T extends Pojo> PreparedStatement<T> prepareStatement(StatementDescriptor<T> desc)
-                    throws DescriptorParsingException {
-                prepareStatement[0] = true;
-                return (PreparedStatement<T>)newStmt;
-            }
-        };
-        @SuppressWarnings("unchecked")
-        WebPreparedStatement<Pojo> mockStmt = mock(WebPreparedStatement.class);
-        PreparedParameters mockParams = new PreparedParameters(3);
-        when(mockStmt.getParams()).thenReturn(mockParams);
-        when(mockStmt.getStatementId()).thenReturn(id);
-        
-        WebPreparedStatementCache stmtCacheSnapshot = mock(WebPreparedStatementCache.class);
-        when(stmtCache.createSnapshot()).thenReturn(stmtCacheSnapshot);
-        webStorage.handlePreparedStmtStateOutOfSync(mockStmt);
-        verify(stmtCache).createSnapshot();
-        verify(stmtCache).get(id);
-        verify(stmtCache).remove(id);
-        assertTrue("expected sendCategoryReRegistrationRequest() to be called", sendCategoryReRegistrationRequest[0]);
-        assertTrue("expected prepareStatement() to be called", prepareStatement[0]);
-        verify(newStmt).setParams(mockParams);
-        verifyNoMoreInteractions(stmtCache);
-    }
-    
-    /**
-     * Test the transition case in {@link WebStorage#handlePreparedStmtStateOutOfSync(WebPreparedStatement)}.
-     * with non-null transition cache and non-null statement cache.
-     * 
-     * This simulates the case where state got out of sync and handlePreparedStmtStateOutOfSync() is
-     * called <strong>not</strong> the first time after an out-of-sync-event happened. I.e.
-     * the base-case path has been entered first when a similar statement tried
-     * to execute, in turn, getting the statement id removed from the main
-     * statement cache.
-     * 
-     * In that case it is expected for the transition cache to become active
-     * allowing the statement to execute successfully. 
-     * 
-     * @throws DescriptorParsingException 
-     * 
-     */
-    @Test
-    public void testHandleStatementStateOutOfSyncTransitionCase() throws DescriptorParsingException {
-        WebPreparedStatementHolder mockHolder = mock(WebPreparedStatementHolder.class);
-        SharedStateId id = new SharedStateId(300, UUID.randomUUID());
-        when(mockHolder.getStatementId()).thenReturn(id);
-        @SuppressWarnings("unchecked")
-        Category<Pojo> foo = mock(Category.class);
-        StatementDescriptor<Pojo> desc = new StatementDescriptor<>(foo, "testing");
-        WebPreparedStatementCache stmtCache = mock(WebPreparedStatementCache.class);
-        // no setup for the id in stmtCache, however the transitionCache,
-        // a snapshot cache - created when the first call to handlePreparedStatementStateOutOfSync()
-        // came in - still "knows" about this record.
-        ExpirableWebPreparedStatementCache transitionCache = mock(ExpirableWebPreparedStatementCache.class);
-        when(transitionCache.isExpired()).thenReturn(false);
-        when(transitionCache.get(id)).thenReturn(desc);
-        when(transitionCache.get(desc)).thenReturn(mockHolder);
-        SharedStateId updatedId = new SharedStateId(301, UUID.randomUUID());
-        WebPreparedStatementHolder newHolder = mock(WebPreparedStatementHolder.class);
-        when(mockHolder.getStatementId()).thenReturn(id);
-        // called twice. once for equality check. once for getting the id and
-        // using it to update the prepared statement id.
-        when(newHolder.getStatementId()).thenReturn(updatedId).thenReturn(updatedId);
-        when(stmtCache.get(desc)).thenReturn(newHolder);
-        WebStorage webStorage = new WebStorage(stmtCache, transitionCache);
-        @SuppressWarnings("unchecked")
-        WebPreparedStatement<Pojo> mockStmt = mock(WebPreparedStatement.class);
-        when(mockStmt.getStatementId()).thenReturn(id);
-        WebPreparedStatement<Pojo> result = webStorage.handlePreparedStmtStateOutOfSync(mockStmt);
-        verify(mockStmt).setStatementId(updatedId);
-        assertSame(mockStmt, result);
-        verify(stmtCache).get(id);
-        verify(stmtCache).get(desc);
-        verify(transitionCache).isExpired();
-        verify(transitionCache).get(id);
-        verify(transitionCache).get(desc);
-        verifyNoMoreInteractions(stmtCache);
-        verifyNoMoreInteractions(transitionCache);
-    }
-
-    @Test
-    public void testConnectedUsernameIsSet() {
-        String expected = "username";
-
-        storage = new WebStorage("http://localhost:" + port + "/",
-                new TrivialStorageCredentials(expected, new char[]{ 'p' }), mock(SSLConfiguration.class));
-
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-
-        Connection c = storage.getConnection();
-        c.connect();
-
-        // wait for connection to happen
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        assertTrue(listener.connectEvent);
-        assertFalse(listener.failedToConnectEvent);
-
-        assertEquals(expected, c.getUsername());
-    }
-
-    @Test
-    public void testFailedConnectUsernameIsUnset() throws IOException {
-        String expected = Connection.UNSET_USERNAME;
-
-        HttpClient client = mock(HttpClient.class);
-        Mockito.doThrow(RuntimeException.class).when(client).execute(any(HttpUriRequest.class), any(HttpContext.class));
-
-        storage = new WebStorage("http://localhost:" + port + "/",
-                new TrivialStorageCredentials("username", new char[]{ 'p' }), client);
-
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-
-        Connection c = storage.getConnection();
-        c.connect();
-
-        // wait for connection to happen
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-        assertTrue(listener.failedToConnectEvent);
-        assertFalse(listener.connectEvent);
-
-        assertEquals(expected, c.getUsername());
-    }
-
-    @Test
-    public void testDisconnectedUsernameIsUnset() {
-        String expected = Connection.UNSET_USERNAME;
-
-        storage = new WebStorage("http://localhost:" + port + "/",
-                new TrivialStorageCredentials("username", new char[]{ 'p' }), mock(SSLConfiguration.class));
-
-        CountDownLatch latch = new CountDownLatch(1);
-        MyListener listener = new MyListener(latch);
-        storage.getConnection().addListener(listener);
-
-        Connection c = storage.getConnection();
-        c.disconnect();
-
-        // wait for connections to finish
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-
-        assertFalse(listener.connectEvent);
-        assertFalse(listener.failedToConnectEvent);
-        assertTrue(listener.disconnectEvent);
-
-        assertEquals(expected, c.getUsername());
-    }
-    
-    static class MyListener implements ConnectionListener {
-
-        private CountDownLatch latch;
-        boolean failedToConnectEvent = false;
-        boolean connectEvent = false;
-        boolean disconnectEvent = false;
-        
-        MyListener(CountDownLatch latch) {
-            this.latch = latch;
-        }
-        
-        @Override
-        public void changed(ConnectionStatus newStatus) {
-            if (newStatus == ConnectionStatus.CONNECTED) {
-                connectEvent = true;
-                latch.countDown();
-            }
-            if (newStatus == ConnectionStatus.FAILED_TO_CONNECT) {
-                failedToConnectEvent = true;
-                latch.countDown();
-            }
-            if (newStatus == ConnectionStatus.DISCONNECTED) {
-                disconnectEvent = true;
-                latch.countDown();
-            }
-        }
-    }
-
-    private class TrivialStorageCredentials implements StorageCredentials {
-        private String user;
-        private char[] pw;
-        private TrivialStorageCredentials(String user, char[] password) {
-            this.user = user;
-            this.pw = password;
-        }
-        @Override
-        public String getUsername() {
-            return user;
-        }
-        @Override
-        public char[] getPassword() {
-            return pw;
-        }
-    }
-    
-    private static class PrepareStatementWebStorage extends WebStorage {
-
-        private int counter;
-        
-        public PrepareStatementWebStorage(String url, StorageCredentials creds,
-                SSLConfiguration sslConf) throws StorageException {
-            super(url, creds, sslConf);
-        }
-        
-        @Override
-        <T extends Pojo> WebPreparedStatementHolder sendPrepareStmtRequest(StatementDescriptor<T> desc, int invokationCounter)
-                throws DescriptorParsingException {
-            int numParams = counter++;
-            int stmtId = counter++;
-            SharedStateId id = new SharedStateId(stmtId, UUID.randomUUID());
-            return new WebPreparedStatementHolder(TestObj.class, numParams, id); 
-        }
-    }
-    
-    private static class TestAggregate implements AggregateResult {
-        // nothing
-    }
-}
-
--- a/web/common/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<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>1.99.12-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>thermostat-web-common</artifactId>
-  <packaging>bundle</packaging>
-
-  <name>Thermostat Web Common</name>
-
-  <dependencies>
-  
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common-test</artifactId>
-      <version>${project.version}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.google.code.gson</groupId>
-      <artifactId>gson</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-beanutils</groupId>
-      <artifactId>commons-beanutils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-common-core</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-storage-core</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.common</Bundle-SymbolicName>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Export-Package>
-              com.redhat.thermostat.web.common,
-              com.redhat.thermostat.web.common.typeadapters,
-            </Export-Package>
-            <!-- Do not autogenerate uses clauses in Manifests -->
-            <_nouses>true</_nouses>
-          </instructions>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <configuration>
-          <excludedGroups>${surefire-perftests-exclusion}</excludedGroups>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-</project>
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/PreparedStatementResponseCode.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * 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.web.common;
-
-import com.redhat.thermostat.storage.core.PreparedStatement;
-
-/**
- * Common response codes for prepared statement responses.
- *
- */
-public interface PreparedStatementResponseCode {
-
-    /**
-     * Response code for successful prepared queries.
-     */
-    public static final int QUERY_SUCCESS = 0;
-    
-    /**
-     * Generic error code for failed queries. Usually
-     * returned if get-more failed for an unknown reason.
-     */
-    public static final int QUERY_FAILURE = -100;
-    
-    
-    /**
-     * Failure code for expired cursors. Usually returned if
-     * get-more requests failed because the underlying cursor
-     * was null.
-     */
-    public static final int GET_MORE_NULL_CURSOR = -151;
-    
-    /**
-     * Response code if patching of a {@link PreparedStatement} failed during
-     * statement execution.
-     * <p>
-     * For example a patching failure could happen if there was a type mismatch
-     * between the descriptor and the parameter provided. Providing not all
-     * parameters and attempting execution of a {@link PreparedStatement} would
-     * be another example.
-     */
-    public static final int ILLEGAL_PATCH = -1;
-    
-    /**
-     * Failure code for mismatching server tokens. This is usually happening if
-     * client and server get out of sync due to re-deployment or the like.
-     * Client should recover from this automatically by clearing the client
-     * cache and preparing statements again.
-     */
-    public static final int PREP_STMT_BAD_STOKEN = -2;
-    
-    /**
-     * Failure to execute a prepared write statement for some unknown reason.
-     */
-    public static final int WRITE_GENERIC_FAILURE = -200;
-    
-}
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/SharedStateId.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * 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.web.common;
-
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * Simple data structure which uniquely identifies shared state between
- * client (WebStorage) and server (WebStorageEndPoint).
- *
- */
-public class SharedStateId {
-
-    // The id of the statement
-    private final int id;
-    // A unique token only used once per webapp deployment.
-    private final UUID serverToken;
-    
-    public SharedStateId(int id, UUID serverToken) {
-        this.id = id;
-        this.serverToken = serverToken;
-    }
-    
-    public int getId() {
-        return id;
-    }
-
-    public UUID getServerToken() {
-        return serverToken;
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (other == null || other.getClass() != SharedStateId.class) {
-            return false;
-        }
-        SharedStateId o = (SharedStateId)other;
-        return id == o.id && serverToken.equals(o.serverToken);
-    }
-    
-    @Override
-    public int hashCode() {
-        return Objects.hash(id, serverToken);
-    }
-    
-    @Override
-    public String toString() {
-        return serverToken + ":" + id;
-    }
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/WebPreparedStatement.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-/*
- * 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.web.common;
-
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.ParsedStatement;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.storage.core.PreparedStatement;
-import com.redhat.thermostat.storage.core.StatementExecutionException;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class WebPreparedStatement<T extends Pojo> implements
-        PreparedStatement<T> {
-    
-    private PreparedParameters params;
-    private SharedStateId statementId;
-    
-    public WebPreparedStatement(int numParams, SharedStateId statementId) {
-        this.params = new PreparedParameters(numParams);
-        this.statementId = statementId;
-    }
-    
-    public WebPreparedStatement() {
-        // nothing. used for serialization
-    }
-
-    public SharedStateId getStatementId() {
-        return statementId;
-    }
-
-    public void setStatementId(SharedStateId statementId) {
-        this.statementId = statementId;
-    }
-
-    public PreparedParameters getParams() {
-        return params;
-    }
-
-    public void setParams(PreparedParameters params) {
-        this.params = params;
-    }
-
-    @Override
-    public void setBoolean(int paramIndex, boolean paramValue) {
-        params.setBoolean(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setBooleanList(int paramIndex, boolean[] paramValue) {
-        params.setBooleanList(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setLong(int paramIndex, long paramValue) {
-        params.setLong(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setLongList(int paramIndex, long[] paramValue) {
-        params.setLongList(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setInt(int paramIndex, int paramValue) {
-        params.setInt(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setIntList(int paramIndex, int[] paramValue) {
-        params.setIntList(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setString(int paramIndex, String paramValue) {
-        params.setString(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setStringList(int paramIndex, String[] paramValue) {
-        params.setStringList(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setDouble(int paramIndex, double paramValue) {
-        params.setDouble(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setDoubleList(int paramIndex, double[] paramValue) {
-        params.setDoubleList(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setPojo(int paramIndex, Pojo paramValue) {
-        params.setPojo(paramIndex, paramValue);
-    }
-
-    @Override
-    public void setPojoList(int paramIndex, Pojo[] paramValue) {
-        params.setPojoList(paramIndex, paramValue);
-    }
-
-    @Override
-    public int execute() throws StatementExecutionException {
-        // actual implementation should override this
-        throw new IllegalStateException();
-    }
-
-    @Override
-    public Cursor<T> executeQuery()
-            throws StatementExecutionException {
-        // actual implementation should override this
-        throw new IllegalStateException();
-    }
-
-    @Override
-    public ParsedStatement<T> getParsedStatement() {
-        // Should never be called on WebPreparedStatement
-        // It should use the implementation of the backing
-        // storage implementation instead.
-        throw new IllegalStateException();
-    }
-
-}
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/WebPreparedStatementResponse.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * 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.web.common;
-
-/**
- * Model class as returned upon preparing statements.
- */
-public class WebPreparedStatementResponse {
-    
-    /**
-     * Response code for untrusted/unknown descriptors.
-     */
-    public static final int ILLEGAL_STATEMENT = -1;
-    
-    /**
-     * Response code for descriptor parsing exceptions.
-     */
-    public static final int DESCRIPTOR_PARSE_FAILED = -2;
-    
-    /**
-     * Response code indicating that the server token
-     * of the client and the token the server is using
-     * did not match.
-     */
-    public static final int CATEGORY_OUT_OF_SYNC = -3;
-    
-    public WebPreparedStatementResponse() {
-        // Should always be set using the setter before it
-        // is retrieved. Since 0 is a bad default for this,
-        // we set it to -1 in order to make this an invalid
-        // value right away.
-        this.numFreeVariables = -1;
-    }
-    
-    private int numFreeVariables;
-    private SharedStateId statementId;
-    
-    public SharedStateId getStatementId() {
-        return statementId;
-    }
-
-    public void setStatementId(SharedStateId statementId) {
-        this.statementId = statementId;
-    }
-
-    public int getNumFreeVariables() {
-        return numFreeVariables;
-    }
-
-    public void setNumFreeVariables(int freeVars) {
-        this.numFreeVariables = freeVars;
-    }
-}
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/WebQueryResponse.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * 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.web.common;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import com.redhat.thermostat.storage.model.Pojo;
-
-/**
- * Model object for prepared query execution responses.
- *
- */
-public class WebQueryResponse<T extends Pojo> {
-    
-    private int cursorId;
-    private boolean hasMoreBatches;
-    private int responseCode;
-    private T[] resultList;
-    
-    public int getResponseCode() {
-        return responseCode;
-    }
-
-    public void setResponseCode(int responseCode) {
-        this.responseCode = responseCode;
-    }
-
-    public T[] getResultList() {
-        return resultList;
-    }
-
-    public void setResultList(T[] resultList) {
-        this.resultList = resultList;
-    }
-    
-    public void setHasMoreBatches(boolean hasMoreBatches) {
-        this.hasMoreBatches = hasMoreBatches;
-    }
-    
-    public boolean hasMoreBatches() {
-        return hasMoreBatches;
-    }
-    
-    public int getCursorId() {
-        return cursorId;
-    }
-
-    public void setCursorId(int cursorId) {
-        this.cursorId = cursorId;
-    }
-
-    public ParameterizedType getRuntimeParametrizedType(final Class<T> dataClass) {
-        ParameterizedType webQueryResponseType = new ParameterizedType() {
-            
-            @Override
-            public Type getRawType() {
-                return WebQueryResponse.class;
-            }
-            
-            @Override
-            public Type getOwnerType() {
-                // top-level type, must return null
-                return null;
-            }
-            
-            @Override
-            public Type[] getActualTypeArguments() {
-                // WebQueryResponse has only one type parameter, which
-                // is the actual data class
-                return new Type[] {
-                        dataClass
-                };
-            }
-        };
-        return webQueryResponseType;
-    }
-}
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,230 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.beans.PropertyDescriptor;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Objects;
-
-import org.apache.commons.beanutils.PropertyUtils;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.model.Pojo;
-
-/**
- * A generic type adapter for types implementing {@link Pojo}. It uses
- * no special knowledge of the actual implementation types.
- *
- */
-class PojoTypeAdapter<T extends Pojo> extends TypeAdapter<Pojo> {
-    
-    private final Class<T> runtimeType;
-    private final Gson gson;
-    private final TypeAdapterFactory pojoFactory;
-    private SoftReference<HashMap<String, PropertyDescriptor>> propsCache;
-    
-    PojoTypeAdapter(TypeAdapterFactory factory, Gson gson, Class<T> runtimeType) {
-        assert(Pojo.class.isAssignableFrom(runtimeType));
-        this.runtimeType = Objects.requireNonNull(runtimeType);
-        this.gson = gson;
-        this.pojoFactory = factory;
-        // cache will be filled once first used.
-        this.propsCache = new SoftReference<>(null);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void write(JsonWriter out, Pojo value) throws IOException {
-        // handle null
-        if (value == null) {
-            out.nullValue();
-            return;
-        }
-        
-        Class<?> cls = value.getClass();
-        if (! cls.isAnnotationPresent(Entity.class)) {
-            System.err.println("attempt to serialize non-Entity class: " + cls.getName());
-            throw new IllegalArgumentException("attempt to serialize non-Entity class: " + cls.getName());
-        }
-        
-        out.beginObject();
-        
-        PropertyDescriptor[] descs = PropertyUtils.getPropertyDescriptors(value);
-        for (PropertyDescriptor desc : descs) {
-            Method readMethod = desc.getReadMethod();
-            if (readMethod != null && readMethod.isAnnotationPresent(Persist.class)) {
-                String name = desc.getName();
-                out.name(name);
-                try {
-                    Object val = PropertyUtils.getProperty(value, name);
-                    if (val == null) {
-                        out.nullValue();
-                    } else {
-                        // non-null member case
-                        if (Pojo.class.isAssignableFrom(val.getClass())) {
-                            // recursive case
-                            PojoTypeAdapter<T> pojoMemAdapter= new PojoTypeAdapter<>(pojoFactory, gson, (Class<T>)val.getClass());
-                            pojoMemAdapter.write(out, (T)val);
-                        } else {
-                            // base case: non-pojo type
-                            Class<?> valClass = val.getClass();
-                            @SuppressWarnings("rawtypes")
-                            TypeToken memberTypeToken = TypeToken.get(valClass);
-                            @SuppressWarnings({"rawtypes"})
-                            TypeAdapter memberTypeAdapter = getNonPojoTypeAdapter(memberTypeToken);
-                            memberTypeAdapter.write(out, val);
-                        }
-                    }
-                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
-                    throw new RuntimeException(e);
-                }
-            } else if (readMethod == null) {
-                System.err.println("WARNING: property without read method: " + value.getClass().getName() + "." + desc.getName());
-            }
-        }
-        
-        out.endObject();
-    }
-
-    @Override
-    public Pojo read(JsonReader in) throws IOException {
-        // handle null
-        JsonToken token = in.peek();
-        if (token == JsonToken.NULL) {
-            return null;
-        }
-        
-        
-        try {
-            in.beginObject();
-            
-            Pojo pojo = runtimeType.newInstance();
-            // loop over names in JSON
-            processNamesValues(pojo, in);
-            
-            in.endObject();
-
-            return pojo;
-        } catch (InstantiationException | IllegalAccessException e) {
-            throw new RuntimeException(e);
-        }
-    }
-    
-    private void processNamesValues(Pojo pojo, JsonReader in) throws IOException {
-        JsonToken token = in.peek();
-        switch(token) {
-        case NAME:
-            String name = in.nextName();
-            processValue(pojo, in, name);
-            // recursive case
-            processNamesValues(pojo, in);
-            break;
-        case END_OBJECT:
-            // Base case
-            return;
-        default:
-            throw new IllegalStateException("Expected NAME or END_OBJECT. Was: " + token);
-        }
-    }
-
-    private void processValue(Pojo pojo, JsonReader in, String name) throws IOException {
-        try {
-            PropertyDescriptor desc = getPropDescriptor(pojo, name);
-            if (desc == null) {
-                throw new IllegalStateException("Property descriptor null for: " + name);
-            }
-            Method writeMethod = desc.getWriteMethod();
-            Object value = null;
-            if (writeMethod != null && writeMethod.isAnnotationPresent(Persist.class)) {
-                Class<?> memberType = desc.getPropertyType();
-                if (Pojo.class.isAssignableFrom(memberType)) {
-                    // recursive case
-                    @SuppressWarnings("unchecked") // We've just checked the cast to Class<T> works
-                    PojoTypeAdapter<T> memberAdapter = new PojoTypeAdapter<>(pojoFactory, gson, (Class<T>)memberType);
-                    value = (Pojo)memberAdapter.read(in);
-                } else {
-                    // base case: non-pojo type
-                    TypeToken<?> memberTypeToken = TypeToken.get(memberType);
-                    TypeAdapter<?> memberTypeAdapter = getNonPojoTypeAdapter(memberTypeToken);
-                    value = memberTypeAdapter.read(in);
-                }
-                PropertyUtils.setProperty(pojo, name, value);
-            }
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            throw new RuntimeException(e);
-        } catch (NoSuchMethodException e) {
-            System.err.println("Setter for '" + name + "' not found. The value will be ignored.");
-        }
-    }
-    
-    private PropertyDescriptor getPropDescriptor(Pojo pojo, String name) {
-        if (propsCache.get() == null) {
-            // build cache
-            HashMap<String, PropertyDescriptor> propDescCache = new HashMap<>();
-            PropertyDescriptor[] descs = PropertyUtils.getPropertyDescriptors(pojo);
-            PropertyDescriptor wanted = null;
-            for (PropertyDescriptor desc: descs) {
-                propDescCache.put(desc.getName(), desc);
-                if (desc.getName().equals(name)) {
-                    wanted = desc;
-                }
-            }
-            propsCache = new SoftReference<>(propDescCache);
-            return wanted;
-        } else {
-            HashMap<String, PropertyDescriptor> cacheMap = propsCache.get();
-            return cacheMap.get(name);
-        }
-    }
-
-    private <S> TypeAdapter<S> getNonPojoTypeAdapter(TypeToken<S> nonPojoType) {
-        return gson.getDelegateAdapter(pojoFactory, nonPojoType);
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class PojoTypeAdapterFactory implements TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (Pojo.class.isAssignableFrom(rawType)) {
-            // We've just verified that we have a Pojo type. The unchecked
-            // cast is safe.
-            @SuppressWarnings("unchecked")
-            Class<T> castedType = (Class<T>)rawType;
-            @SuppressWarnings({ "unchecked", "rawtypes" })
-            TypeAdapter<T> ta = (TypeAdapter<T>)new PojoTypeAdapter(this, gson, castedType);
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-import java.lang.reflect.Array;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.model.Pojo;
-
-/**
- * GSON type adapter for {@link PreparedParameter}.
- *
- */
-class PreparedParameterTypeAdapter extends TypeAdapter<PreparedParameter> {
-
-    private static final String PROP_TYPE = "type";
-    private static final String PROP_VALUE = "value";
-    private static final Set<Class<?>> VALID_CLASSES;
-    private static final Set<Class<?>> PRIMITIVES_NOT_ALLOWING_NULL_VAL;
-    private static final Set<Class<?>> BASIC_TYPES;
-    // maps type names to classes:
-    //    "int" => int.class , "double" => double.class, "[I" => int[].class
-    //    and so on.
-    private static final Map<String, Class<?>> CLASSES_LOOKUP_TABLE;
-    
-    private final Gson gson;
-    
-    static {
-        VALID_CLASSES = new HashSet<>();
-        BASIC_TYPES = new HashSet<>();
-        BASIC_TYPES.add(int.class);
-        BASIC_TYPES.add(long.class);
-        BASIC_TYPES.add(boolean.class);
-        BASIC_TYPES.add(double.class);
-        BASIC_TYPES.add(String.class);
-        CLASSES_LOOKUP_TABLE = new HashMap<>();
-        CLASSES_LOOKUP_TABLE.put(int.class.getName(), int.class);
-        CLASSES_LOOKUP_TABLE.put(long.class.getName(), long.class);
-        CLASSES_LOOKUP_TABLE.put(boolean.class.getName(), boolean.class);
-        CLASSES_LOOKUP_TABLE.put(double.class.getName(), double.class);
-        CLASSES_LOOKUP_TABLE.put(String.class.getName(), String.class);
-        CLASSES_LOOKUP_TABLE.put(int[].class.getName(), int[].class);
-        CLASSES_LOOKUP_TABLE.put(long[].class.getName(), long[].class);
-        CLASSES_LOOKUP_TABLE.put(boolean[].class.getName(), boolean[].class);
-        CLASSES_LOOKUP_TABLE.put(double[].class.getName(), double[].class);
-        CLASSES_LOOKUP_TABLE.put(String[].class.getName(), String[].class);
-        VALID_CLASSES.addAll(CLASSES_LOOKUP_TABLE.values());
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL = new HashSet<>();
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(int.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(long.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(boolean.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(double.class);
-    }
-    
-    
-    PreparedParameterTypeAdapter(Gson gson) {
-        this.gson = gson;
-    }
-    
-    
-    private Class<?> deserializeTypeVal(String className) {
-        Class<?> typeVal = null;
-        if (CLASSES_LOOKUP_TABLE.containsKey(className)) {
-            typeVal = CLASSES_LOOKUP_TABLE.get(className);
-        } else {
-            try {
-                // We need this for Pojo + Pojo list type params. For pojo
-                // lists the name we get passed is the component type of the
-                // array.
-                typeVal = Class.forName(className);
-            } catch (ClassNotFoundException e) {
-                throw new IllegalStateException("Failed to resolve class type for '"
-                        + className + "'.");
-            }
-        }
-        validateSaneClassName(typeVal);
-        return typeVal;
-    }
-
-    private void validatePrimitivesForNull(Object value, Class<?> valType) {
-        if (PRIMITIVES_NOT_ALLOWING_NULL_VAL.contains(valType) && value == null) {
-            // illegal value for primitive type. according to JLS spec they all
-            // have default values and are never null.
-            throw new IllegalStateException( valType + " primitive" +
-                                            " does not accept a null value!");
-        }
-    }
-
-    // Allow valid classes + Pojo types, refuse everything else
-    private void validateSaneClassName(Class<?> clazz) {
-        // isAssignableFrom throws NPE if clazz is null.
-        if (VALID_CLASSES.contains(clazz) ||
-                Pojo.class.isAssignableFrom(clazz)) {
-            return;
-        }
-        throw new IllegalStateException("Illegal type of parameter " + clazz.getCanonicalName());
-    }
-
-    @Override
-    public PreparedParameter read(JsonReader reader) throws IOException {
-        if (reader.peek() == JsonToken.NULL) {
-            reader.nextNull();
-            return null;
-        }
-        reader.beginObject();
-        
-        Class<?> type = readType(reader);
-        
-        assert(type != null);
-        assert(Pojo.class.isAssignableFrom(type) || VALID_CLASSES.contains(type));
-        
-        Object val = readValue(reader, type);
-        reader.endObject();
-        
-        PreparedParameter param = new PreparedParameter();
-        param.setValue(val);
-        param.setType(type);
-        return param;
-    }
-    
-    private Class<?> readType(JsonReader reader) throws IOException {
-        String name = reader.nextName();
-        if (!name.equals(PROP_TYPE)) {
-            throw new IllegalStateException("Expected " + PROP_VALUE + " but was " + name);
-        }
-        String className = reader.nextString();
-        return deserializeTypeVal(className);
-    }
-
-    private Object readValue(JsonReader reader, Class<?> valType) throws IOException {
-        // values may be null. In that case they are missing from the JSON
-        // string. Be sure to handle that case early.
-        if (reader.peek() == JsonToken.END_OBJECT) {
-            return null; // null parameter value
-        }
-        String name = reader.nextName();
-        if (!name.equals(PROP_VALUE)) {
-            throw new IllegalStateException("Expected " + PROP_VALUE + " but was " + name);
-        }
-        
-        JsonToken token = reader.peek();
-        if (token == JsonToken.NULL) {
-            reader.nextNull();
-            // Be sure to not allow null values for primitives. Note:
-            // valType may be an array type for which null is fine.
-            validatePrimitivesForNull(null, valType);
-            return null; // null value
-        }
-        
-        // special case for Pojo/Pojo list types. In that case, the valType
-        // is the component type for arrays. In order to distinguish pojo
-        // lists from pojos, we use JSON's array info about the value element.
-        if (token == JsonToken.BEGIN_ARRAY && !valType.isArray()) {
-            assert(Pojo.class.isAssignableFrom(valType));
-            Class<?> arrayType = Array.newInstance(valType, 0).getClass();
-            TypeAdapter<?> pojoArrayTa = gson.getAdapter(arrayType);
-            Object val = pojoArrayTa.read(reader);
-            return val;
-        } else {
-            TypeAdapter<?> nonPojoTypeAdapter = gson.getAdapter(valType);
-            Object val = nonPojoTypeAdapter.read(reader);
-            validatePrimitivesForNull(val, valType);
-            return val;
-        }
-    }
-
-
-    @Override
-    public void write(JsonWriter writer, PreparedParameter param)
-            throws IOException {
-        if (param == null) {
-            writer.nullValue();
-            return;
-        }
-        writer.beginObject();
-        
-        // serialize type which must not be null
-        writer.name(PROP_TYPE);
-        if (param.getType() == null) {
-            throw new IllegalStateException("Type of prepared parameter must not be null");
-        }
-        String typeStr = param.getType().getName();
-        writer.value(typeStr);
-        
-        // serialize value
-        writer.name(PROP_VALUE);
-        serializeValue(writer, param);
-        
-        writer.endObject();
-    }
-    
-    private void serializeValue(JsonWriter writer, PreparedParameter param) throws IOException {
-        if (param.getValue() == null) {
-            writer.nullValue();
-            return;
-        }
-        
-        Object val = param.getValue();
-        if (val.getClass().isArray()) {
-            serializeArrayValue(writer, param);
-        } else {
-            serializeBasicValue(writer, param);
-        }
-    }
-
-    /*
-     * Serialize single basic type or Pojo.
-     */
-    private void serializeBasicValue(JsonWriter writer, PreparedParameter param) throws IOException {
-        assert(param.getValue() != null);
-        
-        Class<?> type = param.getType();
-        if (BASIC_TYPES.contains(type)) {
-            serializeSingleBasicValue(writer, param.getValue(), param.getType());
-        } else {
-            assert(Pojo.class.isAssignableFrom(param.getType()));
-            serializeSinglePojo(writer, param);
-        }
-    }
-
-    private void serializeSinglePojo(JsonWriter writer, PreparedParameter param) throws IOException {
-        assert(param.getValue() != null);
-        
-        serializeSinglePojoImpl(writer, param.getValue(), param.getType());
-    }
-    
-    private void serializeSinglePojoImpl(JsonWriter writer, Object value, Class<?> type) throws IOException {
-        // precondition(s)
-        assert(Pojo.class.isAssignableFrom(type));
-        assert(value instanceof Pojo);
-        assert(value != null && !value.getClass().isArray());
-        
-        TypeAdapter<Pojo> pojoTypeAdapter = getTypeAdapter(Pojo.class);
-        pojoTypeAdapter.write(writer, (Pojo)value);
-    }
-
-    /*
-     * Serialize an array of primitives or Pojos
-     */
-    private void serializeArrayValue(JsonWriter writer,
-            PreparedParameter param) throws IOException {
-        Class<?> valType = param.getValue().getClass();
-        Class<?> typeType = param.getType();
-        // Special case pojo list types: the value class is of array type for
-        // them, but the type is the component type.
-        if (valType.isArray() && !typeType.isArray()) {
-            assert(Pojo.class.isAssignableFrom(typeType));
-            serializePojoList(writer, param);
-        } else {
-            serializeBasicList(writer, param);
-        }
-    }
-
-    /*
-     * Serialize a list of known primitives: boolean, int, long, double, String
-     */
-    private void serializeBasicList(JsonWriter writer,
-            PreparedParameter param) throws IOException {
-        // preconditions
-        assert(param.getValue() != null);
-        assert(param.getValue().getClass().isArray());
-        assert(param.getType().isArray());
-        
-        writer.beginArray();
-        int length = Array.getLength(param.getValue());
-        for (int i = 0; i < length; i++) {
-            Object elemVal = Array.get(param.getValue(), i);
-            Class<?> elemType = param.getType().getComponentType();
-            serializeSingleBasicValue(writer, elemVal, elemType);
-        }
-        writer.endArray();
-    }
-
-    private void serializeSingleBasicValue(JsonWriter writer, Object object, Class<?> type) throws IOException {
-        assert(!type.isArray());
-        if (object == null) {
-            // must have been a String type
-            // as other primitive types won't allow null
-            writer.nullValue();
-            return;
-        }
-        assert(!object.getClass().isArray());
-        assert(BASIC_TYPES.contains(type));
-        if (type.isPrimitive()) {
-            if (type == int.class) {
-                Integer intVal = (Integer)object;
-                writer.value(intVal);
-            } else if (type == long.class) {
-                writer.value((long)object);
-            } else if (type == double.class) {
-                writer.value((double)object);
-            } else if (type == boolean.class) {
-                writer.value((boolean)object);
-            }
-        } else {
-            assert(object instanceof String);
-            writer.value((String)object);
-        }
-    }
-
-    /*
-     *  Serialized an array of Pojo and only an array of Pojo
-     */
-    private void serializePojoList(JsonWriter writer, PreparedParameter param) throws IOException {
-        // preconditions
-        assert(param.getValue() != null);
-        assert(Pojo.class.isAssignableFrom(param.getType()));
-        assert(param.getValue().getClass().isArray());
-        
-        int length = Array.getLength(param.getValue());
-        writer.beginArray();
-        for (int i = 0; i < length; i++) {
-            Object value = Array.get(param.getValue(), i);
-            serializeSinglePojoImpl(writer, value, param.getType());
-        }
-        writer.endArray();
-    }
-    
-    private <T> TypeAdapter<T> getTypeAdapter(Class<T> typeClass) {
-        return gson.getAdapter(typeClass);
-    }
-    
-}
-
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-
-public class PreparedParameterTypeAdapterFactory implements TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == PreparedParameter.class) {
-            @SuppressWarnings("unchecked") // we've just verified this will work
-            TypeAdapter<T> ta = (TypeAdapter<T>) new PreparedParameterTypeAdapter(gson);
-            return ta;
-        } else {
-            return null;
-        }
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-
-class PreparedParametersTypeAdapter extends TypeAdapter<PreparedParameters> {
-
-    private final Gson gson;
-    private final Field paramsField;
-    
-    PreparedParametersTypeAdapter(Gson gson) {
-        this.gson = gson;
-        this.paramsField = getParametersField();
-    }
-    
-    @Override
-    public void write(JsonWriter out, PreparedParameters value)
-            throws IOException {
-        // handle null
-        if (value == null) {
-            out.nullValue();
-            return;
-        }
-        
-        TypeAdapter<PreparedParameter[]> paramsTa = gson.getAdapter(PreparedParameter[].class);
-        paramsTa.write(out, value.getParams());
-    }
-
-    @Override
-    public PreparedParameters read(JsonReader in) throws IOException {
-        // handle null
-        if (in.peek() == JsonToken.NULL) {
-            in.nextNull();
-            return null;
-        }
-        
-        TypeAdapter<PreparedParameter[]> paramsTa = gson.getAdapter(PreparedParameter[].class);
-        PreparedParameters params = new PreparedParameters(0);
-        PreparedParameter[] payload = paramsTa.read(in);
-        setParamenters(params, payload);
-        return params;
-    }
-
-    private void setParamenters(PreparedParameters params, PreparedParameter[] payload) {
-        // Set parameters via reflection in order to not be forced to
-        // introduce a public setter.
-        try {
-            paramsField.set(params, payload);
-        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
-            throw new IllegalStateException("Failed to set params field");
-        }
-    }
-    
-    private Field getParametersField() {
-        try {
-            Field field = PreparedParameters.class.getDeclaredField("params");
-            field.setAccessible(true);
-            return field;
-        } catch (NoSuchFieldException | SecurityException e) {
-            throw new IllegalStateException("params field not found");
-        }
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-
-public class PreparedParametersTypeAdapterFactory implements TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == PreparedParameters.class) {
-            @SuppressWarnings("unchecked")
-            TypeAdapter<T> ta = (TypeAdapter<T>)new PreparedParametersTypeAdapter(gson);
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-import java.util.UUID;
-
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-class SharedStateIdTypeAdapter extends TypeAdapter<SharedStateId> {
-
-    private static final String PROP_STMT_ID = "sid";
-    private static final String PROP_SERVER_TOKEN = "stok";
-    
-    @Override
-    public void write(JsonWriter out, SharedStateId value) throws IOException {
-        // handle null
-        if (value == null) {
-            out.nullValue();
-            return;
-        }
-        
-        out.beginObject();
-        
-        // statement id
-        out.name(PROP_STMT_ID);
-        out.value(value.getId());
-        
-        // server token, may be null
-        if (value.getServerToken() != null) {
-            out.name(PROP_SERVER_TOKEN);
-            out.value(value.getServerToken().toString());
-        } else {
-            out.name(PROP_SERVER_TOKEN);
-            out.nullValue();
-        }
-        
-        out.endObject();
-        
-    }
-
-    @Override
-    public SharedStateId read(JsonReader in) throws IOException {
-        // handle null
-        if (in.peek() == JsonToken.NULL) {
-            in.nextNull();
-            return null;
-        }
-        
-        in.beginObject();
-        
-        
-        // statement id
-        String name = in.nextName();
-        if (!name.equals(PROP_STMT_ID)) {
-            throw new IllegalStateException("Expected name " + PROP_STMT_ID + " but was " + name);
-        }
-        int stmtId = in.nextInt();
-        
-        UUID serverToken = null;
-        if (in.peek() == JsonToken.NAME) {
-            name = in.nextName();
-            if (!name.equals(PROP_SERVER_TOKEN)) {
-                throw new IllegalStateException("Expected name " + PROP_SERVER_TOKEN + " but was " + name);
-            }
-            String sToken = in.nextString();
-            serverToken = UUID.fromString(sToken);
-        }
-        in.endObject();
-        
-        return new SharedStateId(stmtId, serverToken);
-    }
-
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-public class SharedStateIdTypeAdapterFactory implements TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == SharedStateId.class) {
-            @SuppressWarnings("unchecked")
-            TypeAdapter<T> ta = (TypeAdapter<T>)new SharedStateIdTypeAdapter();
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-
-class WebPreparedStatementResponseTypeAdapter extends
-        TypeAdapter<WebPreparedStatementResponse> {
-    
-    private static final String NUM_FREE_VARS_NAME = "numFreeVars";
-    private static final String STMT_ID_NAME = "stmtId";
-    private final TypeAdapter<SharedStateId> sharedStateTa;
-    
-    WebPreparedStatementResponseTypeAdapter(TypeAdapter<SharedStateId> sharedStateTa) {
-        this.sharedStateTa = sharedStateTa;
-    }
-    
-    @Override
-    public WebPreparedStatementResponse read(JsonReader reader)
-            throws IOException {
-        if (reader.peek() == JsonToken.NULL) {
-            reader.nextNull();
-            return null;
-        }
-        
-        WebPreparedStatementResponse response = new WebPreparedStatementResponse();
-        
-        reader.beginObject();
-        String name = reader.nextName();
-        if (name.equals(NUM_FREE_VARS_NAME)) {
-            response.setNumFreeVariables(reader.nextInt());
-        }
-        name = reader.nextName();
-        if (name.equals(STMT_ID_NAME)) {
-            SharedStateId id = sharedStateTa.read(reader);
-            response.setStatementId(id);
-        }
-        reader.endObject();
-        
-        return response;
-    }
-
-    @Override
-    public void write(JsonWriter writer, WebPreparedStatementResponse value)
-            throws IOException {
-        if (value == null) {
-            writer.nullValue();
-            return;
-        }
-        
-        int freeVars = value.getNumFreeVariables();
-        SharedStateId stmtId = value.getStatementId();
-        
-        writer.beginObject();
-        
-        // Free variables
-        writer.name(NUM_FREE_VARS_NAME);
-        writer.value(freeVars);
-        // stmt id
-        writer.name(STMT_ID_NAME);
-        sharedStateTa.write(writer, stmtId);
-
-        writer.endObject();
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-
-public class WebPreparedStatementResponseTypeAdapterFactory implements
-        TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == WebPreparedStatementResponse.class) {
-            TypeAdapter<SharedStateId> sharedStateIdTa = gson.getAdapter(SharedStateId.class);
-            @SuppressWarnings("unchecked")
-            TypeAdapter<T> ta = (TypeAdapter<T>)new WebPreparedStatementResponseTypeAdapter(sharedStateIdTa);
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-
-@SuppressWarnings("rawtypes")
-class WebPreparedStatementTypeAdapter extends TypeAdapter<WebPreparedStatement> {
-
-    private static final String PROP_PARAMS = "p";
-    private static final String PROP_STMT_ID = "sid";
-    
-    private final TypeAdapter<SharedStateId> sharedStateTa;
-    private final TypeAdapter<PreparedParameters> prepParamsTa;
-    
-    WebPreparedStatementTypeAdapter(Gson gson) {
-        this.sharedStateTa = gson.getAdapter(SharedStateId.class);
-        this.prepParamsTa = gson.getAdapter(PreparedParameters.class);
-    }
-    
-    @Override
-    public void write(JsonWriter out, WebPreparedStatement value)
-            throws IOException {
-        // handle null
-        if (value == null) {
-            out.nullValue();
-            return;
-        }
-        
-        out.beginObject();
-        
-        // statement id
-        out.name(PROP_STMT_ID);
-        sharedStateTa.write(out, value.getStatementId());
-
-        // prepared parameters
-        out.name(PROP_PARAMS);
-        prepParamsTa.write(out, value.getParams());
-        
-        out.endObject();        
-    }
-
-    @Override
-    public WebPreparedStatement read(JsonReader in) throws IOException {
-        // handle null
-        if (in.peek() == JsonToken.NULL) {
-            in.nextNull();
-            return null;
-        }
-        
-        in.beginObject();
-        
-        
-        // statement id
-        String name = in.nextName();
-        if (!name.equals(PROP_STMT_ID)) {
-            throw new IllegalStateException("Expected name " + PROP_STMT_ID + " but was " + name);
-        }
-        SharedStateId id = sharedStateTa.read(in);
-        
-        // params
-        PreparedParameters params = null;
-        // params value might be null and missing.
-        if (in.peek() == JsonToken.NAME) {
-            name = in.nextName();
-            if (!name.equals(PROP_PARAMS)) {
-                throw new IllegalStateException("Expected name " + PROP_PARAMS + " but was " + name);
-            }
-            params = prepParamsTa.read(in);
-        }
-        
-        in.endObject();
-        
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>();
-        stmt.setParams(params);
-        stmt.setStatementId(id);
-        return stmt;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-
-public class WebPreparedStatementTypeAdapterFactory implements
-        TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == WebPreparedStatement.class) {
-            @SuppressWarnings("unchecked") // We've just checked the raw type
-            TypeAdapter<T> ta = (TypeAdapter<T>)new WebPreparedStatementTypeAdapter(gson);
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.io.IOException;
-import java.lang.reflect.Array;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-class WebQueryResponseTypeAdapter<T extends Pojo> extends TypeAdapter<WebQueryResponse<T>> {
-
-    private static final String PROP_RESULT = "payload";
-    private static final String PROP_ERROR_CODE = "errno";
-    private static final String PROP_CURSOR_ID = "cId";
-    private static final String PROP_CURSOR_HAS_MORE_BATCHES = "cHasMore";
-    
-    // The runtime type of the Pojo
-    private final Class<T> runtimePojoType;
-    private final Gson gson;
-    
-    WebQueryResponseTypeAdapter(Type parameterizedType, Gson gson) {
-        this.runtimePojoType = extractPojoImplClassFromType(parameterizedType);
-        this.gson = gson;
-    }
-    
-    @Override
-    public void write(JsonWriter out, WebQueryResponse<T> value)
-            throws IOException {
-        // handle null
-        if (value == null) {
-            out.nullValue();
-            return;
-        }
-        
-        out.beginObject();
-        
-        // response code
-        out.name(PROP_ERROR_CODE);
-        out.value(value.getResponseCode());
-        
-        // cursor id
-        out.name(PROP_CURSOR_ID);
-        out.value(value.getCursorId());
-        
-        // has more batches property
-        out.name(PROP_CURSOR_HAS_MORE_BATCHES);
-        out.value(value.hasMoreBatches());
-        
-        // payload
-        out.name(PROP_RESULT);
-        if (value.getResultList() == null) {
-            out.nullValue();
-        } else {
-            @SuppressWarnings("unchecked")
-            TypeAdapter<T[]> pojoTa = (TypeAdapter<T[]>)gson.getAdapter(value.getResultList().getClass());
-            pojoTa.write(out, value.getResultList());
-        }
-        
-        out.endObject();
-    }
-
-    @Override
-    public WebQueryResponse<T> read(JsonReader in) throws IOException {
-        // handle null
-        if (in.peek() == JsonToken.NULL) {
-            in.nextNull();
-            return null;
-        }
-        
-        in.beginObject();
-        
-        // response code (can't be null)
-        int responseCode = 0;
-        String name = in.nextName();
-        responseCode = in.nextInt();
-        
-        // cursor ID (can't be null)
-        name = in.nextName();
-        int cursorId = in.nextInt();
-        
-        // Has more batches, boolean, can't be null
-        name = in.nextName();
-        boolean hasMoreBatches = in.nextBoolean();
-        
-        if (runtimePojoType == null) {
-            throw new IllegalStateException("Runtime pojo type unknown");
-        }
-        // Result list may be null. If it's there we get a name, otherwise
-        // we are done deserializing
-        T[] resultList = null;
-        if (in.peek() == JsonToken.NAME) {
-            name = in.nextName();
-            if (name.equals(PROP_RESULT)) {
-                @SuppressWarnings("unchecked")
-                T[] arrayType = (T[])Array.newInstance(runtimePojoType, 0);
-                @SuppressWarnings("unchecked")
-                Class<T[]> type = (Class<T[]>)arrayType.getClass();
-                TypeAdapter<T[]> pojoTa = gson.getAdapter(type);
-                resultList = pojoTa.read(in);
-            } else {
-                throw new IllegalStateException("Expected " + PROP_RESULT + " but got " + name);
-            }
-        }
-        
-        in.endObject();
-        
-        WebQueryResponse<T> qResponse = new WebQueryResponse<>();
-        qResponse.setResponseCode(responseCode);
-        qResponse.setCursorId(cursorId);
-        qResponse.setHasMoreBatches(hasMoreBatches);
-        qResponse.setResultList(resultList);
-        return qResponse;
-    }
-    
-    private Class<T> extractPojoImplClassFromType(Type type) {
-        if (type instanceof ParameterizedType) {
-            // fromJson() calls need to pass in the right *parameterized* type token:
-            // example for AgentInformation as T:
-            //   Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-            //   gson.fromJson(jsonStr, queryResponseType)
-            Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
-            Type queryResponseTypeParam = typeParameters[0]; // WebQueryResponse has only one parameterized type T
-            Class<?> pojoClass = (Class<?>)queryResponseTypeParam;
-            if (!Pojo.class.isAssignableFrom(pojoClass)) {
-                throw new IllegalStateException("WebQueryResponse parametrized with non-pojo class: " + pojoClass);
-            } else {
-                @SuppressWarnings("unchecked") // We've just verified it's Pojo assignable.
-                Class<T> retval = (Class<T>)pojoClass;
-                return retval;
-            }
-        }
-        // should-be: write() will be called and only write().
-        return null;
-    }
-
-}
--- a/web/common/src/main/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapterFactory.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import com.google.gson.Gson;
-import com.google.gson.TypeAdapter;
-import com.google.gson.TypeAdapterFactory;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-public class WebQueryResponseTypeAdapterFactory implements TypeAdapterFactory {
-
-    @Override
-    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-        Class<?> rawType = type.getRawType();
-        if (rawType == WebQueryResponse.class) {
-            @SuppressWarnings({ "unchecked", "rawtypes" })
-            TypeAdapter<T> ta = (TypeAdapter<T>)new WebQueryResponseTypeAdapter(type.getType(), gson);
-            return ta;
-        }
-        return null;
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/CategorySerializationTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * 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.web.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Arrays;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class CategorySerializationTest {
-    
-    private static class TestObj implements Pojo {
-        // Dummy class for testing.
-    }
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder().create();
-    }
-    
-    @Test
-    public void canSerializeDeserializeCategory() {
-        Key<Boolean> barKey = new Key<>("bar-key");
-        Category<TestObj> cat = new Category<>("foo-category", TestObj.class, barKey);
-        String str = gson.toJson(cat, Category.class);
-        @SuppressWarnings("unchecked")
-        Category<TestObj> cat2 = (Category<TestObj>)gson.fromJson(str, Category.class);
-        assertNotSame(cat, cat2);
-        assertTrue(cat.equals(cat2));
-        assertEquals(cat.hashCode(), cat2.hashCode());
-        try {
-            cat2.getKeys().add(new Key<>("testme"));
-            fail("keys must be immutable after deserialization");
-        } catch (UnsupportedOperationException e) {
-            // pass
-        }
-        assertEquals(TestObj.class, cat2.getDataClass());
-        assertEquals("foo-category", cat2.getName());
-        assertEquals(barKey, cat2.getKey("bar-key"));
-    }
-
-    @Test
-    public void canSerializeDeserializeCategoryWithIndexedKeys() {
-        Key<Boolean> barKey = new Key<>("bar-key");
-        Category<TestObj> cat = new Category<>("foo-category2", TestObj.class,
-                Arrays.<Key<?>>asList(barKey), Arrays.<Key<?>>asList(barKey));
-        String str = gson.toJson(cat, Category.class);
-        @SuppressWarnings("unchecked")
-        Category<TestObj> cat2 = (Category<TestObj>)gson.fromJson(str, Category.class);
-        assertNotSame(cat, cat2);
-        assertTrue(cat.equals(cat2));
-        assertEquals(cat.hashCode(), cat2.hashCode());
-        try {
-            cat2.getKeys().add(new Key<>("testme"));
-            fail("keys must be immutable after deserialization");
-        } catch (UnsupportedOperationException e) {
-            // pass
-        }
-        assertEquals(TestObj.class, cat2.getDataClass());
-        assertEquals("foo-category2", cat2.getName());
-        assertEquals(barKey, cat2.getKey("bar-key"));
-        assertEquals(Arrays.asList(barKey), cat2.getIndexedKeys());
-    }
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/SharedStateIdTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * 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.web.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.UUID;
-
-import org.junit.Test;
-
-public class SharedStateIdTest {
-    
-    @Test
-    public void testEquals() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(3200, uuid);
-        SharedStateId id2 = new SharedStateId(3200, UUID.randomUUID());
-        SharedStateId id3 = new SharedStateId(300, uuid);
-        SharedStateId equals = new SharedStateId(3200, uuid);
-        
-        assertFalse(id.equals(null));
-        assertTrue(id.equals(equals));
-        assertFalse("Different uuid", id.equals(id2));
-        assertFalse("Different id val", id.equals(id3));
-        assertFalse("UUID and id val different", id3.equals(id2));
-        assertTrue(id.equals(id));
-    }
-
-    @Test
-    public void testHashCode() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(3200, uuid);
-        SharedStateId id2 = new SharedStateId(3200, UUID.randomUUID());
-        SharedStateId id3 = new SharedStateId(300, uuid);
-        SharedStateId equals = new SharedStateId(3200, uuid);
-        
-        assertTrue(id.hashCode() == equals.hashCode());
-        assertTrue("Different uuid", id.hashCode() != id2.hashCode());
-        assertTrue("Different id val", id.hashCode() != id3.hashCode());
-        assertTrue("UUID and id val different", id3.hashCode() != id2.hashCode());
-        assertTrue(id.hashCode() == id.hashCode());
-    }
-    
-    @Test
-    public void testBasic() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(3200, uuid);
-        assertEquals(uuid, id.getServerToken());
-        assertEquals(3200, id.getId());
-    }
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/WebQueryResponseTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * 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.web.common;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.lang.reflect.ParameterizedType;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class WebQueryResponseTest {
-
-    /**
-     * Having this test is important since we need the type info for deserializing
-     * {@link WebQueryResponse}s.
-     */
-    @Test
-    public void canGetCorrectParameterizedType() {
-        WebQueryResponse<TestPojo> response = new WebQueryResponse<>();
-        ParameterizedType type = response
-                .getRuntimeParametrizedType(TestPojo.class);
-        assertNull(type.getOwnerType());
-        assertEquals(1, type.getActualTypeArguments().length);
-        assertEquals(TestPojo.class, type.getActualTypeArguments()[0]);
-        assertEquals(WebQueryResponse.class, type.getRawType());
-    }
-
-    private static class TestPojo implements Pojo {
-        // nothing
-    }
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/JsonPerformanceTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertTrue;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.reflect.TypeToken;
-
-/**
- * 
- * A generic GSON-based performance test for JSON serialization/deserialization.
- *
- * @param <T> The type which should get serialized/deserialized.
- * 
- * @see PreparedParameterJSONPerformanceTest
- */
-public abstract class JsonPerformanceTest<T> {
-    
-    public enum OperationType {
-        DESERIALIZATION,
-        SERIALIZATION
-    }
-    
-    public enum GsonContext {
-        SLOW,
-        FASTER
-    }
-    
-    private static final String EXPECTATION_FORMAT = " (>=%s)";
-    private static final int ITERATIONS_FOR_CUMMULATIVE_AVG = 10;
-    
-    private final boolean debug;
-    private final String testClass;
-    private final Gson oldGson;
-    private final Gson newGson;
-    
-    protected JsonPerformanceTest(boolean debug, String testClass) {
-        this.debug = debug;
-        this.testClass = testClass;
-        this.oldGson = getSlowGson();
-        this.newGson = getFasterGson();
-    }
-    
-    /**
-     * 
-     * @return The base Gson to measure performance against
-     */
-    protected abstract Gson getSlowGson();
-
-    /**
-     * 
-     * @return The "improved" Gson for which the improvement over the Gson as returned by {{@link #getSlowGson()}
-     *         should be measured.
-     */
-    protected abstract Gson getFasterGson();
-    
-    /**
-     * The expected speedup used in asserts for the given iterations.
-     * 
-     * @param type The type of operation: serialization or deserialization.
-     * @param iterations
-     * @return The expected speed-up.
-     */
-    protected abstract double getExpectedSpeedup(OperationType type, int iterations);
-    
-    /**
-     * Formats the string to a valid json string by using
-     * {@code mutator}.
-     * 
-     * @param context The Gson context for this mutation.
-     * @param mutator A unique number for a performance run.
-     * 
-     * @return A valid JSON string representing an instance of type T.
-     */
-    protected abstract String mutateJsonString(GsonContext context, int mutator);
-    
-    /**
-     * Creates a mutated instance of T using mutator
-     * {@code mutator}.
-     * 
-     * @param mutator      A unique number for this performance test run.
-     * 
-     * @return The mutated instance.
-     */
-    protected abstract T mutateToBeSerializedInstance(int mutator);
-    
-    /**
-     * 
-     * @return The {@link TypeToken} for type T so that it can be properly
-     *         deserialized.
-     */
-    protected abstract TypeToken<T> getDeserializeTypeToken();
-    
-    /**
-     * 
-     * @return The number of iterations to run for the cold (not warmed-up)
-     *         serialization performance test.
-     */
-    protected abstract int getColdSerializationIterations();
-    
-    /**
-     * 
-     * @return The number of iterations to run for the "warmed-up" serialization
-     *         performance test.
-     */
-    protected abstract int getWarmSerializationIterations();
-    
-    /**
-     * 
-     * @return The number of iterations to run for the cold (not warmed-up)
-     *         deserialization performance test.
-     */
-    protected abstract int getColdDeserializationIterations();
-    
-    /**
-     * 
-     * @return The number of iterations to run for the "warmed-up" deserialization
-     *         performance test.
-     */
-    protected abstract int getWarmDeserializationIterations();
-    
-    /**
-     * 
-     * @return A delta to increase the "faster" gson serialization speed-up so
-     *         that basic assertions such as {@code speed-up >= 1} work. This is
-     *         useful for the base-case of comparing a gson instance to itself.
-     *         Two performance runs of the same gson are expected to be
-     *         approximately equally fast. Though, it will depend on the system.
-     */
-    protected abstract double getSelfSerializationDelta();
-    
-    /**
-     * 
-     * @return A delta to increase the "faster" gson deserialization speed-up so
-     *         that basic assertions such as {@code speed-up >= 1} work. This is
-     *         useful for the base-case of comparing a gson instance to itself.
-     *         Two performance runs of the same gson are expected to be
-     *         approximately equally fast. Though, it will depend on the system.
-     */
-    protected abstract double getSelfDeserializationDelta();
-    
-    @Test
-    public void verifySerializationSpeedCold() {
-        int iterations = getColdSerializationIterations();
-        double actualSpeedup = getAverageSerializationSpeedup(iterations);
-        final double expectedSpeedup = getExpectedSpeedup(OperationType.SERIALIZATION, iterations);
-        if (debug) {
-            System.out.println(testClass + ": actual cold serialization speed-up: " +
-                    formatSpeedup(actualSpeedup) + String.format(EXPECTATION_FORMAT, formatSpeedup(expectedSpeedup)));
-        }
-        assertTrue("Performance regression? Expected a speed-up of > " + expectedSpeedup +". Speed-up was: " + actualSpeedup, actualSpeedup > expectedSpeedup);
-    }
-    
-    @Test
-    public void verifySerializationSpeedWarm() {
-        int iterations = getWarmSerializationIterations();
-        double actualSpeedup = getAverageSerializationSpeedup(iterations);
-        final double expectedSpeedup = getExpectedSpeedup(OperationType.SERIALIZATION, iterations);
-        if (debug) {
-            System.out.println(testClass + ": actual warmed-up serialization speed-up: " + 
-                    formatSpeedup(actualSpeedup) + String.format(EXPECTATION_FORMAT, formatSpeedup(expectedSpeedup)));
-        }
-        assertTrue("Performance regression? Expected a speed-up of > " + expectedSpeedup +". Speed-up was: " + actualSpeedup, actualSpeedup > expectedSpeedup);
-    }
-    
-    @Test
-    public void verifyDeserializationSpeedCold() {
-        int iterations = getColdDeserializationIterations();
-        double actualSpeedup = getAverageDeserializationSpeedup(iterations);
-        final double expectedSpeedup = getExpectedSpeedup(OperationType.DESERIALIZATION, iterations);
-        if (debug) {
-            System.out.println(testClass + ": actual cold deserialization speed-up: " +
-                formatSpeedup(actualSpeedup) + String.format(EXPECTATION_FORMAT, formatSpeedup(expectedSpeedup)));
-        }
-        assertTrue("Performance regression? Expected a speed-up of > " + expectedSpeedup +". Speed-up was: " + actualSpeedup, actualSpeedup > expectedSpeedup);
-    }
-    
-    @Test
-    public void verifyDeserializationSpeedWarm() {
-        int iterations = getWarmDeserializationIterations();
-        double actualSpeedup = getAverageDeserializationSpeedup(iterations);
-        final double expectedSpeedup = getExpectedSpeedup(OperationType.DESERIALIZATION, iterations);
-        if (debug) {
-            System.out.println(testClass + ": actual warmed-up deserialization speed-up: " +
-                    formatSpeedup(actualSpeedup) + String.format(EXPECTATION_FORMAT, formatSpeedup(expectedSpeedup)));
-        }
-        assertTrue("Performance regression? Expected a speed-up of > " + expectedSpeedup +". Speed-up was: " + actualSpeedup, actualSpeedup > expectedSpeedup);
-    }
-    
-    private double getAverageSerializationSpeedup(final int iterations) {
-        double sum = 0;
-        for (int i = 0; i < ITERATIONS_FOR_CUMMULATIVE_AVG; i++) {
-            sum += measureSerializationSpeed(iterations);
-        }
-        double speedup = sum/ITERATIONS_FOR_CUMMULATIVE_AVG; 
-        double delta = getSelfSerializationDelta();
-        assertTrue("Performance Regression? Expected a speed-up of >= 1, but was: " + (speedup + delta),
-                        (speedup + delta) >= 1);
-        return speedup;
-    }
-    
-    private double measureSerializationSpeed(final int iterations) {
-        PerfTestResult result = runSerializationPerformanceTest(iterations);
-        return result.getSpeedup();
-    }
-    
-    private double getAverageDeserializationSpeedup(final int iterations) {
-        double sum = 0;
-        for (int i = 0; i < ITERATIONS_FOR_CUMMULATIVE_AVG; i++) {
-            sum += measureDeserializationSpeed(iterations);
-        }
-        double speedup = sum/ITERATIONS_FOR_CUMMULATIVE_AVG; 
-        double delta = getSelfDeserializationDelta();
-        assertTrue("Performance Regression? Expected a speed-up of >= 1, but was: " + (speedup + delta),
-                        (speedup + delta) >= 1);
-        return speedup;
-    }
-    
-    private double measureDeserializationSpeed(final int iterations) {
-        PerfTestResult result = runDeserializationPerformanceTest(iterations);
-        return result.getSpeedup();
-    }
-    
-    private PerfTestResult runSerializationPerformanceTest(final int iterations) {
-        List<String> list = new ArrayList<>();
-        double oldSum = 0;
-        double newSum = 0;
-        long start = -1;
-        long end = -1;
-        Gson gson = null;
-        for (int i = 0; i < iterations * 2; i++) {
-            T instance = mutateToBeSerializedInstance(i);
-            if (i % 2 != 0) {
-                gson = newGson;
-            } else {
-                gson = oldGson;
-            }
-            start = System.nanoTime();
-            String json = gson.toJson(instance);
-            end = System.nanoTime();
-            if (i % 2 != 0) {
-                newSum += (end - start);
-            } else {
-                oldSum += (end - start);
-            }
-            // Do something silly just so that the JIT does not optimize-out the
-            // toJson() call.
-            list.add(json);
-        }
-        PerfTestResult res = new PerfTestResult();
-        res.oldPerf = oldSum/iterations;
-        res.newPerf = newSum/iterations;
-        return res;
-    }
-    
-    private PerfTestResult runDeserializationPerformanceTest(final int iterations) {
-        List<T> list = new ArrayList<>();
-
-        double oldSum = 0;
-        double newSum = 0;
-        long start = -1;
-        long end = -1;
-        Gson gson = null;
-        String json;
-        for (int i = 0; i < iterations * 2; i++) {
-            if (i % 2 != 0) {
-                json = mutateJsonString(GsonContext.FASTER, i);
-                gson = newGson;
-            } else {
-                json = mutateJsonString(GsonContext.SLOW, i);
-                gson = oldGson;
-            }
-            start = System.nanoTime();
-            T instance = gson.fromJson(json, getDeserializeTypeToken().getType());
-            end = System.nanoTime();
-            if (i % 2 != 0) {
-                newSum += (end - start);
-            } else {
-                oldSum += (end - start);
-            }
-            // Do something silly just so that the JIT does not optimize-out the
-            // fromJson() call.
-            list.add(instance);
-        }
-        PerfTestResult res = new PerfTestResult();
-        res.oldPerf = oldSum/iterations;
-        res.newPerf = newSum/iterations;
-        return res;
-    }
-    
-    private String formatSpeedup(double value) {
-        DecimalFormat format = new DecimalFormat("#.##");
-        return format.format(value);
-    }
-    
-    private static class PerfTestResult {
-        private double oldPerf;
-        private double newPerf;
-        
-        private double getSpeedup() {
-            return oldPerf/newPerf;
-        }
-    }
-    
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyGSONConverter.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Type;
-
-import org.apache.commons.beanutils.PropertyUtils;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.model.Pojo;
-
-/**
- * Old non-stream GSON API serializer. Used only in performance tests. 
- */
-public class LegacyGSONConverter implements JsonSerializer<Pojo>, JsonDeserializer<Pojo> {
-
-    @Override
-    public Pojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
-        @SuppressWarnings("unchecked")
-        Class<? extends Pojo> targetType = (Class<Pojo>) typeOfT;
-        try {
-            Pojo pojo = targetType.newInstance();
-            PropertyDescriptor[] descs = PropertyUtils.getPropertyDescriptors(pojo);
-            for (PropertyDescriptor desc : descs) {
-                Method writeMethod = desc.getWriteMethod();
-                if (writeMethod != null && writeMethod.isAnnotationPresent(Persist.class)) {
-                    String name = desc.getName();
-                    JsonElement child = json.getAsJsonObject().get(name);
-                    Object value = context.deserialize(child, desc.getPropertyType());
-                    PropertyUtils.setProperty(pojo, name, value);
-                }
-            }
-            return pojo;
-        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public JsonElement serialize(Pojo src, Type typeOfSrc, JsonSerializationContext context) {
-        Class<?> cls = (Class<?>) typeOfSrc;
-        if (! cls.isAnnotationPresent(Entity.class)) {
-            System.err.println("attempt to serialize non-Entity class: " + cls.getName());
-            throw new IllegalArgumentException("attempt to serialize non-Entity class: " + cls.getName());
-        }
-        JsonObject obj = new JsonObject();
-        PropertyDescriptor[] descs = PropertyUtils.getPropertyDescriptors(src);
-        for (PropertyDescriptor desc : descs) {
-            Method readMethod = desc.getReadMethod();
-            if (readMethod != null && readMethod.isAnnotationPresent(Persist.class)) {
-                String name = desc.getName();
-                
-                try {
-                    Object value = PropertyUtils.getProperty(src, name);
-                    obj.add(name, context.serialize(value));
-                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
-                    throw new RuntimeException(e);
-                }
-            } else if (readMethod == null) {
-                System.err.println("WARNING: property without read method: " + src.getClass().getName() + "::" + desc.getName());
-            }
-        }
-        return obj;
-    }
-
-
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyPreparedParameterSerializer.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.model.Pojo;
-
-/**
- * Old non-stream GSON API serializer. Used only in performance tests. 
- */
-public class LegacyPreparedParameterSerializer implements JsonSerializer<PreparedParameter>,
-                                                    JsonDeserializer<PreparedParameter>{
-
-    private static final Logger logger = LoggingUtils.getLogger(LegacyPreparedParameterSerializer.class);
-    private static final String PROP_TYPE = "type";
-    private static final String PROP_VALUE = "value";
-    private static final Set<Class<?>> VALID_CLASSES;
-    private static final Set<Class<?>> PRIMITIVES_NOT_ALLOWING_NULL_VAL;
-    // maps type names to classes:
-    //    "int" => int.class , "double" => double.class, "[I" => int[].class
-    //    and so on.
-    private static final Map<String, Class<?>> CLASSES_LOOKUP_TABLE;
-    
-    static {
-        VALID_CLASSES = new HashSet<>();
-        CLASSES_LOOKUP_TABLE = new HashMap<>();
-        CLASSES_LOOKUP_TABLE.put(int.class.getName(), int.class);
-        CLASSES_LOOKUP_TABLE.put(long.class.getName(), long.class);
-        CLASSES_LOOKUP_TABLE.put(boolean.class.getName(), boolean.class);
-        CLASSES_LOOKUP_TABLE.put(double.class.getName(), double.class);
-        CLASSES_LOOKUP_TABLE.put(String.class.getName(), String.class);
-        CLASSES_LOOKUP_TABLE.put(int[].class.getName(), int[].class);
-        CLASSES_LOOKUP_TABLE.put(long[].class.getName(), long[].class);
-        CLASSES_LOOKUP_TABLE.put(boolean[].class.getName(), boolean[].class);
-        CLASSES_LOOKUP_TABLE.put(double[].class.getName(), double[].class);
-        CLASSES_LOOKUP_TABLE.put(String[].class.getName(), String[].class);
-        VALID_CLASSES.addAll(CLASSES_LOOKUP_TABLE.values());
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL = new HashSet<>();
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(int.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(long.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(boolean.class);
-        PRIMITIVES_NOT_ALLOWING_NULL_VAL.add(double.class);
-    }
-    
-    @Override
-    public JsonElement serialize(PreparedParameter param, Type type,
-            JsonSerializationContext ctxt) {
-        JsonObject result = new JsonObject();
-        JsonElement valueElem = serializeValue(ctxt, param.getValue(), param.getType());
-        result.add(PROP_VALUE, valueElem);
-        JsonPrimitive typeElem = new JsonPrimitive(param.getType().getName());
-        result.add(PROP_TYPE, typeElem);
-        return result;
-    }
-
-    private JsonElement serializeValue(JsonSerializationContext ctxt, Object value, Class<?> type) {
-        JsonElement element;
-        // Special case pojo list types: the value class is of array type for
-        // them, but the type is the component type.
-        if (value != null && value.getClass().isArray() && !type.isArray()) {
-            assert(Pojo.class.isAssignableFrom(type));
-            Class<?> arrayType = Array.newInstance(type, 0).getClass();
-            element = ctxt.serialize(value, arrayType);
-        } else {
-            element = ctxt.serialize(value, type);
-        }
-        return element;
-    }
-
-    @Override
-    public PreparedParameter deserialize(JsonElement jsonElem, Type type,
-            JsonDeserializationContext ctxt) throws JsonParseException {
-        JsonElement typeElem = jsonElem.getAsJsonObject().get(PROP_TYPE);
-        String className = typeElem.getAsString();
-        // perform some sanity checking on the types of classes we actually
-        // de-serialize
-        Class<?> typeVal = deserializeTypeVal(className);
-        validateSaneClassName(typeVal);
-        JsonElement valueElement = jsonElem.getAsJsonObject().get(PROP_VALUE);
-        Object value = deserializeValue(ctxt, valueElement, typeVal);
-        PreparedParameter param = new PreparedParameter();
-        param.setType(typeVal);
-        param.setValue(value);
-        return param;
-    }
-
-    private Class<?> deserializeTypeVal(String className) {
-        Class<?> typeVal = null;
-        if (CLASSES_LOOKUP_TABLE.containsKey(className)) {
-            typeVal = CLASSES_LOOKUP_TABLE.get(className);
-        } else {
-            try {
-                // We need this for Pojo + Pojo list type params. For pojo
-                // lists the name we get passed is the component type of the
-                // array.
-                typeVal = Class.forName(className);
-            } catch (ClassNotFoundException e) {
-                logger.log(Level.WARNING, "Failed to resolve class type for '"
-                        + className + "'.");
-            }
-        }
-        return typeVal;
-    }
-
-    private Object deserializeValue(JsonDeserializationContext ctxt,
-            JsonElement valueElement, Class<?> valType) {
-        // special case for Pojo/Pojo list types. In that case, the valType
-        // is the component type for arrays. In order to distinguish pojo
-        // lists from pojos, we use JSON's array info about the value element.
-        if (valueElement != null && valueElement.isJsonArray() && !valType.isArray()) {
-            assert(Pojo.class.isAssignableFrom(valType));
-            Class<?> arrayType = Array.newInstance(valType, 0).getClass();
-            return ctxt.deserialize(valueElement, arrayType);
-        } else {
-            Object value = ctxt.deserialize(valueElement, valType);
-            validatePrimitivesForNull(value, valType);
-            return value;
-        }
-    }
-
-    private void validatePrimitivesForNull(Object value, Class<?> valType) {
-        if (PRIMITIVES_NOT_ALLOWING_NULL_VAL.contains(valType) && value == null) {
-            // illegal value for primitive type. according to JLS spec they all
-            // have default values and are never null.
-            throw new IllegalStateException( valType + " primitive" +
-                                            " does not accept a null value!");
-        }
-    }
-
-    // Allow valid classes + Pojo types, refuse everything else
-    private void validateSaneClassName(Class<?> clazz) {
-        // isAssignableFrom throws NPE if clazz is null.
-        if (VALID_CLASSES.contains(clazz) ||
-                Pojo.class.isAssignableFrom(clazz)) {
-            return;
-        }
-        throw new IllegalStateException("Illegal type of parameter " + clazz.getCanonicalName());
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyWebPreparedStatementSerializer.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.lang.reflect.Type;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-
-/**
- * Old non-stream GSON API serializer. Used only in performance tests.
- *
- */
-public class LegacyWebPreparedStatementSerializer implements
-        JsonDeserializer<WebPreparedStatement<?>>,
-        JsonSerializer<WebPreparedStatement<?>> {
-    
-    private static final String PROP_PARAMS = "p";
-    private static final String PROP_STMT_ID = "sid";
-
-    @Override
-    public JsonElement serialize(WebPreparedStatement<?> stmt, Type type,
-            JsonSerializationContext ctxt) {
-        JsonObject result = new JsonObject();
-        JsonElement parameters = ctxt.serialize(stmt.getParams(), PreparedParameters.class);
-        result.add(PROP_PARAMS, parameters);
-        JsonElement stmtIdElem = ctxt.serialize(stmt.getStatementId(), SharedStateId.class);
-        result.add(PROP_STMT_ID, stmtIdElem);
-        return result;
-    }
-
-    @Override
-    public WebPreparedStatement<?> deserialize(JsonElement jsonElem, Type type,
-            JsonDeserializationContext ctxt) throws JsonParseException {
-        JsonElement paramsElem = jsonElem.getAsJsonObject().get(PROP_PARAMS);
-        JsonElement stmtIdElem = jsonElem.getAsJsonObject().get(PROP_STMT_ID);
-        PreparedParameters params = ctxt.deserialize(paramsElem, PreparedParameters.class);
-        SharedStateId stmtId = ctxt.deserialize(stmtIdElem, SharedStateId.class);
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>();
-        stmt.setStatementId(stmtId);
-        stmt.setParams(params);
-        return stmt;
-    }
-
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/LegacyWebQueryResponseSerializer.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonDeserializer;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import com.google.gson.JsonSerializer;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-/**
- * Old non-stream GSON API serializer. Used only in performance tests. 
- */
-public class LegacyWebQueryResponseSerializer<T extends Pojo> implements
-        JsonDeserializer<WebQueryResponse<T>>, JsonSerializer<WebQueryResponse<T>> {
-
-    private static final String PROP_RESULT = "payload";
-    private static final String PROP_ERROR_CODE = "errno";
-    
-    @Override
-    public JsonElement serialize(WebQueryResponse<T> qResponse, Type type,
-            JsonSerializationContext ctxt) {
-        JsonObject result = new JsonObject();
-        JsonElement resultsElem = ctxt.serialize(qResponse.getResultList());
-        result.add(PROP_RESULT, resultsElem);
-        JsonPrimitive errnoElem = new JsonPrimitive(qResponse.getResponseCode());
-        result.add(PROP_ERROR_CODE, errnoElem);
-        return result;
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Override
-    public WebQueryResponse<T> deserialize(JsonElement jsonElem, Type type,
-            JsonDeserializationContext ctxt) throws JsonParseException {
-        // fromJson() calls need to pass in the right *parameterized* type token:
-        // example for AgentInformation as T:
-        //   Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-        //   gson.fromJson(jsonStr, queryResponseType)
-        Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
-        Type queryResponseTypeParam = typeParameters[0]; // WebQueryResponse has only one parameterized type T
-        JsonArray resultElem = jsonElem.getAsJsonObject().get(PROP_RESULT).getAsJsonArray();
-        @SuppressWarnings("rawtypes")
-        Class typeOfGeneric = (Class)queryResponseTypeParam;
-        T[] array = (T[])Array.newInstance(typeOfGeneric, resultElem.size());
-        for (int i = 0; i < resultElem.size(); i++) {
-            array[i] = ctxt.deserialize(resultElem.get(i), queryResponseTypeParam);
-        }
-        JsonElement errorCodeElem = jsonElem.getAsJsonObject().get(PROP_ERROR_CODE);
-        int errorCode = ctxt.deserialize(errorCodeElem, int.class);
-        WebQueryResponse<T> qResponse = new WebQueryResponse<>();
-        qResponse.setResponseCode(errorCode);
-        qResponse.setResultList(array);
-        return qResponse;
-    }
-    
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PojoTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.storage.model.AggregateCount;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class PojoTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .create();
-    }
-    
-    @Test
-    public void canSerializePojoLists() {
-        String expectedJson = "[{\"AInt\":200,\"fooString\":\"bar\"}," +
-                               "{\"AInt\":5,\"fooString\":\"baz\"}," +
-                               "{\"AInt\":200,\"fooString\":\"bar\"}]";
-        
-        FooPojo pojo1 = new FooPojo();
-        pojo1.setAInt(200);
-        pojo1.setFooString("bar");
-        
-        FooPojo pojo2 = new FooPojo();
-        pojo2.setAInt(5);
-        pojo2.setFooString("baz");
-        
-        FooPojo[] list = new FooPojo[] {
-                pojo1, pojo2, pojo1
-        };
-        String json = gson.toJson(list);
-        assertEquals(expectedJson, json);
-    }
-    
-    @Test
-    public void canDeserializePojoLists() {
-        String json = "[{\"AInt\":200,\"fooString\":\"bar\"}," +
-                               "{\"AInt\":5,\"fooString\":\"baz\"}," +
-                               "{\"AInt\":200,\"fooString\":\"bar\"}]";
-        
-        FooPojo[] actual = gson.fromJson(json, FooPojo[].class);
-        assertEquals(3, actual.length);
-        assertEquals(200, actual[0].getAInt());
-        assertEquals(5, actual[1].getAInt());
-        assertEquals(200, actual[2].getAInt());
-        assertEquals("bar", actual[0].getFooString());
-        assertEquals("bar", actual[2].getFooString());
-        assertEquals("baz", actual[1].getFooString());
-    }
-    
-    @Test
-    public void canSerializeNullPojo() {
-        FooPojo foo = null;
-        String jsonStr = gson.toJson(foo);
-        assertEquals("null", jsonStr);
-    }
-    
-    // Null values won't show up in the JSON string.
-    @Test
-    public void canSerializeNullMember() {
-        String expectedJson = "{\"AInt\":200,\"fooString\":\"bar\"}";
-        
-        FooPojo foo = new FooPojo();
-        foo.setAInt(200);
-        foo.setFooString("bar");
-        String jsonStr = gson.toJson(foo);
-        assertEquals(expectedJson, jsonStr);
-    }
-    
-    @Test
-    public void canDeserializeWithMembersUnset() {
-        String json = "{\"AInt\":200,\"boolArray\":null,\"fooString\":\"bar\"}";
-
-        FooPojo pojo = gson.fromJson(json, FooPojo.class);
-        assertNotNull(pojo);
-        assertEquals(200, pojo.getAInt());
-        assertEquals("bar", pojo.getFooString());
-        assertNull(pojo.getBoolArray());
-        
-        // Do it again with unset values omitted.
-        json = "{\"fooString\":\"bar\"}";
-        pojo = gson.fromJson(json, FooPojo.class);
-        assertNotNull(pojo);
-        assertEquals("bar", pojo.getFooString());
-        assertNull(pojo.getBoolArray());
-        assertEquals("0 is default int val", 0, pojo.getAInt());
-    }
-    
-    @Test
-    public void canDeserializeBasic() {
-        String json = "{\"AInt\":1223,\"boolArray\":[false,true,false],\"fooString\":\"fooStringValue\"}";
-        
-        FooPojo pojo = gson.fromJson(json, FooPojo.class);
-        assertEquals(1223, pojo.getAInt());
-        assertEquals("fooStringValue", pojo.getFooString());
-        assertEquals(3, pojo.getBoolArray().length);
-        assertFalse(pojo.getBoolArray()[0]);
-        assertTrue(pojo.getBoolArray()[1]);
-        assertFalse(pojo.getBoolArray()[2]);
-    }
-    
-    @Test
-    public void canDeserializeNullPojo() {
-        String nullStr = "null";
-        FooPojo pojo = gson.fromJson(nullStr, FooPojo.class);
-        assertNull(pojo);
-    }
-    
-    @Test
-    public void canSerializeBasic() {
-        String expectedJson = "{\"AInt\":1223,\"boolArray\":[false,true,false],\"fooString\":\"fooStringValue\"}";
-        
-        FooPojo fooPojo = new FooPojo();
-        fooPojo.setBoolArray(new boolean[] { false, true, false });
-        fooPojo.setAInt(1223);
-        fooPojo.setFooString("fooStringValue");
-        String jsonStr = gson.toJson(fooPojo);
-        assertEquals(expectedJson, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeRecursivePojo() {
-        FooPojo fooPojo = new FooPojo();
-        fooPojo.setBoolArray(new boolean[] { false, true, false });
-        fooPojo.setAInt(1223);
-        fooPojo.setFooString("fooStringValue");
-        String fooPojoJson = gson.toJson(fooPojo);
-        
-        String expectedJson = "{\"myLong\":10000000000,\"pojo\":" + fooPojoJson + "}";
-        RecPojo recursive = new RecPojo();
-        recursive.setPojo(fooPojo);
-        recursive.setMyLong(10000000000L);
-        
-        String jsonStr = gson.toJson(recursive);
-        assertEquals(expectedJson, jsonStr);
-    }
-    
-    @Test
-    public void canDeserializeRecursivePojo() {
-        String json = "{\"myLong\":10000000000,\"pojo\":" +
-                                         "{\"AInt\":1223,\"boolArray\":[false,true,false],\"fooString\":\"fooStringValue\"}}";
-        
-        RecPojo rec = gson.fromJson(json, RecPojo.class);
-        
-        assertEquals(10000000000L, rec.getMyLong());
-        assertNotNull(rec.getPojo());
-        
-        FooPojo pojo = rec.getPojo();
-        assertEquals(1223, pojo.getAInt());
-        assertEquals("fooStringValue", pojo.getFooString());
-        assertEquals(3, pojo.getBoolArray().length);
-        assertFalse(pojo.getBoolArray()[0]);
-        assertTrue(pojo.getBoolArray()[1]);
-        assertFalse(pojo.getBoolArray()[2]);
-    }
-    
-    @Test
-    public void canSerializeDeserializeBasic() {
-        // Our test pojo
-        AgentInformation agentInfo = new AgentInformation("testing");
-        agentInfo.setAlive(true);
-        
-        String jsonStr = gson.toJson(agentInfo);
-        
-        AgentInformation actual = gson.fromJson(jsonStr, AgentInformation.class);
-        
-        assertEquals("testing", actual.getAgentId());
-        assertEquals(true, actual.isAlive());
-    }
-    
-    @Test
-    public void canSerializeDeserializeArray() {
-        // Our test pojo
-        AgentInformation agentInfo = new AgentInformation("testing");
-        agentInfo.setAlive(true);
-        AgentInformation[] agentInfos = new AgentInformation[] {
-                agentInfo
-        };
-        
-        String jsonStr = gson.toJson(agentInfos);
-        
-        AgentInformation[] actual = gson.fromJson(jsonStr, AgentInformation[].class);
-        
-        assertEquals("testing", actual[0].getAgentId());
-        assertEquals(true, actual[0].isAlive());
-    }
-    
-    @Test
-    public void canSerializeDeserializeAggregateCount() {
-        long expectedCount = 3333000333L;
-        AggregateCount count = new AggregateCount();
-        count.setCount(expectedCount);
-        String jsonStr = gson.toJson(count);
-        // now do the reverse
-        AggregateCount c2 = gson.fromJson(jsonStr, AggregateCount.class);
-        assertEquals(expectedCount, c2.getCount());
-    }
-    
-    @Entity
-    public static class FooPojo implements Pojo {
-        
-        private String fooString;
-        private int fooInt;
-        private boolean[] boolArray;
-        
-        @Persist
-        public String getFooString() {
-            return fooString;
-        }
-        
-        @Persist
-        public void setFooString(String fooString) {
-            this.fooString = fooString;
-        }
-        
-        @Persist
-        public int getAInt() {
-            return fooInt;
-        }
-        
-        @Persist
-        public void setAInt(int fooInt) {
-            this.fooInt = fooInt;
-        }
-        
-        @Persist
-        public boolean[] getBoolArray() {
-            return boolArray;
-        }
-        
-        @Persist
-        public void setBoolArray(boolean[] boolArray) {
-            this.boolArray = boolArray;
-        }
-        
-        
-    }
-    
-    @Entity
-    public static class RecPojo implements Pojo {
-        
-        private long myLong;
-        private FooPojo pojo;
-        
-        @Persist
-        public long getMyLong() {
-            return myLong;
-        }
-        
-        @Persist
-        public void setMyLong(long myLong) {
-            this.myLong = myLong;
-        }
-        
-        @Persist
-        public FooPojo getPojo() {
-            return pojo;
-        }
-        
-        @Persist
-        public void setPojo(FooPojo pojo) {
-            this.pojo = pojo;
-        }
-        
-    }
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterJSONPerformanceTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import org.junit.experimental.categories.Category;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.testutils.PerformanceTest;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParameterTypeAdapterFactory;
-
-/**
- * JUnit categorized performance test. It'll be only run for
- * the perf-tests profile during a full build.
- */
-@Category(PerformanceTest.class)
-public class PreparedParameterJSONPerformanceTest extends
-        JsonPerformanceTest<PreparedParameter> {
-    
-    private static final boolean DEBUG = true;
-
-    public PreparedParameterJSONPerformanceTest() {
-        super(DEBUG, PreparedParameterJSONPerformanceTest.class.getSimpleName());
-    }
-
-    @Override
-    protected Gson getSlowGson() {
-        return new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapter(PreparedParameter.class, new LegacyPreparedParameterSerializer())
-                    .create();
-    }
-
-    @Override
-    protected Gson getFasterGson() {
-        return new GsonBuilder()
-            .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-            .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-            .create();
-    }
-
-    @Override
-    protected double getExpectedSpeedup(
-            OperationType type,
-            int iterations) {
-        if (type == OperationType.SERIALIZATION && iterations == getColdSerializationIterations()) {
-            return 1.7;
-        } else if (type == OperationType.SERIALIZATION && iterations == getWarmSerializationIterations()) {
-            return 1.3;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getColdDeserializationIterations()) {
-            return 1;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getWarmDeserializationIterations()) {
-            return 1;
-        } else {
-            throw new IllegalStateException("bug");
-        }
-    }
-
-    @Override
-    protected String mutateJsonString(
-            GsonContext context,
-            int mutator) {
-        return String.format("{\"type\":\"int\",\"value\":%d}", mutator);
-    }
-
-    @Override
-    protected PreparedParameter mutateToBeSerializedInstance(int mutator) {
-        PreparedParameter param = new PreparedParameter();
-        param.setValue(mutator);
-        param.setType(int.class);
-        return param;
-    }
-
-    @Override
-    protected TypeToken<PreparedParameter> getDeserializeTypeToken() {
-        return TypeToken.get(PreparedParameter.class);
-    }
-
-    @Override
-    protected int getColdSerializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmSerializationIterations() {
-        return 1000;
-    }
-
-    @Override
-    protected int getColdDeserializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmDeserializationIterations() {
-        return 1000;
-    }
-
-    @Override
-    protected double getSelfSerializationDelta() {
-        return 0.1;
-    }
-
-    @Override
-    protected double getSelfDeserializationDelta() {
-        return 0.1;
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParameterTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,481 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.lang.reflect.Array;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.storage.model.VmInfo.KeyValuePair;
-
-public class PreparedParameterTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                .create();
-    }
-    
-    @Test
-    public void canDeserializeBasic() {
-        // String
-        String jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": \"testing\" }";
-        PreparedParameter param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(String.class, param.getType());
-        assertEquals("testing", param.getValue());
-        // Integer
-        jsonStr = "{ \"type\": \"int\" , \"value\": -1}";
-        param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(int.class, param.getType());
-        assertEquals(-1, param.getValue());
-        // Long
-        jsonStr = "{ \"type\": \"long\" , \"value\": -10}";
-        param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(long.class, param.getType());
-        assertEquals(-10L, param.getValue());
-        jsonStr = "{ \"type\": \"long\" , \"value\": 30000000003}";
-        param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(long.class, param.getType());
-        assertEquals(30000000003L, param.getValue());
-        // Boolean
-        jsonStr = "{ \"type\": \"boolean\" , \"value\": true}";
-        param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(boolean.class, param.getType());
-        assertEquals(true, param.getValue());
-        // String[]
-        String strArrayVal = "[ \"testing1\", \"testing2\", \"3\" ]";
-        jsonStr = "{ \"type\": \"[Ljava.lang.String;\" , \"value\": " + strArrayVal + "}";
-        param = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(String[].class, param.getType());
-        assertTrue(param.getValue() instanceof String[]);
-        String[] vals = (String[])param.getValue();
-        assertEquals(3, vals.length);
-        assertEquals("testing1", vals[0]);
-        assertEquals("testing2", vals[1]);
-        assertEquals("3", vals[2]);
-    }
-    
-    @Test
-    public void allowsBooleanListNullDeserialization() {
-        String jsonStr = "{ \"type\": \"[Z\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(boolean[].class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void allowsIntListNullDeserialization() {
-        String jsonStr = "{ \"type\": \"[I\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(int[].class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void allowsLongListNullDeserialization() {
-        String jsonStr = "{ \"type\": \"[J\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(long[].class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void allowsDoubleListNullDeserialization() {
-        String jsonStr = "{ \"type\": \"[D\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(double[].class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void allowsStringNullDeserialization() {
-        String jsonStr = "{ \"type\": \"java.lang.String\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(String.class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void allowsStringListNullDeserialization() {
-        String jsonStr = "{ \"type\": \"[Ljava.lang.String;\" , \"value\": null}";
-        PreparedParameter p = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(String[].class, p.getType());
-        assertEquals(null, p.getValue());
-    }
-    
-    @Test
-    public void rejectNullForBooleanPrimitive() {
-        String jsonStr = "{ \"type\": \"boolean\" , \"value\": null}";
-        doPrimitiveNullTest(jsonStr, "boolean");
-    }
-    
-    @Test
-    public void rejectNullForIntPrimitive() {
-        String jsonStr = "{ \"type\": \"int\" , \"value\": null}";
-        doPrimitiveNullTest(jsonStr, "int");
-    }
-    
-    @Test
-    public void rejectNullForDoublePrimitive() {
-        String jsonStr = "{ \"type\": \"double\" , \"value\": null}";
-        doPrimitiveNullTest(jsonStr, "double");
-    }
-    
-    @Test
-    public void rejectNullForLongPrimitive() {
-        String jsonStr = "{ \"type\": \"long\" , \"value\": null}";
-        doPrimitiveNullTest(jsonStr, "long");
-    }
-    
-    private void doPrimitiveNullTest(String jsonStr, String typeName) {
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            // The Java language spec does not permit this
-            fail(typeName + " null primitive should not deserialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertEquals(typeName + " primitive does not accept a null value!", cause.getMessage());
-        }
-    }
-    
-    @Test
-    public void failsDeserializationWrongTypeClass() {
-        String jsonStr = "{ \"type\": \"java.io.File\" , \"value\": true}";
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            fail("should have failed to serialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertTrue(cause.getMessage().contains("Illegal type of parameter"));
-        }
-    }
-    
-    @Test
-    public void failsDeserializationIfStringForInt() {
-        String jsonStr = "{ \"type\": \"int\" , \"value\":\"testing\"}";
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            fail("should have failed to serialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertTrue(cause instanceof NumberFormatException);
-        }
-    }
-    
-    @Test
-    public void failsDeserializationIfBooleanForInt() {
-        String jsonStr = "{ \"type\": \"int\" , \"value\": true}";
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            fail("should have failed to serialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertTrue(cause instanceof IllegalStateException);
-        }
-    }
-    
-    @Test
-    public void failsDeserializationIfIntForIntList() {
-        String jsonStr = "{ \"type\": \"[I\" , \"value\": -1}";
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            fail("should have failed to serialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertTrue(cause instanceof IllegalStateException);
-        }
-    }
-    
-    @Test
-    public void failsDeserializationIfDoubleForInt() {
-        String jsonStr = "{ \"type\": \"int\" , \"value\": -1.3}";
-        try {
-            gson.fromJson(jsonStr, PreparedParameter.class);
-            fail("should have failed to serialize");
-        } catch (Exception e) {
-            // pass
-            Throwable cause = e.getCause();
-            assertTrue(cause instanceof NumberFormatException);
-        }
-    }
-    
-    @Test
-    public void canSerializeBasic() {
-        // String
-        String expected = "{\"type\":\"java.lang.String\",\"value\":\"testing\"}";
-        PreparedParameter param = new PreparedParameter();
-        param.setType(String.class);
-        param.setValue("testing");
-        String actual = gson.toJson(param);
-        assertEquals(expected, actual);
-        // Integer
-        expected = "{\"type\":\"int\",\"value\":-1}";
-        param.setType(int.class);
-        param.setValue(-1);
-        actual = gson.toJson(param);
-        assertEquals(expected, actual);
-        // Long
-        expected = "{\"type\":\"long\",\"value\":30000000003}";
-        param.setType(long.class);
-        param.setValue(30000000003L);
-        actual = gson.toJson(param);
-        assertEquals(expected, actual);
-        // boolean
-        expected = "{\"type\":\"boolean\",\"value\":true}";
-        param.setType(boolean.class);
-        param.setValue(true);
-        actual = gson.toJson(param);
-        assertEquals(expected, actual);
-        // String[]
-        String strArrayVal = "[\"testing1\",\"testing2\",\"3\"]";
-        expected = "{\"type\":\"[Ljava.lang.String;\",\"value\":" + strArrayVal + "}";
-        param.setType(String[].class);
-        String[] array = new String[] {
-                "testing1", "testing2", "3"
-        };
-        param.setValue(array);
-        actual = gson.toJson(param);
-        assertEquals(expected, actual);
-    }
-    
-    @Test
-    public void canSerializeDeserializeInteger() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(int.class);
-        expected.setValue(3);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeIntegerArray() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(int[].class);
-        expected.setValue(new int[] { 0, 3, 20 });
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeDouble() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(double.class);
-        expected.setValue(Math.E);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeDoubleArray() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(double[].class);
-        expected.setValue(new double[] { 3.3, 1.0, Math.PI });
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeLong() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(long.class);
-        expected.setValue(30000000003L);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeLongArray() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(long[].class);
-        expected.setValue(new long[] { 3000000000L, 3, 20 });
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeString() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(String.class);
-        expected.setValue("testing");
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeStringArray() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(String[].class);
-        String[] expectedArray = new String[] {
-                "one", "two", "three"      
-        };
-        expected.setValue(expectedArray);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeBoolean() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(boolean.class);
-        expected.setValue(false);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-        
-        expected = new PreparedParameter();
-        expected.setType(boolean.class);
-        expected.setValue(true);
-        jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeBooleanArray() {
-        PreparedParameter expected = new PreparedParameter();
-        expected.setType(boolean[].class);
-        expected.setValue(new boolean[] { true, false, false, true });
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    
-    @Test
-    public void canSerializeDeserializePojos() {
-        PreparedParameter expected = new PreparedParameter();
-        AgentInformation info = new AgentInformation("foo-writer");
-        expected.setType(info.getClass());
-        expected.setValue(info);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-        
-        info = new AgentInformation("some-writer");
-        info.setAlive(true);
-        info.setConfigListenAddress("127.0.0.1:12000");
-        info.setStartTime(System.currentTimeMillis());
-        info.setStopTime(System.currentTimeMillis());
-        expected = new PreparedParameter();
-        expected.setType(info.getClass());
-        expected.setValue(info);
-        jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-        
-        // null pojo
-        expected = new PreparedParameter();
-        expected.setType(AgentInformation.class);
-        expected.setValue(null);
-        jsonStr = gson.toJson(expected, PreparedParameter.class);
-        assertParameterEquals(expected, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeDeserializeInnerClassPojoTypes() {
-        PreparedParameter expected = new PreparedParameter();
-        KeyValuePair pair = new KeyValuePair();
-        pair.setKey("foo");
-        pair.setValue("bar");
-        expected.setType(pair.getClass());
-        expected.setValue(pair);
-        String jsonStr = gson.toJson(expected, PreparedParameter.class);
-        
-        PreparedParameter actual = gson.fromJson(jsonStr, PreparedParameter.class);
-        
-        assertEquals(expected.getType(), actual.getType());
-        assertTrue(actual.getValue() instanceof KeyValuePair);
-        KeyValuePair actualPair = (KeyValuePair)actual.getValue();
-        assertEquals(pair.getKey(), actualPair.getKey());
-        assertEquals(pair.getValue(), actualPair.getValue());
-    }
-    
-    @Test
-    public void canSerializeDeserializePojoLists() {
-        AgentInformation info1 = new AgentInformation("foo-writer");
-        AgentInformation info2 = new AgentInformation("some-writer");
-        info2.setAlive(true);
-        info2.setConfigListenAddress("127.0.0.1:12000");
-        info2.setStartTime(System.currentTimeMillis());
-        info2.setStopTime(System.currentTimeMillis());
-        AgentInformation[] infos = new AgentInformation[] {
-                info1, info2
-        };
-        PreparedParameter param = new PreparedParameter();
-        param.setType(AgentInformation.class);
-        param.setValue(infos);
-        String jsonStr = gson.toJson(param, PreparedParameter.class);
-        assertParameterEquals(param, jsonStr);
-    }
-    
-    private void assertParameterEquals(PreparedParameter expected,
-            String jsonStr) {
-        PreparedParameter actual = gson.fromJson(jsonStr, PreparedParameter.class);
-        assertEquals(expected.getType(), actual.getType());
-        if (actual.getValue() != null && actual.getValue().getClass().isArray()) {
-            // compare element by element
-            Object values = actual.getValue();
-            Object expectedVals = expected.getValue();
-            int expectedLength = Array.getLength(expectedVals);
-            int actualLength = Array.getLength(values);
-            assertEquals(expectedLength, actualLength);
-            // Make sure the deserialized array is of the correct expected type
-            assertEquals(expectedVals.getClass(), values.getClass());
-            for (int i = 0; i < expectedLength; i++) {
-                Object exp = Array.get(expectedVals, i);
-                Object act = Array.get(values, i);
-                assertEquals(exp, act);
-            }
-        } else {
-            assertEquals(expected.getValue(), actual.getValue());
-        }
-    }
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersJSONPerformanceTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import org.junit.experimental.categories.Category;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.testutils.PerformanceTest;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParameterTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.PreparedParametersTypeAdapterFactory;
-
-/**
- * JUnit categorized performance test. It'll be only run for
- * the perf-tests profile.
- */
-@Category(PerformanceTest.class)
-public class PreparedParametersJSONPerformanceTest extends
-        JsonPerformanceTest<PreparedParameters> {
-    
-    private static final String OLD_JSON_FORMAT = "{\"params\":[]}";
-    private static final String NEW_JSON_FORMAT = "[]";
-    private static final boolean DEBUG = true;
-
-    public PreparedParametersJSONPerformanceTest() {
-        super(DEBUG, PreparedParametersJSONPerformanceTest.class.getSimpleName());
-    }
-
-    @Override
-    protected Gson getSlowGson() {
-        return new GsonBuilder()
-                     .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                     .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                     .create();
-    }
-
-    @Override
-    protected Gson getFasterGson() {
-        return new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new PreparedParametersTypeAdapterFactory())
-                    .create();
-    }
-
-    @Override
-    protected double getExpectedSpeedup(OperationType type,
-            int iterations) {
-        if (type == OperationType.SERIALIZATION && iterations == getColdSerializationIterations()) {
-            return 2;
-        } else if (type == OperationType.SERIALIZATION && iterations == getWarmSerializationIterations()) {
-            // actual should really be approaching 1.2.
-            return 0.95;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getColdDeserializationIterations()) {
-            return 1.5;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getWarmDeserializationIterations()) {
-            return 0.95;
-        } else {
-            throw new IllegalStateException("bug");
-        }
-    }
-
-    @Override
-    protected TypeToken<PreparedParameters> getDeserializeTypeToken() {
-        return TypeToken.get(PreparedParameters.class);
-    }
-
-    @Override
-    protected int getColdSerializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmSerializationIterations() {
-        return 10000;
-    }
-
-    @Override
-    protected int getColdDeserializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmDeserializationIterations() {
-        return 10000;
-    }
-
-    @Override
-    protected double getSelfSerializationDelta() {
-        return 0.3;
-    }
-
-    @Override
-    protected double getSelfDeserializationDelta() {
-        return 0.3;
-    }
-
-    @Override
-    protected String mutateJsonString(GsonContext context, int mutator) {
-        if (context == GsonContext.FASTER) {
-            return NEW_JSON_FORMAT;
-        } else if (context == GsonContext.SLOW) {
-            return OLD_JSON_FORMAT;
-        } else {
-            throw new IllegalStateException("bug");
-        }
-    }
-
-    @Override
-    protected PreparedParameters mutateToBeSerializedInstance(int mutator) {
-        return new PreparedParameters(0);
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/PreparedParametersTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class PreparedParametersTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new PreparedParametersTypeAdapterFactory())
-                    .create();
-    }
-    
-    @Test
-    public void canSerializeDeserializeBasic() {
-        PreparedParameters params = new PreparedParameters(5);
-        params.setBoolean(0, true);
-        params.setInt(1, 2300);
-        params.setLong(2, 2200000000L);
-        params.setString(3, "testing");
-        String[] list = new String[] {
-          "a", "b", "c"      
-        };
-        params.setStringList(4, list);
-        
-        String jsonStr = gson.toJson(params, PreparedParameters.class);
-        PreparedParameters actualParams = gson.fromJson(jsonStr, PreparedParameters.class);
-        
-        PreparedParameter[] expected = params.getParams();
-        PreparedParameter[] actual = actualParams.getParams();
-        
-        // last element is the string array, which we check manually
-        for (int i = 0; i < expected.length - 1; i++) {
-            assertEquals(expected[i].getType(), actual[i].getType());
-            assertEquals(expected[i].getValue(), actual[i].getValue());
-        }
-        String actualList[] = (String[])actual[4].getValue();
-        for (int i = 0; i < list.length; i++) {
-            assertEquals(list[i], actualList[i]);
-        }
-    }
-    
-    @Test
-    public void canSerializeDeserializeMixedTypesWithPojoList() {
-        AgentInformation info1 = new AgentInformation("foo-agent");
-        info1.setAlive(true);
-        AgentInformation info2 = new AgentInformation("foo-agent");
-        info2.setAlive(false);
-        info2.setStartTime(System.currentTimeMillis());
-        info2.setStopTime(System.currentTimeMillis());
-        info2.setConfigListenAddress("127.0.0.1:12000");
-        AgentInformation[] infos = new AgentInformation[] {
-                info1, info2
-        };
-        long[] longs = new long[] { 3000000000L, -3, 300 };
-        // String, long[], Pojo[]
-        PreparedParameters params = new PreparedParameters(3);
-        params.setString(0, "foo-param");
-        params.setLongList(1, longs);
-        params.setPojoList(2, infos);
-        
-        String jsonStr = gson.toJson(params, PreparedParameters.class);
-        PreparedParameters actualParams = gson.fromJson(jsonStr, PreparedParameters.class);
-        
-        PreparedParameter[] expected = params.getParams();
-        PreparedParameter[] actual = actualParams.getParams();
-        
-        assertEquals(expected.length, actual.length);
-        
-        PreparedParameter param1 = actual[0];
-        assertEquals("foo-param", param1.getValue());
-        assertEquals(String.class, param1.getType());
-        
-        PreparedParameter param2 = actual[1];
-        assertEquals(long[].class, param2.getType());
-        long[] twoActuals = (long[])param2.getValue();
-        assertEquals(3, twoActuals.length);
-        assertEquals(3000000000L, (long)twoActuals[0]);
-        assertEquals(-3, (long)twoActuals[1]);
-        assertEquals(300, (long)twoActuals[2]);
-        
-        PreparedParameter param3 = actual[2];
-        assertEquals(AgentInformation.class, param3.getType());
-        assertTrue(param3.getValue().getClass().isArray());
-        Pojo[] pojos = (Pojo[])param3.getValue();
-        assertEquals(2, pojos.length);
-        for (int i = 0; i < pojos.length; i++) {
-            assertEquals(infos[i], pojos[i]);
-        }
-    }
-    
-    
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/SharedStateIdTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.web.common.SharedStateId;
-
-public class SharedStateIdTypeAdapterTest {
-
-private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                    .registerTypeAdapter(SharedStateId.class, new SharedStateIdTypeAdapter())
-                    .create();
-    }
-    
-    @Test
-    public void canSerializeBasic() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(3, uuid);
-        String gsonStr = gson.toJson(id);
-        String expectedJSON = "{\"sid\":3,\"stok\":\"" + uuid.toString() + "\"}";
-        assertEquals(expectedJSON, gsonStr);
-    }
-    
-    @Test
-    public void canSerializeNull() {
-        SharedStateId id = new SharedStateId(3000, null);
-        String gsonStr = gson.toJson(id);
-        String expectedJSON = "{\"sid\":3000}";
-        assertEquals(expectedJSON, gsonStr);
-    }
-    
-    @Test
-    public void canDeserializeBasic() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(3, uuid);
-        String json = "{\"sid\":3,\"stok\":\"" + uuid.toString() + "\"}";
-        SharedStateId deserialized = gson.fromJson(json, SharedStateId.class);
-        assertEquals(3, deserialized.getId());
-        assertEquals(uuid, deserialized.getServerToken());
-        assertEquals(id, deserialized);
-    }
-    
-    /**
-     * UUID string value might be null. Make sure deserialization works for
-     * those.
-     */
-    @Test
-    public void canDeserializeNullServerNonce() {
-        String json = "{\"sid\":3}";
-        SharedStateId deserialized = gson.fromJson(json, SharedStateId.class);
-        assertEquals(3, deserialized.getId());
-        assertNull(deserialized.getServerToken());
-    }
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementJSONPerformanceTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.util.UUID;
-
-import org.junit.experimental.categories.Category;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.testutils.PerformanceTest;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.typeadapters.PojoTypeAdapterFactory;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementTypeAdapterFactory;
-
-/**
- * JUnit categorized performance test. It'll be only run for
- * the perf-tests profile during a full build.
- */
-@Category(PerformanceTest.class)
-@SuppressWarnings("rawtypes")
-public class WebPreparedStatementJSONPerformanceTest extends
-        JsonPerformanceTest<WebPreparedStatement> {
-
-    private static final boolean DEBUG = true;
-    
-    public WebPreparedStatementJSONPerformanceTest() {
-        super(DEBUG, WebPreparedStatementJSONPerformanceTest.class.getSimpleName());
-    }
-    
-    @Override
-    protected Gson getSlowGson() {
-        return new GsonBuilder()
-                    .registerTypeHierarchyAdapter(Pojo.class, new LegacyGSONConverter())
-                    .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                    .registerTypeAdapter(WebPreparedStatement.class, new LegacyWebPreparedStatementSerializer())
-                    .create();
-    }
-
-    @Override
-    protected Gson getFasterGson() {
-        return new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                    .create();
-    }
-
-    @Override
-    protected double getExpectedSpeedup(OperationType type, int iterations) {
-        if (type == OperationType.SERIALIZATION && iterations == getColdSerializationIterations()) {
-            return 0.95;
-        } else if (type == OperationType.SERIALIZATION && iterations == getWarmSerializationIterations()) {
-            return 1.5;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getColdDeserializationIterations()) {
-            return 0.95;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getWarmDeserializationIterations()) {
-            return 2;
-        } else {
-            throw new IllegalStateException("Bug");
-        }
-    }
-
-    @Override
-    protected String mutateJsonString(GsonContext ctx, int mutator) {
-        return String.format("{\"sid\":{\"sid\":%d,\"stok\":\"" + UUID.randomUUID() + "\"},\"p\":{\"params\":[]}}", mutator);
-    }
-
-    @Override
-    protected WebPreparedStatement mutateToBeSerializedInstance(int mutator) {
-        SharedStateId id = new SharedStateId(mutator, UUID.randomUUID());
-        WebPreparedStatement retval = new WebPreparedStatement<>(0, id);
-        return retval;
-    }
-
-    @Override
-    protected TypeToken<WebPreparedStatement> getDeserializeTypeToken() {
-        return TypeToken.get(WebPreparedStatement.class);
-    }
-
-    @Override
-    protected int getColdSerializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmSerializationIterations() {
-        return 10000;
-    }
-
-    @Override
-    protected int getColdDeserializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmDeserializationIterations() {
-        return 10000;
-    }
-
-    @Override
-    protected double getSelfSerializationDelta() {
-        return 0.4;
-    }
-
-    @Override
-    protected double getSelfDeserializationDelta() {
-        return 0.1;
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseJSONPerformanceTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import java.util.UUID;
-
-import org.junit.experimental.categories.Category;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.testutils.PerformanceTest;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-import com.redhat.thermostat.web.common.typeadapters.WebPreparedStatementResponseTypeAdapterFactory;
-
-/**
- * JUnit categorized performance test. It'll be only run for
- * the perf-tests profile during a full build.
- */
-@Category(PerformanceTest.class)
-public class WebPreparedStatementResponseJSONPerformanceTest extends
-        JsonPerformanceTest<WebPreparedStatementResponse> {
-
-    // Set to true in order to turn on debugging output
-    private static final boolean DEBUG = true;
-    
-    public WebPreparedStatementResponseJSONPerformanceTest() {
-        super(DEBUG, WebPreparedStatementResponseJSONPerformanceTest.class.getSimpleName()); 
-    }
-    
-    @Override
-    protected Gson getSlowGson() {
-        return new GsonBuilder()
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .create();
-    }
-
-    @Override
-    protected Gson getFasterGson() {
-        return new GsonBuilder()
-                    .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                    .create();
-    }
-
-    @Override
-    protected double getExpectedSpeedup(OperationType type, int iterations) {
-        if (type == OperationType.DESERIALIZATION && iterations == getColdDeserializationIterations()) {
-            return 4;
-        } else if (type == OperationType.DESERIALIZATION && iterations == getWarmDeserializationIterations()) {
-            // Actual speed-up of the warmed up scenario is roughly
-            // >= 1.0. However, there are cases where it falls below it.
-            // A lower bound of 0.95 should be adequate in order for tests to
-            // not fail spuriously (at least not as often).
-            return 0.95;
-        } else if (type == OperationType.SERIALIZATION && iterations == getColdSerializationIterations()) {
-            return 4;
-        } else if (type == OperationType.SERIALIZATION && iterations == getWarmSerializationIterations()) {
-            return 1.2;
-        } else {
-            throw new IllegalStateException("Bug!");
-        }
-    }
-
-    @Override
-    protected String mutateJsonString(GsonContext ctx, int mutator) {
-        int stmtId = (mutator + 1) * 20;
-        int numFreeVars = mutator;
-        return String.format("{\"numFreeVars\":%d,\"stmtId\":{\"sid\":%d,\"stok\":\"%s\"}}", numFreeVars, stmtId, UUID.randomUUID().toString());
-    }
-
-    @Override
-    protected WebPreparedStatementResponse mutateToBeSerializedInstance(int mutator) {
-        WebPreparedStatementResponse response = new WebPreparedStatementResponse();
-        response.setNumFreeVariables(3);
-        SharedStateId id = new SharedStateId(mutator, UUID.randomUUID());
-        response.setStatementId(id);
-        return response;
-    }
-
-    @Override
-    protected TypeToken<WebPreparedStatementResponse> getDeserializeTypeToken() {
-        return TypeToken.get(WebPreparedStatementResponse.class);
-    }
-
-    @Override
-    protected int getColdSerializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmSerializationIterations() {
-        return 10000;
-    }
-
-    @Override
-    protected int getColdDeserializationIterations() {
-        return 1;
-    }
-
-    @Override
-    protected int getWarmDeserializationIterations() {
-        return 2000;
-    }
-
-    @Override
-    protected double getSelfSerializationDelta() {
-        return 0.1;
-    }
-
-    @Override
-    protected double getSelfDeserializationDelta() {
-        return 0;
-    }
-
-}
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementResponseTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonSyntaxException;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-
-public class WebPreparedStatementResponseTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new WebPreparedStatementResponseTypeAdapterFactory())
-                .create();
-    }
-    
-    @Test
-    public void testSerializationDeserializationBasic() {
-        WebPreparedStatementResponse response = new WebPreparedStatementResponse();
-        response.setNumFreeVariables(6);
-        
-        UUID uuid = UUID.randomUUID();
-        SharedStateId stmtId = new SharedStateId(WebPreparedStatementResponse.ILLEGAL_STATEMENT, uuid);
-        response.setStatementId(stmtId);
-        
-        String jsonStr = gson.toJson(response, WebPreparedStatementResponse.class);
-        String expectedString = "{\"numFreeVars\":6,\"stmtId\":{\"sid\":-1,\"stok\":\""+ uuid.toString() + "\"}}";
-        assertEquals(expectedString, jsonStr);
-        
-        WebPreparedStatementResponse actual = gson.fromJson(jsonStr, WebPreparedStatementResponse.class);
-        
-        assertEquals(6, actual.getNumFreeVariables());
-        assertEquals(stmtId, actual.getStatementId());
-    }
-    
-    public void deserializeNull() {
-        String jsonString = "{\"numFreeVars\":11}";
-        WebPreparedStatementResponse resp = gson.fromJson(jsonString, WebPreparedStatementResponse.class);
-        assertNull(resp.getStatementId());
-        assertEquals(11, resp.getNumFreeVariables());
-    }
-    
-    @Test
-    public void canDeserializeBasic() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId stmtId = new SharedStateId(6, uuid);
-        String jsonString = "{\"numFreeVars\":11,\"stmtId\":{\"sid\":6,\"stok\":\""+ uuid.toString() + "\"}}";
-        WebPreparedStatementResponse actual = gson.fromJson(jsonString, WebPreparedStatementResponse.class);
-        assertEquals(stmtId, actual.getStatementId());
-        assertEquals(11, actual.getNumFreeVariables());
-    }
-    
-    @Test(expected=JsonSyntaxException.class)
-    public void testDeserializationFail() {
-        String invalidString = "{\"forbar\":6,\"stmtId\":-1}";
-        gson.fromJson(invalidString, WebPreparedStatementResponse.class);
-    }
-    
-    @Test
-    public void canSerializeDeserializeNull() {
-        WebPreparedStatementResponse response = null;
-        assertNull(response);
-        String json = gson.toJson(response, WebPreparedStatementResponse.class);
-        assertEquals("null", json);
-        WebPreparedStatementResponse actual = gson.fromJson(json, WebPreparedStatementResponse.class);
-        assertNull(actual);
-    }
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebPreparedStatementTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.UUID;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.redhat.thermostat.storage.core.PreparedParameter;
-import com.redhat.thermostat.storage.core.PreparedParameters;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.web.common.SharedStateId;
-import com.redhat.thermostat.web.common.WebPreparedStatement;
-import com.redhat.thermostat.web.common.WebPreparedStatementResponse;
-
-public class WebPreparedStatementTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                .registerTypeAdapterFactory(new WebPreparedStatementTypeAdapterFactory())
-                .registerTypeAdapterFactory(new SharedStateIdTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PreparedParameterTypeAdapterFactory())
-                .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                .create();
-    }
-    
-    @Test
-    public void canSerializeNullParams() {
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>();
-        UUID uuid = UUID.randomUUID();
-        stmt.setStatementId(new SharedStateId(500, uuid));
-        stmt.setParams(null);
-        
-        String expected = "{\"sid\":{\"sid\":500,\"stok\":\"" + uuid.toString() + "\"}}";
-        
-        String actual = gson.toJson(stmt);
-        assertEquals(expected, actual);
-    }
-    
-    @Test
-    public void canDeserializeNullParams() {
-        UUID uuid = UUID.randomUUID();
-        String json = "{\"sid\":{\"sid\":500,\"stok\":\"" + uuid.toString() + "\"}}";
-        
-        WebPreparedStatement<?> stmt = gson.fromJson(json, WebPreparedStatement.class);
-        assertEquals(new SharedStateId(500, uuid), stmt.getStatementId());
-        assertNull(stmt.getParams());
-    }
-    
-    @Test
-    public void canSerializeEmptyParams() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(555, uuid);
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>(0, id);
-        
-        String expected = "{\"sid\":{\"sid\":555,\"stok\":\"" + uuid.toString() + "\"},\"p\":{\"params\":[]}}";
-        String actual = gson.toJson(stmt);
-        assertEquals(expected, actual);
-    }
-    
-    @Test
-    public void canDeserializeEmptyParams() {
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(555, uuid);
-        String json = "{\"sid\":{\"sid\":555,\"stok\":\"" + uuid.toString() + "\"},\"p\":{\"params\":[]}}";
-        
-        WebPreparedStatement<?> stmt = gson.fromJson(json, WebPreparedStatement.class);
-        assertEquals(id, stmt.getStatementId());
-        assertNotNull(stmt.getParams());
-        assertEquals(0, stmt.getParams().getParams().length);
-    }
-    
-    @Test
-    public void canSerializeAndDeserialize() {
-        PreparedParameters params = new PreparedParameters(5);
-        params.setInt(0, 2);
-        params.setString(1, "testing");
-        params.setLong(2, 222L);
-        params.setStringList(3, new String[] { "one", "two" });
-        params.setBoolean(4, true);
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>();
-        stmt.setParams(params);
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(WebPreparedStatementResponse.DESCRIPTOR_PARSE_FAILED, uuid);
-        stmt.setStatementId(id);
-        String jsonString = gson.toJson(stmt, WebPreparedStatement.class);
-        WebPreparedStatement<?> newStmt = gson.fromJson(jsonString, WebPreparedStatement.class);
-        assertNotNull(newStmt);
-        PreparedParameters newParams = newStmt.getParams();
-        PreparedParameter[] parameters = newParams.getParams();
-        assertEquals(5, parameters.length);
-        assertEquals(2, parameters[0].getValue());
-        assertEquals(int.class, parameters[0].getType());
-        assertEquals("testing", parameters[1].getValue());
-        assertEquals(String.class, parameters[1].getType());
-        assertEquals(222L, parameters[2].getValue());
-        assertEquals(long.class, parameters[2].getType());
-        String[] list = (String[])parameters[3].getValue();
-        assertEquals(2, list.length);
-        assertEquals("one", list[0]);
-        assertEquals("two", list[1]);
-        assertEquals(String[].class, parameters[3].getType());
-        assertEquals(true, parameters[4].getValue());
-        assertEquals(boolean.class, parameters[4].getType());
-        assertEquals(id, newStmt.getStatementId());
-    }
-    
-    /*
-     * Writes need Pojo support for serialization. This is a basic test we do
-     * get Pojos across the wire in a prepared context. 
-     */
-    @Test
-    public void canSerializeDeserializePojoParameters() {
-        PreparedParameters params = new PreparedParameters(2);
-        params.setIntList(0, new int[] { 0, 300 });
-        AgentInformation pojo1 = new AgentInformation("foo-agent");
-        AgentInformation pojo2 = new AgentInformation("foo-agent");
-        pojo2.setAlive(true);
-        pojo2.setConfigListenAddress("127.0.0.1:38822");
-        params.setPojoList(1, new AgentInformation[] { pojo1, pojo2 });
-        
-        WebPreparedStatement<?> stmt = new WebPreparedStatement<>();
-        stmt.setParams(params);
-        UUID uuid = UUID.randomUUID();
-        SharedStateId id = new SharedStateId(WebPreparedStatementResponse.DESCRIPTOR_PARSE_FAILED, uuid);
-        stmt.setStatementId(id);
-        
-        String jsonString = gson.toJson(stmt, WebPreparedStatement.class);
-        assertNotNull(jsonString);
-        
-        WebPreparedStatement<?> result = gson.fromJson(jsonString, WebPreparedStatement.class);
-        assertEquals(id, result.getStatementId());
-        assertNotNull(result.getParams());
-    }
-}
-
--- a/web/common/src/test/java/com/redhat/thermostat/web/common/typeadapters/WebQueryResponseTypeAdapterTest.java	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * 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.web.common.typeadapters;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.lang.reflect.Type;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.reflect.TypeToken;
-import com.redhat.thermostat.storage.model.AgentInformation;
-import com.redhat.thermostat.web.common.PreparedStatementResponseCode;
-import com.redhat.thermostat.web.common.WebQueryResponse;
-
-public class WebQueryResponseTypeAdapterTest {
-
-    private Gson gson;
-    
-    @Before
-    public void setup() {
-        gson = new GsonBuilder()
-                    .registerTypeAdapterFactory(new PojoTypeAdapterFactory())
-                    .registerTypeAdapterFactory(new WebQueryResponseTypeAdapterFactory())
-                    .create();
-    }
-    
-    @Test
-    public void canSerializeBasic() {
-        // Our test pojo
-        AgentInformation agentInfo = new AgentInformation("testing");
-        agentInfo.setAlive(false);
-        AgentInformation[] resultList = new AgentInformation[] {
-                agentInfo
-        };
-        
-        // create the query response
-        WebQueryResponse<AgentInformation> response = new WebQueryResponse<>();
-        response.setResultList(resultList);
-        response.setCursorId(300);
-        response.setResponseCode(PreparedStatementResponseCode.ILLEGAL_PATCH);
-        
-        String jsonStr = gson.toJson(response);
-        String expectedJson = "{\"errno\":-1,\"cId\":300,\"cHasMore\":false,\"payload\":[{\"agentId\":\"testing\",\"alive\":false,\"startTime\":0,\"stopTime\":0}]}";
-        assertEquals(expectedJson, jsonStr);
-    }
-    
-    @Test
-    public void canSerializeNoResultList() {
-        // create the query response
-        WebQueryResponse<AgentInformation> response = new WebQueryResponse<>();
-        response.setResultList(null); // should be left out from serialization
-        response.setCursorId(-0xdeadbeef);
-        response.setResponseCode(PreparedStatementResponseCode.ILLEGAL_PATCH);
-        
-        String jsonStr = gson.toJson(response);
-        String expectedJson = "{\"errno\":-1,\"cId\":559038737,\"cHasMore\":false}";
-        assertEquals(expectedJson, jsonStr);
-    }
-    
-    @Test
-    public void canDeserializeNoResultList() {
-        String rawJson = "{\"errno\":-1,\"cId\":444,\"cHasMore\":true}";
-        Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-        WebQueryResponse<AgentInformation> actual = gson.fromJson(rawJson, queryResponseType);
-        assertEquals(true, actual.hasMoreBatches());
-        assertEquals(444, actual.getCursorId());
-        
-        assertNull(actual.getResultList());
-        
-        assertEquals(PreparedStatementResponseCode.ILLEGAL_PATCH, actual.getResponseCode());
-    }
-    
-    @Test
-    public void canDeserializeBasic() {
-        String rawJson = "{\"errno\":-1,\"cId\":444,\"cHasMore\":true,\"payload\":[{\"startTime\":0,\"stopTime\":0,\"alive\":true,\"agentId\":\"testing\"}]}";
-        Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-        WebQueryResponse<AgentInformation> actual = gson.fromJson(rawJson, queryResponseType);
-        assertEquals(true, actual.hasMoreBatches());
-        assertEquals(444, actual.getCursorId());
-        
-        AgentInformation[] actualList = actual.getResultList();
-        
-        assertEquals(PreparedStatementResponseCode.ILLEGAL_PATCH, actual.getResponseCode());
-        assertEquals(1, actualList.length);
-        AgentInformation actualInfo = actualList[0];
-        assertEquals(true, actualInfo.isAlive());
-        assertEquals("testing", actualInfo.getAgentId());
-    }
-    
-    @Test
-    public void canSerializeAndDeserializeBasic() {
-        // Our test pojo
-        AgentInformation agentInfo = new AgentInformation("testing");
-        agentInfo.setAlive(false);
-        AgentInformation[] resultList = new AgentInformation[] {
-                agentInfo
-        };
-        
-        // create the query response
-        WebQueryResponse<AgentInformation> response = new WebQueryResponse<>();
-        response.setResultList(resultList);
-        response.setResponseCode(PreparedStatementResponseCode.ILLEGAL_PATCH);
-        
-        String jsonStr = gson.toJson(response);
-
-        // We need to tell GSON which parametrized type we want it to deserialize
-        // it to.
-        Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-        WebQueryResponse<AgentInformation> actual = gson.fromJson(jsonStr, queryResponseType);
-        
-        AgentInformation[] actualList = actual.getResultList();
-        
-        assertEquals(PreparedStatementResponseCode.ILLEGAL_PATCH, actual.getResponseCode());
-        assertEquals(1, actualList.length);
-        AgentInformation actualInfo = actualList[0];
-        assertEquals(false, actualInfo.isAlive());
-        assertEquals("testing", actualInfo.getAgentId());
-    }
-    
-    @Test
-    public void canSerializeAndDeserializeVariousPojos() {
-        // Our test pojo
-        AgentInformation agentInfo = new AgentInformation("testing");
-        agentInfo.setAlive(false);
-        AgentInformation[] resultList = new AgentInformation[] {
-                agentInfo
-        };
-        
-        // create the query response
-        WebQueryResponse<AgentInformation> response = new WebQueryResponse<>();
-        response.setResultList(resultList);
-        response.setResponseCode(PreparedStatementResponseCode.ILLEGAL_PATCH);
-        
-        String jsonStr = gson.toJson(response);
-        String expectedJson = "{\"errno\":-1,\"cId\":0,\"cHasMore\":false,\"payload\":[{\"agentId\":\"testing\",\"alive\":false,\"startTime\":0,\"stopTime\":0}]}";
-        assertEquals(expectedJson, jsonStr);
-
-        // We need to tell GSON which parametrized type we want it to deserialize
-        // it to.
-        Type queryResponseType = new TypeToken<WebQueryResponse<AgentInformation>>() {}.getType();
-        WebQueryResponse<AgentInformation> actual = gson.fromJson(jsonStr, queryResponseType);
-        
-        AgentInformation[] actualList = actual.getResultList();
-        
-        assertEquals(PreparedStatementResponseCode.ILLEGAL_PATCH, actual.getResponseCode());
-        assertEquals(1, actualList.length);
-        AgentInformation actualInfo = actualList[0];
-        assertEquals(false, actualInfo.isAlive());
-        assertEquals("testing", actualInfo.getAgentId());
-    }
-}
-
--- a/web/pom.xml	Wed May 10 16:01:45 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<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</artifactId>
-    <version>1.99.12-SNAPSHOT</version>
-  </parent>
-
-  <artifactId>thermostat-web</artifactId>
-  <packaging>pom</packaging>
-
-  <name>Thermostat Web</name>
-
-  <modules>
-    <module>common</module>
-    <module>client</module>
-  </modules>
-
-</project>
-