Mercurial > hg > thermostat-ng > agent
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]); - } -}