http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/indexingExample/src/main/java/RyaDirectExample.java ---------------------------------------------------------------------- diff --git a/extras/indexingExample/src/main/java/RyaDirectExample.java b/extras/indexingExample/src/main/java/RyaDirectExample.java index cb69f51..03712ba 100644 --- a/extras/indexingExample/src/main/java/RyaDirectExample.java +++ b/extras/indexingExample/src/main/java/RyaDirectExample.java @@ -20,16 +20,6 @@ import java.net.UnknownHostException; import java.util.List; -import mvm.rya.accumulo.AccumuloRdfConfiguration; -import mvm.rya.api.RdfCloudTripleStoreConfiguration; -import mvm.rya.api.persist.RyaDAOException; -import mvm.rya.indexing.accumulo.ConfigUtils; -import mvm.rya.indexing.accumulo.geo.GeoConstants; -import mvm.rya.indexing.external.PrecomputedJoinIndexerConfig; -import mvm.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType; -import mvm.rya.rdftriplestore.inference.InferenceEngineException; -import mvm.rya.sail.config.RyaSailFactory; - import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.Connector; @@ -63,9 +53,20 @@ import org.openrdf.repository.RepositoryException; import org.openrdf.repository.sail.SailRepository; import org.openrdf.repository.sail.SailRepositoryConnection; import org.openrdf.sail.Sail; +import org.openrdf.sail.SailException; import com.google.common.base.Optional; +import mvm.rya.accumulo.AccumuloRdfConfiguration; +import mvm.rya.api.RdfCloudTripleStoreConfiguration; +import mvm.rya.api.persist.RyaDAOException; +import mvm.rya.indexing.accumulo.ConfigUtils; +import mvm.rya.indexing.accumulo.geo.GeoConstants; +import mvm.rya.indexing.external.PrecomputedJoinIndexerConfig; +import mvm.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType; +import mvm.rya.rdftriplestore.inference.InferenceEngineException; +import mvm.rya.sail.config.RyaSailFactory; + public class RyaDirectExample { private static final Logger log = Logger.getLogger(RyaDirectExample.class); @@ -77,14 +78,13 @@ public class RyaDirectExample { private static final boolean PRINT_QUERIES = true; private static final String INSTANCE = "instance"; private static final String RYA_TABLE_PREFIX = "x_test_triplestore_"; - private static final String AUTHS = ""; + private static final String AUTHS = "U"; public static void main(final String[] args) throws Exception { final Configuration conf = getConf(); conf.setBoolean(ConfigUtils.DISPLAY_QUERY_PLAN, PRINT_QUERIES); log.info("Creating the tables as root."); - // createTables(addRootConf(conf), conf); SailRepository repository = null; SailRepositoryConnection conn = null; @@ -93,7 +93,6 @@ public class RyaDirectExample { log.info("Connecting to Indexing Sail Repository."); final Sail extSail = RyaSailFactory.getInstance(conf); repository = new SailRepository(extSail); - repository.initialize(); conn = repository.getConnection(); createPCJ(conf); @@ -731,7 +730,7 @@ public class RyaDirectExample { throws RepositoryException, AccumuloException, AccumuloSecurityException, TableExistsException, PcjException, InferenceEngineException, NumberFormatException, - UnknownHostException { + UnknownHostException, SailException { final Configuration config = new AccumuloRdfConfiguration(conf); config.set(ConfigUtils.USE_PCJ, "false"); @@ -739,10 +738,9 @@ public class RyaDirectExample { SailRepositoryConnection conn = null; try { - Sail extSail = RyaSailFactory.getInstance(config); + final Sail extSail = RyaSailFactory.getInstance(config); repository = new SailRepository(extSail); - repository.initialize(); conn = repository.getConnection(); final String queryString1 = ""//
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/pom.xml ---------------------------------------------------------------------- diff --git a/extras/rya.console/pom.xml b/extras/rya.console/pom.xml index 1bbb5a0..c2332aa 100644 --- a/extras/rya.console/pom.xml +++ b/extras/rya.console/pom.xml @@ -1,26 +1,28 @@ <?xml version='1.0'?> <!-- -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. ---> + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> <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>org.apache.rya</groupId> <artifactId>rya.extras</artifactId> @@ -30,10 +32,6 @@ under the License. <artifactId>rya.console</artifactId> <name>Apache Rya Console</name> - <properties> - <jar.mainclass>org.springframework.shell.Bootstrap</jar.mainclass> - </properties> - <dependencies> <dependency> <groupId>org.apache.rya</groupId> @@ -49,52 +47,142 @@ under the License. </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.apache.rya</groupId> + <artifactId>rya.indexing</artifactId> + </dependency> + <dependency> + <groupId>org.apache.rya</groupId> + <artifactId>rya.pcj.fluo.api</artifactId> + </dependency> <dependency> <groupId>org.springframework.shell</groupId> <artifactId>spring-shell</artifactId> </dependency> + + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-web</artifactId> + <version>4.1.0.RELEASE</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.accumulo</groupId> + <artifactId>accumulo-minicluster</artifactId> + <version>${accumulo.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.fluo</groupId> + <artifactId>fluo-mini</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.rya</groupId> + <artifactId>accumulo.rya</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + </dependency> </dependencies> <build> <plugins> + <!-- Automatically place Apache 2 license headers at the top of all of the project's Java files. + Rat runs during the 'validate' lifecycle step, so it will fail the build before this one + executes if any of the headers are missing. Run the build with rat turned off to add + missing headers to the Java files. --> + <plugin> + <groupId>com.mycila</groupId> + <artifactId>license-maven-plugin</artifactId> + <version>2.6</version> + <configuration> + <!-- We use a custome Apache 2.0 license because we do not include a copywrite section. --> + <header>src/main/resources/LICENSE.txt</header> + </configuration> + <executions> + <execution> + <phase>process-sources</phase> + <goals> + <goal>format</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- Create an executable jar file for the shell. --> <plugin> <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.0</version> <executions> <execution> - <id>copy-dependencies</id> - <phase>prepare-package</phase> + <phase>package</phase> <goals> - <goal>copy-dependencies</goal> + <goal>shade</goal> </goals> <configuration> - <outputDirectory>${project.build.directory}/lib</outputDirectory> - <overWriteReleases>true</overWriteReleases> - <overWriteSnapshots>true</overWriteSnapshots> - <overWriteIfNewer>true</overWriteIfNewer> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> + <resource>META-INF/spring.handlers</resource> + </transformer> + <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> + <resource>META-INF/spring.schemas</resource> + </transformer> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>org.springframework.shell.Bootstrap</mainClass> + </transformer> + </transformers> </configuration> </execution> </executions> </plugin> + + <!-- Run integration tests. --> <plugin> <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <!--<useUniqueVersions>false</useUniqueVersions> --> - <classpathPrefix>lib/</classpathPrefix> - <mainClass>${jar.mainclass}</mainClass> - </manifest> - <manifestEntries> - <version>${project.version}</version> - </manifestEntries> - </archive> - </configuration> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + + <!-- Generate Code Coverage report. --> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.7.6.201602180812</version> + <executions> + <execution> + <id>default-prepare-agent</id> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>default-report</id> + <phase>prepare-package</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> </plugin> </plugins> - </build> -</project> +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/console/RyaBannerProvider.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/console/RyaBannerProvider.java b/extras/rya.console/src/main/java/mvm/rya/console/RyaBannerProvider.java deleted file mode 100644 index 2d0fac8..0000000 --- a/extras/rya.console/src/main/java/mvm/rya/console/RyaBannerProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -package mvm.rya.console; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.shell.core.CommandMarker; -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.plugin.support.DefaultBannerProvider; -import org.springframework.shell.support.util.OsUtils; -import org.springframework.stereotype.Component; - -/** - * @author Jarred Li - */ -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -public class RyaBannerProvider extends DefaultBannerProvider - implements CommandMarker { - - @CliCommand(value = {"version"}, help = "Displays current CLI version") - @Override - public String getBanner() { - StringBuffer buf = new StringBuffer(); - buf.append("" + - "________ _________ ______ \n" + - "___ __ \\____ _______ _ __ ____/____________________________ /____ \n" + - "__ /_/ /_ / / / __ `/ _ / _ __ \\_ __ \\_ ___/ __ \\_ /_ _ \\\n" + - "_ _, _/_ /_/ // /_/ / / /___ / /_/ / / / /(__ )/ /_/ / / / __/\n" + - "/_/ |_| _\\__, / \\__,_/ \\____/ \\____//_/ /_//____/ \\____//_/ \\___/ \n" + - " /____/ " + OsUtils.LINE_SEPARATOR); - buf.append("Version:" + this.getVersion()); - return buf.toString(); - - } - - @Override - public String getVersion() { - return "3.0.0"; - } - - @Override - public String getWelcomeMessage() { - return "Welcome to the Rya Console"; - } - - @Override - public String getProviderName() { - return "rya"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/console/RyaConsoleCommands.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/console/RyaConsoleCommands.java b/extras/rya.console/src/main/java/mvm/rya/console/RyaConsoleCommands.java deleted file mode 100644 index 3f63b20..0000000 --- a/extras/rya.console/src/main/java/mvm/rya/console/RyaConsoleCommands.java +++ /dev/null @@ -1,230 +0,0 @@ -package mvm.rya.console; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import info.aduna.iteration.CloseableIteration; - -import java.io.FileInputStream; -import java.io.StringReader; -import java.util.Formatter; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; - -import mvm.rya.accumulo.AccumuloRdfConfiguration; -import mvm.rya.accumulo.AccumuloRyaDAO; -import mvm.rya.api.RdfCloudTripleStoreConfiguration; -import mvm.rya.api.domain.RyaStatement; -import mvm.rya.api.domain.RyaURI; -import mvm.rya.api.persist.RyaDAO; -import mvm.rya.api.persist.RyaDAOException; -import mvm.rya.api.persist.query.RyaQueryEngine; -import mvm.rya.api.resolver.RdfToRyaConversions; -import mvm.rya.api.resolver.RyaContext; - -import org.apache.accumulo.core.client.Connector; -import org.apache.accumulo.core.client.ZooKeeperInstance; -import org.apache.accumulo.core.client.mock.MockInstance; -import org.openrdf.model.Statement; -import org.openrdf.rio.RDFHandler; -import org.openrdf.rio.RDFHandlerException; -import org.openrdf.rio.RDFParser; -import org.openrdf.rio.ntriples.NTriplesParserFactory; -import org.springframework.shell.core.CommandMarker; -import org.springframework.shell.core.annotation.CliAvailabilityIndicator; -import org.springframework.shell.core.annotation.CliCommand; -import org.springframework.shell.core.annotation.CliOption; -import org.springframework.stereotype.Component; - -@Component -public class RyaConsoleCommands implements CommandMarker { - - private static final NTriplesParserFactory N_TRIPLES_PARSER_FACTORY = new NTriplesParserFactory(); - - protected final Logger LOG = Logger.getLogger(getClass().getName()); - - private RyaContext ryaContext = RyaContext.getInstance(); - private RyaDAO ryaDAO; - private RDFParser ntrips_parser = null; - - public RyaConsoleCommands() { - ntrips_parser = N_TRIPLES_PARSER_FACTORY.getParser(); - ntrips_parser.setRDFHandler(new RDFHandler() { - - public void startRDF() throws RDFHandlerException { - - } - - public void endRDF() throws RDFHandlerException { - - } - - public void handleNamespace(String s, String s1) throws RDFHandlerException { - - } - - public void handleStatement(Statement statement) throws RDFHandlerException { - try { - RyaStatement ryaStatement = RdfToRyaConversions.convertStatement(statement); - ryaDAO.add(ryaStatement); - } catch (Exception e) { - throw new RDFHandlerException(e); - } - } - - public void handleComment(String s) throws RDFHandlerException { - - } - }); - } - - /** - * commands: - * 1. connect(instance, user, password, zk) - * 1.a. disconnect - * 2. query - * 3. add - */ - - @CliAvailabilityIndicator({"connect"}) - public boolean isConnectAvailable() { - return true; - } - - @CliAvailabilityIndicator({"qt", "add", "load", "disconnect"}) - public boolean isCommandAvailable() { - return ryaDAO != null; - } - - @CliCommand(value = "qt", help = "Query with Triple Pattern") - public String queryTriple( - @CliOption(key = {"subject"}, mandatory = false, help = "Subject") final String subject, - @CliOption(key = {"predicate"}, mandatory = false, help = "Predicate") final String predicate, - @CliOption(key = {"object"}, mandatory = false, help = "Object") final String object, - @CliOption(key = {"context"}, mandatory = false, help = "Context") final String context, - @CliOption(key = {"maxResults"}, mandatory = false, help = "Maximum Number of Results", unspecifiedDefaultValue = "100") final String maxResults - ) { - try { - RdfCloudTripleStoreConfiguration conf = ryaDAO.getConf().clone(); - if (maxResults != null) { - conf.setLimit(Long.parseLong(maxResults)); - } - RyaQueryEngine queryEngine = ryaDAO.getQueryEngine(); - CloseableIteration<RyaStatement, RyaDAOException> query = - queryEngine.query(new RyaStatement( - (subject != null) ? (new RyaURI(subject)) : null, - (predicate != null) ? (new RyaURI(predicate)) : null, - (object != null) ? (new RyaURI(object)) : null, - (context != null) ? (new RyaURI(context)) : null), conf); - StringBuilder sb = new StringBuilder(); - Formatter formatter = new Formatter(sb, Locale.US); - String format = "%-40s %-40s %-40s %-40s\n"; - formatter.format(format, "Subject", "Predicate", - "Object", "Context"); - while (query.hasNext()) { - RyaStatement next = query.next(); - formatter.format(format, next.getSubject().getData(), next.getPredicate().getData(), - next.getObject().getData(), (next.getContext() != null) ? (next.getContext().getData()) : (null)); - sb.append("\n"); - } - return sb.toString(); - } catch (Exception e) { - LOG.log(Level.SEVERE, "", e); - } - return ""; - } - - @CliCommand(value = "load", help = "Load file") - public void load( - @CliOption(key = {"", "file"}, mandatory = true, help = "File of ntriples rdf to load") final String file - ) { - //diff formats? - //diff types of urls - try { - ntrips_parser.parse(new FileInputStream(file), ""); - } catch (Exception e) { - LOG.log(Level.SEVERE, "", e); - } - } - - @CliCommand(value = "add", help = "Add Statement") - public void add( - @CliOption(key = {"", "statement"}, mandatory = true, help = "Statement in NTriples format") final String statement) { - try { - ntrips_parser.parse(new StringReader(statement), ""); - } catch (Exception e) { - LOG.log(Level.SEVERE, "", e); - } - } - - @CliCommand(value = "connect", help = "Connect to Rya Triple Store") - public String connect( - @CliOption(key = {"instance"}, mandatory = true, help = "Accumulo Instance") final String instance, - @CliOption(key = {"user"}, mandatory = true, help = "Accumulo User") final String user, - @CliOption(key = {"pwd"}, mandatory = true, help = "Accumulo Pwd") final String pwd, - @CliOption(key = {"zk"}, mandatory = true, help = "Accumulo Zk (zk=mock for the mock instance)") final String zk, - @CliOption(key = {"pre"}, mandatory = false, help = "Accumulo table prefix", unspecifiedDefaultValue = "rya_") final String pre) { - try { - //using Cloudbase - Connector connector = null; - AccumuloRyaDAO cryaDao = new AccumuloRyaDAO(); - if ("mock".equals(zk)) { - //mock instance - connector = new MockInstance(instance).getConnector(user, pwd); - } else { - connector = new ZooKeeperInstance(instance, zk).getConnector(user, pwd); - } - - cryaDao.setConnector(connector); - AccumuloRdfConfiguration configuration = new AccumuloRdfConfiguration(); - configuration.setTablePrefix(pre); - cryaDao.setConf(configuration); - cryaDao.init(); - this.ryaDAO = cryaDao; - return "Connected to Accumulo"; - } catch (Exception e) { - LOG.log(Level.SEVERE, "", e); - } - return ""; - } - - @CliCommand(value = "disconnect", help = "Disconnect from Rya Store") - public String disconnect() { - if (ryaDAO == null) { - return "Command is not available because Rya is not connected. Please 'connect' first."; - } - try { - this.ryaDAO.destroy(); - this.ryaDAO = null; - } catch (RyaDAOException e) { - LOG.log(Level.SEVERE, "", e); - } - return ""; - } - - public RyaDAO getRyaDAO() { - return ryaDAO; - } - - public void setRyaDAO(RyaDAO ryaDAO) { - this.ryaDAO = ryaDAO; - } -} http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/console/RyaHistoryFileNameProvider.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/console/RyaHistoryFileNameProvider.java b/extras/rya.console/src/main/java/mvm/rya/console/RyaHistoryFileNameProvider.java deleted file mode 100644 index 97182aa..0000000 --- a/extras/rya.console/src/main/java/mvm/rya/console/RyaHistoryFileNameProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package mvm.rya.console; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.shell.plugin.support.DefaultHistoryFileNameProvider; -import org.springframework.stereotype.Component; - -/** - * - * @author Jarred Li - * - */ -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -public class RyaHistoryFileNameProvider extends DefaultHistoryFileNameProvider{ - - @Override - public String getHistoryFileName() { - return "ryaconsole.log"; - } - - @Override - public String getProviderName() { - return "Rya Console History Log"; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/console/RyaPromptProvider.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/console/RyaPromptProvider.java b/extras/rya.console/src/main/java/mvm/rya/console/RyaPromptProvider.java deleted file mode 100644 index b199819..0000000 --- a/extras/rya.console/src/main/java/mvm/rya/console/RyaPromptProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -package mvm.rya.console; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import org.springframework.core.Ordered; -import org.springframework.core.annotation.Order; -import org.springframework.shell.plugin.support.DefaultPromptProvider; -import org.springframework.stereotype.Component; - -/** - * @author Jarred Li - * - */ -@Component -@Order(Ordered.HIGHEST_PRECEDENCE) -public class RyaPromptProvider extends DefaultPromptProvider { - - @Override - public String getPrompt() { - return "rya>"; - } - - - @Override - public String getProviderName() { - return "Rya Console Prompt"; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/RyaAdminCommands.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/RyaAdminCommands.java b/extras/rya.console/src/main/java/mvm/rya/shell/RyaAdminCommands.java new file mode 100644 index 0000000..bd91333 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/RyaAdminCommands.java @@ -0,0 +1,254 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell; + +import static java.util.Objects.requireNonNull; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.shell.core.CommandMarker; +import org.springframework.shell.core.annotation.CliAvailabilityIndicator; +import org.springframework.shell.core.annotation.CliCommand; +import org.springframework.shell.core.annotation.CliOption; +import org.springframework.stereotype.Component; + +import com.google.common.base.Optional; + +import mvm.rya.api.client.RyaClientException; +import mvm.rya.api.client.RyaClient; +import mvm.rya.api.client.GetInstanceDetails; +import mvm.rya.api.client.InstanceDoesNotExistException; +import mvm.rya.api.client.Install.DuplicateInstanceNameException; +import mvm.rya.api.client.Install.InstallConfiguration; +import mvm.rya.api.instance.RyaDetails; +import mvm.rya.shell.SharedShellState.ConnectionState; +import mvm.rya.shell.SharedShellState.ShellState; +import mvm.rya.shell.util.InstallPrompt; +import mvm.rya.shell.util.InstanceNamesFormatter; +import mvm.rya.shell.util.RyaDetailsFormatter; +import mvm.rya.shell.util.SparqlPrompt; + +/** + * Rya Shell commands that have to do with administrative tasks. + */ +@Component +public class RyaAdminCommands implements CommandMarker { + + public static final String CREATE_PCJ_CMD = "create-pcj"; + public static final String DELETE_PCJ_CMD = "delete-pcj"; + public static final String GET_INSTANCE_DETAILS_CMD = "get-instance-details"; + public static final String INSTALL_CMD = "install"; + public static final String LIST_INSTANCES_CMD = "list-instances"; + public static final String UNINSTALL_CMD = "uninstall"; + + private final SharedShellState state; + private final InstallPrompt installPrompt; + private final SparqlPrompt sparqlPrompt; + + /** + * Constructs an instance of {@link RyaAdminCommands}. + * + * @param state - Holds shared state between all of the command classes. (not null) + * @param installPrompt - Prompts a user for installation details. (not null) + * @param sparqlPrompt - TODO doc + */ + @Autowired + public RyaAdminCommands(final SharedShellState state, final InstallPrompt installPrompt, final SparqlPrompt sparqlPrompt) { + this.state = requireNonNull( state ); + this.installPrompt = requireNonNull(installPrompt); + this.sparqlPrompt = requireNonNull(sparqlPrompt); + } + + /** + * Enables commands that only become available once the Shell has been connected to a Rya Storage. + */ + @CliAvailabilityIndicator({ + LIST_INSTANCES_CMD, + INSTALL_CMD }) + public boolean areStorageCommandsAvailable() { + switch(state.getShellState().getConnectionState()) { + case CONNECTED_TO_STORAGE: + case CONNECTED_TO_INSTANCE: + return true; + default: + return false; + } + } + + /** + * Enables commands that are always available once the Shell is connected to a Rya Instance. + */ + @CliAvailabilityIndicator({ + GET_INSTANCE_DETAILS_CMD, + UNINSTALL_CMD }) + public boolean areInstanceCommandsAvailable() { + switch(state.getShellState().getConnectionState()) { + case CONNECTED_TO_INSTANCE: + return true; + default: + return false; + } + } + + /** + * Enables commands that are available when the Shell is connected to a Rya Instance that supports PCJ Indexing. + */ + @CliAvailabilityIndicator({ + CREATE_PCJ_CMD, + DELETE_PCJ_CMD }) + public boolean arePCJCommandsAvailable() { + // 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) { + final GetInstanceDetails getInstanceDetails = shellState.getConnectedCommands().get().getGetInstanceDetails(); + final String ryaInstanceName = state.getShellState().getRyaInstanceName().get(); + try { + final Optional<RyaDetails> instanceDetails = getInstanceDetails.getDetails( ryaInstanceName ); + if(instanceDetails.isPresent()) { + return instanceDetails.get().getPCJIndexDetails().isEnabled(); + } + } catch (final RyaClientException e) { + return false; + } + } + return false; + } + + @CliCommand(value = LIST_INSTANCES_CMD, help = "List the names of the installed Rya instances.") + public String listInstances() { + // Fetch the command that is connected to the store. + final ShellState shellState = state.getShellState(); + final RyaClient commands = shellState.getConnectedCommands().get(); + final Optional<String> ryaInstance = shellState.getRyaInstanceName(); + + try { + // Sort the names alphabetically. + final List<String> instanceNames = commands.getListInstances().listInstances(); + Collections.sort( instanceNames ); + + final String report; + final InstanceNamesFormatter formatter = new InstanceNamesFormatter(); + if(ryaInstance.isPresent()) { + report = formatter.format(instanceNames, ryaInstance.get()); + } else { + report = formatter.format(instanceNames); + } + return report; + + } catch (final RyaClientException e) { + throw new RuntimeException("Can not list the Rya instances. Reason: " + e.getMessage(), e); + } + } + + @CliCommand(value = INSTALL_CMD, help = "Create a new instance of Rya.") + public String install() { + // Fetch the commands that are connected to the store. + final RyaClient commands = state.getShellState().getConnectedCommands().get(); + + String instanceName = null; + InstallConfiguration installConfig = null; + try { + boolean verified = false; + while(!verified) { + // Use the install prompt to fetch the user's installation options. + instanceName = installPrompt.promptInstanceName(); + installConfig = installPrompt.promptInstallConfiguration(); + + // Verify the configuration is what the user actually wants to do. + verified = installPrompt.promptVerified(instanceName, installConfig); + } + + // 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 = GET_INSTANCE_DETAILS_CMD, help = "Print information about how the Rya instance is configured.") + public String getInstanceDetails() { + // Fetch the command that is connected to the store. + final ShellState shellState = state.getShellState(); + final RyaClient commands = shellState.getConnectedCommands().get(); + final String ryaInstance = shellState.getRyaInstanceName().get(); + + try { + final Optional<RyaDetails> details = commands.getGetInstanceDetails().getDetails(ryaInstance); + if(details.isPresent()) { + return new RyaDetailsFormatter().format(details.get()); + } else { + return "This instance of Rya does not have a Rya Details table. Consider migrating to a newer version of Rya."; + } + } catch(final InstanceDoesNotExistException e) { + throw new RuntimeException(String.format("A Rya instance named '%s' does not exist.", ryaInstance), e); + } catch (final RyaClientException e) { + throw new RuntimeException("Could not get the instance details. Reason: " + e.getMessage(), e); + } + } + + @CliCommand(value = CREATE_PCJ_CMD, help = "Creates and starts the maintenance of a new PCJ using a Fluo application.") + public String createPcj() { + // Fetch the command that is connected to the store. + final ShellState shellState = state.getShellState(); + final RyaClient commands = shellState.getConnectedCommands().get(); + final String ryaInstance = shellState.getRyaInstanceName().get(); + + try { + // Prompt the user for the SPARQL. + final String sparql = sparqlPrompt.getSparql(); + // Execute the command. + final String pcjId = commands.getCreatePCJ().createPCJ(ryaInstance, sparql); + // Return a message that indicates the ID of the newly created ID. + return String.format("The PCJ has been created. Its ID is '%s'.", pcjId); + } catch (final InstanceDoesNotExistException e) { + throw new RuntimeException(String.format("A Rya instance named '%s' does not exist.", ryaInstance), e); + } catch (final IOException | RyaClientException e) { + throw new RuntimeException("Could not create the PCJ. Provided reasons: " + e.getMessage(), e); + } + } + + @CliCommand(value = DELETE_PCJ_CMD, help = "Deletes and halts maintenance of a PCJ.") + public String deletePcj( + @CliOption(key = {"pcjId"}, mandatory = true, help = "The ID of the PCJ that will be deleted.") + final String pcjId) { + // Fetch the command that is connected to the store. + final ShellState shellState = state.getShellState(); + final RyaClient commands = shellState.getConnectedCommands().get(); + final String ryaInstance = shellState.getRyaInstanceName().get(); + + try { + // Execute the command. + commands.getDeletePCJ().deletePCJ(ryaInstance, pcjId); + return "The PCJ has been deleted."; + + } catch (final InstanceDoesNotExistException e) { + throw new RuntimeException(String.format("A Rya instance named '%s' does not exist.", ryaInstance), e); + } catch (final RyaClientException e) { + throw new RuntimeException("The PCJ could not be deleted. Provided reason: " + e.getMessage(), e); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/RyaBannerProvider.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/RyaBannerProvider.java b/extras/rya.console/src/main/java/mvm/rya/shell/RyaBannerProvider.java new file mode 100644 index 0000000..cdd706c --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/RyaBannerProvider.java @@ -0,0 +1,97 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell; + +import java.io.IOException; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.shell.core.CommandMarker; +import org.springframework.shell.plugin.support.DefaultBannerProvider; +import org.springframework.stereotype.Component; + +/** + * Customizes the Rya Shell's banner. + */ +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class RyaBannerProvider extends DefaultBannerProvider implements CommandMarker { + private final Logger log = LoggerFactory.getLogger(RyaBannerProvider.class); + + private static final String BANNER = + " _____ _____ _ _ _ \n" + + "| __ \\ / ____| | | | |\n" + + "| |__) | _ __ _ | (___ | |__ ___| | |\n" + + "| _ / | | |/ _` | \\___ \\| '_ \\ / _ \\ | |\n" + + "| | \\ \\ |_| | (_| | ____) | | | | __/ | |\n" + + "|_| \\_\\__, |\\__,_| |_____/|_| |_|\\___|_|_|\n" + + " __/ | \n" + + " |___/ "; + + private String version = null; + + @Override + public String getBanner() { + return BANNER + "\n" + getVersion() + "\n"; + } + + @Override + public String getWelcomeMessage() { + return "Welcome to the Rya Shell.\n" + + "\n" + + "Execute one of the connect commands to start interacting with an instance of Rya.\n" + + "You may press tab at any time to see which of the commands are available."; + } + + @Override + public String getVersion() { + if(version == null) { + version = loadVersion(); + } + return version; + } + + /** + * Loads the version number from the Rya Shell's MANIFEST.MF file. + * + * @return The version number of the Rya Shell. + */ + private String loadVersion() { + final String className = getClass().getSimpleName() + ".class"; + final String classPath = getClass().getResource( className ).toString(); + + try { + final URL classUrl = new URL(classPath); + final JarURLConnection jarConnection = (JarURLConnection) classUrl.openConnection(); + final Manifest manifest = jarConnection.getManifest(); + final Attributes attributes = manifest.getMainAttributes(); + return attributes.getValue("Implementation-Version"); + } catch (final IOException e) { + log.error("Could not load the application's version from it's manifest.", e); + } + + return "UNKNOWN"; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/RyaConnectionCommands.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/RyaConnectionCommands.java b/extras/rya.console/src/main/java/mvm/rya/shell/RyaConnectionCommands.java new file mode 100644 index 0000000..d305a87 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/RyaConnectionCommands.java @@ -0,0 +1,167 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell; + +import static java.util.Objects.requireNonNull; + +import java.io.IOException; +import java.nio.CharBuffer; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.Connector; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.shell.core.CommandMarker; +import org.springframework.shell.core.annotation.CliAvailabilityIndicator; +import org.springframework.shell.core.annotation.CliCommand; +import org.springframework.shell.core.annotation.CliOption; +import org.springframework.stereotype.Component; + +import com.google.common.base.Optional; + +import mvm.rya.api.client.InstanceExists; +import mvm.rya.api.client.RyaClientException; +import mvm.rya.api.client.RyaClient; +import mvm.rya.api.client.accumulo.AccumuloConnectionDetails; +import mvm.rya.api.client.accumulo.AccumuloRyaClientFactory; +import mvm.rya.shell.SharedShellState.ConnectionState; +import mvm.rya.shell.util.ConnectorFactory; +import mvm.rya.shell.util.PasswordPrompt; + +/** + * Spring Shell commands that manage the connection that is used by the shell. + */ +@Component +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_INSTANCE_CMD = "connect-to-instance"; + public static final String DISCONNECT_COMMAND_NAME_CMD = "disconnect"; + + private final SharedShellState sharedState; + private final PasswordPrompt passwordPrompt; + + /** + * Constructs an instance of {@link RyaConnectionCommands}. + * + * @param state - Holds shared state between all of the command classes. (not null) + * @param passwordPrompt - Prompts the user for their password when connecting to a Rya store. (not null) + */ + @Autowired + public RyaConnectionCommands(final SharedShellState state, final PasswordPrompt passwordPrompt) { + this.sharedState = requireNonNull( state ); + this.passwordPrompt = requireNonNull(passwordPrompt); + } + + @CliAvailabilityIndicator({PRINT_CONNECTION_DETAILS_CMD}) + public boolean isPrintConnectionDetailsAvailable() { + return true; + } + + @CliAvailabilityIndicator({CONNECT_ACCUMULO_CMD}) + public boolean areConnectCommandsAvailable() { + return sharedState.getShellState().getConnectionState() == ConnectionState.DISCONNECTED; + } + + @CliAvailabilityIndicator({CONNECT_INSTANCE_CMD}) + public boolean isConnectToInstanceAvailable() { + switch(sharedState.getShellState().getConnectionState()) { + case CONNECTED_TO_STORAGE: + case CONNECTED_TO_INSTANCE: + return true; + default: + return false; + } + } + + @CliAvailabilityIndicator({DISCONNECT_COMMAND_NAME_CMD}) + public boolean isDisconnectAvailable() { + return sharedState.getShellState().getConnectionState() != ConnectionState.DISCONNECTED; + } + + @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 { + return "The shell is not connected to anything."; + } + } + + @CliCommand(value = CONNECT_ACCUMULO_CMD, help = "Connect the shell to an instance of Accumulo.") + public String connectToAccumulo( + @CliOption(key = {"username"}, mandatory = true, help = "The username that will be used to connect to Accummulo.") + final String username, + @CliOption(key = {"instanceName"}, mandatory = true, help = "The name of the Accumulo instance that will be connected to.") + final String instanceName, + @CliOption(key = {"zookeepers"}, mandatory = true, help = "A comma delimited list of zookeeper server hostnames.") + final String zookeepers + ) { + + try { + // Prompt the user for their password. + final char[] password = passwordPrompt.getPassword(); + final Connector connector= new ConnectorFactory().connect(username, CharBuffer.wrap(password), instanceName, zookeepers); + + // Initialize the connected to Accumulo shared state. + final AccumuloConnectionDetails accumuloDetails = new AccumuloConnectionDetails(username, password, instanceName, zookeepers); + final RyaClient commands = AccumuloRyaClientFactory.build(accumuloDetails, connector); + sharedState.connectedToAccumulo(accumuloDetails, commands); + + } catch(IOException | AccumuloException | AccumuloSecurityException e) { + throw new RuntimeException("Could not connect to Accumulo. 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 ") + public void connectToInstance( + @CliOption(key = {"instance"}, mandatory = true, help = "The name of the Rya Instance the shell will interact with.") + final String instance) { + try { + final InstanceExists instanceExists = sharedState.getShellState().getConnectedCommands().get().getInstanceExists(); + + // TODO gracefully fail if that version doen't support it. maybe the list command should go ahead + + // Make sure the requested instance exists. + if(!instanceExists.exists(instance)) { + throw new RuntimeException(String.format("'%s' does not match an existing Rya instance.", instance)); + } + } catch(final RyaClientException e) { + throw new RuntimeException("Could not connect to Rya instance. Reason: " + e.getMessage(), e); + } + + // Store the instance name in the shared state. + sharedState.connectedToInstance(instance); + } + + @CliCommand(value = DISCONNECT_COMMAND_NAME_CMD, help = "Disconnect the shell from the Rya storage it is connect to.") + public void disconnect() { + sharedState.disconnected(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/RyaPromptProvider.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/RyaPromptProvider.java b/extras/rya.console/src/main/java/mvm/rya/shell/RyaPromptProvider.java new file mode 100644 index 0000000..b78fdd9 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/RyaPromptProvider.java @@ -0,0 +1,62 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell; + +import static java.util.Objects.requireNonNull; + +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 mvm.rya.shell.SharedShellState.ShellState; + +/** + * Customizes the Rya Shell's prompt. + */ +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class RyaPromptProvider extends DefaultPromptProvider { + + private final SharedShellState sharedState; + + @Autowired + public RyaPromptProvider(final SharedShellState sharedState) { + this.sharedState = requireNonNull(sharedState); + } + + @Override + public String getPrompt() { + final ShellState state = sharedState.getShellState(); + + switch(state.getConnectionState()) { + case DISCONNECTED: + return "rya> "; + case CONNECTED_TO_STORAGE: + return String.format("rya/%s> ", state.getConnectionDetails().get().getInstanceName()); + case CONNECTED_TO_INSTANCE: + return String.format("rya/%s:%s> ", + state.getConnectionDetails().get().getInstanceName(), + state.getRyaInstanceName().get()); + default: + return "rya> "; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/SharedShellState.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/SharedShellState.java b/extras/rya.console/src/main/java/mvm/rya/shell/SharedShellState.java new file mode 100644 index 0000000..01ab8bf --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/SharedShellState.java @@ -0,0 +1,338 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell; + +import static java.util.Objects.requireNonNull; + +import java.util.Objects; +import java.util.concurrent.locks.ReentrantLock; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; +import javax.annotation.concurrent.ThreadSafe; + +import com.google.common.base.Optional; + +import mvm.rya.api.client.RyaClient; +import mvm.rya.api.client.accumulo.AccumuloConnectionDetails; + +/** + * Holds values that are shared between the various Rya command classes. + */ +@ThreadSafe +@ParametersAreNonnullByDefault +public class SharedShellState { + // The shared nature of this object means we shouldn't assume only a single thread is accessing it. + private final ReentrantLock lock = new ReentrantLock(); + + // The current state. + private ShellState shellState = ShellState.builder() + .setConnectionState( ConnectionState.DISCONNECTED ) + .build(); + + /** + * @return The values that define the state of the Rya Shell. + */ + public ShellState getShellState() { + lock.lock(); + try { + return shellState; + } finally { + lock.unlock(); + } + } + + /** + * This method indicates a shift into the {@link ConnectionState#CONNECTED_TO_STORAGE} state. + * <p/> + * Store the values used by an Accumulo Rya Storage connection. This may + * only be called when the shell is disconnected. + * + * @param connectionDetails - Metadata about the Accumulo connection. (not null) + * @param connectedCommands - Rya Commands that will execute against the Accumulo instance. (not null) + * @throws IllegalStateException Thrown if the shell is already connected to a Rya storage. + */ + public void connectedToAccumulo( + final AccumuloConnectionDetails 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 ) + .setAccumuloConnectionDetails( 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. + * + * @param instanceName - The name of the Rya instance. (not null) + * @throws IllegalStateException Thrown if the shell is disconnected. + */ + public void connectedToInstance(final String instanceName) throws IllegalStateException { + requireNonNull(instanceName); + + lock.lock(); + try { + // Verify the Rya Shell is connected to a storage. + if(shellState.getConnectionState() == ConnectionState.DISCONNECTED) { + throw new IllegalStateException("You can not set a Rya Instance Name before connecting to a Rya Storage."); + } + + // Set the instance name. + shellState = ShellState.builder( shellState ) + .setConnectionState(ConnectionState.CONNECTED_TO_INSTANCE) + .setRyaInstanceName( instanceName ) + .build(); + } finally { + lock.unlock(); + } + } + + /** + * This method indicates a shift into the {@link DISCONNECTED} state. + * <p/> + * Clears all of the values associated with a Rya Storage/Instance connection. + * If the shell is already disconnected, then this method does not do anything. + */ + public void disconnected() { + lock.lock(); + try { + shellState = ShellState.builder() + .setConnectionState(ConnectionState.DISCONNECTED) + .build(); + } finally { + lock.unlock(); + } + } + + /** + * Enumerates the various states a Rya Shell may be in. + */ + public static enum ConnectionState { + /** + * The shell is not connected to a Rya Storage. + */ + DISCONNECTED, + + /** + * The shell is connected to a Rya Storage, but a specific instance hasn't been set. + */ + CONNECTED_TO_STORAGE, + + /** + * The shell is connected to Rya Storage and a specific Rya Instance. + */ + CONNECTED_TO_INSTANCE; + } + + /** + * Values that define the state of a Rya Shell. + */ + @Immutable + @ParametersAreNonnullByDefault + public static final class ShellState { + // Indicates the state of the shell. + private final ConnectionState connectionState; + + // Connection specific values. + private final Optional<AccumuloConnectionDetails> connectionDetails; + private final Optional<RyaClient> connectedCommands; + + // Instance specific values. + private final Optional<String> instanceName; + + private ShellState( + final ConnectionState connectionState, + final Optional<AccumuloConnectionDetails> connectionDetails, + final Optional<RyaClient> connectedCommands, + final Optional<String> instanceName) { + this.connectionState = requireNonNull(connectionState); + this.connectionDetails = requireNonNull(connectionDetails); + this.connectedCommands = requireNonNull(connectedCommands); + this.instanceName = requireNonNull(instanceName); + } + + /** + * @return The {@link ConnectionState} of the Rya Shell. + */ + public ConnectionState getConnectionState() { + return connectionState; + } + + /** + * @return Metadata about the Accumulo connection. The value will not be present + * if the Rya Shell is not connected to a storage. + */ + public Optional<AccumuloConnectionDetails> getConnectionDetails() { + return connectionDetails; + } + + /** + * @return The {@link RyaClient} to use when a command on the shell is issued. + * The value will not be present if the Rya Shell is not connected to a storage. + */ + public Optional<RyaClient> getConnectedCommands() { + return connectedCommands; + } + + /** + * @return The name of the Rya Instance the Rya Shell is issuing commands to. + * The value will not be present if the Rya Shell is not connected to a + * storage or if a target instance has not been set yet. + */ + public Optional<String> getRyaInstanceName() { + return instanceName; + } + + @Override + public int hashCode() { + return Objects.hash(connectionState, connectionDetails, connectedCommands, instanceName); + } + + @Override + public boolean equals(final Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof ShellState) { + final ShellState state = (ShellState)obj; + return Objects.equals(connectionState, state.connectionState) && + Objects.equals(connectionDetails, state.connectionDetails) && + Objects.equals(connectedCommands, state.connectedCommands) && + Objects.equals(instanceName, state.instanceName); + } + return false; + } + + /** + * @return An empty instance of {@link Builder}. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Create an instance of {@link Builder} populated with the values of {code shellState}. + * + * @param shellState - The initial state of the Builder. + * @return An instance of {@link Builder} populated with the values + * of {code shellState}. + */ + public static Builder builder(final ShellState shellState) { + return new Builder(shellState); + } + + /** + * Builds instances of {@link ShellState}. + */ + @ParametersAreNonnullByDefault + public static class Builder { + private ConnectionState connectionState; + + // Connection specific values. + private AccumuloConnectionDetails connectionDetails; + private RyaClient connectedCommands; + + // Instance specific values. + private String instanceName; + + /** + * Constructs an empty instance of {@link Builder}. + */ + public Builder() { } + + /** + * Constructs an instance of {@builder} initialized with the values + * of a {@link ShellState}. + * + * @param shellState - The initial state of the builder. (not null) + */ + public Builder(final ShellState shellState) { + this.connectionState = shellState.getConnectionState(); + this.connectionDetails = shellState.getConnectionDetails().orNull(); + this.connectedCommands = shellState.getConnectedCommands().orNull(); + this.instanceName = shellState.getRyaInstanceName().orNull(); + } + + /** + * @param connectionState - The {@link ConnectionState} of the Rya Shell. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setConnectionState(@Nullable final ConnectionState connectionState) { + this.connectionState = connectionState; + return this; + } + + /** + * @param connectionDetails - Metadata about the Accumulo connection. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setAccumuloConnectionDetails(@Nullable final AccumuloConnectionDetails connectionDetails) { + this.connectionDetails = connectionDetails; + return this; + } + + /** + * @param connectedCommands - The {@link RyaClient} to use when a command on the shell is issued. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setConnectedCommands(@Nullable final RyaClient connectedCommands) { + this.connectedCommands = connectedCommands; + return this; + } + + /** + * @param instanceName - The name of the Rya Instance the Rya Shell is issuing commands to. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setRyaInstanceName(@Nullable final String instanceName) { + this.instanceName = instanceName; + return this; + } + + /** + * @return An instance of {@link ShellState} built using this builder's values. + */ + public ShellState build() { + return new ShellState( + connectionState, + Optional.fromNullable(connectionDetails), + Optional.fromNullable(connectedCommands), + Optional.fromNullable(instanceName)); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/util/ConnectorFactory.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/util/ConnectorFactory.java b/extras/rya.console/src/main/java/mvm/rya/shell/util/ConnectorFactory.java new file mode 100644 index 0000000..23c3e26 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/util/ConnectorFactory.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell.util; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.Connector; +import org.apache.accumulo.core.client.Instance; +import org.apache.accumulo.core.client.ZooKeeperInstance; +import org.apache.accumulo.core.client.security.tokens.PasswordToken; + +/** + * Creates {@link Connector}s that are linked to an instance of Accumulo. + */ +@ParametersAreNonnullByDefault +public class ConnectorFactory { + + /** + * Create a {@link Connector} that uses the provided connection details. + * + * @param username - The username the connection will use. (not null) + * @param password - The password the connection will use. (not null) + * @param instanceName - The name of the Accumulo instance. (not null) + * @param zookeeperHostnames - A comma delimited list of the Zookeeper server hostnames. (not null) + * @return A {@link Connector} that may be used to access the instance of Accumulo. + * @throws AccumuloSecurityException Could not connect for security reasons. + * @throws AccumuloException Could not connect for other reasons. + */ + public Connector connect( + final String username, + final CharSequence password, + final String instanceName, + final String zookeeperHostnames) throws AccumuloException, AccumuloSecurityException { + requireNonNull(username); + requireNonNull(password); + requireNonNull(instanceName); + requireNonNull(zookeeperHostnames); + + // Setup the password token that will be used. + final PasswordToken token = new PasswordToken( password ); + + // Connect to the instance of Accumulo. + final Instance instance = new ZooKeeperInstance(instanceName, zookeeperHostnames); + return instance.getConnector(username, token); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/util/InstallPrompt.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/util/InstallPrompt.java b/extras/rya.console/src/main/java/mvm/rya/shell/util/InstallPrompt.java new file mode 100644 index 0000000..c4a81d2 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/util/InstallPrompt.java @@ -0,0 +1,131 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell.util; + +import java.io.IOException; + +import com.google.common.base.Optional; + +import jline.console.ConsoleReader; +import mvm.rya.api.client.Install.InstallConfiguration; + +/** + * A mechanism for prompting a user of the application for a the parameters + * that will be used when installing an instance of Rya. + */ +public interface InstallPrompt { + + /** + * Prompt the user for the name of the Rya instance that will be created. + * + * @return The value they entered. + * @throws IOException There was a problem reading the value. + */ + public String promptInstanceName() throws IOException; + + /** + * Prompt the user for which features of Rya they want enabled. + * + * @return The value they entered. + * @throws IOException There was a problem reading the values. + */ + public InstallConfiguration promptInstallConfiguration() throws IOException; + + /** + * Prompt the user asking them if they are sure they would like to do the + * install. + * + * @return The value they entered. + * @throws IOException There was a problem reading the value. + */ + public boolean promptVerified(String instanceName, InstallConfiguration installConfig) throws IOException; + + /** + * Prompts a user for install information using a JLine {@link ConsoleReader}. + */ + public static class JLineAccumuloInstallPrompt extends JLinePrompt implements InstallPrompt { + + @Override + public String promptInstanceName() throws IOException { + final ConsoleReader reader = getReader(); + reader.setPrompt("Rya Instance Name: "); + final String instanceName = reader.readLine(); + return instanceName; + } + + @Override + public InstallConfiguration promptInstallConfiguration() throws IOException { + final InstallConfiguration.Builder builder = InstallConfiguration.builder(); + + String prompt = makeFieldPrompt("Use Shard Balancing (improves streamed input write speeds)", false); + final boolean enableTableHashPrefix = promptBoolean(prompt, Optional.of(false)); + builder.setEnableTableHashPrefix( enableTableHashPrefix ); + + prompt = makeFieldPrompt("Use Entity Centric Indexing", true); + final boolean enableEntityCentricIndexing = promptBoolean(prompt, Optional.of(true)); + builder.setEnableEntityCentricIndex( enableEntityCentricIndexing ); + + prompt = makeFieldPrompt("Use Free Text Indexing", true); + final boolean enableFreeTextIndexing = promptBoolean(prompt, Optional.of(true)); + builder.setEnableFreeTextIndex( enableFreeTextIndexing ); + + prompt = makeFieldPrompt("Use Geospatial Indexing", true); + final boolean enableGeoIndexing = promptBoolean(prompt, Optional.of(true)); + builder.setEnableGeoIndex( enableGeoIndexing ); + + prompt = makeFieldPrompt("Use Precomputed Join Indexing", true); + final boolean enablePCJIndexing = promptBoolean(prompt, Optional.of(true)); + builder.setEnablePcjIndex( enablePCJIndexing ); + + if(enablePCJIndexing) { + prompt = "PCJ Updater Fluo Application Name: "; + final String fluoAppName = promptString(prompt, Optional.<String>absent()); + builder.setFluoPcjAppName(fluoAppName); + } + + prompt = makeFieldPrompt("Use Temporal Indexing", true); + final boolean useTemporalIndexing = promptBoolean(prompt, Optional.of(true)); + builder.setEnableTemporalIndex( useTemporalIndexing ); + + return builder.build(); + } + + @Override + public boolean promptVerified(final String instanceName, final InstallConfiguration installConfig) throws IOException { + final ConsoleReader reader = getReader(); + reader.println(); + reader.println("A Rya instance will be installed using the following values:"); + reader.println(" Instance Name: " + instanceName); + reader.println(" Use Shard Balancing: " + installConfig.isTableHashPrefixEnabled()); + reader.println(" Use Entity Centric Indexing: " + installConfig.isEntityCentrixIndexEnabled()); + reader.println(" Use Free Text Indexing: " + installConfig.isFreeTextIndexEnabled()); + reader.println(" Use Geospatial Indexing: " + installConfig.isGeoIndexEnabled()); + + reader.println(" Use Precomputed Join Indexing: " + installConfig.isPcjIndexEnabled()); + if(installConfig.isPcjIndexEnabled()) { + reader.println(" PCJ Updater Fluo Application Name: " + installConfig.getFluoPcjAppName().get()); + } + + reader.println(" Use Temporal Indexing: " + installConfig.isTemporalIndexEnabled()); + reader.println(""); + + return promptBoolean("Continue with the install? ", Optional.<Boolean>absent()); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/extras/rya.console/src/main/java/mvm/rya/shell/util/InstanceNamesFormatter.java ---------------------------------------------------------------------- diff --git a/extras/rya.console/src/main/java/mvm/rya/shell/util/InstanceNamesFormatter.java b/extras/rya.console/src/main/java/mvm/rya/shell/util/InstanceNamesFormatter.java new file mode 100644 index 0000000..dc70894 --- /dev/null +++ b/extras/rya.console/src/main/java/mvm/rya/shell/util/InstanceNamesFormatter.java @@ -0,0 +1,77 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package mvm.rya.shell.util; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * Pretty formats a list of Rya instance names. + */ +@ParametersAreNonnullByDefault +public class InstanceNamesFormatter { + + /** + * Formats the list of Rya instance names with a '*' next to whichever entry + * matches the connected name. + * + * @param names - The Rya instance names. (not null) + * @param connectedName - The instance name that will have a '*' next to it. (not null) + * @return A string holding the pretty formatted list. + */ + public String format(final List<String> names, final String connectedName) { + requireNonNull(names); + requireNonNull(connectedName); + + // Will be -1 if the connected name isn't in the list of names, so none will be starred. + final int connectedIndex = names.indexOf( connectedName ); + + final StringBuilder formatted = new StringBuilder("Rya instance names:\n"); + for(int i = 0; i < names.size(); i++) { + if(i == connectedIndex) { + formatted.append(" * "); + } else { + formatted.append(" "); + } + formatted.append( names.get(i) ).append("\n"); + } + + return formatted.toString(); + } + + /** + * Formats the list of Rya instance names. + * + * @param names - The Rya instance names. (not null) + * @return A string holding the pretty formatted list. + */ + public String format(final List<String> names) { + requireNonNull(names); + + final StringBuilder formatted = new StringBuilder("Rya instance names:\n"); + for(int i = 0; i < names.size(); i++) { + formatted.append(" ").append( names.get(i) ).append("\n"); + } + + return formatted.toString(); + } +} \ No newline at end of file
