You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by ca...@apache.org on 2018/01/06 00:39:13 UTC

[11/15] incubator-rya git commit: RYA-104 Implemented the Rya Shell integration with the Mongo DB interactors.

RYA-104 Implemented the Rya Shell integration with the Mongo DB interactors.


Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/9e8f4a65
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/9e8f4a65
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/9e8f4a65

Branch: refs/heads/master
Commit: 9e8f4a654f47edc7d06fa5ba7bc7011f4716549c
Parents: b642261
Author: kchilton2 <ke...@gmail.com>
Authored: Sun Dec 17 15:23:41 2017 -0500
Committer: kchilton2 <ke...@gmail.com>
Committed: Fri Jan 5 16:48:40 2018 -0500

----------------------------------------------------------------------
 .../client/mongo/MongoConnectionDetails.java    |   4 +-
 .../org/apache/rya/shell/RyaAdminCommands.java  | 112 ++++++++++++---
 .../apache/rya/shell/RyaConnectionCommands.java |  84 +++++++++--
 .../org/apache/rya/shell/RyaPromptProvider.java |   7 +-
 .../org/apache/rya/shell/SharedShellState.java  | 138 ++++++++++++++++---
 .../apache/rya/shell/RyaAdminCommandsTest.java  |  50 +++++--
 .../apache/rya/shell/SharedShellStateTest.java  |   9 +-
 7 files changed, 337 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoConnectionDetails.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoConnectionDetails.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoConnectionDetails.java
