diff --git a/src/main/java/com/basho/riak/client/api/ListException.java b/src/main/java/com/basho/riak/client/api/ListException.java new file mode 100644 index 000000000..3eeefa145 --- /dev/null +++ b/src/main/java/com/basho/riak/client/api/ListException.java @@ -0,0 +1,14 @@ +package com.basho.riak.client.api; + +public class ListException extends Exception +{ + public ListException() + { + super("Bucket and key list operations are expensive and should not be used in production."); + } + + public ListException(Throwable cause) + { + super("Bucket and key list operations are expensive and should not be used in production.", cause); + } +} diff --git a/src/main/java/com/basho/riak/client/api/commands/buckets/ListBuckets.java b/src/main/java/com/basho/riak/client/api/commands/buckets/ListBuckets.java index 80a33da31..fb22ef7b3 100644 --- a/src/main/java/com/basho/riak/client/api/commands/buckets/ListBuckets.java +++ b/src/main/java/com/basho/riak/client/api/commands/buckets/ListBuckets.java @@ -16,6 +16,7 @@ package com.basho.riak.client.api.commands.buckets; import com.basho.riak.client.api.commands.ChunkedResponseIterator; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.StreamableRiakCommand; import com.basho.riak.client.core.FutureOperation; import com.basho.riak.client.core.StreamingRiakFuture; @@ -68,10 +69,15 @@ public final class ListBuckets extends StreamableRiakCommand.StreamableRiakComma private final int timeout; private final BinaryValue type; - ListBuckets(Builder builder) + ListBuckets(Builder builder) throws ListException { this.timeout = builder.timeout; this.type = builder.type; + + if (!builder.allowListing) + { + throw new ListException(); + } } @Override @@ -170,6 +176,7 @@ public static class Builder { private int timeout; private final BinaryValue type; + private boolean allowListing; /** * Construct a Builder for a ListBuckets command. @@ -180,6 +187,21 @@ public Builder(String type) this.type = BinaryValue.create(type); } + /** + * Allow this listing command + *

+ * Bucket and key list operations are expensive and should not + * be used in production, however using this method will allow + * the command to be built. + *

+ * @return a reference to this object. + */ + public Builder withAllowListing() + { + this.allowListing = true; + return this; + } + /** * Construct a Builder for a ListBuckets command. * @param type the bucket type. @@ -208,7 +230,7 @@ public Builder withTimeout(int timeout) * Construct a new ListBuckets command. * @return a new ListBuckets command. */ - public ListBuckets build() + public ListBuckets build() throws ListException { return new ListBuckets(this); } diff --git a/src/main/java/com/basho/riak/client/api/commands/kv/ListKeys.java b/src/main/java/com/basho/riak/client/api/commands/kv/ListKeys.java index beaf3bc71..5e01be6ed 100644 --- a/src/main/java/com/basho/riak/client/api/commands/kv/ListKeys.java +++ b/src/main/java/com/basho/riak/client/api/commands/kv/ListKeys.java @@ -15,6 +15,7 @@ */ package com.basho.riak.client.api.commands.kv; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.StreamableRiakCommand; import com.basho.riak.client.api.commands.ChunkedResponseIterator; import com.basho.riak.client.core.FutureOperation; @@ -78,10 +79,15 @@ public final class ListKeys extends StreamableRiakCommand.StreamableRiakCommandW private final Namespace namespace; private final int timeout; - ListKeys(Builder builder) + ListKeys(Builder builder) throws ListException { this.namespace = builder.namespace; this.timeout = builder.timeout; + + if (!builder.allowListing) + { + throw new ListException(); + } } @Override @@ -163,6 +169,7 @@ public static class Builder { private final Namespace namespace; private int timeout; + private boolean allowListing; /** * Constructs a Builder for a ListKeys command. @@ -177,6 +184,21 @@ public Builder(Namespace namespace) this.namespace = namespace; } + /** + * Allow this listing command + *

+ * Bucket and key list operations are expensive and should not + * be used in production, however using this method will allow + * the command to be built. + *

+ * @return a reference to this object. + */ + public Builder withAllowListing() + { + this.allowListing = true; + return this; + } + /** * Set the Riak-side timeout value. *

@@ -196,7 +218,7 @@ public Builder withTimeout(int timeout) * Construct the ListKeys command. * @return A ListKeys command. */ - public ListKeys build() + public ListKeys build() throws ListException { return new ListKeys(this); } diff --git a/src/main/java/com/basho/riak/client/api/commands/mapreduce/BucketMapReduce.java b/src/main/java/com/basho/riak/client/api/commands/mapreduce/BucketMapReduce.java index fbeab60db..374cabb6d 100644 --- a/src/main/java/com/basho/riak/client/api/commands/mapreduce/BucketMapReduce.java +++ b/src/main/java/com/basho/riak/client/api/commands/mapreduce/BucketMapReduce.java @@ -1,5 +1,6 @@ package com.basho.riak.client.api.commands.mapreduce; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.core.query.Namespace; import com.basho.riak.client.api.commands.mapreduce.filters.KeyFilter; @@ -13,9 +14,14 @@ */ public class BucketMapReduce extends MapReduce { - protected BucketMapReduce(BucketInput input, Builder builder) + protected BucketMapReduce(BucketInput input, Builder builder) throws ListException { super(input, builder); + + if (!builder.allowListing) + { + throw new ListException(); + } } /** @@ -25,6 +31,7 @@ public static class Builder extends MapReduce.Builder { private Namespace namespace; private final List filters = new ArrayList<>(); + private boolean allowListing; @Override protected Builder self() @@ -32,6 +39,21 @@ protected Builder self() return this; } + /** + * Allow this listing command + *

+ * Bucket and key list operations are expensive and should not + * be used in production, however using this method will allow + * the command to be built. + *

+ * @return a reference to this object. + */ + public Builder withAllowListing() + { + this.allowListing = true; + return this; + } + public Builder withNamespace(Namespace namespace) { this.namespace = namespace; @@ -44,7 +66,7 @@ public Builder withKeyFilter(KeyFilter filter) return this; } - public BucketMapReduce build() + public BucketMapReduce build() throws ListException { if (namespace == null) { diff --git a/src/main/java/com/basho/riak/client/api/commands/timeseries/ListKeys.java b/src/main/java/com/basho/riak/client/api/commands/timeseries/ListKeys.java index d1568b3de..46098bba0 100644 --- a/src/main/java/com/basho/riak/client/api/commands/timeseries/ListKeys.java +++ b/src/main/java/com/basho/riak/client/api/commands/timeseries/ListKeys.java @@ -1,5 +1,6 @@ package com.basho.riak.client.api.commands.timeseries; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.AsIsRiakCommand; import com.basho.riak.client.core.operations.ts.ListKeysOperation; import com.basho.riak.client.core.query.timeseries.QueryResult; @@ -17,10 +18,15 @@ public class ListKeys extends AsIsRiakCommand private final String tableName; private final int timeout; - private ListKeys(ListKeys.Builder builder) + private ListKeys(ListKeys.Builder builder) throws ListException { this.tableName = builder.tableName; this.timeout = builder.timeout; + + if (!builder.allowListing) + { + throw new ListException(); + } } @Override @@ -43,6 +49,7 @@ public static class Builder { private final String tableName; private int timeout; + private boolean allowListing; /** * Construct a Builder for a Time Series ListKeys command. @@ -53,6 +60,21 @@ public Builder(String tableName) this.tableName = tableName; } + /** + * Allow this listing command + *

+ * Bucket and key list operations are expensive and should not + * be used in production, however using this method will allow + * the command to be built. + *

+ * @return a reference to this object. + */ + public Builder withAllowListing() + { + this.allowListing = true; + return this; + } + /** * Set the Riak-side timeout value. *

@@ -77,7 +99,7 @@ public Builder withTimeout(int timeout) * Construct a Time Series ListKeys object. * @return a new Time Series ListKeys instance. */ - public ListKeys build() + public ListKeys build() throws ListException { return new ListKeys(this); } diff --git a/src/test/java/com/basho/riak/client/api/commands/buckets/ListBucketsTest.java b/src/test/java/com/basho/riak/client/api/commands/buckets/ListBucketsTest.java index e37b123ec..d1635b1c9 100644 --- a/src/test/java/com/basho/riak/client/api/commands/buckets/ListBucketsTest.java +++ b/src/test/java/com/basho/riak/client/api/commands/buckets/ListBucketsTest.java @@ -1,5 +1,6 @@ package com.basho.riak.client.api.commands.buckets; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.core.*; import com.basho.riak.client.core.operations.ListBucketsOperation; @@ -56,7 +57,7 @@ public void init() throws Exception private void testListBuckets(String bucketType) throws Exception { final BinaryValue type = BinaryValue.createFromUtf8(bucketType); - ListBuckets.Builder list = new ListBuckets.Builder(type); + ListBuckets.Builder list = new ListBuckets.Builder(type).withAllowListing(); client.execute(list.build()); ArgumentCaptor captor = @@ -70,6 +71,13 @@ private void testListBuckets(String bucketType) throws Exception Assert.assertEquals(ByteString.copyFrom(type.unsafeGetValue()), builder.getType()); } + @Test(expected = ListException.class) + public void listBucketsThrowsListException() throws ListException + { + ListBuckets.Builder b = new ListBuckets.Builder("bucket_type"); + b.build(); + } + @Test public void bucketTypeBuiltCorrectly() throws Exception { diff --git a/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListBuckets.java b/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListBuckets.java index 5c00cf163..f570c6e9d 100644 --- a/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListBuckets.java +++ b/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListBuckets.java @@ -16,6 +16,7 @@ package com.basho.riak.client.api.commands.buckets.itest; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.api.commands.buckets.ListBuckets; import com.basho.riak.client.api.commands.kv.StoreValue; @@ -35,6 +36,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; /** @@ -91,7 +93,15 @@ public void testListBucketsStreamingTestType() throws InterruptedException, Exec private void testListBuckets(Namespace namespace) throws InterruptedException, ExecutionException { - ListBuckets listBucketsCommand = new ListBuckets.Builder(namespace.getBucketType()).build(); + ListBuckets listBucketsCommand = null; + try + { + listBucketsCommand = new ListBuckets.Builder(namespace.getBucketType()).withAllowListing().build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } final ListBuckets.Response listResponse = client.execute(listBucketsCommand); @@ -109,7 +119,15 @@ private void testListBuckets(Namespace namespace) throws InterruptedException, E private void testListBucketsStreaming(Namespace namespace) throws InterruptedException, ExecutionException { - ListBuckets listBucketsCommand = new ListBuckets.Builder(namespace.getBucketType()).build(); + ListBuckets listBucketsCommand = null; + try + { + listBucketsCommand = new ListBuckets.Builder(namespace.getBucketType()).withAllowListing().build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } final RiakFuture streamingFuture = client.executeAsyncStreaming(listBucketsCommand, 500); diff --git a/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListKeys.java b/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListKeys.java index dec479329..50616b64a 100644 --- a/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListKeys.java +++ b/src/test/java/com/basho/riak/client/api/commands/buckets/itest/ITestListKeys.java @@ -16,6 +16,7 @@ package com.basho.riak.client.api.commands.buckets.itest; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.api.commands.kv.ListKeys; import com.basho.riak.client.core.RiakFuture; @@ -34,6 +35,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; /** @@ -69,7 +71,15 @@ public void testLargeStreamingListKeys() throws ExecutionException, InterruptedE { assumeTrue(testBucketType); - ListKeys lk = new ListKeys.Builder(typedNamespace).build(); + ListKeys lk = null; + try + { + lk = new ListKeys.Builder(typedNamespace).withAllowListing().build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } final RiakFuture streamFuture = client.executeAsyncStreaming(lk, 200); diff --git a/src/test/java/com/basho/riak/client/api/commands/itest/ITestBucketMapReduce.java b/src/test/java/com/basho/riak/client/api/commands/itest/ITestBucketMapReduce.java index dbd056547..341255d29 100644 --- a/src/test/java/com/basho/riak/client/api/commands/itest/ITestBucketMapReduce.java +++ b/src/test/java/com/basho/riak/client/api/commands/itest/ITestBucketMapReduce.java @@ -16,6 +16,7 @@ package com.basho.riak.client.api.commands.itest; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.core.RiakFuture; import com.basho.riak.client.api.commands.buckets.StoreBucketProperties; @@ -42,6 +43,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; /** * @@ -134,13 +136,21 @@ public void erlangBucketMRTestTypeStreaming() throws InterruptedException, Execu private void erlangBucketMR(String bucketType) throws InterruptedException, ExecutionException { Namespace ns = new Namespace(bucketType, mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withMapPhase(Function.newErlangFunction("riak_kv_mapreduce", "map_object_value"), false) .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_string_to_integer"), false) .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } MapReduce.Response response = client.execute(bmr); @@ -157,13 +167,21 @@ private void erlangBucketMR(String bucketType) throws InterruptedException, Exec private void streamingErlangBucketMR(String bucketType) throws InterruptedException, ExecutionException { Namespace ns = new Namespace(bucketType, mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() - .withNamespace(ns) - .withMapPhase(Function.newErlangFunction("riak_kv_mapreduce", "map_object_value"), false) - .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_string_to_integer"), false) - .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) - .build(); + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() + .withNamespace(ns) + .withMapPhase(Function.newErlangFunction("riak_kv_mapreduce", "map_object_value"), false) + .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_string_to_integer"), false) + .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_sort"), true) + .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } final RiakFuture streamingFuture = client.executeAsyncStreaming(bmr, 10); @@ -231,12 +249,20 @@ public void JsBucketMRTestType() throws InterruptedException, ExecutionException private void JsBucketMR(String bucketType) throws InterruptedException, ExecutionException { Namespace ns = new Namespace(bucketType, mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withMapPhase(Function.newNamedJsFunction("Riak.mapValuesJson"), false) .withReducePhase(Function.newNamedJsFunction("Riak.reduceNumericSort"), true) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } RiakFuture future = client.executeAsync(bmr); @@ -259,12 +285,20 @@ private void JsBucketMR(String bucketType) throws InterruptedException, Executio public void multiPhaseResult() throws InterruptedException, ExecutionException { Namespace ns = new Namespace(Namespace.DEFAULT_BUCKET_TYPE, mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withMapPhase(Function.newNamedJsFunction("Riak.mapValuesJson"), true) .withReducePhase(Function.newNamedJsFunction("Riak.reduceNumericSort"), true) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } RiakFuture future = client.executeAsync(bmr); @@ -288,8 +322,11 @@ public void multiPhaseResult() throws InterruptedException, ExecutionException public void keyFilter() throws InterruptedException, ExecutionException { Namespace ns = new Namespace(Namespace.DEFAULT_BUCKET_TYPE, mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withMapPhase(Function.newNamedJsFunction("Riak.mapValuesJson")) .withReducePhase(Function.newErlangFunction("riak_kv_mapreduce", "reduce_sort"),true) @@ -297,6 +334,11 @@ public void keyFilter() throws InterruptedException, ExecutionException .withKeyFilter(new StringToIntFilter()) .withKeyFilter(new LogicalAndFilter(new LessThanFilter<>(50), new GreaterThanFilter<>(45))) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } RiakFuture future = client.executeAsync(bmr); @@ -315,8 +357,11 @@ public void differentBucketType() throws InterruptedException, ExecutionExceptio Assume.assumeTrue(testBucketType); Namespace ns = new Namespace(mapReduceBucketType.toString(), mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withMapPhase(Function.newAnonymousJsFunction( "function(value, keydata, arg) {" + @@ -327,6 +372,11 @@ public void differentBucketType() throws InterruptedException, ExecutionExceptio " return[];" + "}"), true) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } MapReduce.Response response = client.execute(bmr); @@ -339,8 +389,11 @@ public void differentBucketTypeWithFilter() throws InterruptedException, Executi Assume.assumeTrue(testBucketType); Namespace ns = new Namespace(mapReduceBucketType.toString(), mrBucketName); - BucketMapReduce bmr = - new BucketMapReduce.Builder() + BucketMapReduce bmr = null; + try + { + bmr = new BucketMapReduce.Builder() + .withAllowListing() .withNamespace(ns) .withKeyFilter(new TokenizeFilter("_",3)) .withKeyFilter(new StringToIntFilter()) @@ -351,6 +404,11 @@ public void differentBucketTypeWithFilter() throws InterruptedException, Executi " return [data];" + "}"), true) .build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } RiakFuture future = client.executeAsync(bmr); diff --git a/src/test/java/com/basho/riak/client/api/commands/itest/ITestTimeSeries.java b/src/test/java/com/basho/riak/client/api/commands/itest/ITestTimeSeries.java index c369685f2..77fc8fe2d 100644 --- a/src/test/java/com/basho/riak/client/api/commands/itest/ITestTimeSeries.java +++ b/src/test/java/com/basho/riak/client/api/commands/itest/ITestTimeSeries.java @@ -1,5 +1,6 @@ package com.basho.riak.client.api.commands.itest; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.api.commands.buckets.FetchBucketProperties; import com.basho.riak.client.api.commands.buckets.StoreBucketProperties; @@ -121,7 +122,15 @@ public void test_d_TestListingKeysReturnsThem() throws ExecutionException, Inter { RiakClient client = new RiakClient(cluster); - ListKeys listKeys = new ListKeys.Builder(tableName).build(); + ListKeys listKeys = null; + try + { + listKeys = new ListKeys.Builder(tableName).withAllowListing().build(); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } final RiakFuture listKeysFuture = client.executeAsync(listKeys); diff --git a/src/test/java/com/basho/riak/client/core/operations/itest/ITestBase.java b/src/test/java/com/basho/riak/client/core/operations/itest/ITestBase.java index 886481f12..7667a22d4 100644 --- a/src/test/java/com/basho/riak/client/core/operations/itest/ITestBase.java +++ b/src/test/java/com/basho/riak/client/core/operations/itest/ITestBase.java @@ -15,6 +15,7 @@ */ package com.basho.riak.client.core.operations.itest; +import com.basho.riak.client.api.ListException; import com.basho.riak.client.api.RiakClient; import com.basho.riak.client.api.commands.kv.ListKeys; import com.basho.riak.client.api.commands.kv.MultiDelete; @@ -32,6 +33,7 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.rules.TestName; +import static org.junit.Assert.fail; import java.io.File; import java.io.FileInputStream; @@ -218,8 +220,16 @@ protected static void resetAndEmptyBucket(Namespace namespace) throws Interrupte { RiakClient client = new RiakClient(cluster); - ListKeys listKeys = new ListKeys.Builder(namespace).build(); - final ListKeys.Response listKeyResponse = client.execute(listKeys); + ListKeys.Response listKeyResponse = null; + try + { + ListKeys listKeys = new ListKeys.Builder(namespace).withAllowListing().build(); + listKeyResponse = client.execute(listKeys); + } + catch (ListException ex) + { + fail(ex.getMessage()); + } MultiDelete multiDelete = new MultiDelete.Builder().addLocations(listKeyResponse).build(); final MultiDelete.Response deleteResponse = client.execute(multiDelete);