http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUser.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUser.java b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUser.java new file mode 100644 index 0000000..764e002 --- /dev/null +++ b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUser.java @@ -0,0 +1,95 @@ +/* + * 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 org.apache.rya.api.client.accumulo; + +import static java.util.Objects.requireNonNull; + +import java.util.List; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.Connector; +import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository; +import org.apache.rya.accumulo.utils.RyaTableNames; +import org.apache.rya.accumulo.utils.TablePermissions; +import org.apache.rya.api.client.InstanceDoesNotExistException; +import org.apache.rya.api.client.RemoveUser; +import org.apache.rya.api.client.RyaClientException; +import org.apache.rya.api.instance.RyaDetails; +import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; +import org.apache.rya.api.instance.RyaDetailsUpdater; +import org.apache.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator.CouldNotApplyMutationException; +import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotation; +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * An Accumulo implementation of the {@link DeleteUser} command. + */ +@DefaultAnnotation(NonNull.class) +public class AccumuloRemoveUser extends AccumuloCommand implements RemoveUser { + + private static final TablePermissions TABLE_PERMISSIONS = new TablePermissions(); + + /** + * Constructs an instance of {@link AccumuloDeleteUser}. + * + * @param connectionDetails - Details about the values that were used to create + * the connector to the cluster. (not null) + * @param connector - Provides programmatic access to the instance of Accumulo + * that hosts Rya instance. (not null) + */ + public AccumuloRemoveUser( + final AccumuloConnectionDetails connectionDetails, + final Connector connector) { + super(connectionDetails, connector); + } + + @Override + public void removeUser(final String instanceName, final String username) throws InstanceDoesNotExistException, RyaClientException { + requireNonNull(instanceName); + requireNonNull(username); + + // Update the instance details. + final RyaDetailsUpdater updater = new RyaDetailsUpdater( new AccumuloRyaInstanceDetailsRepository(getConnector(), instanceName) ); + try { + updater.update(originalDetails -> RyaDetails.builder( originalDetails ).removeUser(username).build()); + } catch (RyaDetailsRepositoryException | CouldNotApplyMutationException e) { + throw new RyaClientException("Could not remove the user '" + username + "' from the Rya instance's details.", e); + } + + // Revoke all access to all the instance's tables. + try { + // Build the list of tables that are present within the Rya instance. + final List<String> tables = new RyaTableNames().getTableNames(instanceName, getConnector()); + + // Update the user permissions for those tables. + for(final String table : tables) { + try { + TABLE_PERMISSIONS.revokeAllPermissions(username, table, getConnector()); + } catch (AccumuloException | AccumuloSecurityException e) { + throw new RyaClientException("Could not revoke access to table '" + table + "' from user '" + username + "'.", e); + } + } + } catch (PCJStorageException | RyaDetailsRepositoryException e) { + throw new RyaClientException("Could not determine which tables exist for the '" + instanceName + "' instance of Rya.", e); + } + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java index e0fd25f..02c461f 100644 --- a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java +++ b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloRyaClientFactory.java @@ -24,7 +24,6 @@ import edu.umd.cs.findbugs.annotations.DefaultAnnotation; import edu.umd.cs.findbugs.annotations.NonNull; import org.apache.accumulo.core.client.Connector; - import org.apache.rya.api.client.RyaClient; /** @@ -56,6 +55,8 @@ public class AccumuloRyaClientFactory { new AccumuloBatchUpdatePCJ(connectionDetails, connector), new AccumuloGetInstanceDetails(connectionDetails, connector), new AccumuloInstanceExists(connectionDetails, connector), - new AccumuloListInstances(connectionDetails, connector)); + new AccumuloListInstances(connectionDetails, connector), + new AccumuloAddUser(connectionDetails, connector), + new AccumuloRemoveUser(connectionDetails, connector)); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/entity/EntityCentricIndex.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/entity/EntityCentricIndex.java b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/entity/EntityCentricIndex.java index c9f432e..2a2bde3 100644 --- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/entity/EntityCentricIndex.java +++ b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/entity/EntityCentricIndex.java @@ -1,5 +1,3 @@ -package org.apache.rya.indexing.accumulo.entity; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,8 +16,9 @@ package org.apache.rya.indexing.accumulo.entity; * specific language governing permissions and limitations * under the License. */ +package org.apache.rya.indexing.accumulo.entity; - +import static java.util.Objects.requireNonNull; import static org.apache.rya.accumulo.AccumuloRdfConstants.EMPTY_CV; import static org.apache.rya.accumulo.AccumuloRdfConstants.EMPTY_VALUE; import static org.apache.rya.api.RdfCloudTripleStoreConstants.DELIM_BYTES; @@ -47,12 +46,6 @@ import org.apache.accumulo.core.security.ColumnVisibility; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.Text; import org.apache.log4j.Logger; -import org.openrdf.model.URI; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.primitives.Bytes; - import org.apache.rya.accumulo.AccumuloRdfConfiguration; import org.apache.rya.accumulo.experimental.AbstractAccumuloIndexer; import org.apache.rya.api.RdfCloudTripleStoreConfiguration; @@ -63,6 +56,11 @@ import org.apache.rya.api.resolver.RyaContext; import org.apache.rya.api.resolver.RyaTypeResolverException; import org.apache.rya.api.resolver.triple.TripleRow; import org.apache.rya.indexing.accumulo.ConfigUtils; +import org.openrdf.model.URI; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.primitives.Bytes; public class EntityCentricIndex extends AbstractAccumuloIndexer { @@ -83,7 +81,7 @@ public class EntityCentricIndex extends AbstractAccumuloIndexer { return conf; } - //initialization occurs in setConf because index is created using reflection + //initialization occurs in setConf because index is created using reflection @Override public void setConf(final Configuration conf) { if (conf instanceof AccumuloRdfConfiguration) { @@ -115,23 +113,37 @@ public class EntityCentricIndex extends AbstractAccumuloIndexer { } /** - * Get the Accumulo table used by this index. + * Get the Accumulo table used by this index. * @return table used by instances of this index */ @Override public String getTableName() { return getTableName(conf); } - + /** - * Get the Accumulo table that will be used by this index. - * @param conf + * Get the Accumulo table that will be used by this index. + * + * @param conf - The Rya configuration that specifies which instance of Rya + * the table name will be built for. (not null) * @return table name guaranteed to be used by instances of this index */ - public static String getTableName(Configuration conf) { + public static String getTableName(final Configuration conf) { + requireNonNull(conf); return ConfigUtils.getTablePrefix(conf) + TABLE_SUFFIX; } + /** + * Make the Accumulo table name used by this indexer for a specific instance of Rya. + * + * @param ryaInstanceName - The name of the Rya instance the table name is for. (not null) + * @return The Accumulo table name used by this indexer for a specific instance of Rya. + */ + public static String makeTableName(final String ryaInstanceName) { + requireNonNull(ryaInstanceName); + return ryaInstanceName + TABLE_SUFFIX; + } + @Override public void setMultiTableBatchWriter(final MultiTableBatchWriter writer) throws IOException { try { @@ -253,28 +265,28 @@ public class EntityCentricIndex extends AbstractAccumuloIndexer { * @throws IOException if edge direction can't be extracted as expected. * @throws RyaTypeResolverException if a type error occurs deserializing the statement's object. */ - public static RyaStatement deserializeStatement(Key key, Value value) throws RyaTypeResolverException, IOException { + public static RyaStatement deserializeStatement(final Key key, final Value value) throws RyaTypeResolverException, IOException { assert key != null; assert value != null; - byte[] entityBytes = key.getRowData().toArray(); - byte[] predicateBytes = key.getColumnFamilyData().toArray(); - byte[] data = key.getColumnQualifierData().toArray(); - long timestamp = key.getTimestamp(); - byte[] columnVisibility = key.getColumnVisibilityData().toArray(); - byte[] valueBytes = value.get(); + final byte[] entityBytes = key.getRowData().toArray(); + final byte[] predicateBytes = key.getColumnFamilyData().toArray(); + final byte[] data = key.getColumnQualifierData().toArray(); + final long timestamp = key.getTimestamp(); + final byte[] columnVisibility = key.getColumnVisibilityData().toArray(); + final byte[] valueBytes = value.get(); // main entity is either the subject or object // data contains: column family , var name of other node , data of other node + datatype of object int split = Bytes.indexOf(data, DELIM_BYTES); - byte[] columnFamily = Arrays.copyOf(data, split); - byte[] edgeBytes = Arrays.copyOfRange(data, split + DELIM_BYTES.length, data.length); + final byte[] columnFamily = Arrays.copyOf(data, split); + final byte[] edgeBytes = Arrays.copyOfRange(data, split + DELIM_BYTES.length, data.length); split = Bytes.indexOf(edgeBytes, DELIM_BYTES); - String otherNodeVar = new String(Arrays.copyOf(edgeBytes, split)); - byte[] otherNodeBytes = Arrays.copyOfRange(edgeBytes, split + DELIM_BYTES.length, edgeBytes.length - 2); - byte[] typeBytes = Arrays.copyOfRange(edgeBytes, edgeBytes.length - 2, edgeBytes.length); + final String otherNodeVar = new String(Arrays.copyOf(edgeBytes, split)); + final byte[] otherNodeBytes = Arrays.copyOfRange(edgeBytes, split + DELIM_BYTES.length, edgeBytes.length - 2); + final byte[] typeBytes = Arrays.copyOfRange(edgeBytes, edgeBytes.length - 2, edgeBytes.length); byte[] objectBytes; RyaURI subject; - RyaURI predicate = new RyaURI(new String(predicateBytes)); + final RyaURI predicate = new RyaURI(new String(predicateBytes)); RyaType object; RyaURI context = null; // Expect either: entity=subject.data, otherNodeVar="object", otherNodeBytes={object.data, object.datatype_marker} http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/AccumuloFreeTextIndexer.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/AccumuloFreeTextIndexer.java b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/AccumuloFreeTextIndexer.java index 7d0006a..8c07a8c 100644 --- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/AccumuloFreeTextIndexer.java +++ b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/freetext/AccumuloFreeTextIndexer.java @@ -1,5 +1,3 @@ -package org.apache.rya.indexing.accumulo.freetext; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -8,9 +6,9 @@ package org.apache.rya.indexing.accumulo.freetext; * 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 @@ -18,15 +16,14 @@ package org.apache.rya.indexing.accumulo.freetext; * specific language governing permissions and limitations * under the License. */ +package org.apache.rya.indexing.accumulo.freetext; - - +import static java.util.Objects.requireNonNull; import static org.apache.rya.indexing.accumulo.freetext.query.ASTNodeUtils.getNodeIterator; import java.io.IOException; import java.nio.charset.CharacterCodingException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -58,14 +55,6 @@ import org.apache.commons.lang.Validate; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.Text; import org.apache.log4j.Logger; -import org.openrdf.model.Literal; -import org.openrdf.model.Statement; -import org.openrdf.model.URI; -import org.openrdf.query.QueryEvaluationException; - -import com.google.common.base.Charsets; - -import info.aduna.iteration.CloseableIteration; import org.apache.rya.accumulo.experimental.AbstractAccumuloIndexer; import org.apache.rya.api.RdfCloudTripleStoreConfiguration; import org.apache.rya.api.domain.RyaStatement; @@ -85,6 +74,15 @@ import org.apache.rya.indexing.accumulo.freetext.query.QueryParser; import org.apache.rya.indexing.accumulo.freetext.query.QueryParserTreeConstants; import org.apache.rya.indexing.accumulo.freetext.query.SimpleNode; import org.apache.rya.indexing.accumulo.freetext.query.TokenMgrError; +import org.openrdf.model.Literal; +import org.openrdf.model.Statement; +import org.openrdf.model.URI; +import org.openrdf.query.QueryEvaluationException; + +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; + +import info.aduna.iteration.CloseableIteration; /** * The {@link AccumuloFreeTextIndexer} stores and queries "free text" data from statements into tables in Accumulo. Specifically, this class @@ -218,28 +216,28 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements private void initInternal() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, TableExistsException { - String doctable = getFreeTextDocTablename(conf); - String termtable = getFreeTextTermTablename(conf); + final String doctable = getFreeTextDocTablename(conf); + final String termtable = getFreeTextTermTablename(conf); docTableNumPartitions = ConfigUtils.getFreeTextDocNumPartitions(conf); - int termTableNumPartitions = ConfigUtils.getFreeTextTermNumPartitions(conf); + final int termTableNumPartitions = ConfigUtils.getFreeTextTermNumPartitions(conf); - TableOperations tableOps = ConfigUtils.getConnector(conf).tableOperations(); + final TableOperations tableOps = ConfigUtils.getConnector(conf).tableOperations(); // Create term table partitions - boolean createdTermTable = ConfigUtils.createTableIfNotExists(conf, termtable); + final boolean createdTermTable = ConfigUtils.createTableIfNotExists(conf, termtable); if (createdTermTable && !ConfigUtils.useMockInstance(conf) && termTableNumPartitions > 0) { - TreeSet<Text> splits = new TreeSet<Text>(); + final TreeSet<Text> splits = new TreeSet<Text>(); // split on the "Term List" and "Reverse Term list" boundary splits.add(new Text(ColumnPrefixes.getRevTermListColFam(""))); // Symmetrically split the "Term List" and "Reverse Term list" - int numSubpartitions = ((termTableNumPartitions - 1) / 2); + final int numSubpartitions = ((termTableNumPartitions - 1) / 2); if (numSubpartitions > 0) { - int step = (26 / numSubpartitions); + final int step = (26 / numSubpartitions); for (int i = 0; i < numSubpartitions; i++) { - String nextChar = String.valueOf((char) ('a' + (step * i))); + final String nextChar = String.valueOf((char) ('a' + (step * i))); splits.add(new Text(ColumnPrefixes.getTermListColFam(nextChar))); splits.add(new Text(ColumnPrefixes.getRevTermListColFam(nextChar))); } @@ -248,9 +246,9 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } // Create document (text) table partitions - boolean createdDocTable = ConfigUtils.createTableIfNotExists(conf, doctable); + final boolean createdDocTable = ConfigUtils.createTableIfNotExists(conf, doctable); if (createdDocTable && !ConfigUtils.useMockInstance(conf)) { - TreeSet<Text> splits = new TreeSet<Text>(); + final TreeSet<Text> splits = new TreeSet<Text>(); for (int i = 0; i < docTableNumPartitions; i++) { splits.add(genPartition(i, docTableNumPartitions)); } @@ -276,7 +274,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements //initialization occurs in setConf because index is created using reflection @Override - public void setConf(Configuration conf) { + public void setConf(final Configuration conf) { this.conf = conf; if (!isInit) { try { @@ -291,34 +289,34 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements @Override public Configuration getConf() { - return this.conf; + return conf; } - private void storeStatement(Statement statement) throws IOException { + private void storeStatement(final Statement statement) throws IOException { // if the predicate list is empty, accept all predicates. // Otherwise, make sure the predicate is on the "valid" list - boolean isValidPredicate = validPredicates.isEmpty() || validPredicates.contains(statement.getPredicate()); + final boolean isValidPredicate = validPredicates.isEmpty() || validPredicates.contains(statement.getPredicate()); if (isValidPredicate && (statement.getObject() instanceof Literal)) { // Get the tokens - String text = statement.getObject().stringValue().toLowerCase(); - SortedSet<String> tokens = tokenizer.tokenize(text); + final String text = statement.getObject().stringValue().toLowerCase(); + final SortedSet<String> tokens = tokenizer.tokenize(text); if (!tokens.isEmpty()) { // Get Document Data - String docContent = StatementSerializer.writeStatement(statement); + final String docContent = StatementSerializer.writeStatement(statement); - String docId = Md5Hash.md5Base64(docContent); + final String docId = Md5Hash.md5Base64(docContent); // Setup partition - Text partition = genPartition(docContent.hashCode(), docTableNumPartitions); + final Text partition = genPartition(docContent.hashCode(), docTableNumPartitions); - Mutation docTableMut = new Mutation(partition); - List<Mutation> termTableMutations = new ArrayList<Mutation>(); + final Mutation docTableMut = new Mutation(partition); + final List<Mutation> termTableMutations = new ArrayList<Mutation>(); - Text docIdText = new Text(docId); + final Text docIdText = new Text(docId); // Store the Document Data docTableMut.put(ColumnPrefixes.DOCS_CF_PREFIX, docIdText, new Value(docContent.getBytes(Charsets.UTF_8))); @@ -330,7 +328,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements docTableMut.put(ColumnPrefixes.getContextColFam(statement), docIdText, EMPTY_VALUE); // index the statement terms - for (String token : tokens) { + for (final String token : tokens) { // tie the token to the document docTableMut.put(ColumnPrefixes.getTermColFam(token), docIdText, EMPTY_VALUE); @@ -343,7 +341,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements try { docTableBw.addMutation(docTableMut); termTableBw.addMutations(termTableMutations); - } catch (MutationsRejectedException e) { + } catch (final MutationsRejectedException e) { logger.error("error adding mutation", e); throw new IOException(e); } @@ -354,24 +352,24 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } @Override - public void storeStatement(RyaStatement statement) throws IOException { + public void storeStatement(final RyaStatement statement) throws IOException { storeStatement(RyaToRdfConversions.convertStatement(statement)); } - private static Mutation createEmptyPutMutation(Text row) { - Mutation m = new Mutation(row); + private static Mutation createEmptyPutMutation(final Text row) { + final Mutation m = new Mutation(row); m.put(EMPTY_TEXT, EMPTY_TEXT, EMPTY_VALUE); return m; } - private static Mutation createEmptyPutDeleteMutation(Text row) { - Mutation m = new Mutation(row); + private static Mutation createEmptyPutDeleteMutation(final Text row) { + final Mutation m = new Mutation(row); m.putDelete(EMPTY_TEXT, EMPTY_TEXT); return m; } - private static Text genPartition(int partition, int numParitions) { - int length = Integer.toString(numParitions).length(); + private static Text genPartition(final int partition, final int numParitions) { + final int length = Integer.toString(numParitions).length(); return new Text(String.format("%0" + length + "d", Math.abs(partition % numParitions))); } @@ -385,7 +383,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements public void flush() throws IOException { try { mtbw.flush(); - } catch (MutationsRejectedException e) { + } catch (final MutationsRejectedException e) { logger.error("error flushing the batch writer", e); throw new IOException(e); } @@ -396,31 +394,31 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements public void close() throws IOException { try { mtbw.close(); - } catch (MutationsRejectedException e) { + } catch (final MutationsRejectedException e) { logger.error("error closing the batch writer", e); throw new IOException(e); } } - private Set<String> unrollWildcard(String string, boolean reverse) throws IOException { - Scanner termTableScan = getScanner(getFreeTextTermTablename(conf)); + private Set<String> unrollWildcard(final String string, final boolean reverse) throws IOException { + final Scanner termTableScan = getScanner(getFreeTextTermTablename(conf)); - Set<String> unrolledTerms = new HashSet<String>(); + final Set<String> unrolledTerms = new HashSet<String>(); Text queryTerm; if (reverse) { - String t = StringUtils.removeStart(string, "*").toLowerCase(); + final String t = StringUtils.removeStart(string, "*").toLowerCase(); queryTerm = ColumnPrefixes.getRevTermListColFam(t); } else { - String t = StringUtils.removeEnd(string, "*").toLowerCase(); + final String t = StringUtils.removeEnd(string, "*").toLowerCase(); queryTerm = ColumnPrefixes.getTermListColFam(t); } // perform query and read results termTableScan.setRange(Range.prefix(queryTerm)); - for (Entry<Key, Value> e : termTableScan) { - String term = ColumnPrefixes.removePrefix(e.getKey().getRow()).toString(); + for (final Entry<Key, Value> e : termTableScan) { + final String term = ColumnPrefixes.removePrefix(e.getKey().getRow()).toString(); if (reverse) { unrolledTerms.add(StringUtils.reverse(term)); } else { @@ -436,25 +434,25 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements return unrolledTerms; } - private void unrollWildcards(SimpleNode node) throws IOException { + private void unrollWildcards(final SimpleNode node) throws IOException { if (node instanceof ASTExpression || node instanceof ASTSimpleNode) { - for (SimpleNode n : getNodeIterator(node)) { + for (final SimpleNode n : getNodeIterator(node)) { unrollWildcards(n); } } else if (node instanceof ASTTerm) { - ASTTerm term = (ASTTerm) node; - boolean isWildTerm = term.getType().equals(ASTTerm.WILDTERM); - boolean isPreWildTerm = term.getType().equals(ASTTerm.PREFIXTERM); + final ASTTerm term = (ASTTerm) node; + final boolean isWildTerm = term.getType().equals(ASTTerm.WILDTERM); + final boolean isPreWildTerm = term.getType().equals(ASTTerm.PREFIXTERM); if (isWildTerm || isPreWildTerm) { - Set<String> unrolledTerms = unrollWildcard(term.getTerm(), isPreWildTerm); + final Set<String> unrolledTerms = unrollWildcard(term.getTerm(), isPreWildTerm); // create a new expression - ASTExpression newExpression = new ASTExpression(QueryParserTreeConstants.JJTEXPRESSION); + final ASTExpression newExpression = new ASTExpression(QueryParserTreeConstants.JJTEXPRESSION); newExpression.setType(ASTExpression.OR); newExpression.setNotFlag(term.isNotFlag()); - for (String unrolledTerm : unrolledTerms) { - ASTTerm t = new ASTTerm(QueryParserTreeConstants.JJTTERM); + for (final String unrolledTerm : unrolledTerms) { + final ASTTerm t = new ASTTerm(QueryParserTreeConstants.JJTTERM); t.setNotFlag(false); t.setTerm(unrolledTerm); t.setType(ASTTerm.TERM); @@ -462,8 +460,8 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } // replace "term" node with "expression" node in "term" node parent - SimpleNode parent = (SimpleNode) term.jjtGetParent(); - int index = ASTNodeUtils.getChildIndex(parent, term); + final SimpleNode parent = (SimpleNode) term.jjtGetParent(); + final int index = ASTNodeUtils.getChildIndex(parent, term); Validate.isTrue(index >= 0, "child not found in parent"); @@ -475,7 +473,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } } - private Scanner getScanner(String tablename) throws IOException { + private Scanner getScanner(final String tablename) throws IOException { try { return ConfigUtils.createScanner(tablename, conf); } catch (AccumuloException | AccumuloSecurityException | TableNotFoundException e) { @@ -486,9 +484,9 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements /** {@inheritDoc} */ @Override - public CloseableIteration<Statement, QueryEvaluationException> queryText(String query, StatementConstraints contraints) + public CloseableIteration<Statement, QueryEvaluationException> queryText(final String query, final StatementConstraints contraints) throws IOException { - Scanner docTableScan = getScanner(getFreeTextDocTablename(conf)); + final Scanner docTableScan = getScanner(getFreeTextDocTablename(conf)); // test the query to see if it's parses correctly. SimpleNode root = parseQuery(query); @@ -496,10 +494,10 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements // unroll any wildcard nodes before it goes to the server unrollWildcards(root); - String unrolledQuery = ASTNodeUtils.serializeExpression(root); + final String unrolledQuery = ASTNodeUtils.serializeExpression(root); // Add S P O C constraints to query - StringBuilder constrainedQuery = new StringBuilder("(" + unrolledQuery + ")"); + final StringBuilder constrainedQuery = new StringBuilder("(" + unrolledQuery + ")"); if (contraints.hasSubject()) { constrainedQuery.append(" AND "); @@ -511,8 +509,8 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } if (contraints.hasPredicates()) { constrainedQuery.append(" AND ("); - List<String> predicates = new ArrayList<String>(); - for (URI u : contraints.getPredicates()) { + final List<String> predicates = new ArrayList<String>(); + for (final URI u : contraints.getPredicates()) { predicates.add(ColumnPrefixes.getPredColFam(u.stringValue()).toString()); } constrainedQuery.append(StringUtils.join(predicates, " OR ")); @@ -521,7 +519,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements // Verify that the query is a reasonable size root = parseQuery(constrainedQuery.toString()); - int termCount = ASTNodeUtils.termCount(root); + final int termCount = ASTNodeUtils.termCount(root); if (termCount > queryTermLimit) { throw new IOException("Query contains too many terms. Term limit: " + queryTermLimit + ". Term Count: " + termCount); @@ -531,9 +529,9 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements docTableScan.clearScanIterators(); docTableScan.clearColumns(); - int iteratorPriority = 20; - String iteratorName = "booleanTree"; - IteratorSetting ii = new IteratorSetting(iteratorPriority, iteratorName, BooleanTreeIterator.class); + final int iteratorPriority = 20; + final String iteratorName = "booleanTree"; + final IteratorSetting ii = new IteratorSetting(iteratorPriority, iteratorName, BooleanTreeIterator.class); BooleanTreeIterator.setQuery(ii, constrainedQuery.toString()); docTableScan.addScanIterator(ii); docTableScan.setRange(new Range()); @@ -553,16 +551,16 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements @Override public Statement next() throws QueryEvaluationException { - Entry<Key, Value> entry = i.next(); - Value v = entry.getValue(); + final Entry<Key, Value> entry = i.next(); + final Value v = entry.getValue(); try { - String dataString = Text.decode(v.get(), 0, v.getSize()); - Statement s = StatementSerializer.readStatement(dataString); + final String dataString = Text.decode(v.get(), 0, v.getSize()); + final Statement s = StatementSerializer.readStatement(dataString); return s; - } catch (CharacterCodingException e) { + } catch (final CharacterCodingException e) { logger.error("Error decoding value", e); throw new QueryEvaluationException(e); - } catch (IOException e) { + } catch (final IOException e) { logger.error("Error deserializing statement", e); throw new QueryEvaluationException(e); } @@ -590,14 +588,14 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements * @return * @throws IOException */ - private static SimpleNode parseQuery(String query) throws IOException { + private static SimpleNode parseQuery(final String query) throws IOException { SimpleNode root = null; try { root = QueryParser.parse(query); - } catch (ParseException e) { + } catch (final ParseException e) { logger.error("Parser Exception on Client Side. Query: " + query, e); throw new IOException(e); - } catch (TokenMgrError e) { + } catch (final TokenMgrError e) { logger.error("Token Manager Exception on Client Side. Query: " + query, e); throw new IOException(e); } @@ -605,67 +603,110 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } /** - * Get Free Text Document index table's name - * Use the two table version of this below. This one is required by base class. + * Get Free Text Document index table's name + * Use the two table version of this below. This one is required by base class. */ @Override public String getTableName() { return getFreeTextDocTablename(conf); } - + /** - * Get all the tables used by this index. - * @param conf configuration map - * @return an unmodifiable list of all the table names. + * Make the Accumulo table names used by this indexer for a specific instance of Rya. + * + * @param conf - The Rya configuration that specifies which instance of Rya + * the table names will be built for. (not null) + * @return The Accumulo table names used by this indexer for a specific instance of Rya. */ - public static List<String> getTableNames(Configuration conf) { - return Collections.unmodifiableList( Arrays.asList( - getFreeTextDocTablename(conf), - getFreeTextTermTablename(conf) )); + public static List<String> getTableNames(final Configuration conf) { + requireNonNull(conf); + return Collections.unmodifiableList( + makeTableNames(ConfigUtils.getTablePrefix(conf) ) ); } - + /** * Get the Document index's table name. - * @param conf - * @return the Free Text Document index table's name + * + * @param conf - The Rya configuration that specifies which instance of Rya + * the table names will be built for. (not null) + * @return The Free Text Document index's Accumulo table name for the Rya instance. */ - public static String getFreeTextDocTablename(Configuration conf) { - return org.apache.rya.indexing.accumulo.ConfigUtils.getTablePrefix(conf) + TABLE_SUFFFIX_DOC; + public static String getFreeTextDocTablename(final Configuration conf) { + requireNonNull(conf); + return makeFreeTextDocTablename( ConfigUtils.getTablePrefix(conf) ); } /** * Get the Term index's table name. - * @param conf - * @return the Free Text Term index table's name + * + * @param conf - The Rya configuration that specifies which instance of Rya + * the table names will be built for. (not null) + * @return The Free Text Term index's Accumulo table name for the Rya instance. + */ + public static String getFreeTextTermTablename(final Configuration conf) { + requireNonNull(conf); + return makeFreeTextTermTablename( ConfigUtils.getTablePrefix(conf) ); + } + + /** + * Make the Accumulo table names used by this indexer for a specific instance of Rya. + * + * @param ryaInstanceName - The name of the Rya instance the table names are for. (not null) + * @return The Accumulo table names used by this indexer for a specific instance of Rya. + */ + public static List<String> makeTableNames(final String ryaInstanceName) { + requireNonNull(ryaInstanceName); + return Lists.newArrayList( + makeFreeTextDocTablename(ryaInstanceName), + makeFreeTextTermTablename(ryaInstanceName)); + } + + /** + * Make the Document index's table name. + * + * @param ryaInstanceName - The name of the Rya instance the table names are for. (not null) + * @return The Free Text Document index's Accumulo table name for the Rya instance. + */ + public static String makeFreeTextDocTablename(final String ryaInstanceName) { + requireNonNull(ryaInstanceName); + return ryaInstanceName + TABLE_SUFFFIX_DOC; + } + + /** + * Make the Term index's table name. + * + * @param ryaInstanceName - The name of the Rya instance the table names are for. (not null) + * @return The Free Text Term index's Accumulo table name for the Rya instance. */ - public static String getFreeTextTermTablename(Configuration conf) { - return org.apache.rya.indexing.accumulo.ConfigUtils.getTablePrefix(conf) + TABLE_SUFFIX_TERM; + public static String makeFreeTextTermTablename(final String ryaInstanceName) { + requireNonNull(ryaInstanceName); + return ryaInstanceName + TABLE_SUFFIX_TERM; } - private void deleteStatement(Statement statement) throws IOException { + private void deleteStatement(final Statement statement) throws IOException { // if the predicate list is empty, accept all predicates. // Otherwise, make sure the predicate is on the "valid" list - boolean isValidPredicate = validPredicates.isEmpty() || validPredicates.contains(statement.getPredicate()); + final boolean isValidPredicate = validPredicates.isEmpty() || validPredicates.contains(statement.getPredicate()); if (isValidPredicate && (statement.getObject() instanceof Literal)) { // Get the tokens - String text = statement.getObject().stringValue().toLowerCase(); - SortedSet<String> tokens = tokenizer.tokenize(text); + final String text = statement.getObject().stringValue().toLowerCase(); + final SortedSet<String> tokens = tokenizer.tokenize(text); if (!tokens.isEmpty()) { // Get Document Data - String docContent = StatementSerializer.writeStatement(statement); + final String docContent = StatementSerializer.writeStatement(statement); - String docId = Md5Hash.md5Base64(docContent); + final String docId = Md5Hash.md5Base64(docContent); // Setup partition - Text partition = genPartition(docContent.hashCode(), docTableNumPartitions); + final Text partition = genPartition(docContent.hashCode(), docTableNumPartitions); - Mutation docTableMut = new Mutation(partition); - List<Mutation> termTableMutations = new ArrayList<Mutation>(); + final Mutation docTableMut = new Mutation(partition); + final List<Mutation> termTableMutations = new ArrayList<Mutation>(); - Text docIdText = new Text(docId); + final Text docIdText = new Text(docId); // Delete the Document Data docTableMut.putDelete(ColumnPrefixes.DOCS_CF_PREFIX, docIdText); @@ -678,10 +719,10 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements // Delete the statement terms in index - for (String token : tokens) { + for (final String token : tokens) { if (IS_TERM_TABLE_TOKEN_DELETION_ENABLED) { - int rowId = Integer.parseInt(partition.toString()); - boolean doesTermExistInOtherDocs = doesTermExistInOtherDocs(token, rowId, docIdText); + final int rowId = Integer.parseInt(partition.toString()); + final boolean doesTermExistInOtherDocs = doesTermExistInOtherDocs(token, rowId, docIdText); // Only delete the term from the term table if it doesn't appear in other docs if (!doesTermExistInOtherDocs) { // Delete the term in the term table @@ -698,7 +739,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements try { docTableBw.addMutation(docTableMut); termTableBw.addMutations(termTableMutations); - } catch (MutationsRejectedException e) { + } catch (final MutationsRejectedException e) { logger.error("error adding mutation", e); throw new IOException(e); } @@ -708,7 +749,7 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements } @Override - public void deleteStatement(RyaStatement statement) throws IOException { + public void deleteStatement(final RyaStatement statement) throws IOException { deleteStatement(RyaToRdfConversions.convertStatement(statement)); } @@ -718,36 +759,36 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements * @param currentDocId the current document ID that the search term exists in. * @return {@code true} if the term was found in other documents. {@code false} otherwise. */ - private boolean doesTermExistInOtherDocs(String term, int currentDocId, Text docIdText) { + private boolean doesTermExistInOtherDocs(final String term, final int currentDocId, final Text docIdText) { try { - String freeTextDocTableName = getFreeTextDocTablename(conf); - Scanner scanner = getScanner(freeTextDocTableName); + final String freeTextDocTableName = getFreeTextDocTablename(conf); + final Scanner scanner = getScanner(freeTextDocTableName); - String t = StringUtils.removeEnd(term, "*").toLowerCase(); - Text queryTerm = ColumnPrefixes.getTermColFam(t); + final String t = StringUtils.removeEnd(term, "*").toLowerCase(); + final Text queryTerm = ColumnPrefixes.getTermColFam(t); // perform query and read results scanner.fetchColumnFamily(queryTerm); - for (Entry<Key, Value> entry : scanner) { - Key key = entry.getKey(); - Text row = key.getRow(); - int rowId = Integer.parseInt(row.toString()); + for (final Entry<Key, Value> entry : scanner) { + final Key key = entry.getKey(); + final Text row = key.getRow(); + final int rowId = Integer.parseInt(row.toString()); // We only want to check other documents from the one we're deleting if (rowId != currentDocId) { - Text columnFamily = key.getColumnFamily(); - String columnFamilyValue = columnFamily.toString(); + final Text columnFamily = key.getColumnFamily(); + final String columnFamilyValue = columnFamily.toString(); // Check that the value has the term prefix if (columnFamilyValue.startsWith(ColumnPrefixes.TERM_CF_PREFIX.toString())) { - Text text = ColumnPrefixes.removePrefix(columnFamily); - String value = text.toString(); + final Text text = ColumnPrefixes.removePrefix(columnFamily); + final String value = text.toString(); if (value.equals(term)) { return true; } } } } - } catch (IOException e) { + } catch (final IOException e) { logger.error("Error searching for the existance of the term in other documents", e); } return false; @@ -757,34 +798,34 @@ public class AccumuloFreeTextIndexer extends AbstractAccumuloIndexer implements @Override public void init() { // TODO Auto-generated method stub - + } @Override - public void setConnector(Connector connector) { + public void setConnector(final Connector connector) { // TODO Auto-generated method stub - + } @Override public void destroy() { // TODO Auto-generated method stub - + } @Override - public void purge(RdfCloudTripleStoreConfiguration configuration) { + public void purge(final RdfCloudTripleStoreConfiguration configuration) { // TODO Auto-generated method stub - + } @Override public void dropAndDestroy() { // TODO Auto-generated method stub - + } } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/temporal/AccumuloTemporalIndexer.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/temporal/AccumuloTemporalIndexer.java b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/temporal/AccumuloTemporalIndexer.java index 1a5e803..e9d6c30 100644 --- a/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/temporal/AccumuloTemporalIndexer.java +++ b/extras/indexing/src/main/java/org/apache/rya/indexing/accumulo/temporal/AccumuloTemporalIndexer.java @@ -18,8 +18,11 @@ */ package org.apache.rya.indexing.accumulo.temporal; +import static java.util.Objects.requireNonNull; + import java.io.IOException; import java.nio.charset.CharacterCodingException; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -51,15 +54,6 @@ import org.apache.commons.codec.binary.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.Text; import org.apache.log4j.Logger; -import org.joda.time.DateTime; -import org.openrdf.model.Literal; -import org.openrdf.model.Resource; -import org.openrdf.model.Statement; -import org.openrdf.model.URI; -import org.openrdf.query.QueryEvaluationException; - -import java.util.Arrays; -import info.aduna.iteration.CloseableIteration; import org.apache.rya.accumulo.experimental.AbstractAccumuloIndexer; import org.apache.rya.api.RdfCloudTripleStoreConfiguration; import org.apache.rya.api.domain.RyaStatement; @@ -72,6 +66,14 @@ import org.apache.rya.indexing.TemporalInstant; import org.apache.rya.indexing.TemporalInstantRfc3339; import org.apache.rya.indexing.TemporalInterval; import org.apache.rya.indexing.accumulo.ConfigUtils; +import org.joda.time.DateTime; +import org.openrdf.model.Literal; +import org.openrdf.model.Resource; +import org.openrdf.model.Statement; +import org.openrdf.model.URI; +import org.openrdf.query.QueryEvaluationException; + +import info.aduna.iteration.CloseableIteration; public class AccumuloTemporalIndexer extends AbstractAccumuloIndexer implements TemporalIndexer { @@ -878,7 +880,18 @@ public class AccumuloTemporalIndexer extends AbstractAccumuloIndexer implements @Override public String getTableName() { - return ConfigUtils.getTablePrefix(conf) + TABLE_SUFFIX; + return makeTableName( ConfigUtils.getTablePrefix(conf) ); + } + + /** + * Make the Accumulo table name used by this indexer for a specific instance of Rya. + * + * @param ryaInstanceName - The name of the Rya instance the table name is for. (not null) + * @return The Accumulo table name used by this indexer for a specific instance of Rya. + */ + public static String makeTableName(final String ryaInstanceName) { + requireNonNull(ryaInstanceName); + return ryaInstanceName + TABLE_SUFFIX; } private void deleteStatement(final Statement statement) throws IOException, IllegalArgumentException { http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloAddUserIT.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloAddUserIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloAddUserIT.java new file mode 100644 index 0000000..53e0bf6 --- /dev/null +++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloAddUserIT.java @@ -0,0 +1,267 @@ +/* + * 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 org.apache.rya.api.client.accumulo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.admin.SecurityOperations; +import org.apache.accumulo.core.client.security.tokens.PasswordToken; +import org.apache.accumulo.core.security.SystemPermission; +import org.apache.rya.accumulo.AccumuloITBase; +import org.apache.rya.accumulo.AccumuloRdfConfiguration; +import org.apache.rya.api.client.Install.InstallConfiguration; +import org.apache.rya.api.client.RyaClient; +import org.apache.rya.api.instance.RyaDetails; +import org.apache.rya.indexing.accumulo.ConfigUtils; +import org.apache.rya.sail.config.RyaSailFactory; +import org.junit.Test; +import org.openrdf.model.ValueFactory; +import org.openrdf.sail.Sail; +import org.openrdf.sail.SailConnection; + +import com.google.common.collect.ImmutableList; + +/** + * Integration tests the methods of {@link AccumuloAddUser}. + */ +public class AccumuloAddUserIT extends AccumuloITBase { + + /** + * Ensure that the user who installs the instance of Rya is reported as being a user who can access it. + */ + @Test + public void ryaDetailsIncludesOriginalUser() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + // Create a Rya Client for that user. + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Ensure the Rya instance's details only contain the username of the user who installed the instance. + final ImmutableList<String> expectedUsers = ImmutableList.<String>builder() + .add("userA") + .build(); + + final RyaDetails details = userAClient.getGetInstanceDetails().getDetails("testInstance_").get(); + assertEquals(expectedUsers, details.getUsers()); + } + + /** + * Ensure that when a user is added to a Rya instance that its details are updated to include the new user. + */ + @Test + public void userAddedAlsoAddedToRyaDetails() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Create the user that will be added to the instance of Rya. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Add the user. + userAClient.getAddUser().addUser("testInstance_", "userB"); + + // Ensure the Rya instance's details have been updated to include the added user. + final ImmutableList<String> expectedUsers = ImmutableList.<String>builder() + .add("userA") + .add("userB") + .build(); + + final RyaDetails details = userAClient.getGetInstanceDetails().getDetails("testInstance_").get(); + assertEquals(expectedUsers, details.getUsers()); + } + + /** + * Ensure a user that has not been added to the Rya instance can not interact with it. + */ + @Test + public void userNotAddedCanNotInsert() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Create the user that will not be added to the instance of Rya, but will try to scan it. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + //Try to add a statement the Rya instance with the unauthorized user. This should fail. + boolean securityExceptionThrown = false; + + Sail sail = null; + SailConnection sailConn = null; + try { + final AccumuloRdfConfiguration userBConf = makeRyaConfig("testInstance_", "userB", "userB", getInstanceName(), getZookeepers()); + sail = RyaSailFactory.getInstance(userBConf); + sailConn = sail.getConnection(); + + final ValueFactory vf = sail.getValueFactory(); + sailConn.addStatement(vf.createURI("urn:Alice"), vf.createURI("urn:talksTo"), vf.createURI("urn:Bob")); + + } catch(final RuntimeException e) { + final Throwable cause = e.getCause(); + if(cause instanceof AccumuloSecurityException) { + securityExceptionThrown = true; + } + } finally { + if(sailConn != null) { + try { + sailConn.close(); + } finally { } + } + if(sail != null) { + try { + sail.shutDown(); + } finally { } + } + } + + assertTrue(securityExceptionThrown); + } + + /** + * Ensure a user that has been added to the Rya instance can interact with it. + */ + @Test + public void userAddedCanInsert() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Create the user that will not be added to the instance of Rya, but will try to scan it. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Add the user. + userAClient.getAddUser().addUser("testInstance_", "userB"); + + // Try to add a statement to the Rya instance. This should succeed. + Sail sail = null; + SailConnection sailConn = null; + + try { + final AccumuloRdfConfiguration userBConf = makeRyaConfig("testInstance_", "userB", "userB", getInstanceName(), getZookeepers()); + sail = RyaSailFactory.getInstance(userBConf); + sailConn = sail.getConnection(); + + final ValueFactory vf = sail.getValueFactory(); + sailConn.begin(); + sailConn.addStatement(vf.createURI("urn:Alice"), vf.createURI("urn:talksTo"), vf.createURI("urn:Bob")); + sailConn.close(); + + } finally { + if(sailConn != null) { + try { + sailConn.close(); + } finally { } + } + if(sail != null) { + try { + sail.shutDown(); + } finally { } + } + } + } + + /** + * Ensure nothing happens if you try to add a user that is already there. + */ + @Test + public void addUserTwice() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Create the user that will not be added to the instance of Rya, but will try to scan it. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Add the user. + userAClient.getAddUser().addUser("testInstance_", "userB"); + userAClient.getAddUser().addUser("testInstance_", "userB"); + + // Ensure the Rya instance's details only contain the username of the user who installed the instance. + final ImmutableList<String> expectedUsers = ImmutableList.<String>builder() + .add("userA") + .add("userB") + .build(); + + final RyaDetails details = userAClient.getGetInstanceDetails().getDetails("testInstance_").get(); + assertEquals(expectedUsers, details.getUsers()); + } + + private static AccumuloRdfConfiguration makeRyaConfig( + final String ryaInstanceName, + final String username, + final String password, + final String instanceName, + final String zookeepers) { + final AccumuloRdfConfiguration conf = new AccumuloRdfConfiguration(); + conf.setTablePrefix(ryaInstanceName); + // Accumulo connection information. + conf.set(ConfigUtils.CLOUDBASE_USER, username); + conf.set(ConfigUtils.CLOUDBASE_PASSWORD, password); + conf.set(ConfigUtils.CLOUDBASE_INSTANCE, instanceName); + conf.set(ConfigUtils.CLOUDBASE_ZOOKEEPERS, zookeepers); + conf.set(ConfigUtils.CLOUDBASE_AUTHS, ""); + return conf; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java index 17cc6c7..30eb4ca 100644 --- a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java +++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloBatchUpdatePCJIT.java @@ -23,15 +23,6 @@ import static org.junit.Assert.assertEquals; import java.util.HashSet; import java.util.Set; -import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage; -import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage; -import org.junit.Test; -import org.openrdf.model.ValueFactory; -import org.openrdf.query.BindingSet; -import org.openrdf.query.impl.MapBindingSet; -import org.openrdf.sail.Sail; -import org.openrdf.sail.SailConnection; - import org.apache.rya.accumulo.AccumuloITBase; import org.apache.rya.accumulo.AccumuloRdfConfiguration; import org.apache.rya.api.client.Install.InstallConfiguration; @@ -39,7 +30,15 @@ import org.apache.rya.api.client.RyaClient; import org.apache.rya.indexing.accumulo.ConfigUtils; import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinStorageType; import org.apache.rya.indexing.external.PrecomputedJoinIndexerConfig.PrecomputedJoinUpdaterType; +import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage; +import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage; import org.apache.rya.sail.config.RyaSailFactory; +import org.junit.Test; +import org.openrdf.model.ValueFactory; +import org.openrdf.query.BindingSet; +import org.openrdf.query.impl.MapBindingSet; +import org.openrdf.sail.Sail; +import org.openrdf.sail.SailConnection; /** * Integration tests the methods of {@link AccumuloBatchUpdatePCJ}. http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloGetInstanceDetailsIT.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloGetInstanceDetailsIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloGetInstanceDetailsIT.java index bf4b18c..df03e78 100644 --- a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloGetInstanceDetailsIT.java +++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloGetInstanceDetailsIT.java @@ -27,10 +27,6 @@ import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.TableExistsException; import org.apache.accumulo.core.client.admin.TableOperations; -import org.junit.Test; - -import com.google.common.base.Optional; - import org.apache.rya.accumulo.AccumuloITBase; import org.apache.rya.api.RdfCloudTripleStoreConstants; import org.apache.rya.api.client.GetInstanceDetails; @@ -42,12 +38,14 @@ import org.apache.rya.api.client.RyaClientException; import org.apache.rya.api.instance.RyaDetails; import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails; import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails; -import org.apache.rya.api.instance.RyaDetails.GeoIndexDetails; import org.apache.rya.api.instance.RyaDetails.JoinSelectivityDetails; import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails; import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails.FluoDetails; import org.apache.rya.api.instance.RyaDetails.ProspectorDetails; import org.apache.rya.api.instance.RyaDetails.TemporalIndexDetails; +import org.junit.Test; + +import com.google.common.base.Optional; /** * Tests the methods of {@link AccumuloGetInstanceDetails}. @@ -87,7 +85,7 @@ public class AccumuloGetInstanceDetailsIT extends AccumuloITBase { // The version depends on how the test is packaged, so just grab whatever was stored. .setRyaVersion( details.get().getRyaVersion() ) - .setGeoIndexDetails( new GeoIndexDetails(true) ) + //RYA-215 .setGeoIndexDetails( new GeoIndexDetails(true) ) .setTemporalIndexDetails(new TemporalIndexDetails(true) ) .setFreeTextDetails( new FreeTextIndexDetails(true) ) .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) ) http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUserIT.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUserIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUserIT.java new file mode 100644 index 0000000..69780bc --- /dev/null +++ b/extras/indexing/src/test/java/org/apache/rya/api/client/accumulo/AccumuloRemoveUserIT.java @@ -0,0 +1,168 @@ +/* + * 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 org.apache.rya.api.client.accumulo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.admin.SecurityOperations; +import org.apache.accumulo.core.client.security.tokens.PasswordToken; +import org.apache.accumulo.core.security.SystemPermission; +import org.apache.rya.accumulo.AccumuloITBase; +import org.apache.rya.accumulo.AccumuloRdfConfiguration; +import org.apache.rya.api.client.Install.InstallConfiguration; +import org.apache.rya.api.client.RyaClient; +import org.apache.rya.api.instance.RyaDetails; +import org.apache.rya.indexing.accumulo.ConfigUtils; +import org.apache.rya.sail.config.RyaSailFactory; +import org.junit.Test; +import org.openrdf.model.ValueFactory; +import org.openrdf.sail.Sail; +import org.openrdf.sail.SailConnection; + +import com.google.common.collect.ImmutableList; + +/** + * Integration tests the methods of {@link AccumuloRemoveUser}. + */ +public class AccumuloRemoveUserIT extends AccumuloITBase { + + /** + * Ensure that when a user is removed from a Rya instance that its details are updated to no longer include the user. + */ + @Test + public void removedUserNotInDetails() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Create the user that will be added to the instance of Rya. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + final RyaClient userBClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userB", "userB".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userB", "userB")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Add userB. + userAClient.getAddUser().addUser("testInstance_", "userB"); + + // Remove userA. + userBClient.getRemoveUser().removeUser("testInstance_", "userA"); + + // Ensure the Rya instance's details have been updated to include the added user. + final ImmutableList<String> expectedUsers = ImmutableList.<String>builder() + .add("userB") + .build(); + + final RyaDetails details = userBClient.getGetInstanceDetails().getDetails("testInstance_").get(); + assertEquals(expectedUsers, details.getUsers()); + } + + /** + * Ensure a user that has been removed from the Rya instance can not interact with it. + */ + @Test + public void removedUserCanNotInsert() throws Exception { + final SecurityOperations secOps = super.getConnector().securityOperations(); + + // Create the user that will install the instance of Rya. + secOps.createLocalUser("userA", new PasswordToken("userA")); + secOps.grantSystemPermission("userA", SystemPermission.CREATE_TABLE); + + final RyaClient userAClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userA", "userA".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userA", "userA")); + + // Create the user that will be added to the instance of Rya. + secOps.createLocalUser("userB", new PasswordToken("userB")); + + final RyaClient userBClient = AccumuloRyaClientFactory.build( + new AccumuloConnectionDetails("userB", "userB".toCharArray(), getInstanceName(), getZookeepers()), + super.getClusterInstance().getCluster().getConnector("userB", "userB")); + + // Install the instance of Rya. + userAClient.getInstall().install("testInstance_", InstallConfiguration.builder().build()); + + // Add userB. + userAClient.getAddUser().addUser("testInstance_", "userB"); + + // Remove userA. + userBClient.getRemoveUser().removeUser("testInstance_", "userA"); + + // Show that userA can not insert anything. + boolean securityExceptionThrown = false; + + Sail sail = null; + SailConnection sailConn = null; + try { + final AccumuloRdfConfiguration userAConf = makeRyaConfig("testInstance_", "userA", "userA", getInstanceName(), getZookeepers()); + sail = RyaSailFactory.getInstance(userAConf); + sailConn = sail.getConnection(); + + final ValueFactory vf = sail.getValueFactory(); + sailConn.addStatement(vf.createURI("urn:Alice"), vf.createURI("urn:talksTo"), vf.createURI("urn:Bob")); + + } catch(final RuntimeException e) { + final Throwable cause = e.getCause(); + if(cause instanceof AccumuloSecurityException) { + securityExceptionThrown = true; + } + } finally { + if(sailConn != null) { + try { + sailConn.close(); + } finally { } + } + if(sail != null) { + try { + sail.shutDown(); + } finally { } + } + } + + assertTrue(securityExceptionThrown); + } + + private static AccumuloRdfConfiguration makeRyaConfig( + final String ryaInstanceName, + final String username, + final String password, + final String instanceName, + final String zookeepers) { + final AccumuloRdfConfiguration conf = new AccumuloRdfConfiguration(); + conf.setTablePrefix(ryaInstanceName); + // Accumulo connection information. + conf.set(ConfigUtils.CLOUDBASE_USER, username); + conf.set(ConfigUtils.CLOUDBASE_PASSWORD, password); + conf.set(ConfigUtils.CLOUDBASE_INSTANCE, instanceName); + conf.set(ConfigUtils.CLOUDBASE_ZOOKEEPERS, zookeepers); + conf.set(ConfigUtils.CLOUDBASE_AUTHS, ""); + return conf; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/ab4fca46/extras/indexing/src/test/java/org/apache/rya/indexing/external/tupleSet/AccumuloIndexSetColumnVisibilityTest.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/indexing/external/tupleSet/AccumuloIndexSetColumnVisibilityTest.java b/extras/indexing/src/test/java/org/apache/rya/indexing/external/tupleSet/AccumuloIndexSetColumnVisibilityTest.java index 8cfa97e..751ecab 100644 --- a/extras/indexing/src/test/java/org/apache/rya/indexing/external/tupleSet/AccumuloIndexSetColumnVisibilityTest.java +++ b/extras/indexing/src/test/java/org/apache/rya/indexing/external/tupleSet/AccumuloIndexSetColumnVisibilityTest.java @@ -38,13 +38,26 @@ import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.minicluster.MiniAccumuloCluster; import org.apache.hadoop.conf.Configuration; import org.apache.log4j.Logger; +import org.apache.rya.accumulo.AccumuloRdfConfiguration; +import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository; +import org.apache.rya.api.RdfCloudTripleStoreConfiguration; +import org.apache.rya.api.instance.RyaDetails; +import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails; +import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails; +import org.apache.rya.api.instance.RyaDetails.JoinSelectivityDetails; +import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails; +import org.apache.rya.api.instance.RyaDetails.ProspectorDetails; +import org.apache.rya.api.instance.RyaDetails.TemporalIndexDetails; +import org.apache.rya.api.instance.RyaDetailsRepository; +import org.apache.rya.api.instance.RyaDetailsRepository.AlreadyInitializedException; +import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; +import org.apache.rya.indexing.accumulo.ConfigUtils; import org.apache.rya.indexing.pcj.storage.PrecomputedJoinStorage.PCJStorageException; import org.apache.rya.indexing.pcj.storage.accumulo.AccumuloPcjStorage; import org.apache.rya.indexing.pcj.storage.accumulo.PcjTableNameFactory; import org.apache.rya.indexing.pcj.storage.accumulo.VisibilityBindingSet; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.openrdf.model.impl.NumericLiteralImpl; import org.openrdf.model.impl.URIImpl; @@ -59,21 +72,6 @@ import com.google.common.collect.Sets; import com.google.common.io.Files; import info.aduna.iteration.CloseableIteration; -import org.apache.rya.accumulo.AccumuloRdfConfiguration; -import org.apache.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository; -import org.apache.rya.api.RdfCloudTripleStoreConfiguration; -import org.apache.rya.api.instance.RyaDetails; -import org.apache.rya.api.instance.RyaDetails.EntityCentricIndexDetails; -import org.apache.rya.api.instance.RyaDetails.FreeTextIndexDetails; -import org.apache.rya.api.instance.RyaDetails.GeoIndexDetails; -import org.apache.rya.api.instance.RyaDetails.JoinSelectivityDetails; -import org.apache.rya.api.instance.RyaDetails.PCJIndexDetails; -import org.apache.rya.api.instance.RyaDetails.ProspectorDetails; -import org.apache.rya.api.instance.RyaDetails.TemporalIndexDetails; -import org.apache.rya.api.instance.RyaDetailsRepository; -import org.apache.rya.api.instance.RyaDetailsRepository.AlreadyInitializedException; -import org.apache.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; -import org.apache.rya.indexing.accumulo.ConfigUtils; /** * Tests the evaluation of {@link AccumuloIndexSet}. @@ -176,7 +174,7 @@ public class AccumuloIndexSetColumnVisibilityTest { .setRyaVersion("0.0.0.0") .setFreeTextDetails( new FreeTextIndexDetails(true) ) .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) ) - .setGeoIndexDetails( new GeoIndexDetails(true) ) +//RYA-215 .setGeoIndexDetails( new GeoIndexDetails(true) ) .setTemporalIndexDetails( new TemporalIndexDetails(true) ) .setPCJIndexDetails( PCJIndexDetails.builder()