index 81106f9..d792289 100644
--- a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoConnectionDetails.java
+++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoConnectionDetails.java
@@ -46,7 +46,7 @@ public class MongoConnectionDetails {
      * @param username - The username that was used to establish the connection. (not null)
      * @param password - The password that was used to establish the connection. (not null)
      * @param hostname - The hostname of the Mongo DB that was connected to. (not null)
-     * @param port - The port of the Mongo DB that was connected to. (not null)
+     * @param port - The port of the Mongo DB that was connected to.
      */
     public MongoConnectionDetails(
             final String username,
@@ -97,7 +97,7 @@ public class MongoConnectionDetails {
         return build(ryaInstanceName, null);
     }
 
-    public MongoDBRdfConfiguration build(final String ryaInstanceName, MongoClient mongoClient) {
+    public MongoDBRdfConfiguration build(final String ryaInstanceName, final MongoClient mongoClient) {
         // Note, we don't use the MongoDBRdfConfigurationBuilder here because it explicitly sets
         // authorizations and visibilities to an empty string if they are not set on the builder.
         // If they are null in the MongoRdfConfiguration object, it may do the right thing.

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java b/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
index 8b86d43..cfe13dd 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/RyaAdminCommands.java
@@ -36,6 +36,7 @@ import org.apache.rya.api.client.RyaClientException;
 import org.apache.rya.api.instance.RyaDetails;
 import org.apache.rya.shell.SharedShellState.ConnectionState;
 import org.apache.rya.shell.SharedShellState.ShellState;
+import org.apache.rya.shell.SharedShellState.StorageType;
 import org.apache.rya.shell.util.InstallPrompt;
 import org.apache.rya.shell.util.InstanceNamesFormatter;
 import org.apache.rya.shell.util.RyaDetailsFormatter;
@@ -63,7 +64,8 @@ public class RyaAdminCommands implements CommandMarker {
     public static final String LIST_INCREMENTAL_QUERIES = "list-incremental-queries";
     public static final String PRINT_INSTANCE_DETAILS_CMD = "print-instance-details";
     public static final String INSTALL_CMD = "install";
-    public static final String INSTALL_PARAMETERS_CMD = "install-with-parameters";
+    public static final String INSTALL_ACCUMULO_PARAMETERS_CMD = "install-with-accumulo-parameters";
+    public static final String INSTALL_MONGO_PARAMETERS_CMD = "install-with-mongo-parameters";
     public static final String LIST_INSTANCES_CMD = "list-instances";
     public static final String UNINSTALL_CMD = "uninstall";
     public static final String ADD_USER_CMD = "add-user";
@@ -99,8 +101,7 @@ public class RyaAdminCommands implements CommandMarker {
      */
     @CliAvailabilityIndicator({
         LIST_INSTANCES_CMD,
-        INSTALL_CMD,
-        INSTALL_PARAMETERS_CMD})
+        INSTALL_CMD})
     public boolean areStorageCommandsAvailable() {
         switch(state.getShellState().getConnectionState()) {
             case CONNECTED_TO_STORAGE:
@@ -112,20 +113,52 @@ public class RyaAdminCommands implements CommandMarker {
     }
 
     /**
+     * Enables commands that only become available once the Shell has been connected to an Accumulo Rya Storage.
+     */
+    @CliAvailabilityIndicator({
+        INSTALL_ACCUMULO_PARAMETERS_CMD})
+    public boolean areAccumuloStorageCommandsAvailable() {
+        return isConnectedToStorageType(StorageType.ACCUMULO);
+    }
+
+    /**
+     * Enables commands that only become available once the Shell has been connected to an MongoDB Rya Storage.
+     */
+    @CliAvailabilityIndicator({
+        INSTALL_MONGO_PARAMETERS_CMD})
+    public boolean areMongoStorageCommandsAvailable() {
+        return isConnectedToStorageType(StorageType.MONGO);
+    }
+
+    private boolean isConnectedToStorageType(final StorageType type) {
+        // Enabled if we are connected to the specified storage type.
+        final Optional<StorageType> storageType = state.getShellState().getStorageType();
+        if(storageType.isPresent()) {
+            return areStorageCommandsAvailable() && storageType.get() == type;
+        }
+
+        // Otherwise disabled.
+        return false;
+    }
+
+    /**
      * Enables commands that are always available once the Shell is connected to a Rya Instance.
      */
     @CliAvailabilityIndicator({
         PRINT_INSTANCE_DETAILS_CMD,
-        UNINSTALL_CMD,
+        UNINSTALL_CMD})
+    public boolean areInstanceCommandsAvailable() {
+        return state.getShellState().getConnectionState() == ConnectionState.CONNECTED_TO_INSTANCE;
+    }
+
+    /**
+     * Enables commands that are available when connected to a Rya Instance that supports user management.
+     */
+    @CliAvailabilityIndicator({
         ADD_USER_CMD,
         REMOVE_USER_CMD})
-    public boolean areInstanceCommandsAvailable() {
-        switch(state.getShellState().getConnectionState()) {
-            case CONNECTED_TO_INSTANCE:
-                return true;
-            default:
-                return false;
-        }
+    public boolean areUserCommandAvailable() {
+        return areInstanceCommandsAvailable() && state.getShellState().getStorageType().get() == StorageType.ACCUMULO;
     }
 
     /**
@@ -141,7 +174,8 @@ public class RyaAdminCommands implements CommandMarker {
         // The PCJ commands are only available if the Shell is connected to an instance of Rya
         // that is new enough to use the RyaDetailsRepository and is configured to maintain PCJs.
         final ShellState shellState = state.getShellState();
-        if(shellState.getConnectionState() == ConnectionState.CONNECTED_TO_INSTANCE) {
+        if(shellState.getConnectionState() == ConnectionState.CONNECTED_TO_INSTANCE &&
+                shellState.getStorageType().get() == StorageType.ACCUMULO) {
             final GetInstanceDetails getInstanceDetails = shellState.getConnectedCommands().get().getGetInstanceDetails();
             final String ryaInstanceName = state.getShellState().getRyaInstanceName().get();
             try {
@@ -211,8 +245,8 @@ public class RyaAdminCommands implements CommandMarker {
         }
     }
 
-    @CliCommand(value = INSTALL_PARAMETERS_CMD, help = "Create a new instance of Rya with command line parameters.")
-    public String installWithParameters(
+    @CliCommand(value = INSTALL_ACCUMULO_PARAMETERS_CMD, help = "Create a new Accumulo instance of Rya with command line parameters.")
+    public String installWithAccumuloParameters(
             @CliOption(key = {"instanceName"}, mandatory = true, help = "The name of the Rya instance to create.")
             final String instanceName,
 
@@ -225,8 +259,9 @@ public class RyaAdminCommands implements CommandMarker {
             @CliOption(key = {"enableFreeTextIndex"}, mandatory = false, help = "Use Free Text Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
             final boolean enableFreeTextIndex,
 
-            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
-            final boolean enableGeospatialIndex,
+            // TODO RYA-215
+//            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+//            final boolean enableGeospatialIndex,
 
             @CliOption(key = {"enableTemporalIndex"}, mandatory = false, help = "Use Temporal Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
             final boolean enableTemporalIndex,
@@ -246,7 +281,8 @@ public class RyaAdminCommands implements CommandMarker {
                     .setEnableTableHashPrefix(enableTableHashPrefix)
                     .setEnableEntityCentricIndex(enableEntityCentricIndex)
                     .setEnableFreeTextIndex(enableFreeTextIndex)
-                    .setEnableGeoIndex(enableGeospatialIndex)
+                    // TODO RYA-215
+//                    .setEnableGeoIndex(enableGeospatialIndex)
                     .setEnableTemporalIndex(enableTemporalIndex)
                     .setEnablePcjIndex(enablePcjIndex)
                     .setFluoPcjAppName(fluoPcjAppName)
@@ -268,6 +304,48 @@ public class RyaAdminCommands implements CommandMarker {
         }
     }
 
+    @CliCommand(value = INSTALL_MONGO_PARAMETERS_CMD, help = "Create a new MongoDB instance of Rya with command line parameters.")
+    public String installWithMongoParameters(
+            @CliOption(key = {"instanceName"}, mandatory = true, help = "The name of the Rya instance to create.")
+            final String instanceName,
+
+            @CliOption(key = {"enableFreeTextIndex"}, mandatory = false, help = "Use Free Text Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+            final boolean enableFreeTextIndex,
+
+            // TODO RYA-215
+//            @CliOption(key = {"enableGeospatialIndex"}, mandatory = false, help = "Use Geospatial Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+//            final boolean enableGeospatialIndex,
+
+            @CliOption(key = {"enableTemporalIndex"}, mandatory = false, help = "Use Temporal Indexing.", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true")
+            final boolean enableTemporalIndex) {
+
+        // Fetch the commands that are connected to the store.
+        final RyaClient commands = state.getShellState().getConnectedCommands().get();
+
+        try {
+            final InstallConfiguration installConfig = InstallConfiguration.builder()
+                    .setEnableFreeTextIndex(enableFreeTextIndex)
+                    // TODO RYA-215
+//                    .setEnableGeoIndex(enableGeospatialIndex)
+                    .setEnableTemporalIndex(enableTemporalIndex)
+                    .build();
+
+            // Verify the configuration is what the user actually wants to do.
+            if (!installPrompt.promptVerified(instanceName, installConfig)) {
+                return "Skipping Installation.";
+            }
+
+            // Execute the command.
+            commands.getInstall().install(instanceName, installConfig);
+            return String.format("The Rya instance named '%s' has been installed.", instanceName);
+
+        } catch(final DuplicateInstanceNameException e) {
+            throw new RuntimeException(String.format("A Rya instance named '%s' already exists. Try again with a different name.", instanceName), e);
+        } catch (final IOException | RyaClientException e) {
+            throw new RuntimeException("Could not install a new instance of Rya. Reason: " + e.getMessage(), e);
+        }
+    }
+
     @CliCommand(value = PRINT_INSTANCE_DETAILS_CMD, help = "Print information about how the Rya instance is configured.")
     public String printInstanceDetails() {
         // Fetch the command that is connected to the store.

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/main/java/org/apache/rya/shell/RyaConnectionCommands.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/RyaConnectionCommands.java b/extras/shell/src/main/java/org/apache/rya/shell/RyaConnectionCommands.java
index f5ba451..e518968 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/RyaConnectionCommands.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/RyaConnectionCommands.java
@@ -31,7 +31,12 @@ import org.apache.rya.api.client.RyaClient;
 import org.apache.rya.api.client.RyaClientException;
 import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails;
 import org.apache.rya.api.client.accumulo.AccumuloRyaClientFactory;
+import org.apache.rya.api.client.mongo.MongoConnectionDetails;
+import org.apache.rya.api.client.mongo.MongoRyaClientFactory;
+import org.apache.rya.mongodb.MongoConnectorFactory;
+import org.apache.rya.mongodb.MongoDBRdfConfiguration;
 import org.apache.rya.shell.SharedShellState.ConnectionState;
+import org.apache.rya.shell.SharedShellState.StorageType;
 import org.apache.rya.shell.util.ConnectorFactory;
 import org.apache.rya.shell.util.PasswordPrompt;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,6 +47,7 @@ import org.springframework.shell.core.annotation.CliOption;
 import org.springframework.stereotype.Component;
 
 import com.google.common.base.Optional;
+import com.mongodb.MongoClient;
 
 /**
  * Spring Shell commands that manage the connection that is used by the shell.
@@ -52,6 +58,7 @@ public class RyaConnectionCommands implements CommandMarker {
     // Command line commands.
     public static final String PRINT_CONNECTION_DETAILS_CMD = "print-connection-details";
     public static final String CONNECT_ACCUMULO_CMD = "connect-accumulo";
+    public static final String CONNECT_MONGO_CMD = "connect-mongo";
     public static final String CONNECT_INSTANCE_CMD = "connect-rya";
     public static final String DISCONNECT_COMMAND_NAME_CMD = "disconnect";
 
@@ -75,7 +82,7 @@ public class RyaConnectionCommands implements CommandMarker {
         return true;
     }
 
-    @CliAvailabilityIndicator({CONNECT_ACCUMULO_CMD})
+    @CliAvailabilityIndicator({CONNECT_ACCUMULO_CMD, CONNECT_MONGO_CMD})
     public boolean areConnectCommandsAvailable() {
         return sharedState.getShellState().getConnectionState() == ConnectionState.DISCONNECTED;
     }
@@ -98,17 +105,31 @@ public class RyaConnectionCommands implements CommandMarker {
 
     @CliCommand(value = PRINT_CONNECTION_DETAILS_CMD, help = "Print information about the Shell's Rya storage connection.")
     public String printConnectionDetails() {
-        final Optional<AccumuloConnectionDetails> detailsHolder = sharedState.getShellState().getConnectionDetails();
-
-        if(detailsHolder.isPresent()) {
-            final AccumuloConnectionDetails details = detailsHolder.get();
-            return "The shell is connected to an instance of Accumulo using the following parameters:\n" +
-                    "    Username: " + details.getUsername() + "\n" +
-                    "    Instance Name: " + details.getInstanceName() + "\n" +
-                    "    Zookeepers: " + details.getZookeepers();
-        } else {
+        // Check to see if the shell is connected to any storages.
+        final Optional<StorageType> storageType = sharedState.getShellState().getStorageType();
+        if(!storageType.isPresent()) {
             return "The shell is not connected to anything.";
         }
+
+        // Create a print out based on what it is connected to.
+        switch(storageType.get()) {
+            case ACCUMULO:
+                final AccumuloConnectionDetails accDetails = sharedState.getShellState().getAccumuloDetails().get();
+                return "The shell is connected to an instance of Accumulo using the following parameters:\n" +
+                    "    Username: " + accDetails.getUsername() + "\n" +
+                    "    Instance Name: " + accDetails.getInstanceName() + "\n" +
+                    "    Zookeepers: " + accDetails.getZookeepers();
+
+            case MONGO:
+                final MongoConnectionDetails mongoDetails = sharedState.getShellState().getMongoDetails().get();
+                return "The shell is connected to an instance of MongoDB using the following parameters:\n" +
+                    "    Hostname: "  + mongoDetails.getHostname() + "\n" +
+                    "    Port: " + mongoDetails.getPort() + "\n" +
+                    "    Username:" + mongoDetails.getUsername();
+
+            default:
+                throw new RuntimeException("Unrecognized StorageType: " + storageType.get());
+        }
     }
 
     @CliCommand(value = CONNECT_ACCUMULO_CMD, help = "Connect the shell to an instance of Accumulo.")
@@ -138,6 +159,49 @@ public class RyaConnectionCommands implements CommandMarker {
         return "Connected. You must select a Rya instance to interact with next.";
     }
 
+    @CliCommand(value = CONNECT_MONGO_CMD, help = "Connect the shell to an instance of MongoDB.")
+    public String connectToMongo(
+            @CliOption(key = {"username"}, mandatory = true, help = "The username that will be used to connect to MongoDB.")
+            final String username,
+            @CliOption(key= {"hostname"}, mandatory = true, help = "The hostname of the MongoDB that will be connected to.")
+            final String hostname,
+            @CliOption(key= {"port"}, mandatory = true, help = "The port of the MongoDB that will be connected to.")
+            final String port) {
+
+        // Prompt the user for their password.
+        try {
+            final char[] password = passwordPrompt.getPassword();
+
+            // Set up a configuration file that connects to the specified Mongo DB.
+            final MongoDBRdfConfiguration conf = new MongoDBRdfConfiguration();
+            conf.setMongoInstance(hostname);
+            conf.setMongoPort(port);
+            conf.setMongoUser(username);
+            conf.setMongoPassword(new String(password));
+
+            // Create the singleton instance of Mongo that will be used through out the application.
+            final MongoClient client = MongoConnectorFactory.getMongoClient(conf);
+
+            // Make sure the client is closed at shutdown.
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    MongoConnectorFactory.closeMongoClient();
+                }
+            });
+
+            // Initialize the connected to Mongo shared state.
+            final MongoConnectionDetails connectionDetails = new MongoConnectionDetails(username, password, hostname, Integer.parseInt(port));
+            final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, client);
+            sharedState.connectedToMongo(connectionDetails, ryaClient);
+
+        } catch (final IOException e) {
+            throw new RuntimeException("Could not connection to MongoDB. Reason: " + e.getMessage(), e);
+        }
+
+        return "Connected. You must select a Rya instance to interact with next.";
+    }
+
     @CliCommand(value = CONNECT_INSTANCE_CMD, help = "Connect to a specific Rya instance")
     public void connectToInstance(
             @CliOption(key = {"instance"}, mandatory = true, help = "The name of the Rya instance the shell will interact with.")

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/main/java/org/apache/rya/shell/RyaPromptProvider.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/RyaPromptProvider.java b/extras/shell/src/main/java/org/apache/rya/shell/RyaPromptProvider.java
index ed5f261..a7fd802 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/RyaPromptProvider.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/RyaPromptProvider.java
@@ -20,14 +20,13 @@ package org.apache.rya.shell;
 
 import static java.util.Objects.requireNonNull;
 
+import org.apache.rya.shell.SharedShellState.ShellState;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.shell.plugin.support.DefaultPromptProvider;
 import org.springframework.stereotype.Component;
 
-import org.apache.rya.shell.SharedShellState.ShellState;
-
 /**
  * Customizes the Rya Shell's prompt.
  */
@@ -50,10 +49,10 @@ public class RyaPromptProvider extends DefaultPromptProvider {
             case DISCONNECTED:
                 return "rya> ";
             case CONNECTED_TO_STORAGE:
-                return String.format("rya/%s> ", state.getConnectionDetails().get().getInstanceName());
+                return String.format("rya/%s> ", state.getAccumuloDetails().get().getInstanceName());
             case CONNECTED_TO_INSTANCE:
                 return String.format("rya/%s:%s> ",
-                        state.getConnectionDetails().get().getInstanceName(),
+                        state.getAccumuloDetails().get().getInstanceName(),
                         state.getRyaInstanceName().get());
             default:
                 return "rya> ";

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/main/java/org/apache/rya/shell/SharedShellState.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/main/java/org/apache/rya/shell/SharedShellState.java b/extras/shell/src/main/java/org/apache/rya/shell/SharedShellState.java
index 526b031..6c8a57c 100644
--- a/extras/shell/src/main/java/org/apache/rya/shell/SharedShellState.java
+++ b/extras/shell/src/main/java/org/apache/rya/shell/SharedShellState.java
@@ -23,17 +23,18 @@ import static java.util.Objects.requireNonNull;
 import java.util.Objects;
 import java.util.concurrent.locks.ReentrantLock;
 
-import edu.umd.cs.findbugs.annotations.Nullable;
+import org.apache.rya.api.client.RyaClient;
+import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails;
+import org.apache.rya.api.client.mongo.MongoConnectionDetails;
+
+import com.google.common.base.Optional;
+
 import edu.umd.cs.findbugs.annotations.DefaultAnnotation;
 import edu.umd.cs.findbugs.annotations.NonNull;
+import edu.umd.cs.findbugs.annotations.Nullable;
 import net.jcip.annotations.Immutable;
 import net.jcip.annotations.ThreadSafe;
 
-import com.google.common.base.Optional;
-
-import org.apache.rya.api.client.RyaClient;
-import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails;
-
 /**
  * Holds values that are shared between the various Rya command classes.
  */
@@ -86,7 +87,7 @@ public class SharedShellState {
             // Store the connection details.
             shellState = ShellState.builder()
                 .setConnectionState( ConnectionState.CONNECTED_TO_STORAGE )
-                .setAccumuloConnectionDetails( connectionDetails )
+                .setAccumuloDetails( connectionDetails )
                 .setConnectedCommands( connectedCommands )
                 .build();
         } finally {
@@ -95,6 +96,40 @@ public class SharedShellState {
     }
 
     /**
+     * This method indicates a shift into the {@link ConnectionState#CONNECTED_TO_STORAGE} state.
+     * <p/>
+     * Store the values used by a Mongo Rya Storage connection. This may only be called when
+     * the shell is disconnected.
+     *
+     * @param connectionDetails - Metadata about the Mongo connection. (not null)
+     * @param connectedCommands - Rya Commands that will execute against the Mongo database. (not null)
+     * @throws IllegalStateException Thrown if the shell is already connected to a Rya storage.
+     */
+    public void connectedToMongo(
+            final MongoConnectionDetails connectionDetails,
+            final RyaClient connectedCommands) throws IllegalStateException {
+        requireNonNull(connectionDetails);
+        requireNonNull(connectedCommands);
+
+        lock.lock();
+        try {
+            // Ensure the Rya Shell is disconnected.
+            if(shellState.getConnectionState() != ConnectionState.DISCONNECTED) {
+                throw new IllegalStateException("You must clear the old connection state before you may set a new connection state.");
+            }
+
+            // Store the connection details.
+            shellState = ShellState.builder()
+                    .setConnectionState( ConnectionState.CONNECTED_TO_STORAGE )
+                    .setMongoDetails( connectionDetails )
+                    .setConnectedCommands( connectedCommands )
+                    .build();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
      * This method indicates a shift into the {@link ConnectionState#CONNECTED_TO_INSTANCE} state.
      * <p/>
      * Store the name of the Rya instance all commands will be executed against.
@@ -160,6 +195,21 @@ public class SharedShellState {
     }
 
     /**
+     * Enumerates the various types of Rya Storages the shell may connect to.
+     */
+    public static enum StorageType {
+        /**
+         * The Rya instances are stored in Accumulo.
+         */
+        ACCUMULO,
+
+        /**
+         * The Rya instances are stored in MongoDB.
+         */
+        MONGO;
+    }
+
+    /**
      * Values that define the state of a Rya Shell.
      */
     @Immutable
@@ -169,7 +219,9 @@ public class SharedShellState {
         private final ConnectionState connectionState;
 
         // Connection specific values.
-        private final Optional<AccumuloConnectionDetails> connectionDetails;
+        private final Optional<StorageType> storageType;
+        private final Optional<AccumuloConnectionDetails> accumuloDetails;
+        private final Optional<MongoConnectionDetails> mongoDetails;
         private final Optional<RyaClient> connectedCommands;
 
         // Instance specific values.
@@ -177,11 +229,15 @@ public class SharedShellState {
 
         private ShellState(
                 final ConnectionState connectionState,
-                final Optional<AccumuloConnectionDetails> connectionDetails,
+                final Optional<StorageType> storageType,
+                final Optional<AccumuloConnectionDetails> accumuloDetails,
+                final Optional<MongoConnectionDetails> mongoDetails,
                 final Optional<RyaClient> connectedCommands,
                 final Optional<String> instanceName) {
             this.connectionState = requireNonNull(connectionState);
-            this.connectionDetails = requireNonNull(connectionDetails);
+            this.storageType = requireNonNull(storageType);
+            this.accumuloDetails = requireNonNull(accumuloDetails);
+            this.mongoDetails = requireNonNull(mongoDetails);
             this.connectedCommands = requireNonNull(connectedCommands);
             this.instanceName = requireNonNull(instanceName);
         }
@@ -194,11 +250,28 @@ public class SharedShellState {
         }
 
         /**
+         * @return The type of storage the shell is connected to if it is connected to a storage.
+         */
+        public Optional<StorageType> getStorageType() {
+            return storageType;
+        }
+
+        /**
          * @return Metadata about the Accumulo connection. The value will not be present
-         *   if the Rya Shell is not connected to a storage.
+         *   if the Rya Shell is not connected to a storage or is connected to another type
+         *   of storage.
          */
-        public Optional<AccumuloConnectionDetails> getConnectionDetails() {
-            return connectionDetails;
+        public Optional<AccumuloConnectionDetails> getAccumuloDetails() {
+            return accumuloDetails;
+        }
+
+        /**
+         * @return Metadata about the Mongo connection. The value will not be present
+         *   if the Rya Shell is not connected to a storage or is connected to another type
+         *   of storage.
+         */
+        public Optional<MongoConnectionDetails> getMongoDetails() {
+            return mongoDetails;
         }
 
         /**
@@ -220,7 +293,7 @@ public class SharedShellState {
 
         @Override
         public int hashCode() {
-            return Objects.hash(connectionState, connectionDetails, connectedCommands, instanceName);
+            return Objects.hash(connectionState, accumuloDetails, connectedCommands, instanceName);
         }
 
         @Override
@@ -231,7 +304,7 @@ public class SharedShellState {
             if(obj instanceof ShellState) {
                 final ShellState state = (ShellState)obj;
                 return Objects.equals(connectionState, state.connectionState) &&
-                        Objects.equals(connectionDetails, state.connectionDetails) &&
+                        Objects.equals(accumuloDetails, state.accumuloDetails) &&
                         Objects.equals(connectedCommands, state.connectedCommands) &&
                         Objects.equals(instanceName, state.instanceName);
             }
@@ -264,7 +337,9 @@ public class SharedShellState {
             private ConnectionState connectionState;
 
             // Connection specific values.
-            private AccumuloConnectionDetails connectionDetails;
+            private StorageType storageType;
+            private AccumuloConnectionDetails accumuloDetails;
+            private MongoConnectionDetails mongoDetails;
             private RyaClient connectedCommands;
 
             // Instance specific values.
@@ -283,7 +358,7 @@ public class SharedShellState {
              */
             public Builder(final ShellState shellState) {
                 this.connectionState = shellState.getConnectionState();
-                this.connectionDetails = shellState.getConnectionDetails().orNull();
+                this.accumuloDetails = shellState.getAccumuloDetails().orNull();
                 this.connectedCommands = shellState.getConnectedCommands().orNull();
                 this.instanceName = shellState.getRyaInstanceName().orNull();
             }
@@ -298,11 +373,30 @@ public class SharedShellState {
             }
 
             /**
-             * @param connectionDetails - Metadata about the Accumulo connection.
+             * @param accumuloDetails - Metadata about the Accumulo connection.
+             * @return This {@link Builder} so that method invocations may be chained.
+             */
+            public Builder setAccumuloDetails(@Nullable final AccumuloConnectionDetails accumuloDetails) {
+                // If we are setting the details, clear any old ones.
+                if(accumuloDetails != null) {
+                    this.storageType = StorageType.ACCUMULO;
+                    this.mongoDetails = null;
+                }
+                this.accumuloDetails = accumuloDetails;
+                return this;
+            }
+
+            /**
+             * @param mongoDetails - Metadata about the Mongo connection.
              * @return This {@link Builder} so that method invocations may be chained.
              */
-            public Builder setAccumuloConnectionDetails(@Nullable final AccumuloConnectionDetails connectionDetails) {
-                this.connectionDetails = connectionDetails;
+            public Builder setMongoDetails(@Nullable final MongoConnectionDetails mongoDetails) {
+                // If we are setting the details, clear any old ones.
+                if(mongoDetails != null) {
+                    this.storageType = StorageType.MONGO;
+                    this.accumuloDetails = null;
+                }
+                this.mongoDetails = mongoDetails;
                 return this;
             }
 
@@ -330,7 +424,9 @@ public class SharedShellState {
             public ShellState build() {
                 return new ShellState(
                         connectionState,
-                        Optional.fromNullable(connectionDetails),
+                        Optional.fromNullable(storageType),
+                        Optional.fromNullable(accumuloDetails),
+                        Optional.fromNullable(mongoDetails),
                         Optional.fromNullable(connectedCommands),
                         Optional.fromNullable(instanceName));
             }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java b/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
index 6e21f8d..d8d5b8f 100644
--- a/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
+++ b/extras/shell/src/test/java/org/apache/rya/shell/RyaAdminCommandsTest.java
@@ -48,6 +48,7 @@ import org.apache.rya.api.client.RyaClient;
 import org.apache.rya.api.client.RyaClientException;
 import org.apache.rya.api.client.Uninstall;
 import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails;
+import org.apache.rya.api.client.mongo.MongoConnectionDetails;
 import org.apache.rya.api.instance.RyaDetails;
 import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails;
 import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails;
@@ -354,7 +355,7 @@ public class RyaAdminCommandsTest {
     }
 
     @Test
-    public void installWithParameters() throws DuplicateInstanceNameException, RyaClientException, IOException {
+    public void installWithAccumuloParameters() throws DuplicateInstanceNameException, RyaClientException, IOException {
         // Mock the object that performs the install operation.
         final Install mockInstall = mock(Install.class);
 
@@ -368,7 +369,6 @@ public class RyaAdminCommandsTest {
         final boolean enableTableHashPrefix = false;
         final boolean enableEntityCentricIndex = true;
         final boolean enableFreeTextIndex = false;
-        final boolean enableGeospatialIndex = true;
         final boolean enableTemporalIndex = false;
         final boolean enablePcjIndex = true;
         final String fluoPcjAppName = instanceName + "pcj_updater";
@@ -378,7 +378,6 @@ public class RyaAdminCommandsTest {
                 .setEnableTableHashPrefix(enableTableHashPrefix)
                 .setEnableEntityCentricIndex(enableEntityCentricIndex)
                 .setEnableFreeTextIndex(enableFreeTextIndex)
-                .setEnableGeoIndex(enableGeospatialIndex)
                 .setEnableTemporalIndex(enableTemporalIndex)
                 .setEnablePcjIndex(enablePcjIndex)
                 .setFluoPcjAppName(fluoPcjAppName)
@@ -390,7 +389,7 @@ public class RyaAdminCommandsTest {
         when(mockInstallPrompt.promptVerified(eq(instanceName), eq(installConfig))).thenReturn(true);
 
         final RyaAdminCommands commands = new RyaAdminCommands(state, mockInstallPrompt, mock(SparqlPrompt.class), mock(UninstallPrompt.class));
-        final String message = commands.installWithParameters(instanceName, enableTableHashPrefix, enableEntityCentricIndex, enableFreeTextIndex, enableGeospatialIndex, enableTemporalIndex, enablePcjIndex, fluoPcjAppName);
+        final String message = commands.installWithAccumuloParameters(instanceName, enableTableHashPrefix, enableEntityCentricIndex, enableFreeTextIndex, enableTemporalIndex, enablePcjIndex, fluoPcjAppName);
 
         // Verify the values that were provided to the command were passed through to the Install.
         verify(mockInstall).install(eq(instanceName), eq(installConfig));
@@ -401,7 +400,7 @@ public class RyaAdminCommandsTest {
     }
 
     @Test
-    public void installWithParameters_userAbort() throws DuplicateInstanceNameException, RyaClientException, IOException {
+    public void installWithAccumuloParameters_userAbort() throws DuplicateInstanceNameException, RyaClientException, IOException {
         // Mock the object that performs the install operation.
         final Install mockInstall = mock(Install.class);
 
@@ -415,7 +414,6 @@ public class RyaAdminCommandsTest {
         final boolean enableTableHashPrefix = false;
         final boolean enableEntityCentricIndex = true;
         final boolean enableFreeTextIndex = false;
-        final boolean enableGeospatialIndex = true;
         final boolean enableTemporalIndex = false;
         final boolean enablePcjIndex = true;
         final String fluoPcjAppName = instanceName + "pcj_updater";
@@ -425,7 +423,6 @@ public class RyaAdminCommandsTest {
                 .setEnableTableHashPrefix(enableTableHashPrefix)
                 .setEnableEntityCentricIndex(enableEntityCentricIndex)
                 .setEnableFreeTextIndex(enableFreeTextIndex)
-                .setEnableGeoIndex(enableGeospatialIndex)
                 .setEnableTemporalIndex(enableTemporalIndex)
                 .setEnablePcjIndex(enablePcjIndex)
                 .setFluoPcjAppName(fluoPcjAppName)
@@ -437,7 +434,7 @@ public class RyaAdminCommandsTest {
         when(mockInstallPrompt.promptVerified(eq(instanceName), eq(installConfig))).thenReturn(false);
 
         final RyaAdminCommands commands = new RyaAdminCommands(state, mockInstallPrompt, mock(SparqlPrompt.class), mock(UninstallPrompt.class));
-        final String message = commands.installWithParameters(instanceName, enableTableHashPrefix, enableEntityCentricIndex, enableFreeTextIndex, enableGeospatialIndex, enableTemporalIndex, enablePcjIndex, fluoPcjAppName);
+        final String message = commands.installWithAccumuloParameters(instanceName, enableTableHashPrefix, enableEntityCentricIndex, enableFreeTextIndex, enableTemporalIndex, enablePcjIndex, fluoPcjAppName);
 
         // Verify a message is returned that indicates the success of the operation.
         final String expected = "Skipping Installation.";
@@ -445,6 +442,43 @@ public class RyaAdminCommandsTest {
     }
 
     @Test
+    public void installWithMongoParameters() throws DuplicateInstanceNameException, RyaClientException, IOException {
+        // Mock the object that performs the install operation.
+        final Install mockInstall = mock(Install.class);
+
+        final RyaClient mockCommands = mock(RyaClient.class);
+        when(mockCommands.getInstall()).thenReturn( mockInstall );
+
+        final SharedShellState state = new SharedShellState();
+        state.connectedToMongo(mock(MongoConnectionDetails.class), mockCommands);
+
+        final String instanceName = "unitTests";
+        final boolean enableFreeTextIndex = false;
+        final boolean enableTemporalIndex = false;
+
+        // Execute the command.
+        final InstallConfiguration installConfig = InstallConfiguration.builder()
+                .setEnableFreeTextIndex(enableFreeTextIndex)
+                .setEnableTemporalIndex(enableTemporalIndex)
+                .build();
+
+        final InstallPrompt mockInstallPrompt = mock(InstallPrompt.class);
+        when(mockInstallPrompt.promptInstanceName()).thenReturn( instanceName );
+        when(mockInstallPrompt.promptInstallConfiguration(instanceName)).thenReturn( installConfig );
+        when(mockInstallPrompt.promptVerified(eq(instanceName), eq(installConfig))).thenReturn(true);
+
+        final RyaAdminCommands commands = new RyaAdminCommands(state, mockInstallPrompt, mock(SparqlPrompt.class), mock(UninstallPrompt.class));
+        final String message = commands.installWithMongoParameters(instanceName, enableFreeTextIndex, enableTemporalIndex);
+
+        // Verify the values that were provided to the command were passed through to the Install.
+        verify(mockInstall).install(eq(instanceName), eq(installConfig));
+
+        // Verify a message is returned that indicates the success of the operation.
+        final String expected = "The Rya instance named 'unitTests' has been installed.";
+        assertEquals(expected, message);
+    }
+
+    @Test
     public void listInstances() throws RyaClientException, IOException {
         // Mock the object that performs the list operation.
         final ListInstances mockListInstances = mock(ListInstances.class);

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/9e8f4a65/extras/shell/src/test/java/org/apache/rya/shell/SharedShellStateTest.java
----------------------------------------------------------------------
diff --git a/extras/shell/src/test/java/org/apache/rya/shell/SharedShellStateTest.java b/extras/shell/src/test/java/org/apache/rya/shell/SharedShellStateTest.java
index e79d186..b5f136c 100644
--- a/extras/shell/src/test/java/org/apache/rya/shell/SharedShellStateTest.java
+++ b/extras/shell/src/test/java/org/apache/rya/shell/SharedShellStateTest.java
@@ -21,12 +21,11 @@ package org.apache.rya.shell;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
 
-import org.junit.Test;
-
 import org.apache.rya.api.client.RyaClient;
 import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails;
 import org.apache.rya.shell.SharedShellState.ConnectionState;
 import org.apache.rya.shell.SharedShellState.ShellState;
+import org.junit.Test;
 
 /**
  * Tests the methods of {@link SharedShellState}.
@@ -57,7 +56,7 @@ public class SharedShellStateTest {
         // Verify the state.
         final ShellState expected = ShellState.builder()
                 .setConnectionState(ConnectionState.CONNECTED_TO_STORAGE)
-                .setAccumuloConnectionDetails(connectionDetails)
+                .setAccumuloDetails(connectionDetails)
                 .setConnectedCommands(connectedCommands)
                 .build();
 
@@ -92,7 +91,7 @@ public class SharedShellStateTest {
         // Verify the state.
         final ShellState expected = ShellState.builder()
                 .setConnectionState(ConnectionState.CONNECTED_TO_INSTANCE)
-                .setAccumuloConnectionDetails(connectionDetails)
+                .setAccumuloDetails(connectionDetails)
                 .setConnectedCommands(connectedCommands)
                 .setRyaInstanceName("instance")
                 .build();
@@ -118,7 +117,7 @@ public class SharedShellStateTest {
         // Verify the state.
         final ShellState expected = ShellState.builder()
                 .setConnectionState(ConnectionState.CONNECTED_TO_INSTANCE)
-                .setAccumuloConnectionDetails(connectionDetails)
+                .setAccumuloDetails(connectionDetails)
                 .setConnectedCommands(connectedCommands)
                 .setRyaInstanceName("secondInstance")
                 .build();