mirror of https://github.com/apache/jclouds.git
Issue 108: changed from List to SortedSet
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1941 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
502dc92836
commit
a1ca5773c7
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -328,7 +328,7 @@ public interface S3BlobStore extends BlobStore<BucketMetadata, ObjectMetadata, S
|
|||
@GET
|
||||
@XMLResponseParser(ListAllMyBucketsHandler.class)
|
||||
@Path("/")
|
||||
List<BucketMetadata> listContainers();
|
||||
SortedSet<BucketMetadata> listContainers();
|
||||
|
||||
/**
|
||||
* Copies one object to another bucket, retaining UserMetadata from the source. The destination
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.SortedSet;
|
|||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class ArrayListBucketResponse extends org.jclouds.rest.ArrayBoundedList<ObjectMetadata>
|
||||
public class ArrayListBucketResponse extends org.jclouds.rest.BoundedTreeSet<ObjectMetadata>
|
||||
implements ListBucketResponse {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -4475709781001190244L;
|
||||
|
|
|
@ -80,17 +80,16 @@ public class BucketMetadata extends ContainerMetadata {
|
|||
super.setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Metadata [canonicalUser=").append(canonicalUser).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BucketMetadata [canonicalUser=" + canonicalUser + ", creationDate=" + creationDate
|
||||
+ ", name=" + name + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or
|
||||
* object. The owner of a bucket or object cannot be changed. However, if the object is
|
||||
|
|
|
@ -48,7 +48,7 @@ import java.util.SortedSet;
|
|||
* @author Adrian Cole
|
||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html" />
|
||||
*/
|
||||
public interface ListBucketResponse extends org.jclouds.rest.BoundedList<ObjectMetadata> {
|
||||
public interface ListBucketResponse extends org.jclouds.rest.BoundedSortedSet<ObjectMetadata> {
|
||||
|
||||
/**
|
||||
* Example:
|
||||
|
|
|
@ -54,24 +54,23 @@ import com.google.inject.TypeLiteral;
|
|||
public class S3ContextModuleTest {
|
||||
|
||||
Injector createInjector() {
|
||||
return Guice.createInjector(new RestS3ConnectionModule(),
|
||||
new BlobStoreMapsModule<S3BlobStore, BucketMetadata, ObjectMetadata, S3Object>(
|
||||
new TypeLiteral<S3BlobStore>() {
|
||||
}, new TypeLiteral<BucketMetadata>() {
|
||||
}, new TypeLiteral<ObjectMetadata>() {
|
||||
}, new TypeLiteral<S3Object>() {
|
||||
}), new S3ContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(
|
||||
Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to("user");
|
||||
bindConstant().annotatedWith(
|
||||
Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY)).to("key");
|
||||
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT))
|
||||
.to("http://localhost");
|
||||
super.configure();
|
||||
}
|
||||
}, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(),
|
||||
return Guice.createInjector(new RestS3ConnectionModule(), BlobStoreMapsModule.Builder
|
||||
.newBuilder(new TypeLiteral<S3BlobStore>() {
|
||||
}, new TypeLiteral<BucketMetadata>() {
|
||||
}, new TypeLiteral<ObjectMetadata>() {
|
||||
}, new TypeLiteral<S3Object>() {
|
||||
}).build(), new S3ContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_ACCESSKEYID)).to(
|
||||
"user");
|
||||
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_AWS_SECRETACCESSKEY))
|
||||
.to("key");
|
||||
bindConstant().annotatedWith(Jsr330.named(S3Constants.PROPERTY_S3_ENDPOINT)).to(
|
||||
"http://localhost");
|
||||
super.configure();
|
||||
}
|
||||
}, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(),
|
||||
new ExecutorServiceModule(new WithinThreadExecutorService()));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.integration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.jclouds.aws.s3.S3BlobStore;
|
||||
import org.jclouds.aws.s3.domain.BucketMetadata;
|
||||
|
@ -42,8 +42,8 @@ public class S3ServiceIntegrationTest extends
|
|||
void containerExists() throws Exception {
|
||||
String containerName = getContainerName();
|
||||
try {
|
||||
List<BucketMetadata> list = context.getApi().listContainers();
|
||||
BucketMetadata firstContainer = list.get(0);
|
||||
SortedSet<BucketMetadata> list = context.getApi().listContainers();
|
||||
BucketMetadata firstContainer = list.first();
|
||||
BucketMetadata toMatch = new BucketMetadata(containerName);
|
||||
toMatch.setOwner(firstContainer.getOwner());
|
||||
assert list.contains(toMatch);
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Calendar;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.aws.s3.S3BlobStore;
|
||||
|
@ -264,7 +265,7 @@ public class JCloudsS3Service extends S3Service {
|
|||
@Override
|
||||
protected S3Bucket[] listAllBucketsImpl() throws S3ServiceException {
|
||||
try {
|
||||
List<org.jclouds.aws.s3.domain.BucketMetadata> jcBucketList = connection.listContainers();
|
||||
SortedSet<org.jclouds.aws.s3.domain.BucketMetadata> jcBucketList = connection.listContainers();
|
||||
return Util.convertBuckets(jcBucketList);
|
||||
} catch (Exception e) {
|
||||
Utils.<S3ServiceException> rethrowIfRuntimeOrSameType(e);
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Date;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
@ -81,7 +82,7 @@ public class Util {
|
|||
}
|
||||
|
||||
public static S3Bucket[] convertBuckets(
|
||||
List<org.jclouds.aws.s3.domain.BucketMetadata> jcBucketMDs) {
|
||||
SortedSet<org.jclouds.aws.s3.domain.BucketMetadata> jcBucketMDs) {
|
||||
List<S3Bucket> jsBuckets = new ArrayList<S3Bucket>(jcBucketMDs.size());
|
||||
for (org.jclouds.aws.s3.domain.BucketMetadata jcBucketMD : jcBucketMDs) {
|
||||
jsBuckets.add(convertBucket(jcBucketMD));
|
||||
|
|
|
@ -35,8 +35,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -211,7 +211,7 @@ public class JCloudsS3ServiceLiveTest
|
|||
// Ensure there is at least 1 bucket in S3 account to list and compare.
|
||||
S3Bucket[] jsBuckets = service.listAllBuckets();
|
||||
|
||||
List<org.jclouds.aws.s3.domain.BucketMetadata> jcBuckets = context.getApi()
|
||||
SortedSet<org.jclouds.aws.s3.domain.BucketMetadata> jcBuckets = context.getApi()
|
||||
.listContainers();
|
||||
|
||||
assert jsBuckets.length == jcBuckets.size();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.aws.s3.samples;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -30,6 +31,9 @@ import java.util.concurrent.TimeoutException;
|
|||
import org.jclouds.aws.s3.S3Context;
|
||||
import org.jclouds.aws.s3.S3ContextFactory;
|
||||
import org.jclouds.aws.s3.domain.BucketMetadata;
|
||||
import org.jclouds.blobstore.BlobMap;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
|
||||
/**
|
||||
* This the Main class of an Application that demonstrates the use of the CreateListOwnedBuckets
|
||||
|
@ -44,8 +48,9 @@ public class MainApp {
|
|||
public static int PARAMETERS = 3;
|
||||
public static String INVALID_SYNTAX = "Invalid number of parameters. Syntax is: \"accesskeyid\" \"secretekey\" \"bucketName\" ";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void main(String[] args) throws InterruptedException, ExecutionException,
|
||||
TimeoutException {
|
||||
TimeoutException, IOException {
|
||||
|
||||
if (args.length < PARAMETERS)
|
||||
throw new IllegalArgumentException(INVALID_SYNTAX);
|
||||
|
@ -56,15 +61,19 @@ public class MainApp {
|
|||
String bucketName = args[2];
|
||||
|
||||
// Init
|
||||
S3Context context = S3ContextFactory.createContext(accesskeyid, secretkey);
|
||||
BlobStoreContext context = S3ContextFactory.createContext(accesskeyid, secretkey);
|
||||
|
||||
try {
|
||||
|
||||
// Create Bucket
|
||||
context.getApi().createContainer(bucketName).get(10, TimeUnit.SECONDS);
|
||||
((S3Context) context).getApi().createContainer(bucketName).get(10, TimeUnit.SECONDS);
|
||||
BlobMap blobMap = context.createBlobMap(bucketName);
|
||||
Blob blob = context.newBlob("test");
|
||||
blob.setData("testdata");
|
||||
blobMap.put("test", blob);
|
||||
|
||||
// List bucket
|
||||
for (BucketMetadata bucketObj : context.getApi().listContainers()) {
|
||||
for (BucketMetadata bucketObj : ((S3Context) context).getApi().listContainers()) {
|
||||
System.out.println(String.format(" %1$s", bucketObj));
|
||||
System.out.println(String.format(": %1$s entries%n", context.createInputStreamMap(
|
||||
bucketObj.getName()).size()));
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
package org.jclouds.samples.googleappengine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
|
@ -44,7 +44,8 @@ import org.jclouds.logging.Logger;
|
|||
import org.jclouds.samples.googleappengine.domain.BucketResult;
|
||||
import org.jclouds.samples.googleappengine.functions.MetadataToBucketResult;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.appengine.repackaged.com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Shows an example of how to use @{link S3Connection} injected with Guice.
|
||||
|
@ -85,9 +86,9 @@ public class GetAllBucketsController extends HttpServlet {
|
|||
private void addMyBucketsToRequest(HttpServletRequest request) throws InterruptedException,
|
||||
ExecutionException, TimeoutException {
|
||||
System.err.println(context.getAccount() + ":" + context.getEndPoint());
|
||||
List<BucketMetadata> myBucketMetadata = context.getApi().listContainers();
|
||||
List<BucketResult> myBuckets = Lists.transform(myBucketMetadata,
|
||||
metadataToBucketResultProvider.get());
|
||||
SortedSet<BucketMetadata> myBucketMetadata = context.getApi().listContainers();
|
||||
SortedSet<BucketResult> myBuckets = Sets.newTreeSet(Iterables.transform(myBucketMetadata,
|
||||
metadataToBucketResultProvider.get()));
|
||||
request.setAttribute("buckets", myBuckets);
|
||||
}
|
||||
}
|
|
@ -24,8 +24,7 @@
|
|||
package org.jclouds.samples.googleappengine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -43,6 +42,8 @@ import org.jclouds.aws.s3.domain.ListBucketResponse;
|
|||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Shows an example of how to use @{link S3Connection} injected with Guice.
|
||||
*
|
||||
|
@ -69,7 +70,7 @@ public class JCloudsServlet extends HttpServlet {
|
|||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
public static class BucketResult {
|
||||
public static class BucketResult implements Comparable<BucketResult> {
|
||||
private String name;
|
||||
private String size = "unknown";
|
||||
private String status = "ok";
|
||||
|
@ -97,14 +98,18 @@ public class JCloudsServlet extends HttpServlet {
|
|||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int compareTo(BucketResult o) {
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
try {
|
||||
List<BucketMetadata> myBucketMetadata = context.getApi().listContainers();
|
||||
List<BucketResult> myBuckets = new ArrayList<BucketResult>();
|
||||
SortedSet<BucketMetadata> myBucketMetadata = context.getApi().listContainers();
|
||||
SortedSet<BucketResult> myBuckets = Sets.newTreeSet();
|
||||
for (BucketMetadata metadata : myBucketMetadata) {
|
||||
BucketResult result = new BucketResult();
|
||||
result.setName(metadata.getName());
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.samples.googleappengine.domain;
|
||||
|
||||
public class BucketResult {
|
||||
|
||||
public class BucketResult implements Comparable<BucketResult>{
|
||||
private String name;
|
||||
private String size = "unknown";
|
||||
private String status = "ok";
|
||||
|
@ -51,4 +52,8 @@ public class BucketResult {
|
|||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int compareTo(BucketResult o) {
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.azure.storage.blob;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -45,7 +45,7 @@ import org.jclouds.azure.storage.blob.functions.ReturnTrueIfContainerAlreadyExis
|
|||
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
|
||||
import org.jclouds.azure.storage.blob.xml.AccountNameEnumerationResultsHandler;
|
||||
import org.jclouds.azure.storage.blob.xml.ContainerNameEnumerationResultsHandler;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
|
||||
import org.jclouds.azure.storage.options.CreateOptions;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
|
@ -97,13 +97,13 @@ public interface AzureBlobStore extends BlobStore<ContainerMetadata, BlobMetadat
|
|||
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
|
||||
@Path("/")
|
||||
@QueryParams(keys = "comp", values = "list")
|
||||
List<ContainerMetadata> listContainers();
|
||||
SortedSet<ContainerMetadata> listContainers();
|
||||
|
||||
@GET
|
||||
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
|
||||
@Path("/")
|
||||
@QueryParams(keys = "comp", values = "list")
|
||||
BoundedList<ContainerMetadata> listContainers(ListOptions listOptions);
|
||||
BoundedSortedSet<ContainerMetadata> listContainers(ListOptions listOptions);
|
||||
|
||||
@HEAD
|
||||
@Path("{container}")
|
||||
|
|
|
@ -26,14 +26,14 @@ package org.jclouds.azure.storage.blob.domain;
|
|||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.azure.storage.domain.ArrayBoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedTreeSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class ArrayListBlobsResponse extends ArrayBoundedList<BlobMetadata> implements
|
||||
public class ArrayListBlobsResponse extends BoundedTreeSet<BlobMetadata> implements
|
||||
ListBlobsResponse {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -4475709781001190244L;
|
||||
|
|
|
@ -25,13 +25,13 @@ package org.jclouds.azure.storage.blob.domain;
|
|||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface ListBlobsResponse extends BoundedList<BlobMetadata> {
|
||||
public interface ListBlobsResponse extends BoundedSortedSet<BlobMetadata> {
|
||||
public URI getContainerUrl();
|
||||
|
||||
public String getBlobPrefix();
|
||||
|
|
|
@ -28,8 +28,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
|
||||
import org.jclouds.azure.storage.domain.ArrayBoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedTreeSet;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.util.DateService;
|
||||
|
@ -46,7 +46,7 @@ import javax.inject.Inject;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class AccountNameEnumerationResultsHandler extends
|
||||
ParseSax.HandlerWithResult<BoundedList<ContainerMetadata>> {
|
||||
ParseSax.HandlerWithResult<BoundedSortedSet<ContainerMetadata>> {
|
||||
|
||||
private List<ContainerMetadata> containerMetadata = new ArrayList<ContainerMetadata>();
|
||||
private String prefix;
|
||||
|
@ -66,8 +66,8 @@ public class AccountNameEnumerationResultsHandler extends
|
|||
this.dateParser = dateParser;
|
||||
}
|
||||
|
||||
public BoundedList<ContainerMetadata> getResult() {
|
||||
return new ArrayBoundedList<ContainerMetadata>(containerMetadata, prefix, marker, maxResults,
|
||||
public BoundedSortedSet<ContainerMetadata> getResult() {
|
||||
return new BoundedTreeSet<ContainerMetadata>(containerMetadata, prefix, marker, maxResults,
|
||||
nextMarker);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.lang.reflect.UndeclaredThrowableException;
|
|||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -43,7 +43,7 @@ import org.jclouds.azure.storage.blob.domain.BlobMetadata;
|
|||
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
|
||||
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
|
@ -79,7 +79,7 @@ public class AzureBlobStoreLiveTest {
|
|||
@Test
|
||||
public void testListContainers() throws Exception {
|
||||
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
assert null != response;
|
||||
long initialContainerCount = response.size();
|
||||
assertTrue(initialContainerCount >= 0);
|
||||
|
@ -108,7 +108,7 @@ public class AzureBlobStoreLiveTest {
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
assert null != response;
|
||||
long containerCount = response.size();
|
||||
assertTrue(containerCount >= 1);
|
||||
|
@ -176,7 +176,7 @@ public class AzureBlobStoreLiveTest {
|
|||
@Test
|
||||
public void testListContainersWithOptions() throws Exception {
|
||||
|
||||
BoundedList<ContainerMetadata> response = connection.listContainers(ListOptions.Builder
|
||||
BoundedSortedSet<ContainerMetadata> response = connection.listContainers(ListOptions.Builder
|
||||
.prefix(privateContainer).maxResults(1));
|
||||
assert null != response;
|
||||
long initialContainerCount = response.size();
|
||||
|
@ -196,7 +196,7 @@ public class AzureBlobStoreLiveTest {
|
|||
public void testListOwnedContainers() throws Exception {
|
||||
|
||||
// Test default listing
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
|
||||
// exist, this will fail
|
||||
|
||||
|
@ -204,12 +204,12 @@ public class AzureBlobStoreLiveTest {
|
|||
response = connection.listContainers(ListOptions.Builder.prefix(
|
||||
privateContainer.substring(0, privateContainer.length() - 1)).maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.get(0).getName(), privateContainer);
|
||||
assertEquals(response.first().getName(), privateContainer);
|
||||
|
||||
response = connection.listContainers(ListOptions.Builder.prefix(publicContainer)
|
||||
.maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.get(0).getName(), publicContainer);
|
||||
assertEquals(response.first().getName(), publicContainer);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.jclouds.azure.storage.blob.domain.BlobMetadata;
|
|||
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
|
||||
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azure.storage.blob.options.CreateContainerOptions;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.options.CreateOptions;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
|
@ -66,7 +66,7 @@ public class StubAzureBlobStore extends StubBlobStore<ContainerMetadata, BlobMet
|
|||
super(containerToBlobs, dateService, containerMetaProvider, blobProvider);
|
||||
}
|
||||
|
||||
public BoundedList<ContainerMetadata> listContainers(ListOptions options) {
|
||||
public BoundedSortedSet<ContainerMetadata> listContainers(ListOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ import java.io.InputStream;
|
|||
import java.net.URI;
|
||||
|
||||
import org.jclouds.azure.storage.blob.domain.ContainerMetadata;
|
||||
import org.jclouds.azure.storage.domain.ArrayBoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedTreeSet;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.jclouds.util.DateService;
|
||||
|
@ -60,7 +60,7 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_containers.xml");
|
||||
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
|
||||
BoundedSortedSet<ContainerMetadata> list = new BoundedTreeSet<ContainerMetadata>(ImmutableList
|
||||
.of(new ContainerMetadata(
|
||||
URI.create("http://myaccount.blob.core.windows.net/audio"), dateService
|
||||
.rfc822DateParse("Wed, 13 Aug 2008 20:39:39 GMT"), HttpUtils
|
||||
|
@ -74,7 +74,7 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
|
||||
), null, null, 3, "video");
|
||||
|
||||
BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
|
||||
BoundedSortedSet<ContainerMetadata> result = (BoundedSortedSet<ContainerMetadata>) factory.create(
|
||||
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, list);
|
||||
|
@ -83,7 +83,7 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testApplyInputStreamWithOptions() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_containers_options.xml");
|
||||
BoundedList<ContainerMetadata> list = new ArrayBoundedList<ContainerMetadata>(ImmutableList
|
||||
BoundedSortedSet<ContainerMetadata> list = new BoundedTreeSet<ContainerMetadata>(ImmutableList
|
||||
.of(new ContainerMetadata(
|
||||
URI.create("http://myaccount.blob.core.windows.net/audio"), dateService
|
||||
.rfc822DateParse("Wed, 13 Aug 2008 20:39:39 GMT"), HttpUtils
|
||||
|
@ -96,7 +96,7 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
.fromHexString("0x8CACB9BD7BACAC3"))
|
||||
|
||||
), "prefix", "marker", 1, "video");
|
||||
BoundedList<ContainerMetadata> result = (BoundedList<ContainerMetadata>) factory.create(
|
||||
BoundedSortedSet<ContainerMetadata> result = (BoundedSortedSet<ContainerMetadata>) factory.create(
|
||||
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
|
||||
assertEquals(result, list);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.net.URI;
|
|||
import org.jclouds.azure.storage.blob.domain.ArrayListBlobsResponse;
|
||||
import org.jclouds.azure.storage.blob.domain.BlobMetadata;
|
||||
import org.jclouds.azure.storage.blob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.jclouds.util.DateService;
|
||||
|
@ -79,7 +79,7 @@ public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest
|
|||
|
||||
), null, null, 4, "newblob2.txt", null, "myfolder/");
|
||||
|
||||
BoundedList<ListBlobsResponse> result = (BoundedList<ListBlobsResponse>) factory.create(
|
||||
BoundedSortedSet<ListBlobsResponse> result = (BoundedSortedSet<ListBlobsResponse>) factory.create(
|
||||
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, list);
|
||||
|
|
|
@ -28,7 +28,7 @@ package org.jclouds.azure.storage.domain;
|
|||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface BoundedList<T> extends org.jclouds.rest.BoundedList<T> {
|
||||
public interface BoundedSortedSet<T> extends org.jclouds.rest.BoundedSortedSet<T> {
|
||||
|
||||
String getNextMarker();
|
||||
|
|
@ -30,8 +30,8 @@ import java.util.List;
|
|||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class ArrayBoundedList<T> extends org.jclouds.rest.ArrayBoundedList<T> implements
|
||||
BoundedList<T> {
|
||||
public class BoundedTreeSet<T> extends org.jclouds.rest.BoundedTreeSet<T> implements
|
||||
BoundedSortedSet<T> {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -4475709781001190244L;
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class ArrayBoundedList<T> extends org.jclouds.rest.ArrayBoundedList<T> im
|
|||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ArrayBoundedList<?> other = (ArrayBoundedList<?>) obj;
|
||||
BoundedTreeSet<?> other = (BoundedTreeSet<?>) obj;
|
||||
if (nextMarker == null) {
|
||||
if (other.nextMarker != null)
|
||||
return false;
|
||||
|
@ -68,7 +68,7 @@ public class ArrayBoundedList<T> extends org.jclouds.rest.ArrayBoundedList<T> im
|
|||
+ maxResults + ", prefix=" + prefix + "]";
|
||||
}
|
||||
|
||||
public ArrayBoundedList(List<T> contents, String prefix, String marker, int maxResults,
|
||||
public BoundedTreeSet(List<T> contents, String prefix, String marker, int maxResults,
|
||||
String nextMarker) {
|
||||
super(contents, prefix, marker, maxResults);
|
||||
this.nextMarker = nextMarker;
|
|
@ -33,7 +33,7 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.azure.storage.AzureQueue;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.filters.SharedKeyAuthentication;
|
||||
import org.jclouds.azure.storage.options.CreateOptions;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
|
@ -85,7 +85,7 @@ public interface AzureQueueConnection {
|
|||
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
|
||||
@Path("/")
|
||||
@QueryParams(keys = "comp", values = "list")
|
||||
BoundedList<QueueMetadata> listQueues(ListOptions... listOptions);
|
||||
BoundedSortedSet<QueueMetadata> listQueues(ListOptions... listOptions);
|
||||
|
||||
/**
|
||||
* The Create Queue operation creates a new queue under the specified account.
|
||||
|
|
|
@ -27,8 +27,8 @@ import java.net.URI;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.azure.storage.domain.ArrayBoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedTreeSet;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
||||
|
@ -43,7 +43,7 @@ import javax.inject.Inject;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class AccountNameEnumerationResultsHandler extends
|
||||
ParseSax.HandlerWithResult<BoundedList<QueueMetadata>> {
|
||||
ParseSax.HandlerWithResult<BoundedSortedSet<QueueMetadata>> {
|
||||
|
||||
private List<QueueMetadata> metadata = new ArrayList<QueueMetadata>();
|
||||
private String prefix;
|
||||
|
@ -59,8 +59,8 @@ public class AccountNameEnumerationResultsHandler extends
|
|||
public AccountNameEnumerationResultsHandler() {
|
||||
}
|
||||
|
||||
public BoundedList<QueueMetadata> getResult() {
|
||||
return new ArrayBoundedList<QueueMetadata>(metadata, prefix, marker, maxResults, nextMarker);
|
||||
public BoundedSortedSet<QueueMetadata> getResult() {
|
||||
return new BoundedTreeSet<QueueMetadata>(metadata, prefix, marker, maxResults, nextMarker);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
|
|
|
@ -29,7 +29,7 @@ import static org.testng.Assert.assertTrue;
|
|||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.options.CreateOptions;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
|
||||
|
@ -66,7 +66,7 @@ public class AzureQueueConnectionLiveTest {
|
|||
@Test
|
||||
public void testListQueues() throws Exception {
|
||||
|
||||
BoundedList<QueueMetadata> response = connection.listQueues();
|
||||
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
|
||||
assert null != response;
|
||||
long initialQueueCount = response.size();
|
||||
assertTrue(initialQueueCount >= 0);
|
||||
|
@ -90,7 +90,7 @@ public class AzureQueueConnectionLiveTest {
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
BoundedList<QueueMetadata> response = connection.listQueues();
|
||||
BoundedSortedSet<QueueMetadata> response = connection.listQueues();
|
||||
assert null != response;
|
||||
long queueCount = response.size();
|
||||
assertTrue(queueCount >= 1);
|
||||
|
@ -100,7 +100,7 @@ public class AzureQueueConnectionLiveTest {
|
|||
@Test
|
||||
public void testListQueuesWithOptions() throws Exception {
|
||||
|
||||
BoundedList<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
|
||||
BoundedSortedSet<QueueMetadata> response = connection.listQueues(ListOptions.Builder.prefix(
|
||||
privateQueue).maxResults(1));
|
||||
assert null != response;
|
||||
long initialQueueCount = response.size();
|
||||
|
|
|
@ -28,8 +28,8 @@ import static org.testng.Assert.assertEquals;
|
|||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.azure.storage.domain.ArrayBoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedList;
|
||||
import org.jclouds.azure.storage.domain.BoundedTreeSet;
|
||||
import org.jclouds.azure.storage.domain.BoundedSortedSet;
|
||||
import org.jclouds.azure.storage.queue.domain.QueueMetadata;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -47,12 +47,12 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_queues.xml");
|
||||
BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of(
|
||||
BoundedSortedSet<QueueMetadata> list = new BoundedTreeSet<QueueMetadata>(ImmutableList.of(
|
||||
new QueueMetadata("q1", URI.create("http://myaccount.queue.core.windows.net/q1")),
|
||||
new QueueMetadata("q2", URI.create("http://myaccount.queue.core.windows.net/q2")),
|
||||
new QueueMetadata("q3", URI.create("http://myaccount.queue.core.windows.net/q3"))),
|
||||
"q", null, 3, "q4");
|
||||
BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
|
||||
BoundedSortedSet<QueueMetadata> result = (BoundedSortedSet<QueueMetadata>) factory.create(
|
||||
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
|
||||
assertEquals(result, list);
|
||||
}
|
||||
|
@ -60,12 +60,12 @@ public class AccountNameEnumerationResultsHandlerTest extends BaseHandlerTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testApplyInputStreamWithOptions() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_queues_options.xml");
|
||||
BoundedList<QueueMetadata> list = new ArrayBoundedList<QueueMetadata>(ImmutableList.of(
|
||||
BoundedSortedSet<QueueMetadata> list = new BoundedTreeSet<QueueMetadata>(ImmutableList.of(
|
||||
new QueueMetadata("q4", URI.create("http://myaccount.queue.core.windows.net/q4")),
|
||||
new QueueMetadata("q5", URI.create("http://myaccount.queue.core.windows.net/q5"))),
|
||||
"q", "q4", 3, null);
|
||||
|
||||
BoundedList<QueueMetadata> result = (BoundedList<QueueMetadata>) factory.create(
|
||||
BoundedSortedSet<QueueMetadata> result = (BoundedSortedSet<QueueMetadata>) factory.create(
|
||||
injector.getInstance(AccountNameEnumerationResultsHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, list);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.blobstore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
|
@ -35,7 +35,7 @@ import org.jclouds.http.options.GetOptions;
|
|||
* Provides hooks needed to run a blob store
|
||||
*/
|
||||
public interface BlobStore<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
|
||||
List<C> listContainers();
|
||||
SortedSet<C> listContainers();
|
||||
|
||||
boolean containerExists(String container);
|
||||
|
||||
|
@ -50,7 +50,7 @@ public interface BlobStore<C extends ContainerMetadata, M extends BlobMetadata,
|
|||
*/
|
||||
Future<Boolean> deleteContainer(String container);
|
||||
|
||||
Future<? extends List<M>> listBlobs(String container);
|
||||
Future<? extends SortedSet<M>> listBlobs(String container);
|
||||
|
||||
Future<byte[]> putBlob(String container, B blob);
|
||||
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.blobstore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
|
||||
|
@ -34,12 +34,12 @@ import org.jclouds.blobstore.domain.BlobMetadata;
|
|||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface ListableMap<B extends BlobMetadata, K, V> extends Map<K, V> {
|
||||
public interface ListableMap<M extends BlobMetadata, K, V> extends Map<K, V> {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return blob listing that this map represents
|
||||
*/
|
||||
List<B> listContainer();
|
||||
SortedSet<M> listContainer();
|
||||
|
||||
}
|
|
@ -43,7 +43,7 @@ import org.jclouds.http.HttpUtils.MD5InputStreamResult;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Blob<M extends BlobMetadata> {
|
||||
public class Blob<M extends BlobMetadata> implements Comparable<Blob<M>> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
|
@ -217,4 +217,8 @@ public class Blob<M extends BlobMetadata> {
|
|||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public int compareTo(Blob<M> o) {
|
||||
return (this == o) ? 0 : getKey().compareTo(o.getKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ContainerMetadata {
|
||||
public class ContainerMetadata implements Comparable<ContainerMetadata> {
|
||||
|
||||
protected String name;
|
||||
|
||||
|
@ -77,4 +77,8 @@ public class ContainerMetadata {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int compareTo(ContainerMetadata o) {
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ import java.io.FileInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -314,7 +314,7 @@ public class BaseBlobIntegrationTest<S extends BlobStore<C, M, B>, C extends Con
|
|||
|
||||
private void assertContainerEmptyDeleting(String containerName, String key)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
List<M> listing = context.getApi().listBlobs(containerName).get(10, TimeUnit.SECONDS);
|
||||
SortedSet<M> listing = context.getApi().listBlobs(containerName).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(listing.size(), 0, String.format(
|
||||
"deleting %s, we still have %s left in container %s, using encoding %s", key,
|
||||
listing.size(), containerName, LOCAL_ENCODING));
|
||||
|
|
|
@ -26,7 +26,7 @@ package org.jclouds.blobstore.integration.internal;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
@ -126,7 +126,8 @@ public class BaseContainerIntegrationTest<S extends BlobStore<C, M, B>, C extend
|
|||
String containerName = getContainerName();
|
||||
try {
|
||||
add15UnderRoot(containerName);
|
||||
List<M> container = context.getApi().listBlobs(containerName).get(10, TimeUnit.SECONDS);
|
||||
SortedSet<M> container = context.getApi().listBlobs(containerName).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(container.size(), 15);
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.blobstore.integration.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
|
@ -40,7 +40,7 @@ public class BaseServiceIntegrationTest<S extends BlobStore<C, M, B>, C extends
|
|||
|
||||
@Test(groups = { "integration", "live" })
|
||||
void containerDoesntExist() throws Exception {
|
||||
List<C> list = context.getApi().listContainers();
|
||||
SortedSet<C> list = context.getApi().listContainers();
|
||||
assert !list.contains(new ContainerMetadata("shouldntexist"));
|
||||
}
|
||||
|
||||
|
|
|
@ -141,9 +141,9 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
|
|||
};
|
||||
}
|
||||
|
||||
public Future<? extends List<M>> listBlobs(final String name) {
|
||||
return new FutureBase<List<M>>() {
|
||||
public List<M> get() throws InterruptedException, ExecutionException {
|
||||
public Future<? extends SortedSet<M>> listBlobs(final String name) {
|
||||
return new FutureBase<SortedSet<M>>() {
|
||||
public SortedSet<M> get() throws InterruptedException, ExecutionException {
|
||||
final Map<String, B> realContents = getContainerToBlobs().get(name);
|
||||
|
||||
if (realContents == null)
|
||||
|
@ -155,7 +155,7 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
|
|||
}
|
||||
}));
|
||||
|
||||
return Lists.newArrayList(contents);
|
||||
return Sets.newTreeSet(contents);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -247,8 +247,8 @@ public class StubBlobStore<C extends ContainerMetadata, M extends BlobMetadata,
|
|||
}
|
||||
}
|
||||
|
||||
public List<C> listContainers() {
|
||||
return Lists.newArrayList(Iterables.transform(getContainerToBlobs().keySet(),
|
||||
public SortedSet<C> listContainers() {
|
||||
return Sets.newTreeSet(Iterables.transform(getContainerToBlobs().keySet(),
|
||||
new Function<String, C>() {
|
||||
public C apply(String name) {
|
||||
C cmd = containerMetaProvider.get();
|
||||
|
|
|
@ -23,14 +23,14 @@
|
|||
*/
|
||||
package org.jclouds.rest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public interface BoundedList<T> extends List<T> {
|
||||
public interface BoundedSortedSet<T> extends SortedSet<T> {
|
||||
|
||||
String getPrefix();
|
||||
|
|
@ -23,10 +23,10 @@
|
|||
*/
|
||||
package org.jclouds.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class ArrayBoundedList<T> extends ArrayList<T> implements BoundedList<T> {
|
||||
public class BoundedTreeSet<T> extends TreeSet<T> implements BoundedSortedSet<T> {
|
||||
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -7133632087734650835L;
|
||||
|
@ -34,7 +34,7 @@ public class ArrayBoundedList<T> extends ArrayList<T> implements BoundedList<T>
|
|||
protected final String marker;
|
||||
protected final int maxResults;
|
||||
|
||||
public ArrayBoundedList(List<T> contents, String prefix, String marker, int maxResults) {
|
||||
public BoundedTreeSet(List<T> contents, String prefix, String marker, int maxResults) {
|
||||
this.addAll(contents);
|
||||
this.prefix = prefix;
|
||||
this.marker = marker;
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.mezeo.pcs2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.ws.rs.DELETE;
|
||||
|
@ -83,7 +83,7 @@ public interface PCSBlobStore extends BlobStore<ContainerMetadata, FileMetadata,
|
|||
@Headers(keys = "X-Cloud-Depth", values = "2")
|
||||
@Path("/contents")
|
||||
@Endpoint(RootContainer.class)
|
||||
List<ContainerMetadata> listContainers();
|
||||
SortedSet<ContainerMetadata> listContainers();
|
||||
|
||||
@GET
|
||||
@ExceptionParser(ReturnFalseIfContainerNotFound.class)
|
||||
|
@ -111,7 +111,7 @@ public interface PCSBlobStore extends BlobStore<ContainerMetadata, FileMetadata,
|
|||
@Headers(keys = "X-Cloud-Depth", values = "2")
|
||||
@Path("/containers/{containerResourceId}/contents")
|
||||
@Endpoint(PCS.class)
|
||||
Future<? extends List<FileMetadata>> listBlobs(
|
||||
Future<? extends SortedSet<FileMetadata>> listBlobs(
|
||||
@PathParam("containerResourceId") @ParamParser(ContainerNameToResourceId.class) String containerName);
|
||||
|
||||
@POST
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.jclouds.mezeo.pcs2.functions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -20,12 +20,12 @@ public class FindIdInContainerList implements Function<String, String> {
|
|||
}
|
||||
|
||||
public String apply(String key) {
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
return idForNameInListOrException(key, response);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String idForNameInListOrException(String toFind, List<ContainerMetadata> containerMetadataList) {
|
||||
String idForNameInListOrException(String toFind, SortedSet<ContainerMetadata> containerMetadataList) {
|
||||
for (ContainerMetadata data : containerMetadataList) {
|
||||
if (toFind.equals(data.getName())) {
|
||||
String path = data.getUrl().getPath();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.jclouds.mezeo.pcs2.functions;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -25,7 +25,7 @@ public class FindIdInFileList implements Function<Key, String> {
|
|||
}
|
||||
|
||||
public String apply(Key key) {
|
||||
List<FileMetadata> response;
|
||||
SortedSet<FileMetadata> response;
|
||||
try {
|
||||
response = connection.listBlobs(key.getContainer()).get(10, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
|
@ -36,7 +36,7 @@ public class FindIdInFileList implements Function<Key, String> {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String idForNameInListOrException(String container, String toFind, List<FileMetadata> response) {
|
||||
String idForNameInListOrException(String container, String toFind, SortedSet<FileMetadata> response) {
|
||||
for (FileMetadata data : response) {
|
||||
if (toFind.equals(data.getKey())) {
|
||||
String path = data.getUrl().getPath();
|
||||
|
|
|
@ -30,7 +30,7 @@ import static org.testng.Assert.assertTrue;
|
|||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -73,7 +73,7 @@ public class PCSBlobStoreLiveTest {
|
|||
|
||||
@Test
|
||||
public void testListContainers() throws Exception {
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
assertNotNull(response);
|
||||
long initialContainerCount = response.size();
|
||||
assertTrue(initialContainerCount >= 0);
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -76,13 +76,13 @@ import org.jclouds.util.Utils;
|
|||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.internal.ImmutableList;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code PCSConnection}
|
||||
|
@ -102,11 +102,11 @@ public class PCSBlobStoreTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Future<? extends List<FileMetadata>> listBlobs(String containerName) {
|
||||
return new StubBlobStore.FutureBase<List<FileMetadata>>() {
|
||||
public List<FileMetadata> get() throws InterruptedException, ExecutionException {
|
||||
public Future<? extends SortedSet<FileMetadata>> listBlobs(String containerName) {
|
||||
return new StubBlobStore.FutureBase<SortedSet<FileMetadata>>() {
|
||||
public SortedSet<FileMetadata> get() throws InterruptedException, ExecutionException {
|
||||
|
||||
return ImmutableList
|
||||
return ImmutableSortedSet
|
||||
.of(
|
||||
new FileMetadata(
|
||||
"more",
|
||||
|
@ -132,8 +132,8 @@ public class PCSBlobStoreTest {
|
|||
|
||||
}
|
||||
|
||||
public List<ContainerMetadata> listContainers() {
|
||||
return ImmutableList
|
||||
public SortedSet<ContainerMetadata> listContainers() {
|
||||
return ImmutableSortedSet
|
||||
.of(new ContainerMetadata(
|
||||
"mycontainer",
|
||||
URI
|
||||
|
@ -383,7 +383,6 @@ public class PCSBlobStoreTest {
|
|||
JaxrsAnnotationProcessor<PCSBlobStore> processor;
|
||||
private JaxrsAnnotationProcessor<PCSUtil> utilProcessor;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@BeforeClass
|
||||
void setupFactory() {
|
||||
Injector injector = Guice.createInjector(new AbstractModule() {
|
||||
|
@ -431,12 +430,12 @@ public class PCSBlobStoreTest {
|
|||
throws UnsupportedEncodingException {
|
||||
return new BasicAuthentication(user, password);
|
||||
}
|
||||
}, new JaxrsModule(), new BlobStoreMapsModule(new TypeLiteral<PCSBlobStore>() {
|
||||
}, new JaxrsModule(), BlobStoreMapsModule.Builder.newBuilder(new TypeLiteral<PCSBlobStore>() {
|
||||
}, new TypeLiteral<ContainerMetadata>() {
|
||||
}, new TypeLiteral<FileMetadata>() {
|
||||
}, new TypeLiteral<PCSFile>() {
|
||||
}), new PCSContextModule(), new ExecutorServiceModule(new WithinThreadExecutorService()),
|
||||
new JavaUrlHttpCommandExecutorServiceModule());
|
||||
}).build(), new PCSContextModule(), new ExecutorServiceModule(
|
||||
new WithinThreadExecutorService()), new JavaUrlHttpCommandExecutorServiceModule());
|
||||
|
||||
processor = injector.getInstance(Key
|
||||
.get(new TypeLiteral<JaxrsAnnotationProcessor<PCSBlobStore>>() {
|
||||
|
|
|
@ -31,26 +31,22 @@ import com.google.inject.TypeLiteral;
|
|||
public class PCSContextModuleTest {
|
||||
|
||||
Injector createInjector() {
|
||||
return Guice.createInjector(new RestPCSBlobStoreModule(),
|
||||
new BlobStoreMapsModule<PCSBlobStore, ContainerMetadata, FileMetadata, PCSFile>(
|
||||
new TypeLiteral<PCSBlobStore>() {
|
||||
}, new TypeLiteral<ContainerMetadata>() {
|
||||
}, new TypeLiteral<FileMetadata>() {
|
||||
}, new TypeLiteral<PCSFile>() {
|
||||
}), new PCSContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_USER))
|
||||
.to("user");
|
||||
bindConstant()
|
||||
.annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_PASSWORD)).to(
|
||||
"key");
|
||||
bindConstant()
|
||||
.annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_ENDPOINT)).to(
|
||||
"http://localhost");
|
||||
super.configure();
|
||||
}
|
||||
}, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(),
|
||||
return Guice.createInjector(new RestPCSBlobStoreModule(), BlobStoreMapsModule.Builder
|
||||
.newBuilder(new TypeLiteral<PCSBlobStore>() {
|
||||
}, new TypeLiteral<ContainerMetadata>() {
|
||||
}, new TypeLiteral<FileMetadata>() {
|
||||
}, new TypeLiteral<PCSFile>() {
|
||||
}).build(), new PCSContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_USER)).to("user");
|
||||
bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_PASSWORD)).to(
|
||||
"key");
|
||||
bindConstant().annotatedWith(Jsr330.named(PCSConstants.PROPERTY_PCS2_ENDPOINT)).to(
|
||||
"http://localhost");
|
||||
super.configure();
|
||||
}
|
||||
}, new ParserModule(), new JavaUrlHttpCommandExecutorServiceModule(),
|
||||
new ExecutorServiceModule(new WithinThreadExecutorService()));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.jclouds.mezeo.pcs2.domain.ContainerMetadata;
|
|||
import org.jclouds.util.DateService;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.internal.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ContainerResourceId}
|
||||
|
@ -45,7 +45,7 @@ import com.google.inject.internal.ImmutableList;
|
|||
public class FindIdInContainerListTest {
|
||||
private DateService dateService = new DateService();
|
||||
|
||||
private final ImmutableList<ContainerMetadata> OF = ImmutableList
|
||||
private final ImmutableSortedSet<ContainerMetadata> OF = ImmutableSortedSet
|
||||
.of(new ContainerMetadata(
|
||||
"test1",
|
||||
URI
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.jclouds.mezeo.pcs2.domain.FileMetadata;
|
|||
import org.jclouds.util.DateService;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.internal.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedSet;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ContainerResourceId}
|
||||
|
@ -47,7 +47,7 @@ import com.google.inject.internal.ImmutableList;
|
|||
public class FindIdInFileListIdTest {
|
||||
private DateService dateService = new DateService();
|
||||
|
||||
private final ImmutableList<FileMetadata> OF = ImmutableList.of(new FileMetadata("more", URI
|
||||
private final ImmutableSortedSet<FileMetadata> OF = ImmutableSortedSet.of(new FileMetadata("more", URI
|
||||
.create("https://pcsbeta.mezeo.net/v2/files/5C81DADC-AAEE-11DE-9D55-B39340AEFF3A"),
|
||||
dateService.fromSeconds(1254005157), dateService.fromSeconds(1254005158), dateService
|
||||
.fromSeconds(1254005159), "adrian@jclouds.org", false, false, 1, 254288,
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -96,13 +96,13 @@ public interface CloudFilesBlobStore extends
|
|||
@ResponseParser(ParseContainerListFromJsonResponse.class)
|
||||
@QueryParams(keys = "format", values = "json")
|
||||
@Path("/")
|
||||
List<ContainerMetadata> listContainers();
|
||||
SortedSet<ContainerMetadata> listContainers();
|
||||
|
||||
@GET
|
||||
@ResponseParser(ParseContainerListFromJsonResponse.class)
|
||||
@QueryParams(keys = "format", values = "json")
|
||||
@Path("/")
|
||||
List<ContainerMetadata> listContainers(ListContainerOptions options);
|
||||
SortedSet<ContainerMetadata> listContainers(ListContainerOptions options);
|
||||
|
||||
@HEAD
|
||||
@Path("{container}")
|
||||
|
@ -122,7 +122,7 @@ public interface CloudFilesBlobStore extends
|
|||
@QueryParams(keys = "format", values = "json")
|
||||
@ResponseParser(ParseBlobMetadataListFromJsonResponse.class)
|
||||
@Path("{container}")
|
||||
Future<? extends List<BlobMetadata>> listBlobs(@PathParam("container") String container);
|
||||
Future<? extends SortedSet<BlobMetadata>> listBlobs(@PathParam("container") String container);
|
||||
|
||||
@PUT
|
||||
@Path("{container}/{key}")
|
||||
|
@ -175,7 +175,7 @@ public interface CloudFilesBlobStore extends
|
|||
@QueryParams(keys = "format", values = "json")
|
||||
@Path("/")
|
||||
@Endpoint(CloudFilesCDN.class)
|
||||
List<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options);
|
||||
SortedSet<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options);
|
||||
|
||||
// TODO: Container name is not included in CDN HEAD response headers, so we cannot populate it
|
||||
// here.
|
||||
|
|
|
@ -30,7 +30,7 @@ import static org.testng.Assert.fail;
|
|||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -111,7 +111,7 @@ public class CloudFilesBlobStoreLiveTest {
|
|||
|
||||
// List CDN metadata for containers, and ensure all CDN info is available for enabled
|
||||
// container
|
||||
List<ContainerCDNMetadata> cdnMetadataList = connection.listCDNContainers();
|
||||
SortedSet<ContainerCDNMetadata> cdnMetadataList = connection.listCDNContainers();
|
||||
assertTrue(cdnMetadataList.size() >= 1);
|
||||
assertTrue(Iterables.any(cdnMetadataList, new Predicate<ContainerCDNMetadata>() {
|
||||
public boolean apply(ContainerCDNMetadata cdnMetadata) {
|
||||
|
@ -132,7 +132,7 @@ public class CloudFilesBlobStoreLiveTest {
|
|||
cdnMetadataList = connection.listCDNContainers(ListCdnContainerOptions.Builder.afterMarker(
|
||||
containerNameWithCDN.substring(0, containerNameWithCDN.length() - 1)).maxResults(1));
|
||||
assertEquals(cdnMetadataList.size(), 1);
|
||||
assertEquals(cdnMetadataList.get(0).getName(), containerNameWithCDN);
|
||||
assertEquals(cdnMetadataList.first().getName(), containerNameWithCDN);
|
||||
|
||||
// Enable CDN with PUT for the same container, this time with a custom TTL
|
||||
long ttl = 4000;
|
||||
|
@ -168,7 +168,7 @@ public class CloudFilesBlobStoreLiveTest {
|
|||
|
||||
@Test
|
||||
public void testListOwnedContainers() throws Exception {
|
||||
List<ContainerMetadata> response = connection.listContainers();
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
assertNotNull(response);
|
||||
long initialContainerCount = response.size();
|
||||
assertTrue(initialContainerCount >= 0);
|
||||
|
@ -188,12 +188,12 @@ public class CloudFilesBlobStoreLiveTest {
|
|||
response = connection.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerJsr330[0].substring(0, containerJsr330[0].length() - 1)).maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.get(0).getName(), containerJsr330[0]);
|
||||
assertEquals(response.first().getName(), containerJsr330[0]);
|
||||
|
||||
response = connection.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerJsr330[0]).maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.get(0).getName(), containerJsr330[1]);
|
||||
assertEquals(response.first().getName(), containerJsr330[1]);
|
||||
|
||||
// Cleanup and test containers have been removed
|
||||
assertTrue(connection.deleteContainer(containerJsr330[0]).get(10, TimeUnit.SECONDS));
|
||||
|
@ -233,12 +233,12 @@ public class CloudFilesBlobStoreLiveTest {
|
|||
String containerName1 = bucketPrefix + ".hello";
|
||||
assertTrue(connection.createContainer(containerName1).get(10, TimeUnit.SECONDS));
|
||||
// List only the container just created, using a marker with the container name less 1 char
|
||||
List<ContainerMetadata> response = connection
|
||||
SortedSet<ContainerMetadata> response = connection
|
||||
.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerName1.substring(0, containerName1.length() - 1)).maxResults(1));
|
||||
assertNotNull(response);
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.get(0).getName(), bucketPrefix + ".hello");
|
||||
assertEquals(response.first().getName(), bucketPrefix + ".hello");
|
||||
|
||||
String containerName2 = bucketPrefix + "?should-be-illegal-question-char";
|
||||
try {
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
@ -63,7 +63,7 @@ public class StubCloudFilesBlobStore extends
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<ContainerMetadata> listContainers(ListContainerOptions options) {
|
||||
public SortedSet<ContainerMetadata> listContainers(ListContainerOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ public class StubCloudFilesBlobStore extends
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options) {
|
||||
public SortedSet<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue