mirror of https://github.com/apache/jclouds.git
JCLOUDS-929: Implement generic delimiter support.
The patch adds delimiter option support in the generic blob store interface. A live integration test is added to verify that jclouds correctly lists objects separated by a delimiter.
This commit is contained in:
parent
1fe90b03c9
commit
a29d75a5d1
|
@ -30,4 +30,9 @@ public class AtmosContainerLiveTest extends BaseContainerLiveTest {
|
|||
public void testContainerListWithPrefix() {
|
||||
throw new SkipException("Prefix option has not been plumbed down to Atmos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("Delimiter support is not yet implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CRED
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", testName = "SwiftContainerLiveTest")
|
||||
|
@ -36,4 +37,10 @@ public class SwiftContainerLiveTest extends BaseContainerLiveTest {
|
|||
setIfTestSystemPropertyPresent(props, CREDENTIAL_TYPE);
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("Delimiter support is not yet implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.jclouds.s3.blobstore.integration;
|
|||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = "live", testName = "S3ContainerLiveTest")
|
||||
|
@ -27,4 +28,10 @@ public class S3ContainerLiveTest extends BaseContainerLiveTest {
|
|||
provider = "s3";
|
||||
BaseBlobStoreIntegrationTest.SANITY_CHECK_RETURNED_BUCKET_NAME = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("not yet implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,4 +58,9 @@ public class SwiftContainerLiveTest extends BaseContainerLiveTest {
|
|||
public void testContainerListWithPrefix() {
|
||||
throw new SkipException("Prefix option has not been plumbed down to Swift");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("The test fails as the path parameter elides subdirectories");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
public static final ImmutableListContainerOptions NONE = new ImmutableListContainerOptions(
|
||||
new ListContainerOptions());
|
||||
|
||||
private String delimiter;
|
||||
private String dir;
|
||||
private String prefix;
|
||||
private boolean recursive;
|
||||
|
@ -48,12 +49,13 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
}
|
||||
|
||||
ListContainerOptions(Integer maxKeys, String marker, String dir, boolean recursive,
|
||||
boolean detailed, String prefix) {
|
||||
boolean detailed, String prefix, String delimiter) {
|
||||
super(maxKeys, marker);
|
||||
this.dir = dir;
|
||||
this.recursive = recursive;
|
||||
this.detailed = detailed;
|
||||
this.prefix = prefix;
|
||||
this.delimiter = delimiter;
|
||||
}
|
||||
|
||||
public static class ImmutableListContainerOptions extends ListContainerOptions {
|
||||
|
@ -124,6 +126,16 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
return delegate.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListContainerOptions delimiter(String delimiterString) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDelimiter() {
|
||||
return delegate.getDelimiter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
|
@ -135,6 +147,10 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
return dir;
|
||||
}
|
||||
|
||||
public String getDelimiter() {
|
||||
return delimiter;
|
||||
}
|
||||
|
||||
public boolean isRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
@ -200,6 +216,15 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* specify the delimiter to be used when listing
|
||||
*
|
||||
*/
|
||||
public ListContainerOptions delimiter(String delimiterString) {
|
||||
this.delimiter = delimiterString;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
|
@ -249,11 +274,18 @@ public class ListContainerOptions extends ListOptions implements Cloneable {
|
|||
ListContainerOptions options = new ListContainerOptions();
|
||||
return options.prefix(prefix);
|
||||
}
|
||||
/**
|
||||
* @see ListContainerOptions#delimiter(String)
|
||||
*/
|
||||
public static ListContainerOptions delimiter(String delimiterString) {
|
||||
ListContainerOptions options = new ListContainerOptions();
|
||||
return options.delimiter(delimiterString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListContainerOptions clone() {
|
||||
return new ListContainerOptions(getMaxResults(), getMarker(), dir, recursive, detailed, prefix);
|
||||
return new ListContainerOptions(getMaxResults(), getMarker(), dir, recursive, detailed, prefix, delimiter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -382,6 +382,9 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
|||
|
||||
public void execute(final String containerName,
|
||||
ListContainerOptions listOptions) {
|
||||
if (listOptions.getDelimiter() != null || listOptions.getPrefix() != null) {
|
||||
throw new IllegalArgumentException("Prefix and delimiter support has not yet been added");
|
||||
}
|
||||
final AtomicBoolean deleteFailure = new AtomicBoolean();
|
||||
int retries = maxErrors;
|
||||
|
||||
|
|
|
@ -133,6 +133,29 @@ public class BaseContainerLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
blobStore.putBlob(containerName, blobStore.blobBuilder("foo").payload("").build());
|
||||
checkEqualNames(ImmutableSet.of(prefix, prefix + "foo", prefix + "bar"),
|
||||
blobStore.list(containerName, ListContainerOptions.Builder.prefix(prefix)));
|
||||
}
|
||||
finally {
|
||||
returnContainer(containerName);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = "live")
|
||||
public void testDelimiterList() throws InterruptedException {
|
||||
final String containerName = getContainerName();
|
||||
BlobStore blobStore = view.getBlobStore();
|
||||
String payload = "foo";
|
||||
try {
|
||||
blobStore.putBlob(containerName, blobStore.blobBuilder("test/foo/foo").payload(payload).build());
|
||||
blobStore.putBlob(containerName, blobStore.blobBuilder("test/bar/foo").payload(payload).build());
|
||||
blobStore.putBlob(containerName, blobStore.blobBuilder("foo").payload(payload).build());
|
||||
blobStore.putBlob(containerName, blobStore.blobBuilder("test-foo").payload(payload).build());
|
||||
blobStore.putBlob(containerName, blobStore.blobBuilder("test-bar").payload(payload).build());
|
||||
checkEqualNames(ImmutableSet.of("foo", "test/", "test-foo", "test-bar"), blobStore.list(
|
||||
containerName, ListContainerOptions.Builder.delimiter("/")));
|
||||
checkEqualNames(ImmutableSet.of("test/foo/foo", "test/bar/foo", "foo", "test-foo", "test-bar"),
|
||||
blobStore.list(containerName, ListContainerOptions.Builder.delimiter("\\")));
|
||||
checkEqualNames(ImmutableSet.of("test-", "test/foo/foo", "test/bar/foo", "foo"), blobStore.list(
|
||||
containerName, ListContainerOptions.Builder.delimiter("-")));
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
}
|
||||
|
@ -173,5 +196,4 @@ public class BaseContainerLiveTest extends BaseBlobStoreIntegrationTest {
|
|||
recycleContainerAndAddToPool(containerName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,13 @@ public class ListOptionsTest {
|
|||
assertEquals(options.getDir(), "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimiter() {
|
||||
ListContainerOptions options = new ListContainerOptions();
|
||||
options.delimiter("-");
|
||||
assertEquals(options.getDelimiter(), "-");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathStatic() {
|
||||
ListContainerOptions options = inDirectory("test");
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.jclouds.azureblob.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test(groups = { "live" })
|
||||
|
@ -24,4 +25,10 @@ public class AzureBlobContainerLiveTest extends BaseContainerLiveTest {
|
|||
public AzureBlobContainerLiveTest() {
|
||||
provider = "azureblob";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("The delimiter support has not been plumbed through to Azure blob");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,4 +34,9 @@ public class HPCloudObjectStorageContainerLiveTest extends BaseContainerLiveTest
|
|||
@Test
|
||||
public void testPublicAccessInNonDefaultLocationWithBigBlob() { throw new SkipException("Locations are ignored"); }
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testDelimiterList() {
|
||||
throw new SkipException("\"path\" parameter elides subdirectories");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue