changeset 2644:13807543d358

Remove MongoDB storage implementation Reviewed-by: neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-May/022999.html
author Elliott Baron <ebaron@redhat.com>
date Wed, 10 May 2017 16:01:45 -0400
parents 26cec0f14ad6
children d58c740a1a0b
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 pom.xml storage/mongo/pom.xml storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/MongoStorageProvider.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/Activator.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/DoubleArrayCodec.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/IntegerArrayCodec.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/LocaleResources.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnection.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoCursor.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoExpressionParser.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoPojoConverter.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoQuery.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/StringArrayCodec.java storage/mongo/src/main/resources/com/redhat/thermostat/storage/mongodb/strings.properties storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/DoubleArrayCodecTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/IntegerArrayCodecTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/LocaleResourcesTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnectionTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoCursorTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoExpressionParserTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoPojoConverterTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoQueryTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageProviderTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/StringArrayCodecTest.java storage/pom.xml
diffstat 32 files changed, 1 insertions(+), 4791 deletions(-) [+]
line wrap: on
line diff
--- a/distribution/assembly/core-assembly-macosx.xml	Wed May 10 15:59:23 2017 -0400
+++ b/distribution/assembly/core-assembly-macosx.xml	Wed May 10 16:01:45 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-storage-mongodb</include>
         <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
--- a/distribution/assembly/core-assembly-windows.xml	Wed May 10 15:59:23 2017 -0400
+++ b/distribution/assembly/core-assembly-windows.xml	Wed May 10 16:01:45 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-storage-mongodb</include>
         <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
--- a/distribution/assembly/core-assembly.xml	Wed May 10 15:59:23 2017 -0400
+++ b/distribution/assembly/core-assembly.xml	Wed May 10 16:01:45 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-storage-mongodb</include>
         <include>com.redhat.thermostat:thermostat-web-client</include>
         <include>com.redhat.thermostat:thermostat-system-backend</include>
         <include>org.osgi:org.osgi.compendium</include>
--- a/distribution/config/commands/agent.properties	Wed May 10 15:59:23 2017 -0400
+++ b/distribution/config/commands/agent.properties	Wed May 10 16:01:45 2017 -0400
@@ -2,7 +2,6 @@
           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.storage.mongodb=@project.version@, \
           com.redhat.thermostat.process=@project.version@ \
           @agent_extra_bundles@
 
@@ -25,4 +24,4 @@
 
 environments = cli
 
-command-groups=thermostat-core
\ No newline at end of file
+command-groups=thermostat-core
--- a/distribution/pom.xml	Wed May 10 15:59:23 2017 -0400
+++ b/distribution/pom.xml	Wed May 10 16:01:45 2017 -0400
@@ -491,11 +491,6 @@
         <artifactId>thermostat-system-backend</artifactId>
         <version>${project.version}</version>
     </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-storage-mongodb</artifactId>
-        <version>${project.version}</version>
-    </dependency>
 
     <!-- Plugins -->
 
--- a/pom.xml	Wed May 10 15:59:23 2017 -0400
+++ b/pom.xml	Wed May 10 16:01:45 2017 -0400
@@ -251,9 +251,6 @@
          used. -->
     <jcommon.version>1.0.17</jcommon.version>
     <jgraphx.version>2.3.0.5</jgraphx.version>
-    <mongo-driver.version>3.2.1</mongo-driver.version>
-    <!-- the OSGi Bundle-Version; should match the manifest in the jar -->
-    <mongo-driver.osgi-version>3.2.1</mongo-driver.osgi-version>
     <commons-beanutils.version>1.8.3</commons-beanutils.version>
     <commons-cli.version>1.2</commons-cli.version>
     <commons-io.version>2.4</commons-io.version>
@@ -650,11 +647,6 @@
         <version>${jgraphx.version}</version>
       </dependency>
       <dependency>
-        <groupId>org.mongodb</groupId>
-        <artifactId>mongo-java-driver</artifactId>
-        <version>${mongo-driver.version}</version>
-      </dependency>
-      <dependency>
         <groupId>commons-beanutils</groupId>
         <artifactId>commons-beanutils</artifactId>
         <version>${commons-beanutils.version}</version>
