RYA-119 Added MongoDB Column Visibility (called Document Visibility). This adds a new field to each document called documentVisibility which uses a boolean expression to determine if the user can access the document. The boolean expression is in Disjunctive Normal Formal so that the expression's grouping is simplified enough that MongoDB can run Set operations on it to determine if the document is viewable. The expression is stored as an array in MongoDB. Closes #162.
Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/cc1cc712 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/cc1cc712 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/cc1cc712 Branch: refs/heads/master Commit: cc1cc712df43d6d0854eccbb7ea61ca58e5fe61f Parents: 0e61333 Author: ejwhite922 <[email protected]> Authored: Wed Nov 2 09:51:32 2016 -0400 Committer: Caleb Meier <[email protected]> Committed: Wed May 31 18:20:38 2017 -0700 ---------------------------------------------------------------------- .../java/org/apache/rya/api/persist/RyaDAO.java | 12 +- dao/mongodb.rya/pom.xml | 5 + .../apache/rya/mongodb/MongoDBQueryEngine.java | 32 +- .../rya/mongodb/MongoDBRdfConfiguration.java | 52 ++- .../org/apache/rya/mongodb/MongoDBRyaDAO.java | 125 ++--- .../apache/rya/mongodb/MongoDbRdfConstants.java | 39 ++ .../dao/SimpleMongoDBStorageStrategy.java | 42 +- .../operators/aggregation/AggregationUtil.java | 105 +++++ .../aggregation/PipelineOperators.java | 108 +++++ .../operators/aggregation/SetOperators.java | 142 ++++++ .../aggregation/VariableOperators.java | 73 +++ .../operators/query/ArrayOperators.java | 57 +++ .../operators/query/ComparisonOperators.java | 85 ++++ .../operators/query/ConditionalOperators.java | 125 +++++ .../operators/query/LogicalOperators.java | 102 +++++ .../document/util/AuthorizationsUtil.java | 60 +++ .../util/DisjunctiveNormalFormConverter.java | 270 +++++++++++ .../DocumentVisibilityConversionException.java | 62 +++ .../document/util/DocumentVisibilityUtil.java | 331 ++++++++++++++ .../document/visibility/DocumentVisibility.java | 100 ++++ .../visibility/DocumentVisibilityAdapter.java | 143 ++++++ .../RyaStatementBindingSetCursorIterator.java | 197 ++++---- .../iter/RyaStatementCursorIterator.java | 161 ++++--- .../org/apache/rya/mongodb/MongoDBRyaDAOIT.java | 454 ++++++++++++++++++- .../apache/rya/mongodb/MongoDBRyaDAOTest.java | 109 +++-- .../SimpleMongoDBStorageStrategyTest.java | 39 +- .../DisjunctiveNormalFormConverterTest.java | 155 +++++++ .../util/DocumentVisibilityUtilTest.java | 139 ++++++ .../DocumentVisibilityAdapterTest.java | 167 +++++++ 29 files changed, 3126 insertions(+), 365 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/common/rya.api/src/main/java/org/apache/rya/api/persist/RyaDAO.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/org/apache/rya/api/persist/RyaDAO.java b/common/rya.api/src/main/java/org/apache/rya/api/persist/RyaDAO.java index c3d314b..57aae1b 100644 --- a/common/rya.api/src/main/java/org/apache/rya/api/persist/RyaDAO.java +++ b/common/rya.api/src/main/java/org/apache/rya/api/persist/RyaDAO.java @@ -8,9 +8,9 @@ package org.apache.rya.api.persist; * 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 @@ -46,7 +46,7 @@ public interface RyaDAO<C extends RdfCloudTripleStoreConfiguration> extends RyaC /** * - * @return true if the store is already initiailized + * @return true if the store is already initialized * @throws RyaDAOException */ public boolean isInitialized() throws RyaDAOException; @@ -69,10 +69,10 @@ public interface RyaDAO<C extends RdfCloudTripleStoreConfiguration> extends RyaC /** * Add and commit a collection of RyaStatements * - * @param statement + * @param statementIter * @throws RyaDAOException */ - public void add(Iterator<RyaStatement> statement) throws RyaDAOException; + public void add(Iterator<RyaStatement> statementIter) throws RyaDAOException; /** * Delete a RyaStatement. The Configuration should provide the auths to perform the delete @@ -89,7 +89,7 @@ public interface RyaDAO<C extends RdfCloudTripleStoreConfiguration> extends RyaC * @param conf * @throws RyaDAOException */ - public void dropGraph(C conf, RyaURI... graphs) throws RyaDAOException; + public void dropGraph(C conf, RyaURI... graphs) throws RyaDAOException; /** * Delete a collection of RyaStatements. http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/pom.xml ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/pom.xml b/dao/mongodb.rya/pom.xml index 3566e2a..1c9edd8 100644 --- a/dao/mongodb.rya/pom.xml +++ b/dao/mongodb.rya/pom.xml @@ -81,6 +81,11 @@ Tests will fail with the following error when using 32bit JVM on either Linux or </dependency> <dependency> + <groupId>org.apache.accumulo</groupId> + <artifactId>accumulo-core</artifactId> + </dependency> + + <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java index ce2ac6b..2b49e61 100644 --- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBQueryEngine.java @@ -23,21 +23,11 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.io.Closeable; import java.io.IOException; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.calrissian.mango.collect.CloseableIterable; -import org.openrdf.query.BindingSet; - -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBObject; -import com.mongodb.MongoClient; - -import info.aduna.iteration.CloseableIteration; import org.apache.rya.api.domain.RyaStatement; import org.apache.rya.api.persist.RyaDAOException; import org.apache.rya.api.persist.query.BatchRyaQuery; @@ -49,9 +39,17 @@ import org.apache.rya.mongodb.iter.NonCloseableRyaStatementCursorIterator; import org.apache.rya.mongodb.iter.RyaStatementBindingSetCursorIterator; import org.apache.rya.mongodb.iter.RyaStatementCursorIterable; import org.apache.rya.mongodb.iter.RyaStatementCursorIterator; +import org.calrissian.mango.collect.CloseableIterable; +import org.openrdf.query.BindingSet; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.MongoClient; + +import info.aduna.iteration.CloseableIteration; /** * Date: 7/17/12 @@ -62,11 +60,11 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio private MongoDBRdfConfiguration configuration; private final MongoClient mongoClient; private final DBCollection coll; - private final MongoDBStorageStrategy strategy; + private final MongoDBStorageStrategy<RyaStatement> strategy; public MongoDBQueryEngine(final MongoDBRdfConfiguration conf, final MongoClient mongoClient) { this.mongoClient = checkNotNull(mongoClient); - final DB db = mongoClient.getDB( conf.get(MongoDBRdfConfiguration.MONGO_DB_NAME)); + final DB db = mongoClient.getDB(conf.get(MongoDBRdfConfiguration.MONGO_DB_NAME)); coll = db.getCollection(conf.getTriplesCollectionName()); strategy = new SimpleMongoDBStorageStrategy(); } @@ -93,7 +91,7 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio final Set<DBObject> queries = new HashSet<DBObject>(); final DBObject query = strategy.getQuery(stmt); queries.add(query); - final RyaStatementCursorIterator iterator = new RyaStatementCursorIterator(coll, queries, strategy); + final RyaStatementCursorIterator iterator = new RyaStatementCursorIterator(coll, queries, strategy, conf.getAuthorizations()); if (maxResults != null) { iterator.setMaxResults(maxResults); @@ -120,7 +118,7 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio } // TODO not sure what to do about regex ranges? - final RyaStatementBindingSetCursorIterator iterator = new RyaStatementBindingSetCursorIterator(coll, rangeMap, strategy); + final RyaStatementBindingSetCursorIterator iterator = new RyaStatementBindingSetCursorIterator(coll, rangeMap, strategy, conf.getAuthorizations()); if (maxResults != null) { iterator.setMaxResults(maxResults); @@ -147,7 +145,7 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio } // TODO not sure what to do about regex ranges? - final RyaStatementCursorIterator iterator = new RyaStatementCursorIterator(coll, queries, strategy); + final RyaStatementCursorIterator iterator = new RyaStatementCursorIterator(coll, queries, strategy, configuration.getAuthorizations()); if (maxResults != null) { iterator.setMaxResults(maxResults); @@ -168,7 +166,7 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio // TODO not sure what to do about regex ranges? // TODO this is gross - final RyaStatementCursorIterable iterator = new RyaStatementCursorIterable(new NonCloseableRyaStatementCursorIterator(new RyaStatementCursorIterator(coll, queries, strategy))); + final RyaStatementCursorIterable iterator = new RyaStatementCursorIterable(new NonCloseableRyaStatementCursorIterator(new RyaStatementCursorIterator(coll, queries, strategy, configuration.getAuthorizations()))); return iterator; } catch (final Exception e) { @@ -187,7 +185,7 @@ public class MongoDBQueryEngine implements RyaQueryEngine<MongoDBRdfConfiguratio // TODO not sure what to do about regex ranges? // TODO this is gross - final RyaStatementCursorIterable iterator = new RyaStatementCursorIterable(new NonCloseableRyaStatementCursorIterator(new RyaStatementCursorIterator(coll, queries, strategy))); + final RyaStatementCursorIterable iterator = new RyaStatementCursorIterable(new NonCloseableRyaStatementCursorIterator(new RyaStatementCursorIterator(coll, queries, strategy, configuration.getAuthorizations()))); return iterator; } catch (final Exception e) { http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRdfConfiguration.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRdfConfiguration.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRdfConfiguration.java index e88abee..067b682 100644 --- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRdfConfiguration.java +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRdfConfiguration.java @@ -8,9 +8,9 @@ package org.apache.rya.mongodb; * 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 @@ -22,6 +22,7 @@ package org.apache.rya.mongodb; import java.util.List; import java.util.Properties; +import org.apache.accumulo.core.security.Authorizations; import org.apache.hadoop.conf.Configuration; import org.apache.rya.api.RdfCloudTripleStoreConfiguration; @@ -45,7 +46,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { super(); } - public MongoDBRdfConfiguration(Configuration other) { + public MongoDBRdfConfiguration(final Configuration other) { super(other); } @@ -53,7 +54,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Creates a MongoRdfConfiguration object from a Properties file. This * method assumes that all values in the Properties file are Strings and * that the Properties file uses the keys below. - * + * * <br> * <ul> * <li>"mongo.auths" - String of Mongo authorizations. Empty auths used by default. @@ -70,13 +71,13 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * <li>"use.inference" - Use backward chaining inference during query. False by default. * </ul> * <br> - * + * * @param props * - Properties file containing Mongo specific configuration * parameters * @return MongoRdfConfiguration with properties set */ - public static MongoDBRdfConfiguration fromProperties(Properties props) { + public static MongoDBRdfConfiguration fromProperties(final Properties props) { return MongoDBRdfConfigurationBuilder.fromProperties(props); } @@ -88,15 +89,24 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { public MongoDBRdfConfiguration clone() { return new MongoDBRdfConfiguration(this); } + + public Authorizations getAuthorizations() { + final String[] auths = getAuths(); + if (auths == null || auths.length == 0) { + return MongoDbRdfConstants.ALL_AUTHORIZATIONS; + } + return new Authorizations(auths); + } + /** * @return name of Mongo Collection containing Rya triples */ public String getTriplesCollectionName() { return this.get(MONGO_COLLECTION_PREFIX, "rya") + "_triples"; } - + /** - * @return name of Mongo Collection + * @return name of Mongo Collection */ public String getCollectionName() { return this.get(MONGO_COLLECTION_PREFIX, "rya"); @@ -106,7 +116,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets Mongo Collection name * @param name - name of Mongo Collection to connect to */ - public void setCollectionName(String name) { + public void setCollectionName(final String name) { Preconditions.checkNotNull(name); this.set(MONGO_COLLECTION_PREFIX, name); } @@ -122,7 +132,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets name of Mongo Host * @param name - name of Mongo Host to connect to */ - public void setMongoInstance(String name) { + public void setMongoInstance(final String name) { Preconditions.checkNotNull(name); this.set(MONGO_INSTANCE, name); } @@ -138,7 +148,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets port that Mongo will run on * @param name - Mongo port to connect to */ - public void setMongoPort(String name) { + public void setMongoPort(final String name) { Preconditions.checkNotNull(name); this.set(MONGO_INSTANCE_PORT, name); } @@ -154,7 +164,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets name of MongoDB * @param name - name of MongoDB to connect to */ - public void setMongoDBName(String name) { + public void setMongoDBName(final String name) { Preconditions.checkNotNull(name); this.set(MONGO_DB_NAME, name); } @@ -164,10 +174,10 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * if set to true. By default this is set to false. * @param useMock */ - public void setUseMock(boolean useMock) { + public void setUseMock(final boolean useMock) { this.setBoolean(USE_MOCK_MONGO, useMock); } - + /** * Get whether an embedded Mongo is being used as the backing * for Rya. @@ -188,7 +198,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets name of Mongo User * @param user - name of Mongo user to connect to */ - public void setMongoUser(String user) { + public void setMongoUser(final String user) { Preconditions.checkNotNull(user); set(MONGO_USER, user); } @@ -204,7 +214,7 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { * Sets Mongo password * @param password - password to connect to Mongo */ - public void setMongoPassword(String password) { + public void setMongoPassword(final String password) { Preconditions.checkNotNull(password); set(MONGO_USER_PASSWORD, password); } @@ -216,20 +226,20 @@ public class MongoDBRdfConfiguration extends RdfCloudTripleStoreConfiguration { return get(MONGO_USER_PASSWORD); } - public void setAdditionalIndexers(Class<? extends MongoSecondaryIndex>... indexers) { - List<String> strs = Lists.newArrayList(); - for (Class<?> ai : indexers) { + public void setAdditionalIndexers(final Class<? extends MongoSecondaryIndex>... indexers) { + final List<String> strs = Lists.newArrayList(); + for (final Class<?> ai : indexers){ strs.add(ai.getName()); } - setStrings(CONF_ADDITIONAL_INDEXERS, strs.toArray(new String[] {})); + setStrings(CONF_ADDITIONAL_INDEXERS, strs.toArray(new String[]{})); } public List<MongoSecondaryIndex> getAdditionalIndexers() { return getInstances(CONF_ADDITIONAL_INDEXERS, MongoSecondaryIndex.class); } - public void setMongoClient(MongoClient client) { + public void setMongoClient(final MongoClient client) { Preconditions.checkNotNull(client); this.mongoClient = client; } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRyaDAO.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRyaDAO.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRyaDAO.java index 07051a9..be77673 100644 --- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRyaDAO.java +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDBRyaDAO.java @@ -26,17 +26,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.apache.accumulo.core.security.Authorizations; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; - -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBObject; -import com.mongodb.DuplicateKeyException; -import com.mongodb.InsertOptions; -import com.mongodb.MongoClient; - -import de.flapdoodle.embed.mongo.tests.MongodForTestsFactory; import org.apache.rya.api.RdfCloudTripleStoreConfiguration; import org.apache.rya.api.domain.RyaStatement; import org.apache.rya.api.domain.RyaURI; @@ -49,6 +41,14 @@ import org.apache.rya.mongodb.dao.MongoDBNamespaceManager; import org.apache.rya.mongodb.dao.MongoDBStorageStrategy; import org.apache.rya.mongodb.dao.SimpleMongoDBNamespaceManager; import org.apache.rya.mongodb.dao.SimpleMongoDBStorageStrategy; +import org.apache.rya.mongodb.document.util.DocumentVisibilityUtil; + +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.DuplicateKeyException; +import com.mongodb.InsertOptions; +import com.mongodb.MongoClient; /** * Default DAO for mongo backed RYA allowing for CRUD operations. @@ -61,34 +61,39 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ private DB db; private DBCollection coll; private MongoDBQueryEngine queryEngine; - private MongoDBStorageStrategy storageStrategy; + private MongoDBStorageStrategy<RyaStatement> storageStrategy; private MongoDBNamespaceManager nameSpaceManager; private List<MongoSecondaryIndex> secondaryIndexers; + private Authorizations auths; /** - * Creates a new {@link MongoDBRyaDAO} - * @param conf + * Creates a new instance of {@link MongoDBRyaDAO}. + * @param conf the {@link MongoDBRdfConfiguration}. * @throws RyaDAOException */ public MongoDBRyaDAO(final MongoDBRdfConfiguration conf) throws RyaDAOException, NumberFormatException, UnknownHostException { - this.conf = conf; - mongoClient = MongoConnectorFactory.getMongoClient(conf); - conf.setMongoClient(mongoClient); - init(); + this(conf, MongoConnectorFactory.getMongoClient(conf)); } - - public MongoDBRyaDAO(final MongoDBRdfConfiguration conf, final MongoClient mongoClient) throws RyaDAOException{ + /** + * Creates a new instance of {@link MongoDBRyaDAO}. + * @param conf the {@link MongoDBRdfConfiguration}. + * @param mongoClient the {@link MongoClient}. + * @throws RyaDAOException + */ + public MongoDBRyaDAO(final MongoDBRdfConfiguration conf, final MongoClient mongoClient) throws RyaDAOException { this.conf = conf; this.mongoClient = mongoClient; conf.setMongoClient(mongoClient); + auths = conf.getAuthorizations(); init(); } @Override public void setConf(final MongoDBRdfConfiguration conf) { this.conf = conf; + this.auths = conf.getAuthorizations(); } public MongoClient getMongoClient(){ @@ -111,21 +116,21 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ @Override public void init() throws RyaDAOException { - secondaryIndexers = conf.getAdditionalIndexers(); - for(final MongoSecondaryIndex index: secondaryIndexers) { - index.setConf(conf); - index.setClient(mongoClient); - } + secondaryIndexers = conf.getAdditionalIndexers(); + for(final MongoSecondaryIndex index: secondaryIndexers) { + index.setConf(conf); + index.setClient(mongoClient); + } - db = mongoClient.getDB(conf.get(MongoDBRdfConfiguration.MONGO_DB_NAME)); - coll = db.getCollection(conf.getTriplesCollectionName()); - nameSpaceManager = new SimpleMongoDBNamespaceManager(db.getCollection(conf.getNameSpacesCollectionName())); - queryEngine = new MongoDBQueryEngine(conf, mongoClient); - storageStrategy = new SimpleMongoDBStorageStrategy(); - storageStrategy.createIndices(coll); - for(final MongoSecondaryIndex index: secondaryIndexers) { - index.init(); - } + db = mongoClient.getDB(conf.get(MongoDBRdfConfiguration.MONGO_DB_NAME)); + coll = db.getCollection(conf.getTriplesCollectionName()); + nameSpaceManager = new SimpleMongoDBNamespaceManager(db.getCollection(conf.getNameSpacesCollectionName())); + queryEngine = new MongoDBQueryEngine(conf, mongoClient); + storageStrategy = new SimpleMongoDBStorageStrategy(); + storageStrategy.createIndices(coll); + for(final MongoSecondaryIndex index: secondaryIndexers) { + index.init(); + } } @Override @@ -146,9 +151,14 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ public void add(final RyaStatement statement) throws RyaDAOException { // add it to the collection try { - coll.insert(storageStrategy.serialize(statement)); - for(final RyaSecondaryIndexer index: secondaryIndexers) { - index.storeStatement(statement); + final boolean canAdd = DocumentVisibilityUtil.doesUserHaveDocumentAccess(auths, statement.getColumnVisibility()); + if (canAdd) { + coll.insert(storageStrategy.serialize(statement)); + for(final RyaSecondaryIndexer index: secondaryIndexers) { + index.storeStatement(statement); + } + } else { + throw new RyaDAOException("User does not have the required authorizations to add statement"); } } catch (final IOException e) { log.error("Unable to add: " + statement.toString()); @@ -160,21 +170,25 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ } @Override - public void add(final Iterator<RyaStatement> statement) throws RyaDAOException { + public void add(final Iterator<RyaStatement> statementIter) throws RyaDAOException { final List<DBObject> dbInserts = new ArrayList<DBObject>(); - while (statement.hasNext()){ - final RyaStatement ryaStatement = statement.next(); - final DBObject insert = storageStrategy.serialize(ryaStatement); - dbInserts.add(insert); - - try { - for (final RyaSecondaryIndexer index : secondaryIndexers) { - index.storeStatement(ryaStatement); + while (statementIter.hasNext()){ + final RyaStatement ryaStatement = statementIter.next(); + final boolean canAdd = DocumentVisibilityUtil.doesUserHaveDocumentAccess(auths, ryaStatement.getColumnVisibility()); + if (canAdd) { + final DBObject insert = storageStrategy.serialize(ryaStatement); + dbInserts.add(insert); + + try { + for (final RyaSecondaryIndexer index : secondaryIndexers) { + index.storeStatement(ryaStatement); + } + } catch (final IOException e) { + log.error("Failed to add: " + ryaStatement.toString() + " to the indexer"); } - } catch (final IOException e) { - log.error("Failed to add: " + ryaStatement.toString() + " to the indexer"); + } else { + throw new RyaDAOException("User does not have the required authorizations to add statement"); } - } coll.insert(dbInserts, new InsertOptions().continueOnError(true)); } @@ -182,8 +196,13 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ @Override public void delete(final RyaStatement statement, final MongoDBRdfConfiguration conf) throws RyaDAOException { - final DBObject obj = storageStrategy.getQuery(statement); - coll.remove(obj); + final boolean canDelete = DocumentVisibilityUtil.doesUserHaveDocumentAccess(auths, statement.getColumnVisibility()); + if (canDelete) { + final DBObject obj = storageStrategy.getQuery(statement); + coll.remove(obj); + } else { + throw new RyaDAOException("User does not have the required authorizations to delete statement"); + } } @Override @@ -197,9 +216,13 @@ public final class MongoDBRyaDAO implements RyaDAO<MongoDBRdfConfiguration>{ final MongoDBRdfConfiguration conf) throws RyaDAOException { while (statements.hasNext()){ final RyaStatement ryaStatement = statements.next(); - coll.remove(storageStrategy.getQuery(ryaStatement)); + final boolean canDelete = DocumentVisibilityUtil.doesUserHaveDocumentAccess(auths, ryaStatement.getColumnVisibility()); + if (canDelete) { + coll.remove(storageStrategy.getQuery(ryaStatement)); + } else { + throw new RyaDAOException("User does not have the required authorizations to delete statement"); + } } - } @Override http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDbRdfConstants.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDbRdfConstants.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDbRdfConstants.java new file mode 100644 index 0000000..138e72a --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/MongoDbRdfConstants.java @@ -0,0 +1,39 @@ +/* + * 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.mongodb; + +import org.apache.accumulo.core.security.Authorizations; +import org.apache.rya.mongodb.document.visibility.DocumentVisibility; + +/** + * Interface MongoDbRdfConstants. Holds constants for MongoDB related + * operations. + */ +public interface MongoDbRdfConstants { + /** + * Constant Authorization that allows user to view all documents. + */ + public static final Authorizations ALL_AUTHORIZATIONS = Authorizations.EMPTY; + + /** + * Constant representing a non-{@code null} {@link DocumentVisibility} which + * should be used if the document does not specify a document visibility. + */ + public static final DocumentVisibility EMPTY_DV = new DocumentVisibility(new byte[0]); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/dao/SimpleMongoDBStorageStrategy.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/dao/SimpleMongoDBStorageStrategy.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/dao/SimpleMongoDBStorageStrategy.java index 5024110..bbcb13b 100644 --- a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/dao/SimpleMongoDBStorageStrategy.java +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/dao/SimpleMongoDBStorageStrategy.java @@ -32,6 +32,9 @@ import org.apache.rya.api.domain.RyaType; import org.apache.rya.api.domain.RyaURI; import org.apache.rya.api.domain.StatementMetadata; import org.apache.rya.api.persist.query.RyaQuery; +import org.apache.rya.mongodb.document.visibility.DocumentVisibility; +import org.apache.rya.mongodb.document.visibility.DocumentVisibilityAdapter; +import org.apache.rya.mongodb.document.visibility.DocumentVisibilityAdapter.MalformedDocumentVisibilityException; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.model.vocabulary.XMLSchema; @@ -44,15 +47,18 @@ import com.mongodb.DBObject; */ public class SimpleMongoDBStorageStrategy implements MongoDBStorageStrategy<RyaStatement> { private static final Logger LOG = Logger.getLogger(SimpleMongoDBStorageStrategy.class); - protected static final String ID = "_id"; - protected static final String OBJECT_TYPE = "objectType"; - protected static final String URI_TYPE_VALUE = XMLSchema.ANYURI.stringValue(); - protected static final String CONTEXT = "context"; - protected static final String PREDICATE = "predicate"; - protected static final String OBJECT = "object"; - protected static final String SUBJECT = "subject"; + + public static final String ID = "_id"; + public static final String OBJECT_TYPE = "objectType"; + public static final String OBJECT_TYPE_VALUE = XMLSchema.ANYURI.stringValue(); + public static final String CONTEXT = "context"; + public static final String PREDICATE = "predicate"; + public static final String OBJECT = "object"; + public static final String SUBJECT = "subject"; public static final String TIMESTAMP = "insertTimestamp"; - protected static final String STATEMENT_METADATA = "statementMetadata"; + public static final String STATEMENT_METADATA = "statementMetadata"; + public static final String DOCUMENT_VISIBILITY = "documentVisibility"; + protected ValueFactoryImpl factory = new ValueFactoryImpl(); @Override @@ -96,12 +102,18 @@ public class SimpleMongoDBStorageStrategy implements MongoDBStorageStrategy<RyaS @Override public RyaStatement deserializeDBObject(final DBObject queryResult) { - final Map result = queryResult.toMap(); + final Map<?, ?> result = queryResult.toMap(); final String subject = (String) result.get(SUBJECT); final String object = (String) result.get(OBJECT); final String objectType = (String) result.get(OBJECT_TYPE); final String predicate = (String) result.get(PREDICATE); final String context = (String) result.get(CONTEXT); + DocumentVisibility documentVisibility = null; + try { + documentVisibility = DocumentVisibilityAdapter.toDocumentVisibility(queryResult); + } catch (final MalformedDocumentVisibilityException e) { + LOG.error("Unable to convert document visibility"); + } final Long timestamp = (Long) result.get(TIMESTAMP); final String statementMetadata = (String) result.get(STATEMENT_METADATA); RyaType objectRya = null; @@ -120,17 +132,18 @@ public class SimpleMongoDBStorageStrategy implements MongoDBStorageStrategy<RyaS statement = new RyaStatement(new RyaURI(subject), new RyaURI(predicate), objectRya); } + statement.setColumnVisibility(documentVisibility.flatten()); if(timestamp != null) { statement.setTimestamp(timestamp); } if(statementMetadata != null) { try { - StatementMetadata metadata = new StatementMetadata(statementMetadata); + final StatementMetadata metadata = new StatementMetadata(statementMetadata); statement.setStatementMetadata(metadata); } - catch (Exception ex){ + catch (final Exception ex){ LOG.debug("Error deserializing metadata for statement", ex); - } + } } return statement; } @@ -157,16 +170,17 @@ public class SimpleMongoDBStorageStrategy implements MongoDBStorageStrategy<RyaS if (statement.getMetadata() == null){ statement.setStatementMetadata(StatementMetadata.EMPTY_METADATA); } - BasicDBObject doc = new BasicDBObject(ID, new String(Hex.encodeHex(bytes))) + final BasicDBObject dvObject = DocumentVisibilityAdapter.toDBObject(statement.getColumnVisibility()); + final BasicDBObject doc = new BasicDBObject(ID, new String(Hex.encodeHex(bytes))) .append(SUBJECT, statement.getSubject().getData()) .append(PREDICATE, statement.getPredicate().getData()) .append(OBJECT, statement.getObject().getData()) .append(OBJECT_TYPE, statement.getObject().getDataType().toString()) .append(CONTEXT, context) .append(STATEMENT_METADATA, statement.getMetadata().toString()) + .append(DOCUMENT_VISIBILITY, dvObject.get(DOCUMENT_VISIBILITY)) .append(TIMESTAMP, statement.getTimestamp()); return doc; - } @Override http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/AggregationUtil.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/AggregationUtil.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/AggregationUtil.java new file mode 100644 index 0000000..6e4f250 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/AggregationUtil.java @@ -0,0 +1,105 @@ +/* + * 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.mongodb.document.operators.aggregation; + +import static org.apache.rya.mongodb.document.operators.aggregation.PipelineOperators.redact; +import static org.apache.rya.mongodb.document.operators.aggregation.SetOperators.anyElementTrue; +import static org.apache.rya.mongodb.document.operators.aggregation.SetOperators.setIsSubsetNullSafe; +import static org.apache.rya.mongodb.document.operators.aggregation.VariableOperators.map; +import static org.apache.rya.mongodb.document.operators.query.ArrayOperators.size; +import static org.apache.rya.mongodb.document.operators.query.ComparisonOperators.eq; +import static org.apache.rya.mongodb.document.operators.query.LogicalOperators.or; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.accumulo.core.security.Authorizations; +import org.apache.rya.mongodb.MongoDbRdfConstants; +import org.apache.rya.mongodb.dao.SimpleMongoDBStorageStrategy; +import org.apache.rya.mongodb.document.operators.aggregation.PipelineOperators.RedactAggregationResult; +import org.apache.rya.mongodb.document.util.AuthorizationsUtil; + +import com.google.common.collect.Lists; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; + +/** + * Utility methods for MongoDB aggregation. + */ +public final class AggregationUtil { + /** + * Private constructor to prevent instantiation. + */ + private AggregationUtil() { + } + + /** + * Creates a MongoDB $redact aggregation pipeline that only include + * documents whose document visibility match the provided authorizations. + * All other documents are excluded. + * @param authorizations the {@link Authorization}s to include in the + * $redact. Only documents that match the authorizations will be returned. + * @return the {@link List} of {@link DBObject}s that represents the $redact + * aggregation pipeline. + */ + public static List<DBObject> createRedactPipeline(final Authorizations authorizations) { + if (MongoDbRdfConstants.ALL_AUTHORIZATIONS.equals(authorizations)) { + return Lists.newArrayList(); + } + + final List<String> authList = AuthorizationsUtil.getAuthorizationsStrings(authorizations); + + final String documentVisibilityField = "$" + SimpleMongoDBStorageStrategy.DOCUMENT_VISIBILITY; + + final String mapVariableCursorName = "dvItemCursorTag"; + + final BasicDBObject anyElementTrue = + anyElementTrue( + map( + documentVisibilityField, + mapVariableCursorName, + setIsSubsetNullSafe( + "$$" + mapVariableCursorName, + authList.toArray() + ) + ) + ); + + // If the field is empty then there are no authorizations required, + // so all users should be able to view it when they query. + final BasicDBObject isFieldSizeZero = + eq( + size(documentVisibilityField), + 0 + ); + + final BasicDBObject orExpression = or(anyElementTrue, isFieldSizeZero); + + final List<DBObject> pipeline = new ArrayList<>(); + pipeline.add( + redact( + orExpression, + RedactAggregationResult.DESCEND, + RedactAggregationResult.PRUNE + ) + ); + + return pipeline; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/PipelineOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/PipelineOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/PipelineOperators.java new file mode 100644 index 0000000..b73a6c7 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/PipelineOperators.java @@ -0,0 +1,108 @@ +/* + * 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.mongodb.document.operators.aggregation; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.rya.mongodb.document.operators.query.ConditionalOperators.cond; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; + +/** + * Utility methods for pipeline operators. + */ +public final class PipelineOperators { + /** + * The result that the $redact aggregation resolves to. + */ + public static enum RedactAggregationResult { + /** + * $redact returns the fields at the current document level, excluding + * embedded documents. To include embedded documents and embedded + * documents within arrays, apply the $cond expression to the embedded + * documents to determine access for these embedded documents. + */ + DESCEND("$$DESCEND"), + /** + * $redact excludes all fields at this current document/embedded + * document level, without further inspection of any of the excluded + * fields. This applies even if the excluded field contains embedded + * documents that may have different access levels. + */ + PRUNE("$$PRUNE"), + /** + * $redact returns or keeps all fields at this current + * document/embedded document level, without further inspection of the + * fields at this level. This applies even if the included field + * contains embedded documents that may have different access levels. + */ + KEEP("$$KEEP"); + + private final String resultName; + + /** + * Creates a new {@link RedactAggregationResult}. + * @param resultName the name of the redact aggregation result. + */ + private RedactAggregationResult(final String resultName) { + this.resultName = resultName; + } + + @Override + public String toString() { + return resultName; + } + } + + /** + * Private constructor to prevent instantiation. + */ + private PipelineOperators() { + } + + /** + * Creates a $redact expression. + * @param expression the expression to run redact on. + * @param acceptResult the {@link RedactAggregationResult} to return when + * the expression passes. + * @param rejectResult the {@link RedactAggregationResult} to return when + * the expression fails. + * @return the $redact expression {@link BasicDBObject}. + */ + public static BasicDBObject redact(final BasicDBObject expression, final RedactAggregationResult acceptResult, final RedactAggregationResult rejectResult) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) redact(builder, expression, acceptResult, rejectResult).get(); + } + + /** + * Creates a $redact expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression to run redact on. + * @param acceptResult the {@link RedactAggregationResult} to return when + * the expression passes. + * @param rejectResult the {@link RedactAggregationResult} to return when + * the expression fails. + * @return the $redact expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder redact(final BasicDBObjectBuilder builder, final BasicDBObject expression, final RedactAggregationResult acceptResult, final RedactAggregationResult rejectResult) { + checkNotNull(builder); + builder.add("$redact", cond(expression, acceptResult.toString(), rejectResult.toString())); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/SetOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/SetOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/SetOperators.java new file mode 100644 index 0000000..d5b8738 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/SetOperators.java @@ -0,0 +1,142 @@ +/* + * 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.mongodb.document.operators.aggregation; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.rya.mongodb.document.operators.query.ConditionalOperators.ifNull; + +import java.util.Arrays; +import java.util.Collections; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; +import com.mongodb.DBObject; + +/** + * Utility methods for MongoDB set operators. + */ +public final class SetOperators { + /** + * Private constructor to prevent instantiation. + */ + private SetOperators() { + } + + /** + * Checks if the field intersects the set. + * @param field the field to check. + * @param set the set to check. + * @return the $setIntersection expression {@link BasicDBObject}. + */ + public static BasicDBObject setIntersection(final String field, final Object[] set) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) setIntersection(builder, field, set).get(); + } + + /** + * Checks if the field intersects the set. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param field the field to check. + * @param set the set to check. + * @return the $setIntersection expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder setIntersection(final BasicDBObjectBuilder builder, final String field, final Object[] set) { + checkNotNull(builder); + builder.add("$setIntersection", Arrays.asList(field, set)); + return builder; + } + + /** + * Checks if the expression is a subset of the set. + * @param expression the expression to see if it's in the set. + * @param set the set to check against. + * @return the $setIsSubset expression {@link BasicDBObject}. + */ + public static BasicDBObject setIsSubset(final DBObject expression, final Object[] set) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) setIsSubset(builder, expression, set).get(); + } + + /** + * Checks if the expression is a subset of the set. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression to see if it's in the set. + * @param set the set to check against. + * @return the $setIsSubset expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder setIsSubset(final BasicDBObjectBuilder builder, final DBObject expression, final Object[] set) { + checkNotNull(builder); + builder.add("$setIsSubset", Arrays.asList(expression, set).toArray(new Object[0])); + return builder; + } + + /** + * Checks if the field is a subset of the set and is safe if the field is + * null. + * @param field the field to see if it's in the set. + * @param set the set to check against. + * @return the $setIsSubset expression {@link BasicDBObject}. + */ + public static BasicDBObject setIsSubsetNullSafe(final String field, final Object[] set) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) setIsSubsetNullSafe(builder, field, set).get(); + } + + /** + * Checks if the field is a subset of the set and is safe if the field is + * null. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param field the field to see if it's in the set. + * @param set the set to check against. + * @return the $setIsSubset expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder setIsSubsetNullSafe(final BasicDBObjectBuilder builder, final String field, final Object[] set) { + checkNotNull(builder); + final Object emptyAccess = Collections.emptyList().toArray(); + return setIsSubset(builder, + ifNull( + field, + emptyAccess + ), + set + ); + } + + /** + * Checks if any elements from the expression are {@code true}. + * @param expression the expression to see if any elements are {@code true}. + * @return the $anyElementTrue expression {@link BasicDBObject}. + */ + public static BasicDBObject anyElementTrue(final DBObject expression) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) anyElementTrue(builder, expression).get(); + } + + /** + * Checks if any elements from the expression are {@code true}. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression to see if any elements are {@code true}. + * @return the $anyElementTrue expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder anyElementTrue(final BasicDBObjectBuilder builder, final DBObject expression) { + checkNotNull(builder); + builder.add("$anyElementTrue", expression); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/VariableOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/VariableOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/VariableOperators.java new file mode 100644 index 0000000..1fcf8e3 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/aggregation/VariableOperators.java @@ -0,0 +1,73 @@ +/* + * 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.mongodb.document.operators.aggregation; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; +import com.mongodb.DBObject; + +/** + * Utility methods for variable operators. + */ +public final class VariableOperators { + /** + * Private constructor to prevent instantiation. + */ + private VariableOperators() { + } + + /** + * Applies an expression to each item in an array and returns an array with + * the applied results. + * @param input an expression that resolves to an array. + * @param as the variable name for the items in the {@code input} array. + * The {@code in} expression accesses each item in the {@code input} array + * by this variable. + * @param in the expression to apply to each item in the {@code input} + * array. The expression accesses the item by its variable name. + * @return the $map expression {@link BasicDBObject}. + */ + public static BasicDBObject map(final String input, final String as, final DBObject in) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) map(builder, input, as, in).get(); + } + + /** + * Applies an expression to each item in an array and returns an array with + * the applied results. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param input an expression that resolves to an array. + * @param as the variable name for the items in the {@code input} array. + * The {@code in} expression accesses each item in the {@code input} array + * by this variable. + * @param in the expression to apply to each item in the {@code input} + * array. The expression accesses the item by its variable name. + * @return the $map expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder map(final BasicDBObjectBuilder builder, final String input, final String as, final DBObject in) { + checkNotNull(builder); + builder.push("$map") + .add("input", input) + .add("as", as) + .add("in", in); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ArrayOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ArrayOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ArrayOperators.java new file mode 100644 index 0000000..1413ce8 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ArrayOperators.java @@ -0,0 +1,57 @@ +/* + * 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.mongodb.document.operators.query; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; + +/** + * Utility methods for array operators. + */ +public final class ArrayOperators { + /** + * Private constructor to prevent instantiation. + */ + private ArrayOperators() { + } + + /** + * Creates an $size MongoDB expression. + * @param expression the expression to get the size of. + * @return the $size expression {@link BasicDBObject}. + */ + public static BasicDBObject size(final Object expression) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) size(builder, expression).get(); + } + + /** + * Creates an $size MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression to get the size of. + * @return the $size expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder size(final BasicDBObjectBuilder builder, final Object expression) { + checkNotNull(builder); + builder.add("$size", expression); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ComparisonOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ComparisonOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ComparisonOperators.java new file mode 100644 index 0000000..596493a --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ComparisonOperators.java @@ -0,0 +1,85 @@ +/* + * 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.mongodb.document.operators.query; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Arrays; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; + +/** + * Utility methods for comparison operators. + */ +public final class ComparisonOperators { + /** + * Private constructor to prevent instantiation. + */ + private ComparisonOperators() { + } + + /** + * Creates a $gt MongoDB expression. + * @param expression the expression. + * @param value the value to test if the expression is greater than + * @return the $gt expression {@link BasicDBObject}. + */ + public static BasicDBObject gt(final BasicDBObject expression, final Number value) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) gt(builder, expression, value).get(); + } + + /** + * Creates a $gt MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression. + * @param value the value to test if the expression is greater than + * @return the $gt expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder gt(final BasicDBObjectBuilder builder, final BasicDBObject expression, final Number value) { + checkNotNull(builder); + builder.add("$gt", Arrays.asList(expression, value)); + return builder; + } + + /** + * Creates an $eq MongoDB expression. + * @param expression1 the first expression. + * @param expression2 the second expression. + * @return the $eq expression {@link BasicDBObject}. + */ + public static BasicDBObject eq(final BasicDBObject expression1, final Object expression2) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) eq(builder, expression1, expression2).get(); + } + + /** + * Creates an $eq MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression1 the first expression. + * @param expression2 the second expression. + * @return the $eq expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder eq(final BasicDBObjectBuilder builder, final BasicDBObject expression1, final Object expression2) { + checkNotNull(builder); + builder.add("$eq", Arrays.asList(expression1, expression2)); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ConditionalOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ConditionalOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ConditionalOperators.java new file mode 100644 index 0000000..c976519 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/ConditionalOperators.java @@ -0,0 +1,125 @@ +/* + * 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.mongodb.document.operators.query; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Arrays; + +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; + +/** + * Utility methods for conditional operators. + */ +public final class ConditionalOperators { + /** + * Private constructor to prevent instantiation. + */ + private ConditionalOperators() { + } + + /** + * Creates an "if-then-else" MongoDB expression. + * @param ifStatement the "if" statement {@link BasicDBObject}. + * @param thenResult the {@link Object} to return when the + * {@code ifStatement} is {@code true}. + * @param elseResult the {@link Object} to return when the + * {@code ifStatement} is {@code false}. + * @return the "if" expression {@link BasicDBObject}. + */ + public static BasicDBObject ifThenElse(final BasicDBObject ifStatement, final Object thenResult, final Object elseResult) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) ifThenElse(builder, ifStatement, thenResult, elseResult).get(); + } + + /** + * Creates an "if-then-else" MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param ifStatement the "if" statement {@link BasicDBObject}. + * @param thenResult the {@link Object} to return when the + * {@code ifStatement} is {@code true}. + * @param elseResult the {@link Object} to return when the + * {@code ifStatement} is {@code false}. + * @return the "if" expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder ifThenElse(final BasicDBObjectBuilder builder, final BasicDBObject ifStatement, final Object thenResult, final Object elseResult) { + checkNotNull(builder); + builder.add("if", ifStatement); + builder.append("then", thenResult); + builder.append("else", elseResult); + return builder; + } + + /** + * Checks if the expression is {@code null} and replaces it if it is. + * @param expression the expression to {@code null} check. + * @param replacementExpression the expression to replace it with if it's + * {@code null}. + * @return the $ifNull expression {@link BasicDBObject}. + */ + public static BasicDBObject ifNull(final Object expression, final Object replacementExpression) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) ifNull(builder, expression, replacementExpression).get(); + } + + /** + * Checks if the expression is {@code null} and replaces it if it is. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression to {@code null} check. + * @param replacementExpression the expression to replace it with if it's + * {@code null}. + * @return the $ifNull expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder ifNull(final BasicDBObjectBuilder builder, final Object expression, final Object replacementExpression) { + checkNotNull(builder); + builder.add("$ifNull", Arrays.asList(expression, replacementExpression)); + return builder; + } + + /** + * Creates an "$cond" MongoDB expression. + * @param expression the expression {@link BasicDBObject}. + * @param thenResult the {@link Object} to return when the + * {@code expression} is {@code true}. + * @param elseResult the {@link Object} to return when the + * {@code expression} is {@code false}. + * @return the $cond expression {@link BasicDBObject}. + */ + public static BasicDBObject cond(final BasicDBObject expression, final Object thenResult, final Object elseResult) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) cond(builder, expression, thenResult, elseResult).get(); + } + + /** + * Creates an "$cond" MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param expression the expression {@link BasicDBObject}. + * @param thenResult the {@link Object} to return when the + * {@code expression} is {@code true}. + * @param elseResult the {@link Object} to return when the + * {@code expression} is {@code false}. + * @return the $cond expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder cond(final BasicDBObjectBuilder builder, final BasicDBObject expression, final Object thenResult, final Object elseResult) { + checkNotNull(builder); + builder.add("$cond", ifThenElse(expression, thenResult, elseResult)); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/LogicalOperators.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/LogicalOperators.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/LogicalOperators.java new file mode 100644 index 0000000..07dae18 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/operators/query/LogicalOperators.java @@ -0,0 +1,102 @@ +/* + * 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.mongodb.document.operators.query; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; + +import com.google.common.collect.Lists; +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; + +/** + * Utility methods for logical operators. + */ +public final class LogicalOperators { + /** + * Private constructor to prevent instantiation. + */ + private LogicalOperators() { + } + + /** + * Creates an $and MongoDB expression. + * @param lhs the left-hand side operand. + * @param rhs the right-hand side operand. + * @param extras any additional operands. + * @return the $and expression {@link BasicDBObject}. + */ + public static BasicDBObject and(final BasicDBObject lhs, final BasicDBObject rhs, final BasicDBObject... extras) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) and(builder, lhs, rhs, extras).get(); + } + + /** + * Creates an $and MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param lhs the left-hand side operand. + * @param rhs the right-hand side operand. + * @param extras any additional operands. + * @return the $and expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder and(final BasicDBObjectBuilder builder, final BasicDBObject lhs, final BasicDBObject rhs, final BasicDBObject... extras) { + checkNotNull(builder); + final List<BasicDBObject> operands = Lists.newArrayList(lhs, rhs); + + if (extras != null && extras.length > 0) { + operands.addAll(Lists.newArrayList(extras)); + } + + builder.add("$and", operands); + return builder; + } + + /** + * Creates an $or MongoDB expression. + * @param lhs the left-hand side operand. + * @param rhs the right-hand side operand. + * @param extras any additional operands. + * @return the $or expression {@link BasicDBObject}. + */ + public static BasicDBObject or(final BasicDBObject lhs, final BasicDBObject rhs, final BasicDBObject... extras) { + final BasicDBObjectBuilder builder = BasicDBObjectBuilder.start(); + return (BasicDBObject) or(builder, lhs, rhs, extras).get(); + } + + /** + * Creates an $or MongoDB expression. + * @param builder the {@link BasicDBObjectBuilder}. (not {@code null}) + * @param lhs the left-hand side operand. + * @param rhs the right-hand side operand. + * @param extras any additional operands. + * @return the $or expression {@link BasicDBObjectBuilder}. + */ + public static BasicDBObjectBuilder or(final BasicDBObjectBuilder builder, final BasicDBObject lhs, final BasicDBObject rhs, final BasicDBObject... extras) { + checkNotNull(builder); + final List<BasicDBObject> operands = Lists.newArrayList(lhs, rhs); + + if (extras != null && extras.length > 0) { + operands.addAll(Lists.newArrayList(extras)); + } + + builder.add("$or", operands); + return builder; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/cc1cc712/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/util/AuthorizationsUtil.java ---------------------------------------------------------------------- diff --git a/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/util/AuthorizationsUtil.java b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/util/AuthorizationsUtil.java new file mode 100644 index 0000000..f467cd8 --- /dev/null +++ b/dao/mongodb.rya/src/main/java/org/apache/rya/mongodb/document/util/AuthorizationsUtil.java @@ -0,0 +1,60 @@ +/* + * 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.mongodb.document.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.accumulo.core.security.Authorizations; + +import com.google.common.base.Charsets; + +/** + * Utility methods for {@link Authorizations}. + */ +public final class AuthorizationsUtil { + /** + * Private constructor to prevent instantiation. + */ + private AuthorizationsUtil() { + } + + /** + * Gets the authorizations in sorted order. + * @param authorizations the {@link Authorizations}. + * @return authorizations, each as a string encoded in UTF-8 + */ + public static String[] getAuthorizationsStringArray(final Authorizations authorizations) { + return getAuthorizationsStrings(authorizations).toArray(new String[0]); + } + + /** + * Gets the authorizations in sorted order. The returned list is not modifiable. + * @param authorizations the {@link Authorizations} + * @return authorizations, each as a string encoded in UTF-8 + */ + public static List<String> getAuthorizationsStrings(final Authorizations authorizations) { + final List<String> copy = new ArrayList<>(authorizations.getAuthorizations().size()); + for (final byte[] auth : authorizations.getAuthorizations()) { + copy.add(new String(auth, Charsets.UTF_8)); + } + return Collections.unmodifiableList(copy); + } +} \ No newline at end of file