--- a/storage/mongo/pom.xml	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +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-storage</artifactId>
-    <version>1.99.12-SNAPSHOT</version>
-  </parent>
-  
-  <artifactId>thermostat-storage-mongodb</artifactId>
-  <packaging>bundle</packaging>
-
-  <name>Thermostat Storage Library for MongoDB</name>
-  <url>${project.parent.url}</url>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-SymbolicName>com.redhat.thermostat.storage.mongodb</Bundle-SymbolicName>
-            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
-            <Bundle-Activator>com.redhat.thermostat.storage.mongodb.internal.Activator</Bundle-Activator>
-            <Export-Package>
-              com.redhat.thermostat.storage.mongodb
-            </Export-Package>
-            <Private-Package>
-              com.redhat.thermostat.storage.mongodb.internal
-            </Private-Package>
-            <!-- Do not autogenerate uses clauses in Manifests -->
-            <_nouses>true</_nouses>
-          </instructions>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-  
-  <dependencies>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</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>org.apache.felix</groupId>
-      <artifactId>org.apache.felix.framework</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-beanutils</groupId>
-      <artifactId>commons-beanutils</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-collections</groupId>
-      <artifactId>commons-collections</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>commons-logging</groupId>
-      <artifactId>commons-logging</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.mongodb</groupId>
-      <artifactId>mongo-java-driver</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.powermock</groupId>
-      <artifactId>powermock-api-mockito</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.powermock</groupId>
-      <artifactId>powermock-module-junit4</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-    	<groupId>com.redhat.thermostat</groupId>
-    	<artifactId>thermostat-storage-core</artifactId>
-    	<version>${project.version}</version>
-    </dependency>
-    <dependency>
-        <groupId>com.redhat.thermostat</groupId>
-        <artifactId>thermostat-common-core</artifactId>
-        <version>${project.version}</version>
-    </dependency>
-    <!-- For the mongodb setup command -->
-    <dependency>
-      <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-launcher</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-  </dependencies>
-
-</project>
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/MongoStorageProvider.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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.storage.mongodb;
-
-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.QueuedStorage;
-import com.redhat.thermostat.storage.core.Storage;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.StorageProvider;
-import com.redhat.thermostat.storage.mongodb.internal.MongoStorage;
-
-public class MongoStorageProvider implements StorageProvider {
-
-    private String url;
-    private StorageCredentials creds;
-    private SSLConfiguration sslConf;
-
-    public void setConfig(String url, StorageCredentials creds, SSLConfiguration sslConf) {
-        this.url = url;
-        this.creds = creds;
-        this.sslConf = sslConf;
-    }
-
-    @Override
-    public Storage createStorage() {
-        MongoStorage storage = new MongoStorage(url, creds, sslConf);
-        if (LoggingUtils.getEffectiveLogLevel(LoggingUtils.getLogger(MongoStorageProvider.class)).intValue() <= LoggingUtils.LogLevel.PERFLOG.getLevel().intValue()) {
-            PerformanceLogFormatterBuilder builder = PerformanceLogFormatterBuilder.create();
-            PerformanceLogFormatter lf = builder.setLoggedTimeUnit(TimeUnit.NANOSECONDS)
-                                              .build();
-            return new QueuedStorage(storage, lf); 
-        }
-        return new QueuedStorage(storage);
-    }
-
-    @Override
-    public boolean canHandleProtocol() {
-        return url.startsWith("mongodb://");
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/Activator.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +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.storage.mongodb.internal;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-import com.redhat.thermostat.storage.core.StorageProvider;
-import com.redhat.thermostat.storage.mongodb.MongoStorageProvider;
-
-public class Activator implements BundleActivator {
-
-    @SuppressWarnings("rawtypes")
-    private ServiceRegistration reg;
-    
-    @Override
-    public void start(BundleContext context) throws Exception {
-        StorageProvider prov = new MongoStorageProvider();
-        reg = context.registerService(StorageProvider.class.getName(), prov, null);
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        reg.unregister();
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/DoubleArrayCodec.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +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.storage.mongodb.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bson.AbstractBsonReader;
-import org.bson.AbstractBsonReader.State;
-import org.bson.BsonReader;
-import org.bson.BsonType;
-import org.bson.BsonWriter;
-import org.bson.codecs.Codec;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.DoubleCodec;
-import org.bson.codecs.EncoderContext;
-
-public class DoubleArrayCodec implements Codec<double[]> {
-    
-    private final DoubleCodec primitiveCodec = new DoubleCodec();
-    
-    @Override
-    public void encode(BsonWriter writer, double[] value,
-            EncoderContext encoderContext) {
-        writer.writeStartArray();
-        for (double d: value) {
-            writer.writeDouble(d);
-        }
-        writer.writeEndArray();
-    }
-
-    @Override
-    public Class<double[]> getEncoderClass() {
-        return double[].class;
-    }
-
-    @Override
-    public double[] decode(BsonReader reader, DecoderContext decoderContext) {
-        if (reader.getCurrentBsonType() != BsonType.ARRAY) {
-            throw new IllegalStateException("Expected array type, was: " + reader.getCurrentBsonType());
-        }
-        reader.readStartArray();
-        List<Double> values = new ArrayList<>();
-        while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
-            double val = primitiveCodec.decode(reader, decoderContext);
-            values.add(val);
-        }
-        reader.readEndArray();
-        double[] result = new double[values.size()];
-        for (int i = 0; i < values.size(); i++) {
-            result[i] = values.get(i);
-        }
-        return result;
-    }
-
-}
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/IntegerArrayCodec.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bson.BsonReader;
-import org.bson.BsonType;
-import org.bson.BsonWriter;
-import org.bson.codecs.Codec;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.EncoderContext;
-import org.bson.codecs.IntegerCodec;
-
-public class IntegerArrayCodec implements Codec<int[]> {
-    
-    private final IntegerCodec primCodec = new IntegerCodec();
-
-    @Override
-    public void encode(BsonWriter writer, int[] value,
-            EncoderContext encoderContext) {
-        writer.writeStartArray();
-        for (int i: value) {
-            primCodec.encode(writer, i, encoderContext);
-        }
-        writer.writeEndArray();
-    }
-
-    @Override
-    public Class<int[]> getEncoderClass() {
-        return int[].class;
-    }
-
-    @Override
-    public int[] decode(BsonReader reader, DecoderContext decoderContext) {
-        reader.readStartArray();
-        List<Integer> values = new ArrayList<>();
-        while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
-            int val = primCodec.decode(reader, decoderContext);
-            values.add(val);
-        }
-        reader.readEndArray();
-        int[] result = new int[values.size()];
-        for (int i = 0; i < values.size(); i++) {
-            result[i] = values.get(i);
-        }
-        return result;
-    }
-
-}
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/LocaleResources.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +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.storage.mongodb.internal;
-
-import com.redhat.thermostat.shared.locale.Translate;
-
-
-public enum LocaleResources {
-    
-    COMMON_PATHS_SERVICE_UNAVAILABLE,
-    MONGODB_SETUP_FILE_EXISTS,
-    ALREADY_CONNECTED_TO_STORAGE_WARNING,
-    UNKNOWN_STORAGE_URL,
-    STORAGE_SERVICE_UNAVAILABLE,
-    MONGOSTORAGE_RETRIEVAL_FAILED,
-    STAMP_FILE_CREATION_FAILED,
-    MONGODB_USER_SETUP_COMPLETE,
-    LAUNCHER_SERVICE_UNAVAILABLE,
-    INTERRUPTED_WAITING_FOR_STORAGE_STOP,
-    STORAGE_STOP_FAILED,
-    USER_SETUP_COMPLETE,
-    USER_SETUP_FAILED,
-    UNRECOGNIZED_PAYLOAD_FROM_STORAGE_CMD,
-    ADDING_USER_FAILED,
-    INTERRUPTED_WAITING_FOR_ADD_USER,
-    DISPATCHER_WRONG_OPTION,
-    USERNAME_PROMPT,
-    PASSWORD_PROMPT
-    ;
-
-    static final String RESOURCE_BUNDLE = "com.redhat.thermostat.storage.mongodb.strings";
-
-    public static Translate<LocaleResources> createLocalizer() {
-        return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class);
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnection.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +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.storage.mongodb.internal;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSocketFactory;
-
-import org.bson.codecs.configuration.CodecRegistries;
-import org.bson.codecs.configuration.CodecRegistry;
-
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientOptions.Builder;
-import com.mongodb.MongoCredential;
-import com.mongodb.MongoException;
-import com.mongodb.ServerAddress;
-import com.mongodb.client.MongoDatabase;
-import com.redhat.thermostat.common.ssl.SSLContextFactory;
-import com.redhat.thermostat.common.ssl.SslInitException;
-import com.redhat.thermostat.common.utils.HostPortPair;
-import com.redhat.thermostat.common.utils.HostPortsParser;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.shared.config.InvalidConfigurationException;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.Connection;
-import com.redhat.thermostat.storage.core.ConnectionException;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-
-class MongoConnection extends Connection {
-
-    private static final Logger logger = LoggingUtils.getLogger(MongoConnection.class);
-    static final String THERMOSTAT_DB_NAME = "thermostat";
-
-    private final String url;
-    private final StorageCredentials creds;
-    private final SSLConfiguration sslConf;
-    private final MongoClientOptions.Builder builder;
-    private MongoClient m = null;
-    private MongoDatabase db = null;
-
-    MongoConnection(String url, StorageCredentials creds, SSLConfiguration sslConf) {
-        this(url, creds, sslConf, new MongoClientOptions.Builder());
-    }
-    
-    MongoConnection(String url, StorageCredentials creds, SSLConfiguration sslConf, MongoClientOptions.Builder builder) {
-        this.url = url;
-        this.creds = creds;
-        this.sslConf = sslConf;
-        this.builder = builder;
-    }
-
-    @Override
-    public void connect() {
-        try {
-            createConnection();
-            /* the mongo java driver does not ensure this connection is actually working */
-            testConnection();
-            connected = true;
-
-        } catch (IOException | MongoException | InvalidConfigurationException | IllegalArgumentException e) {
-            logger.log(Level.WARNING, "Failed to connect to storage", e);
-            setUsername(Connection.UNSET_USERNAME);
-            fireChanged(ConnectionStatus.FAILED_TO_CONNECT);
-            throw new ConnectionException(e.getMessage(), e);
-        }
-        fireChanged(ConnectionStatus.CONNECTED);
-    }
-
-    @Override
-    public void disconnect() {
-        connected = false;
-        db = null;
-        if (m != null) {
-            m.close();
-        }
-        setUsername(Connection.UNSET_USERNAME);
-        fireChanged(ConnectionStatus.DISCONNECTED);
-    }
-
-    MongoDatabase getDatabase() {
-        return db;
-    }
-
-    // package visibility for testing purposes.
-    void createConnection() throws MongoException, InvalidConfigurationException, UnknownHostException {
-        String username = creds.getUsername();
-        setUsername(username);
-        char[] password = creds.getPassword();
-        try {
-            this.m = createMongoClient(username, password, builder);
-            this.db = m.getDatabase(THERMOSTAT_DB_NAME);
-        } finally {
-            if (password != null) {
-                Arrays.fill(password, '\0');
-            }
-        }
-    }
-
-    MongoClient createMongoClient(String username, char[] password, Builder builder) throws UnknownHostException, MongoException {
-        if (sslConf.enableForBackingStorage()) {
-            logger.log(Level.FINE, "Using SSL socket for mongodb:// protocol");
-            SSLSocketFactory factory = createSSLSocketFactory();
-            builder.socketFactory(factory);
-        } else {
-            logger.log(Level.FINE, "Using plain socket for mongodb://");
-        }
-        MongoCredential creds = MongoCredential.createCredential(username, THERMOSTAT_DB_NAME, password);
-        CodecRegistry defaultCodecRegistry = MongoClient.getDefaultCodecRegistry();
-        CodecRegistry arrayCodecRegistry = CodecRegistries.fromCodecs(
-                                                new DoubleArrayCodec(),
-                                                new IntegerArrayCodec(),
-                                                new StringArrayCodec());
-        CodecRegistry ourCodecRegistry = CodecRegistries.fromRegistries(
-                                                defaultCodecRegistry,
-                                                arrayCodecRegistry);
-        builder.codecRegistry(ourCodecRegistry);
-        MongoClientOptions opts = builder.build();
-        return getMongoClientInstance(getServerAddress(), Arrays.asList(creds), opts);
-    }
-    
-    MongoClient getMongoClientInstance(ServerAddress address, List<MongoCredential> creds, MongoClientOptions opts) {
-        return new MongoClient(address, creds, opts);
-    }
-
-    private SSLSocketFactory createSSLSocketFactory() {
-        SSLContext ctxt = null;
-        try {
-            ctxt = SSLContextFactory.getClientContext(sslConf);
-        } catch (SslInitException e) {
-            logger.log(Level.WARNING, "Failed to get SSL context!", e);
-            throw new MongoException(e.getMessage(), e);
-        }
-        SSLParameters params = SSLContextFactory.getSSLParameters(ctxt);
-        // Perform HTTPS compatible host name checking.
-        if (!sslConf.disableHostnameVerification()) {
-            params.setEndpointIdentificationAlgorithm("HTTPS");
-        }
-        SSLSocketFactory factory = SSLContextFactory.wrapSSLFactory(
-                ctxt.getSocketFactory(), params);
-        logger.log(Level.FINE, "factory is: " + factory.getClass().getName());
-        return factory;
-    }
-
-    ServerAddress getServerAddress() throws InvalidConfigurationException, UnknownHostException {
-        // Strip mongodb prefix: "mongodb://".length() == 10
-        String hostPort = url.substring(10);
-        HostPortsParser parser = new HostPortsParser(hostPort);
-        parser.parse();
-        HostPortPair ipPort = parser.getHostsPorts().get(0);
-        ServerAddress addr = new ServerAddress(ipPort.getHost(), ipPort.getPort());
-        return addr;
-    }
-
-    private void testConnection() {
-        db.getCollection("agent-config").count();
-    }
-    
-    // Testing hook
-    MongoClient getMongo() {
-        return this.m;
-    }
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoCursor.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import java.util.NoSuchElementException;
-
-import org.bson.Document;
-
-import com.mongodb.MongoException;
-import com.mongodb.client.FindIterable;
-import com.redhat.thermostat.storage.core.BasicBatchCursor;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.model.Pojo;
-
-class MongoCursor<T extends Pojo> extends BasicBatchCursor<T> {
-
-    private final FindIterable<Document> findIterable;
-    private final Class<T> resultClass;
-    private final com.mongodb.client.MongoCursor<Document> cursor;
-
-    MongoCursor(FindIterable<Document> iterable, Class<T> resultClass) {
-        this.findIterable = iterable;
-        this.resultClass = resultClass;
-        this.cursor = iterable.iterator();
-    }
-
-    @Override
-    public boolean hasNext() {
-        try {
-            return cursor.hasNext();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    @Override
-    public T next() {
-        try {
-            Document next = cursor.next();
-            if (next == null) {
-                throw new NoSuchElementException();
-            }
-            MongoPojoConverter converter = new MongoPojoConverter();
-            return converter.convertMongoToPojo(next, resultClass);
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    @Override
-    public void setBatchSize(int n) throws IllegalArgumentException {
-        super.setBatchSize(n); // validates input
-        findIterable.batchSize(n);
-    }
-    
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoExpressionParser.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +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.storage.mongodb.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.bson.Document;
-
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.query.BinaryComparisonExpression;
-import com.redhat.thermostat.storage.query.BinaryComparisonOperator;
-import com.redhat.thermostat.storage.query.BinaryLogicalExpression;
-import com.redhat.thermostat.storage.query.BinaryLogicalOperator;
-import com.redhat.thermostat.storage.query.BinarySetMembershipExpression;
-import com.redhat.thermostat.storage.query.BinarySetMembershipOperator;
-import com.redhat.thermostat.storage.query.ComparisonExpression;
-import com.redhat.thermostat.storage.query.Expression;
-import com.redhat.thermostat.storage.query.LiteralExpression;
-import com.redhat.thermostat.storage.query.LiteralSetExpression;
-import com.redhat.thermostat.storage.query.UnaryLogicalExpression;
-import com.redhat.thermostat.storage.query.UnaryLogicalOperator;
-
-public class MongoExpressionParser {
-    
-    public Document parse(Expression expr) {
-        Document result;
-        if (expr instanceof BinaryComparisonExpression) {
-            result = parseBinaryComparisonExpression((BinaryComparisonExpression<?>) expr);
-        }
-        else if (expr instanceof BinarySetMembershipExpression) {
-            result = parseBinarySetComparisonExpression((BinarySetMembershipExpression<?>) expr);
-        }
-        else if (expr instanceof BinaryLogicalExpression) {
-            // LHS OP RHS ==> { OP : [ LHS, RHS ] }
-            BinaryLogicalExpression<?, ?> biExpr = (BinaryLogicalExpression<?, ?>) expr;
-            BinaryLogicalOperator op = biExpr.getOperator();
-            
-            Document leftResult = parse(biExpr.getLeftOperand());
-            Document rightResult = parse(biExpr.getRightOperand());
-            List<Document> list = new ArrayList<>();
-            list.add(leftResult);
-            list.add(rightResult);
-            
-            result = new Document(getLogicalOperator(op), list);
-        }
-        else if (expr instanceof UnaryLogicalExpression) {
-            UnaryLogicalExpression<?> uniExpr = (UnaryLogicalExpression<?>) expr;
-            ComparisonExpression operand = uniExpr.getOperand();
-            UnaryLogicalOperator op = uniExpr.getOperator();
-            // Special case
-            if (op == UnaryLogicalOperator.NOT && operand instanceof BinaryComparisonExpression) {
-                BinaryComparisonExpression<?> binExpr = (BinaryComparisonExpression<?>) operand;
-                if (binExpr.getOperator() == BinaryComparisonOperator.EQUALS) {
-                    // TODO Convert to $ne?
-                    throw new IllegalArgumentException("Cannot use $not with equality");
-                }
-            }
-            Document object = parse(operand);
-            insertUnaryLogicalOperator(object, op);
-            result = object;
-        }
-        else {
-            throw new IllegalArgumentException("Unknown Expression of type " + expr.getClass());
-        }
-        
-        return result;
-    }
-
-    private void insertUnaryLogicalOperator(Document object, UnaryLogicalOperator op) {
-        String strOp = getLogicalOperator(op);
-        // OP { LHS : RHS } => { LHS : { OP : RHS }}
-        // Apply operator to each key
-        Set<String> keySet = object.keySet();
-        for (String key : keySet) {
-            Object value = object.get(key);
-            Document newValue = new Document(strOp, value);
-            object.put(key, newValue);
-        }
-    }
-
-    private <T> Document parseBinaryComparisonExpression(BinaryComparisonExpression<T> expr) {
-        Document document = new Document();
-        LiteralExpression<Key<T>> leftExpr = expr.getLeftOperand();
-        LiteralExpression<T> rightExpr = expr.getRightOperand();
-        BinaryComparisonOperator op = expr.getOperator();
-        if (op == BinaryComparisonOperator.EQUALS) {
-            // LHS == RHS => { LHS : RHS }
-            document.append(leftExpr.getValue().getName(), rightExpr.getValue());
-        }
-        else {
-            // LHS OP RHS => { LHS : { OP : RHS } }
-            String mongoOp = getComparisonOperator(op);
-            Document subDoc = new Document(mongoOp, rightExpr.getValue());
-            document.append(leftExpr.getValue().getName(), subDoc);
-        }
-        return document;
-    }
-    
-    private <T> Document parseBinarySetComparisonExpression(BinarySetMembershipExpression<T> expr) {
-        LiteralExpression<Key<T>> leftExpr = expr.getLeftOperand();
-        LiteralSetExpression<T> rightExpr = expr.getRightOperand();
-        BinarySetMembershipOperator op = expr.getOperator();
-        // LHS OP [ RHS ] => { LHS : { OP : [ RHS ] } }
-        String mongoOp = getSetMembershipOperator(op);
-        Document subDoc = new Document(mongoOp, rightExpr.getValues());
-        Document document = new Document(leftExpr.getValue().getName(), subDoc);
-
-        return document;
-    }
-    
-    private String getComparisonOperator(BinaryComparisonOperator operator) {
-        String result;
-        switch (operator) {
-        case NOT_EQUAL_TO:
-            result = "$ne";
-            break;
-        case LESS_THAN:
-            result = "$lt";
-            break;
-        case LESS_THAN_OR_EQUAL_TO:
-            result = "$lte";
-            break;
-        case GREATER_THAN:
-            result = "$gt";
-            break;
-        case GREATER_THAN_OR_EQUAL_TO:
-            result = "$gte";
-            break;
-        default:
-            throw new IllegalArgumentException("MongoQuery can not handle " + operator);
-        }
-        return result;
-    }
-    
-    private String getSetMembershipOperator(BinarySetMembershipOperator operator) {
-        String result;
-        switch (operator) {
-        case IN:
-            result = "$in";
-            break;
-        case NOT_IN:
-            result = "$nin";
-            break;
-        default:
-            throw new IllegalArgumentException("MongoQuery can not handle " + operator);
-        }
-        return result;
-    }
-    
-    private String getLogicalOperator(BinaryLogicalOperator operator) {
-        String result;
-        switch (operator) {
-        case AND:
-            result = "$and";
-            break;
-        case OR:
-            result = "$or";
-            break;
-        default:
-            throw new IllegalArgumentException("MongoQuery can not handle " + operator);
-        }
-        return result;
-    }
-    
-    private String getLogicalOperator(UnaryLogicalOperator operator) {
-        String result;
-        switch (operator) {
-        case NOT:
-            result = "$not";
-            break;
-        default:
-            throw new IllegalArgumentException("MongoQuery can not handle " + operator);
-        }
-        return result;
-    }
-    
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoPojoConverter.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +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.storage.mongodb.internal;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Array;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.beanutils.PropertyUtils;
-import org.bson.Document;
-
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.model.Pojo;
-
-// We have to use raw types and unchecked casts, since we don't have
-// the relevant generic type info in this class. Suppress warnings
-// in this class.
-@SuppressWarnings({"rawtypes", "unchecked"})
-class MongoPojoConverter {
-
-    public Document convertPojoToMongo(Pojo obj) {
-        try {
-            return convertPojoToMongoImpl(obj);
-        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    private Document convertPojoToMongoImpl(Pojo obj) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        Document dbObj = new Document();
-        PropertyDescriptor[] descs = PropertyUtils.getPropertyDescriptors(obj);
-        for (PropertyDescriptor desc : descs) {
-            storePropertyToDBObject(obj, dbObj, desc);
-        }
-        return dbObj;
-    }
-
-    private void storePropertyToDBObject(Pojo obj, Document dbObj, PropertyDescriptor desc) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        if (hasPersistentAnnotation(desc)) {
-            String name = desc.getName();
-            Object value = PropertyUtils.getProperty(obj, name);
-            if (desc.getPropertyType().isArray()) {
-                value = convertIndexedProperty(value);
-            }
-            if (value instanceof Pojo) {
-                value = convertPojoToMongoImpl((Pojo) value);
-            }
-            dbObj.put(name, value);
-        }
-    }
-
-    private Object convertIndexedProperty(Object values) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        int length = Array.getLength(values);
-        List list = new ArrayList(length);
-        for (int i = 0; i < length; i++) {
-            Object value = Array.get(values, i);
-            if (value instanceof Pojo) {
-                value = convertPojoToMongoImpl((Pojo) value);
-            }
-            list.add(value);
-        }
-        return list;
-    }
-
-    public <T extends Pojo> T convertMongoToPojo(Document dbObj, Class<T> pojoClass) {
-        try {
-            return convertMongoToPojoImpl(dbObj, pojoClass);
-        } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException ex) {
-            throw new StorageException(ex);
-        }
-    }
-
-    private <T extends Pojo> T convertMongoToPojoImpl(Document dbObj, Class pojoClass) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        if (dbObj == null) {
-            return null;
-        }
-        T pojo = (T) pojoClass.newInstance();
-        Set<String> keys = dbObj.keySet();
-        for (String name : keys) {
-            if (! name.equals("_id")) {
-                storePropertyToPojo(dbObj, pojo, name);
-            }
-        }
-        return pojo;
-    }
-
-    private <T extends Pojo> void storePropertyToPojo(Document dbObj, T pojo, String name)
-            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
-
-        PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(pojo, name);
-        if (hasPersistentAnnotation(desc)) {
-            Object value = dbObj.get(name);
-            if (desc.getPropertyType().isArray()) {
-                value = convertIndexedPropertyFromMongo(desc, (List) value);
-            }
-            if (value instanceof Document) {
-                value = convertMongoToPojoImpl((Document) value, desc.getPropertyType());
-            }
-            PropertyUtils.setProperty(pojo, name, value);
-        } else {
-            throw new StorageException("no available mapping for extra property: '" + name + "' in " + pojo.getClass().getName());
-        }
-    }
-
-    private Object convertIndexedPropertyFromMongo(PropertyDescriptor desc, List values) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
-        Class componentType = desc.getPropertyType().getComponentType();
-        Object array = Array.newInstance(componentType, values.size());
-        int i = 0;
-        for (Object value : values) {
-            if (value instanceof Document) {
-                value = convertMongoToPojoImpl((Document) value, componentType);
-            }
-            Array.set(array, i, value);
-            i++;
-        }
-        return array;
-    }
-
-    private boolean hasPersistentAnnotation(PropertyDescriptor desc) {
-        if (desc == null) {
-            return false;
-        }
-        Method writeMethod = desc.getWriteMethod();
-        Method readMethod = desc.getReadMethod();
-        return writeMethod != null && writeMethod.isAnnotationPresent(Persist.class)
-               && readMethod != null && readMethod.isAnnotationPresent(Persist.class);
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoQuery.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +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.storage.mongodb.internal;
-
-import java.util.Objects;
-
-import org.bson.Document;
-
-import com.redhat.thermostat.storage.core.AbstractQuery;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.Statement;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.storage.query.Expression;
-
-public class MongoQuery<T extends Pojo> extends AbstractQuery<T> {
-
-    private MongoStorage storage;
-    private Document query = new Document();
-    
-    private boolean hasClauses = false;
-    private Category<T> category;
-    private Class<T> resultClass;
-    private MongoExpressionParser parser;
-    private Expression expression = null;
-
-    MongoQuery(MongoStorage storage, Category<T> category) {
-        this(storage, category, new MongoExpressionParser());
-    }
-    
-    MongoQuery(MongoStorage storage, Category<T> category, MongoExpressionParser parser) {
-        this.storage = storage;
-        this.category = category;
-        this.parser = parser;
-        this.resultClass = category.getDataClass();
-    }
-
-    public Category<T> getCategory() {
-        return category;
-    }
-
-    public void setCategory(Category<T> category) {
-        this.category = category;
-    }
-
-    @Override
-    public void where(Expression expr) {
-        expression = expr;
-        query = parser.parse(expr);
-        hasClauses = true;
-    }
-
-    Document getGeneratedQuery() {
-        return query;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof MongoQuery)) {
-            return false;
-        }
-        MongoQuery<?> other = (MongoQuery<?>) obj;
-        return Objects.equals(getCategory(), other.getCategory()) && Objects.equals(this.query, other.query);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(getCategory(), this.query);
-    }
-
-    boolean hasClauses() {
-        return hasClauses ;
-    }
-
-    @Override
-    public Cursor<T> execute() {
-        return storage.findAllPojos(this, resultClass);
-    }
-
-    @Override
-    public Expression getWhereExpression() {
-        return expression;
-    }
-
-    @Override
-    public Statement<T> getRawDuplicate() {
-        return new MongoQuery<>(storage, category);
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,725 +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.storage.mongodb.internal;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.logging.Logger;
-
-import org.bson.Document;
-
-import com.mongodb.MongoException;
-import com.mongodb.client.DistinctIterable;
-import com.mongodb.client.FindIterable;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoDatabase;
-import com.mongodb.client.gridfs.GridFSBucket;
-import com.mongodb.client.gridfs.GridFSBuckets;
-import com.mongodb.client.gridfs.GridFSDownloadStream;
-import com.mongodb.client.model.CreateCollectionOptions;
-import com.mongodb.client.model.UpdateOptions;
-import com.mongodb.client.result.DeleteResult;
-import com.mongodb.client.result.UpdateResult;
-import com.redhat.thermostat.common.utils.LoggingUtils;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.AbstractQuery.Sort;
-import com.redhat.thermostat.storage.core.Add;
-import com.redhat.thermostat.storage.core.AggregateQuery;
-import com.redhat.thermostat.storage.core.AggregateQuery.AggregateFunction;
-import com.redhat.thermostat.storage.core.BackingStorage;
-import com.redhat.thermostat.storage.core.Category;
-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.Key;
-import com.redhat.thermostat.storage.core.PreparedStatement;
-import com.redhat.thermostat.storage.core.PreparedStatementFactory;
-import com.redhat.thermostat.storage.core.Query;
-import com.redhat.thermostat.storage.core.Remove;
-import com.redhat.thermostat.storage.core.Replace;
-import com.redhat.thermostat.storage.core.SaveFileListener;
-import com.redhat.thermostat.storage.core.SaveFileListener.EventType;
-import com.redhat.thermostat.storage.core.SchemaInfo;
-import com.redhat.thermostat.storage.core.SchemaInfoInserter;
-import com.redhat.thermostat.storage.core.Statement;
-import com.redhat.thermostat.storage.core.StatementDescriptor;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.core.Update;
-import com.redhat.thermostat.storage.model.AggregateCount;
-import com.redhat.thermostat.storage.model.AggregateResult;
-import com.redhat.thermostat.storage.model.DistinctResult;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.storage.query.Expression;
-
-/**
- * Implementation of the Storage interface that uses MongoDB to store the instrumentation data.
- *
- * In this implementation, each CATEGORY is given a distinct collection.
- */
-public class MongoStorage implements BackingStorage, SchemaInfoInserter {
-    
-    private static final Logger logger = LoggingUtils.getLogger(MongoStorage.class);
-    
-    private class MongoDistinctQuery<T extends Pojo> extends AggregateQuery<T> {
-
-        private final Category<T> category;
-        
-        private MongoDistinctQuery(MongoQuery<T> queryToAggregate, Category<T> category) {
-            super(AggregateFunction.DISTINCT, queryToAggregate);
-            this.category = category;
-        }
-        
-        @Override
-        public Cursor<T> execute() {
-            return executeDistinctQuery(this, category, (MongoQuery<T>)queryToAggregate);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            MongoQuery<T> query = (MongoQuery<T>) this.queryToAggregate;
-            MongoDistinctQuery<T> aggQuery = new MongoDistinctQuery<>(query, category);
-            // Distinct queries require this param. It's static so pass this
-            // on to duplicates.
-            aggQuery.setAggregateKey(getAggregateKey());
-            return aggQuery;
-        }
-        
-    }
-    
-    private class MongoCountQuery<T extends Pojo> extends AggregateQuery<T> {
-        
-        private final Category<T> category;
-        
-        private MongoCountQuery(MongoQuery<T> queryToAggregate, Category<T> category) {
-            super(AggregateFunction.COUNT, queryToAggregate);
-            this.category = category;
-        }
-
-        @Override
-        public Cursor<T> execute() {
-            return executeGetCount(category, (MongoQuery<T>)this.queryToAggregate);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            MongoQuery<T> query = (MongoQuery<T>) this.queryToAggregate;
-            MongoCountQuery<T> dupe = new MongoCountQuery<>(query, category);
-            // Count aggregates have an optional key to aggregate. Optional for
-            // backwards compat reasons. Be sure to copy it over if it was set.
-            if (getAggregateKey() != null) {
-                dupe.setAggregateKey(getAggregateKey());
-            }
-            return dupe;
-        }
-    }
-    
-    private static abstract class MongoSetter<T extends Pojo> {
-        
-        protected final Document values;
-        protected final Category<T> category;
-        
-        private MongoSetter(Category<T> category) {
-            this.category = category;
-            this.values = new Document();
-        }
-        
-        private Object convertPojo(Object value) {
-            // convert pojo values to mongo DB objects if need be
-            if (value instanceof Pojo) {
-                Pojo pojo = (Pojo)value;
-                MongoPojoConverter converter = new MongoPojoConverter();
-                value = converter.convertPojoToMongo(pojo);
-            } else if (value instanceof Pojo[]) {
-                List<Document> pojos = new ArrayList<>();
-                MongoPojoConverter converter = new MongoPojoConverter();
-                Pojo[] list = (Pojo[])value;
-                for (Pojo p: list) {
-                    Document converted = converter.convertPojoToMongo(p);
-                    pojos.add(converted);
-                }
-                value = pojos;
-            }
-            return value;
-        }
-        
-        protected void set(String key, Object value) {
-            // convert Pojo/list of Pojos to DBObject/list of DBObjects
-            // if need be
-            value = convertPojo(value);
-            values.put(key, value);
-        }
-    }
-
-    private class MongoAdd<T extends Pojo> extends MongoSetter<T>
-            implements Add<T> {
-        
-        private MongoAdd(Category<T> category) {
-            super(category);
-        }
-        
-        @Override
-        public int apply() {
-            return addImpl(category, values);
-        }
-
-        @Override
-        public void set(String key, Object value) {
-            super.set(key, value);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            return new MongoAdd<>(category);
-        }
-        
-    }
-
-    private class MongoReplace<T extends Pojo> extends MongoSetter<T>
-            implements Replace<T> {
-        
-        private Document query;
-        private final MongoExpressionParser parser;
-
-        private MongoReplace(Category<T> category) {
-            super(category);
-            this.parser = new MongoExpressionParser();
-        }
-        
-        @Override
-        public int apply() {
-            if (query == null) {
-                String msg = "where expression must be set. " +
-                             "Please call where() before apply().";
-                throw new IllegalStateException(msg);
-            }
-            return (int)replaceImpl(category, values, query);
-        }
-
-        @Override
-        public void where(Expression expression) {
-            this.query = parser.parse(Objects.requireNonNull(expression));
-        }
-
-        @Override
-        public void set(String key, Object value) {
-            super.set(key, value);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            return new MongoReplace<>(category);
-        }
-        
-    }
-    
-    private class MongoUpdate<T extends Pojo> extends MongoSetter<T>
-            implements Update<T> {
-
-        private static final String SET_MODIFIER = "$set";
-
-        private Document query;
-        private final MongoExpressionParser parser;
-
-        private MongoUpdate(Category<T> category) {
-            super(category);
-            this.parser = new MongoExpressionParser();
-        }
-
-        @Override
-        public void where(Expression expr) {
-            query = parser.parse(expr);
-        }
-
-        @Override
-        public void set(String key, Object value) {
-            super.set(key, value);
-        }
-
-        @Override
-        public int apply() {
-            Document setValues = new Document(SET_MODIFIER, values);
-            return (int)updateImpl(category, setValues, query);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            return new MongoUpdate<>(category);
-        }
-    }
-    
-    private class MongoRemove<T extends Pojo> implements Remove<T> {
-
-        private final Category<T> category;
-        private Document query;
-        private final MongoExpressionParser parser;
-        
-        private MongoRemove(Category<T> category) {
-            this(category, new MongoExpressionParser());
-        }
-        
-        private MongoRemove(Category<T> category, MongoExpressionParser parser) {
-            this.parser = parser;
-            this.category = category;
-        }
-
-        @Override
-        public void where(Expression expr) {
-            query = parser.parse(expr);
-        }
-        
-        @Override
-        public int apply() {
-            if (query == null) {
-                query = new Document();
-            }
-            return (int)removePojo(category, query);
-        }
-
-        @Override
-        public Statement<T> getRawDuplicate() {
-            return new MongoRemove<>(category);
-        }
-        
-    }
-
-    private final MongoConnection conn;
-    private final Map<String, MongoCollection<Document>> collectionCache = new HashMap<>();
-    private final CountDownLatch connectedLatch;
-    private volatile MongoDatabase db = null;
-
-    // For testing only
-    MongoStorage(MongoDatabase db, CountDownLatch latch) {
-        this.db = db;
-        this.connectedLatch = latch;
-        this.conn = null;
-    }
-    
-    MongoStorage(MongoConnection connection) {
-        this.conn = connection;
-        connectedLatch = new CountDownLatch(1);
-        
-        // We register a connection listener in order for the mongo-java-driver
-        // DB object to be valid once it's first used (that's usually in
-        // registerCategory())
-        conn.addListener(new ConnectionListener() {
-            @Override
-            public void changed(ConnectionStatus newStatus) {
-                switch (newStatus) {
-                case CONNECTED:
-                    if (db == null) {
-                        // Main success entry point
-                        db = conn.getDatabase();
-                        createSchemaInfo();
-                        // This is important. See comment in registerCategory().
-                        connectedLatch.countDown();
-                    }
-                    break;
-                case FAILED_TO_CONNECT:
-                    // Main connection-failure entry-point
-                    connectedLatch.countDown();
-                    break;
-                case CONNECTING:
-                    // no-op
-                    break;
-                case DISCONNECTED:
-                    // mark the db object invalid
-                    db = null;
-                    break;
-                }
-            }
-        });
-    }
-    
-    public MongoStorage(String url, StorageCredentials creds, SSLConfiguration sslConf) {
-        this(new MongoConnection(url, creds, sslConf));
-    }
-    
-    @Override
-    public Connection getConnection() {
-        return conn;
-    }
-
-    @Override
-    public <T extends Pojo> Add<T> createAdd(Category<T> into) {
-        MongoAdd<T> add = new MongoAdd<>(into);
-        return add;
-    }
-
-    @Override
-    public <T extends Pojo> Replace<T> createReplace(Category<T> into) {
-        MongoReplace<T> replace = new MongoReplace<>(into);
-        return replace;
-    }
-
-    private <T extends Pojo> Cursor<T> executeGetCount(Category<T> category, MongoQuery<T> queryToAggregate) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(category);
-            long count = 0L;
-            Document query = queryToAggregate.getGeneratedQuery();
-            if (coll != null) {
-                count = coll.count(query);
-            }
-            AggregateCount result = new AggregateCount();
-            result.setCount(count);
-            return result.getCursor();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-    
-    private <T extends Pojo> Cursor<T> executeDistinctQuery(MongoDistinctQuery<T> aggQuery, Category<T> category, MongoQuery<T> queryToAggregate) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(category);
-            Document query = queryToAggregate.getGeneratedQuery();
-            String[] distinctValues;
-            Key<?> aggregateKey = aggQuery.getAggregateKey();
-            if (coll != null) {
-                String key = aggregateKey.getName();
-                DistinctIterable<String> iterable = coll.distinct(key, query, String.class);
-                distinctValues = convertToStringList(iterable, key);
-            } else {
-                distinctValues = new String[0];
-            }
-            DistinctResult result = new DistinctResult();
-            result.setKey(aggregateKey);
-            result.setValues(distinctValues);
-            return result.getCursor();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-    
-    private String[] convertToStringList(Iterable<String> iterable, String keyName) {
-        List<String> stringList = new ArrayList<>();
-        Iterator<String> iter = iterable.iterator();
-        while (iter.hasNext()) {
-            String item  = iter.next();
-            // Mongodb might give us null values.
-            if (item != null) {
-                stringList.add(item);
-            }
-        }
-        return stringList.toArray(new String[0]);
-    }
-
-    private <T extends Pojo> int addImpl(final Category<T> cat, final Document values) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(cat);
-            assertContainsWriterID(values);
-            coll.insertOne(values);
-            return 1;
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    private <T extends Pojo> long replaceImpl(final Category<T> cat, final Document values, final Document query) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(cat);
-            assertContainsWriterID(values);
-            UpdateResult result = coll.replaceOne(query, values, new UpdateOptions().upsert(true));
-            return result.getModifiedCount();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    private void assertContainsWriterID(final Document values) {
-        if (values.get(Key.AGENT_ID.getName()) == null) {
-            throw new AssertionError("agentId must be set");
-        }
-    }
-
-    private <T extends Pojo> long updateImpl(Category<T> category, Document values, Document query) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(category);
-            UpdateResult result = coll.updateOne(query, values);
-            return result.getModifiedCount();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    private long removePojo(Category<?> category, Document query) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(category);
-            DeleteResult result = coll.deleteMany(query);
-            return result.getDeletedCount();
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    private MongoCollection<Document> getCachedCollection(Category<?> category) {
-        String collName = category.getName();
-        MongoCollection<Document> coll = collectionCache.get(collName);
-        if (coll == null && !collectionExists(collName)) {
-            throw new IllegalStateException("Categories need to be registered before being used");
-        }
-        return coll;
-    }
-
-    // TODO: This method is only temporary to enable tests, until we come up with a better design,
-    // in particular, the collection should be stored in the category itself. It must not be called
-    // from production code.
-    void mapCategoryToDBCollection(Category<?> category, MongoCollection<Document> coll) {
-        collectionCache.put(category.getName(), coll);
-    }
-
-
-    @Override
-    public void purge(String agentId) {
-        try {
-            Document query = new Document(Key.AGENT_ID.getName(), agentId);
-            for (String collectionName : db.listCollectionNames()) {
-                // Mongodb creates an internal collection called
-                // "system.indexes". Don't delete anything in there as this
-                // would throw MongoException later (error code 12050,
-                // msg: "cannot delete from system namespace"
-                if (collectionName.startsWith("system.")) {
-                    continue;
-                }
-                MongoCollection<Document> coll = db.getCollection(collectionName);
-                coll.deleteMany(query);
-            }
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-    
-    @Override
-    public void registerCategory(Category<?> category) {
-        try {
-            Class<?> dataClass = category.getDataClass();
-            if (AggregateResult.class.isAssignableFrom(dataClass)) {
-                // adapted aggregate category, no need to actually register
-                return;
-            }
-            String name = category.getName();
-            if (collectionCache.containsKey(name)) {
-                throw new IllegalStateException("Category may only be associated with one backend.");
-            }
-
-            // The db field is only set once we've got a connection
-            // established. Wait until we actually get notification
-            // this has happened. Without this sychronization we might
-            // get NPEs since the connection handshake might still be
-            // ongoing.
-            try {
-                connectedLatch.await();
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
-
-            MongoCollection<Document> coll;
-            Boolean isSchemaInfo = SchemaInfo.CATEGORY.getName().equals(category.getName());
-            
-            // Check if category is SchemaInfo, in this case it doesn't need to create this collection
-            if ( !isSchemaInfo && !collectionExists(name)) {
-                db.createCollection(name, new CreateCollectionOptions().capped(false));
-                coll = db.getCollection(name);
-                List<Key<?>> indexKeys = category.getIndexedKeys();
-                // primarily on the first key then on subsequent keys
-                if (indexKeys.size() >= 1) {
-                    Document indexDoc = new Document(indexKeys.get(0).getName(), 1);
-                    for (int i = 1; i < indexKeys.size(); i++) {
-                        Key<?> key = indexKeys.get(i);
-                        indexDoc.append(key.getName(), 1);
-                    }
-                    coll.createIndex(indexDoc);
-                }
-            } else {
-                coll = db.getCollection(name);
-            }
-            collectionCache.put(name, coll);
-            if(!isSchemaInfo) {
-                insertSchemaInfo(category);
-            }
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    @Override
-    public <T extends Pojo> Query<T> createQuery(Category<T> category) {
-        return new MongoQuery<T>(this, category);
-    }
-
-    @Override
-    public <T extends Pojo> Update<T> createUpdate(Category<T> category) {
-        return new MongoUpdate<>(category);
-    }
-
-    @Override
-    public <T extends Pojo> Remove<T> createRemove(Category<T> category) {
-        return new MongoRemove<>(category);
-    }
-
-    <T extends Pojo> Cursor<T> findAllPojos(MongoQuery<T> mongoQuery, Class<T> resultClass) {
-        try {
-            MongoCollection<Document> coll = getCachedCollection(mongoQuery.getCategory());
-            FindIterable<Document> iterable;
-            Document generatedQuery = mongoQuery.getGeneratedQuery();
-            logger.fine("generated query is: " + generatedQuery);
-            if (mongoQuery.hasClauses()) {
-                iterable = coll.find(mongoQuery.getGeneratedQuery());
-            } else {
-                iterable = coll.find();
-            }
-            iterable.batchSize(Cursor.DEFAULT_BATCH_SIZE);
-            iterable = applySortAndLimit(mongoQuery, iterable);
-            Cursor<T> mongoCursor = new MongoCursor<T>(iterable, resultClass);
-            return mongoCursor;
-        } catch (MongoException me) {
-            throw new StorageException(me);
-        }
-    }
-
-    private FindIterable<Document> applySortAndLimit(MongoQuery<?> query, FindIterable<Document> dbCursor) {
-        Document orderBy = new Document();
-        List<Sort> sorts = query.getSorts();
-        for (Sort sort : sorts) {
-            orderBy.append(sort.getKey().getName(), sort.getDirection().getValue());
-        }
-        dbCursor.sort(orderBy);
-        int limit = query.getLimit();
-        if (limit > 0) {
-            dbCursor.limit(limit);
-        }
-        return dbCursor;
-    }
-
-    @Override
-    public void saveFile(String filename, InputStream data, SaveFileListener listener) {
-        Objects.requireNonNull(listener);
-        try {
-            GridFSBucket gridFsBucket = createGridFSBucket();
-            gridFsBucket.uploadFromStream(filename, data);
-            listener.notify(EventType.SAVE_COMPLETE, null);
-        } catch (MongoException me) {
-            listener.notify(EventType.EXCEPTION_OCCURRED, new StorageException(me));
-        }
-    }
-
-    // package-private for testing
-    GridFSBucket createGridFSBucket() {
-        return GridFSBuckets.create(db);
-    }
-
-    @Override
-    public InputStream loadFile(String filename) {
-        try {
-            GridFSBucket gridFsBucket = createGridFSBucket();
-            GridFSDownloadStream downloadStream = gridFsBucket.openDownloadStreamByName(filename);
-            return downloadStream;
-        } catch (MongoException me) {
-            return null;
-        }
-    }
-
-    @Override
-    public void shutdown() {}
-
-    /*
-     *  QueuedStorage decorator uses this method and "wraps" the returned
-     *  PreparedStatement so that it executes in a queued fashion.
-     */
-    @Override
-    public <T extends Pojo> PreparedStatement<T> prepareStatement(StatementDescriptor<T> statementDesc)
-            throws DescriptorParsingException {
-        // FIXME: Use some kind of cache in order to avoid parsing of
-        // descriptors each time this is called. At least if the descriptor
-        // class is the same we should be able to do something here.
-        return PreparedStatementFactory.getInstance(this, statementDesc);
-    }
-
-    @Override
-    public <T extends Pojo> AggregateQuery<T> createAggregateQuery(
-            AggregateFunction function, Category<T> category) {
-        MongoQuery<T> query = (MongoQuery<T>)createQuery(category);
-        switch (function) {
-        case COUNT:
-            return new MongoCountQuery<>(query, category);
-        case DISTINCT:
-            return new MongoDistinctQuery<>(query, category); 
-        default:
-            throw new IllegalStateException("function not supported: "
-                    + function);
-        }
-    }
-
-    @Override
-    public void createSchemaInfo() {
-        if (!collectionExists(SchemaInfo.CATEGORY.getName())) {
-            db.createCollection(SchemaInfo.CATEGORY.getName(), new CreateCollectionOptions().capped(false));
-        }
-    }
-
-    @Override
-    public <T extends Pojo> void insertSchemaInfo(Category<T> category) {
-        MongoCollection<Document> coll = db.getCollection(SchemaInfo.CATEGORY.getName());
-        
-        Document categoryInfo = new Document();
-        categoryInfo.put(SchemaInfo.NAME.getName(), category.getName());
-        categoryInfo.put(Key.TIMESTAMP.getName(), System.currentTimeMillis());
-        Document query = new Document(SchemaInfo.NAME.getName(), category.getName());
-        coll.replaceOne(query, categoryInfo, new UpdateOptions().upsert(true));
-        
-    }
-    
-    private boolean collectionExists(String name) {
-        Iterator<String> it = db.listCollectionNames().iterator();
-        while (it.hasNext()) {
-            String collection = it.next();
-            if (collection.equalsIgnoreCase(name)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
-
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/StringArrayCodec.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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.storage.mongodb.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.bson.BsonReader;
-import org.bson.BsonType;
-import org.bson.BsonWriter;
-import org.bson.codecs.Codec;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.EncoderContext;
-import org.bson.codecs.StringCodec;
-
-public class StringArrayCodec implements Codec<String[]> {
-
-    private final StringCodec primCodec = new StringCodec();
-    
-    @Override
-    public void encode(BsonWriter writer, String[] value,
-            EncoderContext encoderContext) {
-        writer.writeStartArray();
-        for (String val: value) {
-            primCodec.encode(writer, val, encoderContext);
-        }
-        writer.writeEndArray();
-    }
-
-    @Override
-    public Class<String[]> getEncoderClass() {
-        return String[].class;
-    }
-
-    @Override
-    public String[] decode(BsonReader reader, DecoderContext decoderContext) {
-        reader.readStartArray();
-        List<String> values = new ArrayList<>();
-        while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) {
-            String val = primCodec.decode(reader, decoderContext);
-            values.add(val);
-        }
-        reader.readEndArray();
-        return values.toArray(new String[0]);
-    }
-
-}
--- a/storage/mongo/src/main/resources/com/redhat/thermostat/storage/mongodb/strings.properties	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-COMMON_PATHS_SERVICE_UNAVAILABLE = CommonPaths service unavailable.
-# Note: single quotes are an escape character. We want '<filename>' in the
-# transformed string, NOT a literal {0}.
-MONGODB_SETUP_FILE_EXISTS = File ''{0}'' exists, skipping setup.
-ALREADY_CONNECTED_TO_STORAGE_WARNING = Already connected to storage. This is\
- unexpected since we are about to connect to storage again. Bug?
-# Note the '' in Don't. Grrr, MessageFormat
-UNKNOWN_STORAGE_URL = Don''t know how to setup storage credentials for URL ''{0}''.
-STORAGE_SERVICE_UNAVAILABLE = Storage service unavailable.
-MONGOSTORAGE_RETRIEVAL_FAILED = Failed to retrieve MongoStorage instance from\
- Storage service.
-STAMP_FILE_CREATION_FAILED = Failed to write stamp file ''{0}''.
-MONGODB_USER_SETUP_COMPLETE = mongodb user setup complete.
-LAUNCHER_SERVICE_UNAVAILABLE = Launcher service unavailable.
-INTERRUPTED_WAITING_FOR_STORAGE_STOP = Got interrupted waiting for storage to stop.
-STORAGE_STOP_FAILED = Stopping storage failed.
-USER_SETUP_COMPLETE = User setup complete!
-USER_SETUP_FAILED = User setup failed. See previous errors for details.
-UNRECOGNIZED_PAYLOAD_FROM_STORAGE_CMD = Unrecognized payload from StorageCommand.
-ADDING_USER_FAILED = Adding mongodb user failed.
-INTERRUPTED_WAITING_FOR_ADD_USER = Got interrupted waiting for add-mongodb-user command to finish.
-DISPATCHER_WRONG_OPTION = Either option -s or -d are required.
-# Space at end, hence the '\'
-USERNAME_PROMPT = Please enter the username you''d like to add to mongodb storage at ''{0}'':\ 
-# Space at end, hence the '\'
-PASSWORD_PROMPT = Please enter the desired password for this user:\ 
\ No newline at end of file
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/DoubleArrayCodecTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-
-import org.bson.BsonReader;
-import org.bson.BsonWriter;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.EncoderContext;
-import org.bson.json.JsonReader;
-import org.bson.json.JsonWriter;
-import org.junit.Test;
-
-public class DoubleArrayCodecTest {
-    
-    private final double DELTA = 0.0001;
-
-    @Test
-    public void canEncodeDoubleArray() {
-        double[] values = new double[] {
-           Math.PI, 123.232, -2.32
-        };
-        DoubleArrayCodec codec = new DoubleArrayCodec();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        BsonWriter writer = new JsonWriter(new PrintWriter(baos));
-        EncoderContext ctxt = EncoderContext.builder().build();
-        
-        writer.writeStartDocument();
-        writer.writeName("foo");
-        codec.encode(writer, values, ctxt);
-        writer.writeEndDocument();
-        writer.flush();
-        String json = new String(baos.toByteArray());
-        assertTrue(json.contains("\"foo\""));
-        assertTrue(json.contains("[" + values[0] + ", " + values[1] + ", " + values[2] + "]"));
-    }
-    
-    @Test
-    public void canDecodeDoubleArray() {
-        String json = "{ \"foo\" : [3.141592653589793, 123.232, -2.32] }";
-        BsonReader reader = new JsonReader(json);
-        reader.readStartDocument();
-        String name = reader.readName();
-        assertEquals("foo", name);
-        DoubleArrayCodec codec = new DoubleArrayCodec();
-        double[] decoded = codec.decode(reader, DecoderContext.builder().build());
-        reader.readEndDocument();
-        assertEquals(Math.PI, decoded[0], DELTA);
-        assertEquals(123.232, decoded[1], DELTA);
-        assertEquals(-2.32, decoded[2], DELTA);
-    }
-}
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/IntegerArrayCodecTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-
-import org.bson.BsonReader;
-import org.bson.BsonWriter;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.EncoderContext;
-import org.bson.json.JsonReader;
-import org.bson.json.JsonWriter;
-import org.junit.Test;
-
-public class IntegerArrayCodecTest {
-
-    @Test
-    public void canEncodeIntegerArray() {
-        int[] values = new int[] {
-           333, Integer.MAX_VALUE, -902
-        };
-        IntegerArrayCodec codec = new IntegerArrayCodec();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        BsonWriter writer = new JsonWriter(new PrintWriter(baos));
-        EncoderContext ctxt = EncoderContext.builder().build();
-        
-        writer.writeStartDocument();
-        writer.writeName("foo");
-        codec.encode(writer, values, ctxt);
-        writer.writeEndDocument();
-        writer.flush();
-        String json = new String(baos.toByteArray());
-        assertTrue(json.contains("\"foo\""));
-        assertTrue(json.contains("[" + values[0] + ", " + values[1] + ", " + values[2] + "]"));
-    }
-    
-    @Test
-    public void canDecodeIntegerArray() {
-        String json = "{ \"foo\" : [333, 2147483647, -902] }";
-        BsonReader reader = new JsonReader(json);
-        reader.readStartDocument();
-        String name = reader.readName();
-        assertEquals("foo", name);
-        IntegerArrayCodec codec = new IntegerArrayCodec();
-        int[] decoded = codec.decode(reader, DecoderContext.builder().build());
-        reader.readEndDocument();
-        assertEquals(333, decoded[0]);
-        assertEquals(Integer.MAX_VALUE, decoded[1]);
-        assertEquals(-902, decoded[2]);
-    }
-}
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/LocaleResourcesTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.shared.locale.LocalizedString;
-import com.redhat.thermostat.shared.locale.Translate;
-import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
-
-public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
-
-    @Override
-    protected Class<LocaleResources> getEnumClass() {
-        return LocaleResources.class;
-    }
-
-    @Override
-    protected String getResourceBundle() {
-        return LocaleResources.RESOURCE_BUNDLE;
-    }
-    
-    /*
-     * MessageFormat[1] treats single quotes as an escape character.
-     * 
-     * Having something like -->'{0}'<-- in strings.properties makes the
-     * pattern look like a literal {0} to MessageFormat. That is, the parameter
-     * does not get substituted. The correct pattern is ''{0}''.
-     * 
-     * These tests make sure params get properly substituted and don't show
-     * up wrongly at runtime.
-     * 
-     * [1] http://docs.oracle.com/javase/7/docs/api/java/text/MessageFormat.html
-     */
-    @Test
-    public void canBindVariables() {
-        Translate<LocaleResources> t = LocaleResources.createLocalizer();
-        doStringSubstitutionTest(t, LocaleResources.MONGODB_SETUP_FILE_EXISTS);
-        doStringSubstitutionTest(t, LocaleResources.STAMP_FILE_CREATION_FAILED);
-        doStringSubstitutionTest(t, LocaleResources.UNKNOWN_STORAGE_URL);
-        doStringSubstitutionTest(t, LocaleResources.USERNAME_PROMPT);
-    }
-    
-    private void doStringSubstitutionTest(Translate<LocaleResources> t, LocaleResources res) {
-        String filename = "foobar";
-        LocalizedString string = t.localize(res, filename);
-        assertTrue("String '" + string.getContents() + "' should have contained '" + filename + "'", string.getContents().contains(filename));
-    }
-
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnectionTest.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.whenNew;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.List;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSocketFactory;
-
-import org.bson.Document;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoCredential;
-import com.mongodb.MongoException;
-import com.mongodb.ServerAddress;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoDatabase;
-import com.redhat.thermostat.common.ssl.SSLContextFactory;
-import com.redhat.thermostat.common.utils.HostPortsParser;
-import com.redhat.thermostat.shared.config.InvalidConfigurationException;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-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.ConnectionException;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-
-@RunWith(PowerMockRunner.class)
-// There is a bug (resolved as wontfix) in powermock which results in
-// java.lang.LinkageError if javax.management.* classes aren't ignored by
-// Powermock. More here: http://code.google.com/p/powermock/issues/detail?id=277
-// SSL tests need this and having that annotation on method level doesn't seem
-// to solve the issue.
-@PowerMockIgnore( {"javax.management.*"})
-public class MongoConnectionTest {
-
-    private MongoConnection conn;
-    private ConnectionListener listener;
-    private SSLConfiguration mockSSLConf;
-
-    @Before
-    public void setUp() {
-        mockSSLConf = mock(SSLConfiguration.class);
-        when(mockSSLConf.enableForBackingStorage()).thenReturn(false);
-
-        StorageCredentials creds = mock(StorageCredentials.class);
-        when(creds.getUsername()).thenReturn("foo-user");
-        when(creds.getPassword()).thenReturn("foo-password".toCharArray());
-
-        conn = new MongoConnection("mongodb://127.0.0.1:27518", creds, mockSSLConf);
-        listener = mock(ConnectionListener.class);
-        conn.addListener(listener);
-    }
-
-    @After
-    public void tearDown() {
-        conn = null;
-    }
-
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testConnectSuccess() throws Exception {
-        setupDatabaseMocks(mock(MongoDatabase.class), mock(MongoClient.class));
-
-        conn.connect();
-
-        verify(listener).changed(ConnectionStatus.CONNECTED);
-    }
-    
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testDisconnect() throws Exception {
-        MongoClient m = mock(MongoClient.class);
-        setupDatabaseMocks(mock(MongoDatabase.class), m);
-        conn.connect();
-
-        verify(listener).changed(ConnectionStatus.CONNECTED);
-        
-        conn.disconnect();
-        verify(m).close();
-        verify(listener).changed(ConnectionStatus.DISCONNECTED);
-    }
-
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testConnectIOException() throws Exception {
-        IOException fakeException = new IOException();
-        PowerMockito.whenNew(MongoClient.class).withParameterTypes(
-                                                    ServerAddress.class,
-                                                    List.class,
-                                                    MongoClientOptions.class)
-                                               .withArguments(
-                                                    any(ServerAddress.class),
-                                                    any(List.class),
-                                                    any(MongoClientOptions.class))
-                                               .thenThrow(fakeException);
-        boolean exceptionThrown = false;
-        try {
-            conn.connect();
-            fail("Should have thrown IOException");
-        } catch (ConnectionException ex) {
-            exceptionThrown = true;
-            assertTrue("Expected fake exception to be thrown. Nothing else.",
-                    ex.getCause() == fakeException);
-        }
-        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
-        assertTrue(exceptionThrown);
-    }
-
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testConnectMongoException() throws Exception {
-        MongoException fakeException = new MongoException("fluff");
-        PowerMockito.whenNew(MongoClient.class).withParameterTypes(
-                                                    ServerAddress.class,
-                                                    List.class,
-                                                    MongoClientOptions.class)
-                                               .withArguments(
-                                                    any(ServerAddress.class),
-                                                    any(List.class),
-                                                    any(MongoClientOptions.class))
-                                               .thenThrow(fakeException);
-        boolean exceptionThrown = false;
-        try {
-            conn.connect();
-            fail("Should have thrown MongoException");
-        } catch (ConnectionException ex) {
-            exceptionThrown = true;
-            assertTrue("Expected fake exception to be thrown. Nothing else.",
-                    ex.getCause() == fakeException);
-        }
-
-        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
-        assertTrue(exceptionThrown);
-    }
-    
-    @PrepareForTest({ MongoConnection.class, HostPortsParser.class })
-    @Test
-    public void testConnectInvalidConfigurationexception() throws Exception {
-        HostPortsParser failingParser = mock(HostPortsParser.class);
-        doThrow(new InvalidConfigurationException("let's pretend the configuration is invalid"))
-                .when(failingParser).parse();
-
-        PowerMockito
-            .whenNew(HostPortsParser.class)
-            .withParameterTypes(String.class)
-            .withArguments(anyString())
-            .thenReturn(failingParser);
-
-        boolean exceptionThrown = false;
-        try {
-            conn.connect();
-        } catch (ConnectionException ex) {
-            exceptionThrown = true;
-        }
-
-        verify(listener).changed(ConnectionStatus.FAILED_TO_CONNECT);
-        assertTrue(exceptionThrown);
-    }
-
-    @PrepareForTest({ MongoConnection.class,
-        SSLContextFactory.class, SSLContext.class, SSLSocketFactory.class })
-    @Test
-    public void verifySSLSocketFactoryUsedIfSSLEnabled() throws Exception {
-        when(mockSSLConf.enableForBackingStorage()).thenReturn(true);
-        
-        PowerMockito.mockStatic(SSLContextFactory.class);
-        // SSL classes need to be mocked with PowerMockito
-        SSLContext context = PowerMockito.mock(SSLContext.class);
-        when(SSLContextFactory.getClientContext(isA(SSLConfiguration.class))).thenReturn(context);
-        SSLSocketFactory factory = PowerMockito.mock(SSLSocketFactory.class);
-        when(SSLContextFactory.wrapSSLFactory(any(SSLSocketFactory.class), any(SSLParameters.class))).thenReturn(factory);
-        SSLParameters params = mock(SSLParameters.class);
-        when(SSLContextFactory.getSSLParameters(context)).thenReturn(params);
-        MongoClient mockMongo = mock(MongoClient.class);
-        ArgumentCaptor<MongoClientOptions> mongoOptCaptor = ArgumentCaptor.forClass(MongoClientOptions.class);
-        whenNew(MongoClient.class).withParameterTypes(ServerAddress.class,
-                List.class, MongoClientOptions.class).withArguments(any(ServerAddress.class),
-                any(List.class), mongoOptCaptor.capture()).thenReturn(mockMongo);
-        MongoDatabase mockDb = mock(MongoDatabase.class);
-        when(mockMongo.getDatabase(eq(MongoConnection.THERMOSTAT_DB_NAME))).thenReturn(mockDb);
-        @SuppressWarnings("unchecked")
-        MongoCollection<Document> mockCollection = mock(MongoCollection.class);
-        when(mockDb.getCollection(any(String.class))).thenReturn(mockCollection);
-        conn.connect();
-        verify(params).setEndpointIdentificationAlgorithm("HTTPS");
-        MongoClient mongo = conn.getMongo();
-        assertEquals(mockMongo, mongo);
-        MongoClientOptions opts = mongoOptCaptor.getValue();
-        SocketFactory sockFactory = opts.getSocketFactory();
-        assertTrue(sockFactory instanceof SSLSocketFactory);
-        assertEquals(factory, sockFactory);
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Test
-    public void verifyNoSSLSocketFactoryUsedIfSSLDisabled() throws Exception {
-        StorageCredentials c = mock(StorageCredentials.class);
-        when(c.getUsername()).thenReturn("foo-user");
-        when(c.getPassword()).thenReturn("foo-bar".toCharArray());
-        MongoClientOptions.Builder builder = mock(MongoClientOptions.Builder.class);
-        final MongoClient client = mock(MongoClient.class);
-        MongoDatabase db = mock(MongoDatabase.class);
-        when(client.getDatabase(any(String.class))).thenReturn(db);
-        when(db.getCollection(any(String.class))).thenReturn(mock(MongoCollection.class));
-        MongoConnection connection = new MongoConnection("mongodb://127.0.0.1:27518", c, mock(SSLConfiguration.class), builder) {
-
-            @Override
-            MongoClient getMongoClientInstance(ServerAddress addr, List<MongoCredential> creds, MongoClientOptions opts) {
-                return client;
-            }
-
-        };
-        connection.connect();
-        verify(builder, times(0)).socketFactory(any(SocketFactory.class));
-    }
-    
-    @Test
-    public void canGetServerAddress() {
-        SSLConfiguration sslConf = mock(SSLConfiguration.class);
-        StorageCredentials creds = mock(StorageCredentials.class);
-        MongoConnection connection = new MongoConnection("mongodb://127.0.1.1:23452", creds, sslConf);
-        ServerAddress addr = null;
-        try {
-            addr = connection.getServerAddress();
-        } catch (UnknownHostException e) {
-            fail("Should not have thrown exception!");
-        }
-        assertEquals(23452, addr.getPort());
-        assertEquals("127.0.1.1", addr.getHost());
-    }
-
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testConnectedUsernameIsSet() throws Exception {
-        String expected = "username";
-
-        MongoDatabase db = mock(MongoDatabase.class);
-        setupDatabaseMocks(db, mock(MongoClient.class));
-
-        StorageCredentials creds = mock(StorageCredentials.class);
-        when(creds.getUsername()).thenReturn(expected);
-        when(creds.getPassword()).thenReturn(new char[] { 'p' });
-
-        conn = new MongoConnection("mongodb://127.0.0.1:27518", creds, mockSSLConf);
-        conn.connect();
-
-        assertEquals(expected, conn.getUsername());
-    }
-
-    @PrepareForTest({ MongoConnection.class })
-    @Test
-    public void testFailedConnectUsernameIsUnset() throws Exception {
-        String expected = Connection.UNSET_USERNAME;
-        boolean expect = false;
-
-        MongoDatabase db = mock(MongoDatabase.class);
-        setupDatabaseMocks(db, mock(MongoClient.class));
-
-        StorageCredentials creds = mock(StorageCredentials.class);
-        // null username is not permitted, provoking connection exception.
-        when(creds.getUsername()).thenReturn(null);
-
-        conn = new MongoConnection("mongodb://127.0.0.1:27518", creds, mockSSLConf);
-        try {
-            conn.connect();
-        } catch (ConnectionException e) {
-            //Expected a ConnectionException
-            expect = true;
-        }
-        assertEquals(expected, conn.getUsername());
-        assertTrue(expect);
-    }
-
-    @Test
-    public void testDisconnectedUsernameIsUnset() throws Exception {
-        String expected = Connection.UNSET_USERNAME;
-
-        conn = new MongoConnection("mongodb://127.0.0.1:27518", mock(StorageCredentials.class), mockSSLConf);
-        conn.disconnect();
-
-        assertEquals(expected, conn.getUsername());
-    }
-
-    private void setupDatabaseMocks(MongoDatabase db, MongoClient m) throws Exception {
-        @SuppressWarnings("unchecked")
-        MongoCollection<Document> collection = mock(MongoCollection.class);
-        when(db.getCollection("agent-config")).thenReturn(collection);
-
-        when(m.getDatabase(MongoConnection.THERMOSTAT_DB_NAME)).thenReturn(db);
-        PowerMockito.whenNew(MongoClient.class).withParameterTypes(
-                                                    ServerAddress.class,
-                                                    List.class,
-                                                    MongoClientOptions.class)
-                                               .withArguments(
-                                                    any(ServerAddress.class),
-                                                    any(List.class),
-                                                    any(MongoClientOptions.class))
-                                               .thenReturn(m);
-    }
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoCursorTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import java.util.NoSuchElementException;
-
-import org.bson.Document;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.mongodb.client.FindIterable;
-import com.redhat.thermostat.storage.core.Cursor;
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.model.BasePojo;
-
-public class MongoCursorTest {
-
-    @Entity
-    public static class TestClass extends BasePojo {
-        
-        public TestClass() {
-            super(null);
-        }
-        
-        private String key1;
-        private String key2;
-        private String key3;
-        private String key4;
-        @Persist
-        public String getKey1() {
-            return key1;
-        }
-        @Persist
-        public void setKey1(String key1) {
-            this.key1 = key1;
-        }
-        @Persist
-        public String getKey2() {
-            return key2;
-        }
-        @Persist
-        public void setKey2(String key2) {
-            this.key2 = key2;
-        }
-        @Persist
-        public String getKey3() {
-            return key3;
-        }
-        @Persist
-        public void setKey3(String key3) {
-            this.key3 = key3;
-        }
-        @Persist
-        public String getKey4() {
-            return key4;
-        }
-        @Persist
-        public void setKey4(String key4) {
-            this.key4 = key4;
-        }
-    }
-
-    private FindIterable<Document> dbCursor;
-    private Cursor<TestClass> cursor;
-
-    @Before
-    public void setUp() {
-        
-        Document value1 = new Document();
-        value1.put("key1", "test1");
-        value1.put("key2", "test2");
-        Document value2 = new Document();
-        value2.put("key3", "test3");
-        value2.put("key4", "test4");
-
-        @SuppressWarnings("unchecked")
-        FindIterable<Document> local = mock(FindIterable.class);
-        dbCursor = local;
-        when(dbCursor.batchSize(Cursor.DEFAULT_BATCH_SIZE)).thenReturn(dbCursor);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<Document> iterator = mock(com.mongodb.client.MongoCursor.class);
-        when(dbCursor.iterator()).thenReturn(iterator);
-        when(iterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(iterator.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
-        when(dbCursor.sort(any(Document.class))).thenReturn(dbCursor);
-        when(dbCursor.limit(anyInt())).thenReturn(dbCursor);
-        cursor = new MongoCursor<TestClass>(dbCursor, TestClass.class);
-    }
-
-    @After
-    public void tearDown() {
-        dbCursor = null;
-        cursor = null;
-    }
-
-    @Test
-    public void verifySimpleCursor() {
-        assertTrue(cursor.hasNext());
-        TestClass obj1 = cursor.next();
-        assertEquals("test1", obj1.getKey1());
-        assertEquals("test2", obj1.getKey2());
-
-        assertTrue(cursor.hasNext());
-        TestClass obj2 = cursor.next();
-        assertEquals("test3", obj2.getKey3());
-        assertEquals("test4", obj2.getKey4());
-
-        assertFalse(cursor.hasNext());
-        try {
-            cursor.next();
-            fail("Cursor should throw a NoSuchElementException!");
-        } catch (NoSuchElementException e) {
-            // pass
-        }
-    }
-    
-    @Test
-    public void testBatchSize() {
-        @SuppressWarnings("unchecked")
-        FindIterable<Document> findIterable = mock(FindIterable.class);
-        Cursor<TestClass> mC = new MongoCursor<>(findIterable, TestClass.class);
-        verify(findIterable).iterator();
-        try {
-            mC.setBatchSize(-1);
-            fail("expected IAE for batch size of -1");
-        } catch (IllegalArgumentException e) {
-            // pass
-            assertEquals("Batch size must be > 0", e.getMessage());
-        }
-        try {
-            mC.setBatchSize(0);
-            fail("expected IAE for batch size of 0");
-        } catch (IllegalArgumentException e) {
-            // pass
-            assertEquals("Batch size must be > 0", e.getMessage());
-        }
-        // this updates the iterator
-        mC.setBatchSize(333);
-        verify(findIterable).batchSize(333);
-        verifyNoMoreInteractions(findIterable);
-    }
-
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoExpressionParserTest.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.bson.Document;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.query.Expression;
-import com.redhat.thermostat.storage.query.ExpressionFactory;
-
-public class MongoExpressionParserTest {
-    
-    private final Key<Integer> KEY_1 = new Key<>("test");
-    private final Key<Integer> KEY_2 = new Key<>("test2");
-    private final Key<String> KEY_3 = new Key<>("key");
-    
-    private MongoExpressionParser parser;
-    private ExpressionFactory factory;
-
-    @Before
-    public void setUp() throws Exception {
-        parser = new MongoExpressionParser();
-        factory = new ExpressionFactory();
-    }
-
-    @Test
-    public void testWhereEquals() {
-        Expression expr = factory.equalTo(KEY_3, "value");
-        Document query = new Document();
-        query.put(KEY_3.getName(), "value");
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testWhereNotEquals() {
-        Expression expr = factory.notEqualTo(KEY_3, "value");
-        Document query = new Document();
-        Document notEqual = new Document("$ne", "value");
-        query.put(KEY_3.getName(), notEqual);
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testWhereGreaterThan() {
-        Expression expr = factory.greaterThan(KEY_3, "value");
-        Document query = new Document();
-        Document greaterThan = new Document("$gt", "value");
-        query.put(KEY_3.getName(), greaterThan);
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testWhereGreaterThanOrEqualTo() {
-        Expression expr = factory.greaterThanOrEqualTo(KEY_3, "value");
-        Document query = new Document();
-        Document greaterThanEqual = new Document("$gte", "value");
-        query.put(KEY_3.getName(), greaterThanEqual);
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testWhereLessThan() {
-        Expression expr = factory.lessThan(KEY_3, "value");
-        Document query = new Document();
-        Document lessThan = new Document("$lt", "value");
-        query.put(KEY_3.getName(), lessThan);
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testWhereLessThanOrEqualTo() {
-        Expression expr = factory.lessThanOrEqualTo(KEY_3, "value");
-        Document query = new Document();
-        Document lessThanEqual = new Document("$lte", "value");
-        query.put(KEY_3.getName(), lessThanEqual);
-        assertEquals(query, parser.parse(expr));
-    }
-    
-    @Test
-    public void testWhereIn() {
-        Set<String> values = new HashSet<>(Arrays.asList("value", "values"));
-        Expression expr = factory.in(KEY_3, values, String.class);
-        Document query = new Document();
-        Document in = new Document("$in", values);
-        query.put(KEY_3.getName(), in);
-        assertEquals(query, parser.parse(expr));
-    }
-    
-    @Test
-    public void testWhereNotIn() {
-        Set<String> values = new HashSet<>(Arrays.asList("value", "values"));
-        Expression expr = factory.notIn(KEY_3, values, String.class);
-        Document query = new Document();
-        Document notIn = new Document("$nin", values);
-        query.put(KEY_3.getName(), notIn);
-        assertEquals(query, parser.parse(expr));
-    }
-
-    @Test
-    public void testMultiWhere() {
-        Expression expr = factory.and(factory.lessThanOrEqualTo(KEY_1, 1), factory.greaterThan(KEY_1, 2));
-        Document lte = new Document("test", new Document("$lte", 1));
-        Document gt = new Document("test", new Document("$gt", 2));
-        Document and = new Document("$and", Arrays.asList(lte, gt));
-        assertEquals(and, parser.parse(expr));
-    }
-    
-    @Test
-    public void testMultiWhere2() {
-        Expression expr = factory.and(factory.lessThanOrEqualTo(KEY_1, 1), factory.greaterThan(KEY_2, 2));
-
-        Document lte = new Document("test", new Document("$lte", 1));
-        Document gt = new Document("test2", new Document("$gt", 2));
-        Document and = new Document("$and", Arrays.asList(lte, gt));
-        assertEquals(and, parser.parse(expr));
-    }
-    
-    @Test
-    public void testMultiWhere3() {
-        Expression expr = factory.and(factory.equalTo(KEY_1, 1), factory.greaterThan(KEY_1, 2));
-
-        Document eq = new Document("test", 1);
-        Document gt = new Document("test", new Document("$gt", 2));
-        Document and = new Document("$and", Arrays.asList(eq, gt));
-        assertEquals(and, parser.parse(expr));
-    }
-    
-    @Test
-    public void testMultiWhere4() {
-        Expression expr = factory.and(factory.equalTo(KEY_1, 1), factory.greaterThan(KEY_2, 2));
-
-        Document eq = new Document("test", 1);
-        Document gt = new Document("test2", new Document("$gt", 2));
-        Document and = new Document("$and", Arrays.asList(eq, gt));
-        assertEquals(and, parser.parse(expr));
-    }
-    
-    @Test
-    public void testWhereOr() {
-        Expression expr = factory.or(factory.equalTo(KEY_1, 1), factory.greaterThan(KEY_2, 2));
-
-        Document eq = new Document("test", 1);
-        Document gt = new Document("test2", new Document("$gt", 2));
-        Document or = new Document("$or", Arrays.asList(eq, gt));
-        assertEquals(or, parser.parse(expr));
-    }
-    
-    @Test
-    public void testWhereNotCompare() {
-        Expression expr = factory.not(factory.greaterThan(KEY_1, 1));
-
-        Document gt = new Document("$not", new Document("$gt", 1));
-        Document not = new Document("test", gt);
-        assertEquals(not, parser.parse(expr));
-    }
-    
-    @Test
-    public void testWhereNotSetCompare() {
-        Set<Integer> values = new HashSet<>(Arrays.asList(1, 2));
-        Expression expr = factory.not(factory.in(KEY_1, values, Integer.class));
-
-        Document in = new Document("$not", new Document("$in", values));
-        Document not = new Document("test", in);
-        assertEquals(not, parser.parse(expr));
-    }
-    
-    @Test(expected=IllegalArgumentException.class)
-    public void testWhereLogicalNotEquals() {
-        Expression expr = factory.not(factory.equalTo(KEY_1, 1));
-        parser.parse(expr);
-    }
-    
-    @Test
-    public void testWhere3() {
-        Expression expr = factory.and(
-                factory.lessThanOrEqualTo(KEY_3, "value"),
-                factory.and(factory.equalTo(KEY_1, 1),
-                        factory.greaterThan(KEY_2, 2)));
-
-        Document lte = new Document("key", new Document("$lte", "value"));
-        Document eq = new Document("test", 1);
-        Document gt = new Document("test2", new Document("$gt", 2));
-        Document andEqualToGreaterThan = new Document("$and", Arrays.asList(eq, gt));
-        Document and = new Document("$and", Arrays.asList(lte, andEqualToGreaterThan));
-        assertEquals(and, parser.parse(expr));
-    }
-
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoPojoConverterTest.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,327 +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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.bson.Document;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.Entity;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.core.StorageException;
-import com.redhat.thermostat.storage.model.Pojo;
-
-public class MongoPojoConverterTest {
-
-    @Entity
-    public static class SimplePojo implements Pojo {
-        
-        private String test;
-        private String ignored;
-
-
-        @Persist
-        public String getTest() {
-            return test;
-        }
-
-        @Persist
-        public void setTest(String test) {
-            this.test = test;
-        }
-
-        public String getIgnored() {
-            return ignored;
-        }
-
-        public void setIgnored(String ignored) {
-            this.ignored = ignored;
-        }
-        
-    }
-
-    @Entity
-    public static class NestedPojo extends SimplePojo {
-
-        private SimplePojo nested;
-
-        @Persist
-        public SimplePojo getNested() {
-            return nested;
-        }
-
-        @Persist
-        public void setNested(SimplePojo nested) {
-            this.nested = nested;
-        }
-    }
-
-    @Entity
-    public static class IndexedPojo extends SimplePojo {
-
-        private SimplePojo[] indexed;
-
-        @Persist
-        public SimplePojo[] getIndexed() {
-            return indexed;
-        }
-
-        @Persist
-        public void setIndexed(SimplePojo[] indexed) {
-            this.indexed = indexed;
-        }
-    }
-
-    @Entity
-    public static class PrimitiveIndexedPojo extends SimplePojo {
-
-        private int[] indexed;
-
-        @Persist
-        public int[] getIndexed() {
-            return indexed;
-        }
-
-        @Persist
-        public void setIndexed(int[] indexed) {
-            this.indexed = indexed;
-        }
-    }
-
-    public static class BrokenPojo1 extends SimplePojo {
-        @SuppressWarnings("unused")
-        private int broken;
-
-        @Persist
-        public void setBroken(int broken) {
-            this.broken = broken;
-        }
-    }
-
-    public static class BrokenPojo2 extends SimplePojo {
-        private int broken;
-
-        @Persist
-        public void setBroken(int broken) {
-            this.broken = broken;
-        }
-
-        public int getBroken() {
-            return broken;
-        }
-    }
-
-    @Test
-    public void testConvertSimplePojoToMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        SimplePojo obj = new SimplePojo();
-        obj.setTest("fluff");
-        Document dbObject = conv.convertPojoToMongo(obj);
-        assertEquals(1, dbObject.keySet().size());
-        assertEquals("fluff", dbObject.get("test"));
-    }
-
-    @Test
-    public void testConvertSimplePojoFromMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document dbObj = new Document();
-        dbObj.put("test", "fluff");
-        SimplePojo obj = conv.convertMongoToPojo(dbObj, SimplePojo.class);
-        assertEquals("fluff", obj.getTest());
-        assertNull(obj.getIgnored());
-    }
-
-    @Test(expected=StorageException.class)
-    public void testConvertSimplePojoFromMongoExtraProperty() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document dbObj = new Document();
-        dbObj.put("test", "fluff");
-        dbObj.put("foo", "bar");
-        conv.convertMongoToPojo(dbObj, SimplePojo.class);
-    }
-
-    @Test(expected=StorageException.class)
-    public void testConvertSimplePojoFromMongoBrokenPojo1() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document dbObj = new Document();
-        dbObj.put("broken", "foo");
-        conv.convertMongoToPojo(dbObj, BrokenPojo1.class);
-    }
-
-
-    @Test(expected=StorageException.class)
-    public void testConvertSimplePojoFromMongoBrokenPojo2() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document dbObj = new Document();
-        dbObj.put("broken", "foo");
-        conv.convertMongoToPojo(dbObj, BrokenPojo2.class);
-    }
-
-    @Test
-    public void testConvertNestedPojoToMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        NestedPojo obj = new NestedPojo();
-        obj.setTest("foo");
-        SimplePojo nested = new SimplePojo();
-        nested.setTest("bar");
-        obj.setNested(nested);
-        Document dbObject = conv.convertPojoToMongo(obj);
-        assertEquals(2, dbObject.keySet().size());
-        assertEquals("foo", dbObject.get("test"));
-        Document nestedDbObj = (Document) dbObject.get("nested");
-        assertEquals(1, nestedDbObj.keySet().size());
-        assertEquals("bar", nestedDbObj.get("test"));
-    }
-
-    @Test
-    public void testConvertNestedPojoFromMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document nested = new Document();
-        nested.put("test", "bar");
-        Document dbObj = new Document();
-        dbObj.put("test", "foo");
-        dbObj.put("nested", nested);
-        NestedPojo obj = conv.convertMongoToPojo(dbObj, NestedPojo.class);
-        assertEquals("foo", obj.getTest());
-        assertNull(obj.getIgnored());
-        assertNotNull(obj.getNested());
-        assertEquals("bar", obj.getNested().getTest());
-        assertEquals(null, obj.getNested().getIgnored());
-    }
-
-    @Test
-    public void testConvertIndexedPojoToMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        IndexedPojo obj = new IndexedPojo();
-        obj.setTest("test");
-        SimplePojo obj1 = new SimplePojo();
-        obj1.setTest("test1");
-        SimplePojo obj2 = new SimplePojo();
-        obj2.setTest("test2");
-        SimplePojo obj3 = new SimplePojo();
-        obj3.setTest("test3");
-        obj.setIndexed(new SimplePojo[] { obj1, obj2, obj3 });
-
-        Document dbObject = conv.convertPojoToMongo(obj);
-        assertEquals(2, dbObject.keySet().size());
-        assertEquals("test", dbObject.get("test"));
-        List<?> indexedDbObj = (List<?>) dbObject.get("indexed");
-        assertEquals(3, indexedDbObj.size());
-
-        Document dbObj1 = (Document) indexedDbObj.get(0);
-        assertEquals(1, dbObj1.keySet().size());
-        assertEquals("test1", dbObj1.get("test"));
-
-        Document dbObj2 = (Document) indexedDbObj.get(1);
-        assertEquals(1, dbObj2.keySet().size());
-        assertEquals("test2", dbObj2.get("test"));
-
-        Document dbObj3 = (Document) indexedDbObj.get(2);
-        assertEquals(1, dbObj3.keySet().size());
-        assertEquals("test3", dbObj3.get("test"));
-    }
-
-    @Test
-    public void testConvertPrimitiveIndexedPojoToMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        PrimitiveIndexedPojo obj = new PrimitiveIndexedPojo();
-        obj.setTest("test");
-        obj.setIndexed(new int[] { 1, 2, 3 });
-
-        Document dbObject = conv.convertPojoToMongo(obj);
-        assertEquals(2, dbObject.keySet().size());
-        assertEquals("test", dbObject.get("test"));
-        List<?> indexedDbObj = (List<?>) dbObject.get("indexed");
-        assertEquals(3, indexedDbObj.size());
-
-        assertEquals(1, indexedDbObj.get(0));
-        assertEquals(2, indexedDbObj.get(1));
-        assertEquals(3, indexedDbObj.get(2));
-
-    }
-
-    @Test
-    public void testConvertIndexedPojoFromMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document indexed = new Document();
-        indexed.put("test", "test");
-        Document dbObj1 = new Document();
-        dbObj1.put("test", "test1");
-        Document dbObj2 = new Document();
-        dbObj2.put("test", "test2");
-        Document dbObj3 = new Document();
-        dbObj3.put("test", "test3");
-        indexed.put("indexed", Arrays.asList(dbObj1, dbObj2, dbObj3));
-
-        IndexedPojo obj = conv.convertMongoToPojo(indexed, IndexedPojo.class);
-        assertEquals("test", obj.getTest());
-        assertNull(obj.getIgnored());
-        assertNotNull(obj.getIndexed());
-        SimplePojo[] indexedObj = obj.getIndexed();
-        assertEquals("test1", indexedObj[0].getTest());
-        assertNull(indexedObj[0].getIgnored());
-        assertEquals("test2", indexedObj[1].getTest());
-        assertNull(indexedObj[1].getIgnored());
-        assertEquals("test3", indexedObj[2].getTest());
-        assertNull(indexedObj[2].getIgnored());
-    }
-
-    @Test
-    public void testConvertPrimitiveIndexedPojoFromMongo() {
-        MongoPojoConverter conv = new MongoPojoConverter();
-        Document indexed = new Document();
-        indexed.put("test", "test");
-        indexed.put("indexed", Arrays.asList(1, 2, 3));
-
-        PrimitiveIndexedPojo obj = conv.convertMongoToPojo(indexed, PrimitiveIndexedPojo.class);
-        assertEquals("test", obj.getTest());
-        assertNull(obj.getIgnored());
-        assertNotNull(obj.getIndexed());
-        int[] indexedObj = obj.getIndexed();
-        assertEquals(1, indexedObj[0]);
-        assertEquals(2, indexedObj[1]);
-        assertEquals(3, indexedObj[2]);
-    }
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoQueryTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.bson.Document;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.storage.query.Expression;
-
-public class MongoQueryTest {
-    
-    private static class TestClass implements Pojo {
-        
-    }
-
-    private static MongoStorage storage;
-    private static Category<TestClass> category;
-    private static MongoExpressionParser parser;
-    private static Document dbObject;
-
-    @BeforeClass
-    public static void setUp() {
-        storage = mock(MongoStorage.class);
-        category = new Category<>("some-collection", TestClass.class);
-        parser = mock(MongoExpressionParser.class);
-        dbObject = new Document();
-        when(parser.parse(any(Expression.class))).thenReturn(dbObject);
-    }
-
-    @AfterClass
-    public static void tearDown() {
-        storage = null;
-        category = null;
-        parser = null;
-    }
-
-    @Test
-    public void testEmptyQuery() {
-        MongoQuery<TestClass> query = new MongoQuery<>(storage, category, parser);
-        Document mongoQuery = query.getGeneratedQuery();
-        assertFalse(query.hasClauses());
-        assertTrue(mongoQuery.keySet().isEmpty());
-    }
-
-    @Test
-    public void testCollectionName() {
-        MongoQuery<TestClass> query = new MongoQuery<>(storage, category, parser);
-        assertEquals("some-collection", query.getCategory().getName());
-    }
-    
-    @Test
-    public void testWhere() {
-        MongoQuery<TestClass> query = new MongoQuery<>(storage, category, parser);
-        Expression expr = mock(Expression.class);
-        query.where(expr);
-        Document generatedQuery = query.getGeneratedQuery();
-        assertTrue(query.hasClauses());
-        assertEquals(dbObject, generatedQuery);
-    }
-    
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageProviderTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-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.mongodb.MongoStorageProvider;
-
-public class MongoStorageProviderTest {
-
-    @Test
-    public void createStorageReturnsQueuedStorage() {
-        MongoStorageProvider provider = new MongoStorageProvider();
-        provider.setConfig("mongodb://something.com", null, null);
-        Storage result = provider.createStorage();
-        assertTrue(result instanceof QueuedStorage);
-        assertFalse(result instanceof SecureStorage);
-    }
-
-    @Test
-    public void canHandleMongoProtocol() {
-        MongoStorageProvider provider = new MongoStorageProvider();
-        provider.setConfig("mongodb://something.com", null, null);
-        assertTrue(provider.canHandleProtocol());
-    }
-
-    @Test
-    public void cannotHandleNotMongoProtocol() {
-        MongoStorageProvider provider = new MongoStorageProvider();
-        provider.setConfig("http://something.com", null, null);
-        assertFalse(provider.canHandleProtocol());
-    }
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorageTest.java	Wed May 10 15:59:23 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,948 +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.storage.mongodb.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.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.concurrent.CountDownLatch;
-
-import org.bson.Document;
-import org.bson.conversions.Bson;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PowerMockIgnore;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import com.mongodb.MongoClient;
-import com.mongodb.client.DistinctIterable;
-import com.mongodb.client.FindIterable;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoDatabase;
-import com.mongodb.client.MongoIterable;
-import com.mongodb.client.gridfs.GridFSBucket;
-import com.mongodb.client.model.CreateCollectionOptions;
-import com.mongodb.client.model.UpdateOptions;
-import com.mongodb.client.result.DeleteResult;
-import com.mongodb.client.result.UpdateResult;
-import com.redhat.thermostat.common.internal.test.Bug;
-import com.redhat.thermostat.shared.config.SSLConfiguration;
-import com.redhat.thermostat.storage.core.Add;
-import com.redhat.thermostat.storage.core.AggregateQuery;
-import com.redhat.thermostat.storage.core.AggregateQuery.AggregateFunction;
-import com.redhat.thermostat.storage.core.BackingStorage;
-import com.redhat.thermostat.storage.core.Category;
-import com.redhat.thermostat.storage.core.CategoryAdapter;
-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.Entity;
-import com.redhat.thermostat.storage.core.Key;
-import com.redhat.thermostat.storage.core.Persist;
-import com.redhat.thermostat.storage.core.Query;
-import com.redhat.thermostat.storage.core.Remove;
-import com.redhat.thermostat.storage.core.Replace;
-import com.redhat.thermostat.storage.core.SaveFileListener;
-import com.redhat.thermostat.storage.core.SaveFileListener.EventType;
-import com.redhat.thermostat.storage.core.SchemaInfo;
-import com.redhat.thermostat.storage.core.Statement;
-import com.redhat.thermostat.storage.core.StorageCredentials;
-import com.redhat.thermostat.storage.core.Update;
-import com.redhat.thermostat.storage.model.AggregateCount;
-import com.redhat.thermostat.storage.model.BasePojo;
-import com.redhat.thermostat.storage.model.DistinctResult;
-import com.redhat.thermostat.storage.model.Pojo;
-import com.redhat.thermostat.storage.query.Expression;
-import com.redhat.thermostat.storage.query.ExpressionFactory;
-
-//There is a bug (resolved as wontfix) in powermock which results in
-//java.lang.LinkageError if javax.management.* classes aren't ignored by
-//Powermock. More here: http://code.google.com/p/powermock/issues/detail?id=277
-//SSL tests need this and having that annotation on method level doesn't seem
-//to solve the issue.
-@PowerMockIgnore( {"javax.management.*"})
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ MongoCollection.class, MongoDatabase.class, MongoStorage.class, MongoConnection.class })
-public class MongoStorageTest {
-
-    @Entity
-    public static class TestClass extends BasePojo {
-        
-        public TestClass() {
-            super(null);
-        }
-        private String key1;
-        private String key2;
-        private String key3;
-        private String key4;
-        private String key5;
-        @Persist
-        public String getKey1() {
-            return key1;
-        }
-        @Persist
-        public void setKey1(String key1) {
-            this.key1 = key1;
-        }
-        @Persist
-        public String getKey2() {
-            return key2;
-        }
-        @Persist
-        public void setKey2(String key2) {
-            this.key2 = key2;
-        }
-        @Persist
-        public String getKey3() {
-            return key3;
-        }
-        @Persist
-        public void setKey3(String key3) {
-            this.key3 = key3;
-        }
-        @Persist
-        public String getKey4() {
-            return key4;
-        }
-        @Persist
-        public void setKey4(String key4) {
-            this.key4 = key4;
-        }
-        @Persist
-        public String getKey5() {
-            return key5;
-        }
-        @Persist
-        public void setKey5(String key5) {
-            this.key5 = key5;
-        }
-    }
-
-    private static final Key<String> key1 = new Key<>("key1");
-    private static final Key<String> key2 = new Key<>("key2");
-    private static final Key<String> key3 = new Key<>("key3");
-    private static final Key<String> key4 = new Key<>("key4");
-    private static final Key<String> key5 = new Key<>("key5");
-    private static final Category<TestClass> testCategory = new Category<>("MongoStorageTest", TestClass.class, key1, key2, key3, key4, key5);
-    private static final Category<TestClass> emptyTestCategory = new Category<>("MongoEmptyCategory", TestClass.class);
-
-    private String url;
-    private StorageCredentials creds;
-    private SSLConfiguration sslConf;
-    private MongoClient m;
-    private MongoDatabase db;
-    private MongoCollection<Document> testCollection, emptyTestCollection, mockedCollection;
-    private FindIterable<Document> cursor;
-    private ExpressionFactory factory;
-
-    private MongoStorage makeStorage() {
-        MongoStorage storage = new MongoStorage(url, creds, sslConf);
-        storage.mapCategoryToDBCollection(testCategory, testCollection);
-        storage.mapCategoryToDBCollection(emptyTestCategory, emptyTestCollection);
-        return storage;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setUp() throws Exception {
-        url = "mongodb://127.0.0.1:27518";
-        creds = mock(StorageCredentials.class);
-        sslConf = mock(SSLConfiguration.class);
-        db = PowerMockito.mock(MongoDatabase.class);
-        m = PowerMockito.mock(MongoClient.class);
-        mockedCollection = mock(MongoCollection.class);
-        when(m.getDatabase(anyString())).thenReturn(db);
-        when(db.getCollection("agent-config")).thenReturn(mockedCollection);
-
-        Document value1 = new Document();
-        value1.put("key1", "test1");
-        value1.put("key2", "test2");
-        Document value2 = new Document();
-        value2.put("key3", "test3");
-        value2.put("key4", "test4");
-
-        cursor = mock(FindIterable.class);
-        com.mongodb.client.MongoCursor<Document> mongoCursor = mock(com.mongodb.client.MongoCursor.class);
-        
-        when(cursor.iterator()).thenReturn(mongoCursor);
-        when(mongoCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(mongoCursor.next()).thenReturn(value1).thenReturn(value2).thenReturn(null);
-
-        testCollection = PowerMockito.mock(MongoCollection.class);
-        when(testCollection.find(any(Document.class))).thenReturn(cursor);
-        when(testCollection.find()).thenReturn(cursor);
-        when(testCollection.count()).thenReturn(2L);
-        
-        // mock for remove
-        DeleteResult result = mock(DeleteResult.class);
-        when(testCollection.deleteOne(any(Document.class))).thenReturn(result);
-        when(result.getDeletedCount()).thenReturn(1L);
-        // mock for update
-        UpdateResult updateResult = mock(UpdateResult.class);
-        when(updateResult.getModifiedCount()).thenReturn(1L);
-        when(testCollection.updateOne(any(Document.class), any(Document.class))).thenReturn(updateResult);
-        // mock for replace
-        UpdateResult replaceResult = mock(UpdateResult.class);
-        when(replaceResult.getModifiedCount()).thenReturn(2L);
-        when(testCollection.replaceOne(any(Document.class), any(Document.class))).thenReturn(replaceResult);
-        
-        emptyTestCollection = PowerMockito.mock(MongoCollection.class);
-        when(emptyTestCollection.count()).thenReturn(0L);
-        
-        factory = new ExpressionFactory();
-        
-        MongoIterable<String> mongoIterable = mock(MongoIterable.class);
-        com.mongodb.client.MongoCursor<String> it = mock(com.mongodb.client.MongoCursor.class);
-        when(it.hasNext()).thenReturn(true).thenReturn(true);
-        when(it.next()).thenReturn("testCollection").thenReturn("emptyTestCollection");
-        when(mongoIterable.iterator()).thenReturn(it);
-        when(db.listCollectionNames()).thenReturn(mongoIterable);
-        when(db.getCollection("testCollection")).thenReturn(testCollection);
-        when(db.getCollection("emptyTestCollection")).thenReturn(emptyTestCollection);
-    }
-
-    @After
-    public void tearDown() {
-        url = null;
-        m = null;
-        db = null;
-        testCollection = null;
-        emptyTestCollection = null;
-        cursor = null;
-    }
-    
-    @Test
-    public void isBackingStorage() {
-        MongoStorage storage = new MongoStorage(url, creds, sslConf);
-        assertTrue(storage instanceof BackingStorage);
-    }
-    
-    @Test
-    public void verifyConnectEventSetsDb() {
-        MongoConnection mockConnection = mock(MongoConnection.class);
-        
-        // This adds a listener which we capture
-        new MongoStorage(mockConnection);
-        ArgumentCaptor<ConnectionListener> captor = ArgumentCaptor.forClass(ConnectionListener.class);
-        verify(mockConnection).addListener(captor.capture());
-        ConnectionListener listener = captor.getValue();
-        assertNotNull(listener);
-        when(mockConnection.getDatabase()).thenReturn(db);
-        @SuppressWarnings("unchecked")
-        MongoIterable<String> mockIterable = mock(MongoIterable.class);
-        when(db.listCollectionNames()).thenReturn(mockIterable);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor = mock(com.mongodb.client.MongoCursor.class);
-        when(mockCursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(mockCursor.next()).thenReturn("foo-bar-collection");
-        when(mockIterable.iterator()).thenReturn(mockCursor);
-        listener.changed(ConnectionStatus.CONNECTED);
-        verify(mockConnection).getDatabase();
-        verify(db).createCollection(eq("schema-info"), any(CreateCollectionOptions.class));
-    }
-
-    @Bug(id="PR2941",
-            url="http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=2941",
-            summary="Multiple clients rapidly connecting to webstorage produces exceptions")
-    @Test
-    public void verifyConnectionOnlyInitializesDbOnce() {
-        MongoConnection mockConnection = mock(MongoConnection.class);
-
-        // This adds a listener which we capture
-        new MongoStorage(mockConnection);
-        ArgumentCaptor<ConnectionListener> captor = ArgumentCaptor.forClass(ConnectionListener.class);
-        verify(mockConnection).addListener(captor.capture());
-        ConnectionListener listener = captor.getValue();
-        assertNotNull(listener);
-        when(mockConnection.getDatabase()).thenReturn(db);
-        @SuppressWarnings("unchecked")
-        MongoIterable<String> mockIterable = mock(MongoIterable.class);
-        when(db.listCollectionNames()).thenReturn(mockIterable);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor = mock(com.mongodb.client.MongoCursor.class);
-        when(mockCursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(mockCursor.next()).thenReturn("foo-bar-collection");
-        when(mockIterable.iterator()).thenReturn(mockCursor);
-
-        listener.changed(ConnectionStatus.CONNECTED);
-        verify(mockConnection).getDatabase();
-        verify(db).createCollection(eq("schema-info"), any(CreateCollectionOptions.class));
-
-        // verify the MongoStorage isn't reinitializing on the second connection success
-        listener.changed(ConnectionStatus.CONNECTED);
-        verify(mockConnection).getDatabase();
-        verify(db).createCollection(eq("schema-info"), any(CreateCollectionOptions.class));
-    }
-    
-    @Test(expected=NullPointerException.class)
-    public void verifyDisconnectedEventInvalidatesDb() {
-        MongoConnection mockConnection = mock(MongoConnection.class);
-        
-        // This adds a listener which we capture
-        MongoStorage storage = new MongoStorage(mockConnection);
-        
-        ArgumentCaptor<ConnectionListener> captor = ArgumentCaptor.forClass(ConnectionListener.class);
-        verify(mockConnection).addListener(captor.capture());
-        ConnectionListener listener = captor.getValue();
-        assertNotNull(listener);
-        
-        // fire a connecting event for good measure. It should do nothing.
-        listener.changed(ConnectionStatus.CONNECTING);
-        
-        listener.changed(ConnectionStatus.CONNECTED);
-        verify(mockConnection).getDatabase();
-        
-        // This should set the db instance to null
-        listener.changed(ConnectionStatus.DISCONNECTED);
-        
-        @SuppressWarnings("unchecked")
-        Category<FakeDataClass> cat = mock(Category.class);
-        when(cat.getDataClass()).thenReturn(FakeDataClass.class);
-        // this throws NPE due to the null DB instance
-        storage.registerCategory(cat);
-    }
-    
-    @Test
-    public void testRegisterCategory() throws Exception {
-        MongoDatabase db = PowerMockito.mock(MongoDatabase.class);
-        CountDownLatch latch = new CountDownLatch(1);
-        MongoStorage storage = new MongoStorage(db, latch);
-        latch.countDown();
-        
-        when(db.getCollection(SchemaInfo.CATEGORY.getName())).thenReturn(testCollection);
-        storage.registerCategory(SchemaInfo.CATEGORY);
-        verify(db, times(0)).createCollection(eq(SchemaInfo.CATEGORY.getName()), any(CreateCollectionOptions.class));
-        verify(testCollection, times(0)).replaceOne(any(Document.class), any(Document.class));
-        try {
-            storage.registerCategory(SchemaInfo.CATEGORY);
-            fail();
-        } catch (IllegalStateException ex) {
-            assertEquals("Category may only be associated with one backend.", ex.getMessage());
-        }
-        
-        @SuppressWarnings("unchecked")
-        MongoIterable<String> mockIterable = mock(MongoIterable.class);
-        when(db.listCollectionNames()).thenReturn(mockIterable);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor = mock(com.mongodb.client.MongoCursor.class);
-        when(mockIterable.iterator()).thenReturn(mockCursor);
-        Key<String> key = new Key<>("key1");
-        Category<TestObj> category = new Category<>("testRegisterCategory", TestObj.class, key);
-        storage.registerCategory(category);
-        Category<AggregateCount> countCat = new CategoryAdapter<TestObj, AggregateCount>(category).getAdapted(AggregateCount.class);
-        storage.registerCategory(countCat);
-        
-        ArgumentCaptor<Document> msgCaptor = ArgumentCaptor.forClass(Document.class);
-        ArgumentCaptor<Document> msgCaptor2 = ArgumentCaptor.forClass(Document.class);
-        Document expectedObject1 = new Document(SchemaInfo.NAME.getName(), category.getName());
-        
-        verify(testCollection).replaceOne(msgCaptor.capture(), msgCaptor2.capture(), any(UpdateOptions.class));
-        
-        Document resultObject1 = msgCaptor.getValue();
-        Document resultObject2 = msgCaptor2.getValue();
-       
-        assertEquals(expectedObject1, resultObject1);
-        assertTrue(resultObject2.get(SchemaInfo.NAME.getName()) != null);
-        assertTrue(resultObject2.get(Key.TIMESTAMP.getName()) != null);
-        
-        assertEquals(category.getName(), resultObject2.get(SchemaInfo.NAME.getName()));
-        assertNotNull(resultObject2.get(Key.TIMESTAMP.getName()));
-    }
-    
-    private static class TestObj implements Pojo {
-        // Dummy class for testing.
-    }
-
-    @Test
-    public void verifyFindAllReturnsCursor() throws Exception {
-        MongoStorage storage = makeStorage();
-        Query<TestClass> query = storage.createQuery(testCategory);
-        Cursor<TestClass> cursor = query.execute();
-        assertNotNull(cursor);
-    }
-
-    @Test
-    public void verifyFindAllCallsDBCollectionFind() throws Exception {
-        MongoStorage storage = makeStorage();
-        Query<TestClass> query = storage.createQuery(testCategory);
-        ExpressionFactory factory = new ExpressionFactory();
-        Expression expr = factory.equalTo(key1, "fluff");
-        query.where(expr);
-        query.execute();
-        verify(testCollection).find(any(Document.class));
-    }
-
-    @Test
-    public void verifyFindAllCallsDBCollectionFindWithCorrectQuery() throws Exception {
-        MongoStorage storage = makeStorage();
-
-        @SuppressWarnings("unchecked")
-        MongoQuery<TestClass> query = mock(MongoQuery.class);
-        when(query.hasClauses()).thenReturn(true);
-        Document generatedQuery = mock(Document.class);
-        when(query.getGeneratedQuery()).thenReturn(generatedQuery);
-        when(query.getCategory()).thenReturn(testCategory);
-
-        storage.findAllPojos(query, TestClass.class);
-
-        verify(testCollection).find(same(generatedQuery));
-    }
-
-    @Test
-    public void verifyFindAllReturnsCorrectCursor() throws Exception {
-        MongoStorage storage = makeStorage();
-        // TODO find a way to test this that isn't just testing MongoCursor
-        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        Query<TestClass> query = storage.createQuery(testCategory);
-        Cursor<TestClass> cursor = query.execute();
-
-        verifyDefaultCursor(cursor);
-    }
-
-    @Test
-    public void verifyFindAllWithSortAndLimit() throws Exception {
-        MongoStorage storage = makeStorage();
-        // TODO find a way to test this that isn't just testing MongoCursor
-        // Because we mock the DBCollection, the contents of this query don't actually determine the result.
-        Query<TestClass> query = storage.createQuery(testCategory);
-        query.sort(key1, Query.SortDirection.ASCENDING);
-        query.limit(3);
-
-        Cursor<TestClass> cursor = query.execute();
-
-        verifyDefaultCursor(cursor);
-        ArgumentCaptor<Document> orderBy = ArgumentCaptor.forClass(Document.class);
-        verify(this.cursor).sort(orderBy.capture());
-        assertTrue(orderBy.getValue().get("key1") != null);
-        assertEquals(1, orderBy.getValue().get("key1"));
-        verify(this.cursor).limit(3);
-    }
-
-    @Test
-    public void verifyFindAllFromCategoryCallsDBCollectionFindAll() throws Exception {
-        MongoStorage storage = makeStorage();
-        Query<TestClass> query = storage.createQuery(testCategory);
-        query.execute();
-        verify(testCollection).find();
-    }
-
-    @Test
-    public void verifyFindAllFromCategoryReturnsCorrectCursor() throws Exception {
-        MongoStorage storage = makeStorage();
-        Query<TestClass> query = storage.createQuery(testCategory);
-        Cursor<TestClass> cursor = query.execute();
-
-        verifyDefaultCursor(cursor);
-    }
-
-    private void verifyDefaultCursor(Cursor<TestClass> cursor) {
-        assertTrue(cursor.hasNext());
-        TestClass obj1 = cursor.next();
-        assertEquals("test1", obj1.getKey1());
-        assertEquals("test2", obj1.getKey2());
-
-        assertTrue(cursor.hasNext());
-        TestClass obj2 = cursor.next();
-        assertEquals("test3", obj2.getKey3());
-        assertEquals("test4", obj2.getKey4());
-
-        assertFalse(cursor.hasNext());
-        try {
-            cursor.next();
-            fail("Cursor should throw a NoSuchElementException!");
-        } catch (NoSuchElementException e) {
-            // pass
-        }
-    }
-
-    @Test (expected=NullPointerException.class)
-    public void verifySaveFileNullListenerThrowsException() throws Exception{
-        InputStream dataStream = new ByteArrayInputStream(new byte[0]);
-        MongoStorage storage = makeStorage();
-        storage.saveFile("test", dataStream, null);
-    }
-
-    @Test
-    public void verifySaveFile() throws Exception {
-        byte[] data = new byte[] { 1, 2, 3 };
-        InputStream dataStream = new ByteArrayInputStream(data);
-
-        SaveFileListener saveFileListener = mock(SaveFileListener.class);
-
-        CountDownLatch latch = new CountDownLatch(0);
-        MongoDatabase db = mock(MongoDatabase.class);
-        final GridFSBucket mockBucket = mock(GridFSBucket.class);
-        MongoStorage storage = new MongoStorage(db, latch) {
-            
-            @Override
-            GridFSBucket createGridFSBucket() {
-                return mockBucket;
-            }
-        };
-        storage.saveFile("test", dataStream, saveFileListener);
-
-        verify(saveFileListener).notify(EventType.SAVE_COMPLETE, null);
-        verify(mockBucket).uploadFromStream("test", dataStream);
-    }
-
-    @Test
-    public void verifyPutChunkUsesCorrectChunkAgent() throws Exception {
-        MongoStorage storage = makeStorage();
-        TestClass pojo = new TestClass();
-        pojo.setAgentId("123");
-        Add<TestClass> add = storage.createAdd(testCategory);
-        add.set(Key.AGENT_ID.getName(), pojo.getAgentId());
-        add.apply();
-        ArgumentCaptor<Document> dbobj = ArgumentCaptor.forClass(Document.class);
-        verify(testCollection).insertOne(dbobj.capture());
-        Document val = dbobj.getValue();
-        assertEquals("123", val.get("agentId"));
-    }
-    
-    /*
-     *  This test verifies if pojo types get converted correctly. This
-     *  add isn't really using the correct type parameter. It should be using
-     *  a pojo which has itself Pojo properties defined. For the sake of this
-     *  test this "hack" should be sufficient.
-     */
-    @Test
-    public void verifyPojoTypeGetsConverted() throws Exception {
-        MongoStorage storage = makeStorage();
-        TestClass pojo = new TestClass();
-        pojo.setKey1("val1");
-        pojo.setKey3("val3");
-        Add<?> add = storage.createAdd(testCategory);
-        add.set("agentId", "ignored");
-        add.set("foo-pojo-key", pojo);
-        add.apply();
-        ArgumentCaptor<Document> dbobj = ArgumentCaptor.forClass(Document.class);
-        verify(testCollection).insertOne(dbobj.capture());
-        Document val = dbobj.getValue();
-        assertTrue(val.get("foo-pojo-key") instanceof Document);
-        Document pojoVal = (Document)val.get("foo-pojo-key");
-        assertEquals("val1", pojoVal.get("key1"));
-        assertEquals("val3", pojoVal.get("key3"));
-    }
-    
-    @Test
-    public void verifyPojoListGetsConverted() throws Exception {
-        MongoStorage storage = makeStorage();
-        TestClass pojo = new TestClass();
-        pojo.setKey1("val1");
-        pojo.setKey3("val3");
-        TestClass[] list = new TestClass[] { pojo };
-        Add<?> add = storage.createAdd(testCategory);
-        add.set("agentId", "ignored");
-        add.set("foo-pojo-key", list);
-        add.apply();
-        ArgumentCaptor<Document> dbobj = ArgumentCaptor.forClass(Document.class);
-        verify(testCollection).insertOne(dbobj.capture());
-        Document val = dbobj.getValue();
-        assertTrue(val.get("foo-pojo-key") instanceof List);
-        @SuppressWarnings("unchecked")
-        List<Document> result = (List<Document>)val.get("foo-pojo-key");
-        assertEquals(1, result.size());
-        Document pojoVal = result.get(0);
-        assertEquals("val1", pojoVal.get("key1"));
-        assertEquals("val3", pojoVal.get("key3"));
-    }
-    
-    @Test
-    public void verifyAggregateDistinct() throws Exception {
-        // setup
-        @SuppressWarnings("unchecked")
-        DistinctIterable<String> iterable = mock(DistinctIterable.class);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor = mock(com.mongodb.client.MongoCursor.class);
-        when(iterable.iterator()).thenReturn(mockCursor);
-        when(mockCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(mockCursor.next()).thenReturn("-1").thenReturn("200");
-        when(testCollection.distinct(eq(key1.getName()), any(Document.class), eq(String.class))).thenReturn(iterable);
-        
-        MongoStorage storage = makeStorage();
-        CategoryAdapter<TestClass, DistinctResult> adapter = new CategoryAdapter<>(testCategory);
-        Category<DistinctResult> adaptedCategory = adapter.getAdapted(DistinctResult.class);
-        AggregateQuery<DistinctResult> aggQuery = storage.createAggregateQuery(AggregateFunction.DISTINCT, adaptedCategory);
-        aggQuery.setAggregateKey(key1);
-        Cursor<DistinctResult> cursor = aggQuery.execute();
-        assertTrue(cursor.hasNext());
-        DistinctResult r = cursor.next();
-        String[] expected = new String[] { "-1", "200" };
-        assertArrayEquals(expected, r.getValues());
-        assertEquals(key1, r.getKey());
-        
-        // do it again with a list of booleans
-        @SuppressWarnings("unchecked")
-        DistinctIterable<String> iterable2 = mock(DistinctIterable.class);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor2 = mock(com.mongodb.client.MongoCursor.class);
-        when(iterable2.iterator()).thenReturn(mockCursor2);
-        when(mockCursor2.hasNext()).thenReturn(true).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(mockCursor2.next()).thenReturn("false").thenReturn("true").thenReturn("true");
-        when(testCollection.distinct(eq(key2.getName()), any(Document.class), eq(String.class))).thenReturn(iterable2);
-        aggQuery = storage.createAggregateQuery(AggregateFunction.DISTINCT, adaptedCategory);
-        aggQuery.setAggregateKey(key2);
-        cursor = aggQuery.execute();
-        assertTrue(cursor.hasNext());
-        r = cursor.next();
-        expected = new String[] { "false", "true", "true" };
-        assertArrayEquals(expected, r.getValues());
-        assertEquals(key2, r.getKey());
-    }
-    
-    /*
-     * The statement descriptor subsystem uses getRawDuplicate. That duplicate
-     * needs to keep the key parameter set for distinct aggregate queries.
-     */
-    @Test
-    public void canDuplicateAggregateDistinct() throws Exception {
-        MongoStorage storage = makeStorage();
-        CategoryAdapter<TestClass, DistinctResult> adapter = new CategoryAdapter<>(testCategory);
-        Category<DistinctResult> adaptedCategory = adapter.getAdapted(DistinctResult.class);
-        AggregateQuery<DistinctResult> aggQuery = storage.createAggregateQuery(AggregateFunction.DISTINCT, adaptedCategory);
-        assertNull(aggQuery.getAggregateKey());
-        aggQuery.setAggregateKey(key1);
-        
-        Statement<DistinctResult> stmt = aggQuery.getRawDuplicate();
-        AggregateQuery<DistinctResult> rawCopy = (AggregateQuery<DistinctResult>) stmt;
-        assertEquals("Expected key to be copied for dupe", key1, rawCopy.getAggregateKey());
-    }
-    
-    /*
-     * The statement descriptor subsystem uses getRawDuplicate. That duplicate
-     * needs to keep the key parameter if set for count aggregates.
-     */
-    @Test
-    public void canDuplicateAggregateCountWithKey() throws Exception {
-        MongoStorage storage = makeStorage();
-        CategoryAdapter<TestClass, AggregateCount> adapter = new CategoryAdapter<>(testCategory);
-        Category<AggregateCount> adaptedCategory = adapter.getAdapted(AggregateCount.class);
-        AggregateQuery<AggregateCount> aggQuery = storage.createAggregateQuery(AggregateFunction.COUNT, adaptedCategory);
-        
-        // Produce duplicate without key set
-        assertNull(aggQuery.getAggregateKey());
-        Statement<AggregateCount> stmt = aggQuery.getRawDuplicate();
-        assertTrue(stmt instanceof AggregateQuery);
-        AggregateQuery<AggregateCount> rawCopy = (AggregateQuery<AggregateCount>) stmt;
-
-        // Duplicate with key set
-        aggQuery.setAggregateKey(key1);
-        assertNotNull(aggQuery.getAggregateKey());
-        stmt = aggQuery.getRawDuplicate();
-        assertTrue(stmt instanceof AggregateQuery);
-        rawCopy = (AggregateQuery<AggregateCount>) stmt;
-        assertEquals("Expected key to be copied for dupe", key1, rawCopy.getAggregateKey());
-    }
-    
-    private static void assertArrayEquals(String[] expected, String[] actual) {
-        assertEquals(expected.length, actual.length);
-        for (int i = 0; i < expected.length; i++) {
-            assertEquals(expected[i], actual[i]);
-        }
-    }
-
-    @Test
-    public void verifyPutChunkDoesNotUseGlobalAgent() throws Exception {
-        MongoStorage storage = makeStorage();
-        Add<TestClass> add = storage.createAdd(testCategory);
-        try {
-            add.apply();
-            fail("We do not allow null agentId");
-        } catch (AssertionError e) {
-            // pass
-        }
-        Replace<TestClass> replace = storage.createReplace(testCategory);
-        ExpressionFactory factory = new ExpressionFactory();
-        Expression whereExp = factory.equalTo(Key.AGENT_ID, "foobar");
-        replace.where(whereExp);
-        try {
-            replace.apply();
-            fail("We do not allow null agentId");
-        } catch (AssertionError e) {
-            // pass
-        }
-    }
-
-    @Test
-    public void verifyLoadFile() throws Exception {
-        final GridFSBucket mockBucket = mock(GridFSBucket.class);
-        MongoStorage storage = new MongoStorage(mock(MongoDatabase.class), new CountDownLatch(0)) {
-            
-            @Override
-            GridFSBucket createGridFSBucket() {
-                return mockBucket;
-            }
-        };
-        storage.loadFile("test");
-        verify(mockBucket).openDownloadStreamByName("test");
-    }
-
-    @Test
-    public void verifySimpleUpdate() {
-        MongoStorage storage = makeStorage();
-        Update<TestClass> update = storage.createUpdate(testCategory);
-        Expression expr = factory.equalTo(Key.AGENT_ID, "test1");
-        update.where(expr);
-        update.set(key2.getName(), "test2");
-        update.apply();
-
-        ArgumentCaptor<Document> queryCaptor = ArgumentCaptor.forClass(Document.class);
-        ArgumentCaptor<Document> valueCaptor = ArgumentCaptor.forClass(Document.class);
-        
-        verify(testCollection).updateOne(queryCaptor.capture(), valueCaptor.capture());
-        Document query = queryCaptor.getValue();
-        assertTrue(query.get(Key.AGENT_ID.getName()) != null);
-        assertEquals("test1", query.get(Key.AGENT_ID.getName()));
-
-        Document set = valueCaptor.getValue();
-        assertEquals(1, set.keySet().size());
-        assertTrue(set.get("$set") != null);
-        Document values = (Document) set.get("$set");
-        assertEquals(1, values.keySet().size());
-        assertTrue(values.get(key2.getName()) != null);
-        assertEquals("test2", values.get(key2.getName()));
-    }
-
-    @Test
-    public void verifyMultiFieldUpdate() {
-        MongoStorage storage = makeStorage();
-        Update<TestClass> update = storage.createUpdate(testCategory);
-        Expression expr = factory.equalTo(Key.AGENT_ID, "test1");
-        update.where(expr);
-        update.set(key2.getName(), "test2");
-        update.set(key3.getName(), "test3");
-        update.apply();
-
-        ArgumentCaptor<Document> queryCaptor = ArgumentCaptor.forClass(Document.class);
-        ArgumentCaptor<Document> valueCaptor = ArgumentCaptor.forClass(Document.class);
-        
-        verify(testCollection).updateOne(queryCaptor.capture(), valueCaptor.capture());
-        Document query = queryCaptor.getValue();
-        assertTrue(query.get(Key.AGENT_ID.getName()) != null);
-        assertEquals("test1", query.get(Key.AGENT_ID.getName()));
-
-        Document set = valueCaptor.getValue();
-        assertTrue(set.get("$set") != null);
-        Document values = (Document) set.get("$set");
-        assertTrue(values.get("key2") != null);
-        assertEquals("test2", values.get("key2"));
-        assertTrue(values.get("key3") != null);
-        assertEquals("test3", values.get("key3"));
-    }
-
-    @Test
-    public void verifyReplace() {
-        TestClass pojo = new TestClass();
-        pojo.setAgentId("123");
-        pojo.setKey1("test1");
-        pojo.setKey2("test2");
-        pojo.setKey3("test3");
-        pojo.setKey4("test4");
-        pojo.setKey5("test5");
-
-        MongoStorage storage = makeStorage();
-        when(testCollection.replaceOne(any(Bson.class), any(Document.class), any(UpdateOptions.class))).thenReturn(mock(UpdateResult.class));
-        Replace<TestClass> replace = storage.createReplace(testCategory);
-        ExpressionFactory factory = new ExpressionFactory();
-        Expression first = factory.equalTo(key1, "test1");
-        Expression second = factory.equalTo(key2, "test2");
-        Expression and = factory.and(first, second);
-        replace.where(and);
-        replace.set("key1", pojo.getKey1());
-        replace.set("key2", pojo.getKey2());
-        replace.set("key3", pojo.getKey3());
-        replace.set("key4", pojo.getKey4());
-        replace.set("key5", pojo.getKey5());
-        replace.set(Key.AGENT_ID.getName(), pojo.getAgentId());
-        replace.apply();
-
-        ArgumentCaptor<Document> queryCaptor = ArgumentCaptor.forClass(Document.class);
-        ArgumentCaptor<Document> valueCaptor = ArgumentCaptor.forClass(Document.class);
-        verify(testCollection).replaceOne(queryCaptor.capture(), valueCaptor.capture(), any(UpdateOptions.class));
-
-        Document query = queryCaptor.getValue();
-        assertEquals("expected explicit and query", 1, query.keySet().size());
-        Object andObj = query.get("$and");
-        assertNotNull(andObj);
-        assertTrue(andObj instanceof List);
-        @SuppressWarnings("unchecked")
-        List<Document> list = (List<Document>)andObj;
-        assertEquals("expected two operands", 2, list.size());
-        Document firstCond = list.get(0);
-        Document secondCond = list.get(1);
-        assertEquals("test1", firstCond.get("key1"));
-        assertEquals("test2", secondCond.get("key2"));
-
-        Document value = valueCaptor.getValue();
-        assertEquals(6, value.keySet().size());
-        assertEquals("test1", value.get("key1"));
-        assertEquals("test2", value.get("key2"));
-        assertEquals("test3", value.get("key3"));
-        assertEquals("test4", value.get("key4"));
-        assertEquals("test5", value.get("key5"));
-        assertEquals("123", value.get("agentId"));
-    }
-
-    @Test
-    public void verifyRemove() {
-        MongoStorage storage = makeStorage();
-        when(testCollection.deleteMany(any(Bson.class))).thenReturn(mock(DeleteResult.class));
-        Remove<TestClass> remove = storage.createRemove(testCategory);
-        Expression expr = factory.equalTo(Key.AGENT_ID, "test1");
-        remove.where(expr);
-
-        remove.apply();
-
-        verify(testCollection).deleteMany(new Document(Key.AGENT_ID.getName(), "test1"));
-    }
-
-    @Test
-    public void verifyRemoveWithoutWhere() {
-        MongoStorage storage = makeStorage();
-        when(testCollection.deleteMany(any(Bson.class))).thenReturn(mock(DeleteResult.class));
-        Remove<TestClass> remove = storage.createRemove(testCategory);
-
-        remove.apply();
-
-        verify(testCollection).deleteMany(new Document());
-    }
-
-    @Test
-    public void verifyDBPurge() throws Exception {
-        MongoDatabase database = mock(MongoDatabase.class);
-        @SuppressWarnings("unchecked")
-        MongoIterable<String> stringIterable = mock(MongoIterable.class);
-        @SuppressWarnings("unchecked")
-        com.mongodb.client.MongoCursor<String> mockCursor = mock(com.mongodb.client.MongoCursor.class);
-        when(mockCursor.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
-        when(mockCursor.next()).thenReturn(testCategory.getName()).thenReturn(emptyTestCategory.getName());
-        when(stringIterable.iterator()).thenReturn(mockCursor);
-        when(database.listCollectionNames()).thenReturn(stringIterable);
-        when(database.getCollection(eq(testCategory.getName()))).thenReturn(testCollection);
-        when(database.getCollection(eq(emptyTestCategory.getName()))).thenReturn(emptyTestCollection);
-        MongoStorage storage = new MongoStorage(database, new CountDownLatch(0));
-        String agentId = "agentId123";
-        Document query = new Document(Key.AGENT_ID.getName(), agentId);
-        storage.purge(agentId);
-        
-        verify(testCollection, times(1)).deleteMany(query);
-        verify(emptyTestCollection, times(1)).deleteMany(query);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void verifySchemaInfoNotExists() throws Exception {
-        MongoDatabase db = PowerMockito.mock(MongoDatabase.class);
-        MongoIterable<String> mockIterable = mock(MongoIterable.class);
-        when(db.listCollectionNames()).thenReturn(mockIterable);
-        when(mockIterable.iterator()).thenReturn(mock(com.mongodb.client.MongoCursor.class));
-        CountDownLatch latch = new CountDownLatch(1);
-        MongoStorage storage = new MongoStorage(db, latch);
-        ArgumentCaptor<String> categoryNameCaptor = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<CreateCollectionOptions> createOptions = ArgumentCaptor.forClass(CreateCollectionOptions.class);
-        
-        storage.createSchemaInfo();
-        verify(db, times(1)).createCollection(categoryNameCaptor.capture(), createOptions.capture());
-        assertEquals(SchemaInfo.CATEGORY.getName(), categoryNameCaptor.getValue());
-        CreateCollectionOptions actual = createOptions.getValue();
-        assertFalse(actual.isCapped());
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Test
-    public void verifySchemaInfoExists() throws Exception {
-        MongoDatabase db = PowerMockito.mock(MongoDatabase.class);
-        MongoIterable<String> mockIterable = mock(MongoIterable.class);
-        when(db.listCollectionNames()).thenReturn(mockIterable);
-        com.mongodb.client.MongoCursor<String> cursor = mock(com.mongodb.client.MongoCursor.class);
-        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
-        when(cursor.next()).thenReturn(SchemaInfo.CATEGORY.getName());
-        when(mockIterable.iterator()).thenReturn(cursor);
-        CountDownLatch latch = new CountDownLatch(1);
-        MongoStorage storage = new MongoStorage(db, latch);
-        
-        when(db.getCollection(eq(SchemaInfo.CATEGORY.getName()))).thenReturn(mock(MongoCollection.class));
-        storage.createSchemaInfo();
-        verify(db, times(0)).createCollection(any(String.class), any(CreateCollectionOptions.class));
-    }
-    
-    @Test
-    public void verifyInsertSchemaInfo() throws Exception {
-        MongoDatabase db = PowerMockito.mock(MongoDatabase.class);
-        CountDownLatch latch = new CountDownLatch(1);
-        MongoStorage storage = new MongoStorage(db, latch);
-        ArgumentCaptor<Document> basicDBCaptor1 = ArgumentCaptor.forClass(Document.class);
-        ArgumentCaptor<Document> basicDBCaptor2 = ArgumentCaptor.forClass(Document.class);
-        Document expected1 = new Document(SchemaInfo.NAME.getName(), testCategory.getName());
-        
-        when(db.getCollection(SchemaInfo.CATEGORY.getName())).thenReturn(testCollection);
-        storage.insertSchemaInfo(testCategory);
-        verify(testCollection).replaceOne(basicDBCaptor1.capture(), basicDBCaptor2.capture(), any(UpdateOptions.class));
-
-        assertEquals(expected1, basicDBCaptor1.getValue());
-        Document arg = (Document) basicDBCaptor2.getValue();
-        
-        assertTrue( arg.get(SchemaInfo.NAME.getName()) != null );
-        assertEquals(testCategory.getName(), arg.get(SchemaInfo.NAME.getName()));
-        assertTrue( arg.get(Key.TIMESTAMP.getName()) != null );
-        assertNotNull(arg.get(Key.TIMESTAMP.getName()));
-    }
-    
-    private static class FakeDataClass implements Pojo {};
-}
-
--- a/storage/mongo/src/test/java/com/redhat/thermostat/storage/mongodb/internal/StringArrayCodecTest.java	Wed May 10 15:59:23 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.storage.mongodb.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintWriter;
-
-import org.bson.BsonReader;
-import org.bson.BsonWriter;
-import org.bson.codecs.DecoderContext;
-import org.bson.codecs.EncoderContext;
-import org.bson.json.JsonReader;
-import org.bson.json.JsonWriter;
-import org.junit.Test;
-
-public class StringArrayCodecTest {
-
-    @Test
-    public void canEncodeStringArray() {
-        String[] values = new String[] {
-           "first", "second", "third\"arg"
-        };
-        StringArrayCodec codec = new StringArrayCodec();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        BsonWriter writer = new JsonWriter(new PrintWriter(baos));
-        EncoderContext ctxt = EncoderContext.builder().build();
-        
-        writer.writeStartDocument();
-        writer.writeName("foo");
-        codec.encode(writer, values, ctxt);
-        writer.writeEndDocument();
-        writer.flush();
-        String json = new String(baos.toByteArray());
-        assertTrue(json.contains("\"foo\""));
-        assertTrue(json.contains("[\"" + values[0] + "\", \"" + values[1] + "\", \"" + values[2].replace("\"", "\\\"") + "\"]"));
-    }
-    
-    @Test
-    public void canDecodeStringArray() {
-        String json = "{ \"foo\" : [\"first\", \"second\", \"third\\\"arg\"] }";
-        BsonReader reader = new JsonReader(json);
-        reader.readStartDocument();
-        String name = reader.readName();
-        assertEquals("foo", name);
-        StringArrayCodec codec = new StringArrayCodec();
-        String[] decoded = codec.decode(reader, DecoderContext.builder().build());
-        reader.readEndDocument();
-        assertEquals("first", decoded[0]);
-        assertEquals("second", decoded[1]);
-        assertEquals("third\"arg", decoded[2]);
-    }
-}
--- a/storage/pom.xml	Wed May 10 15:59:23 2017 -0400
+++ b/storage/pom.xml	Wed May 10 16:01:45 2017 -0400
@@ -60,7 +60,6 @@
 
   <modules>
     <module>core</module>
-    <module>mongo</module>
     <module>testutils</module>
   </modules>