mirror of https://github.com/apache/jclouds.git
Issue 73: cloudfiles now in blobstore
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2011 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
92b7a3ea89
commit
73cd1e3241
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -58,11 +59,11 @@ import org.jclouds.rackspace.cloudfiles.functions.ObjectName;
|
|||
import org.jclouds.rackspace.cloudfiles.functions.ParseAccountMetadataResponseFromHeaders;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseCdnUriFromHeaders;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseContainerCDNMetadataFromHeaders;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseContainerCDNMetadataListFromGsonResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseContainerCDNMetadataListFromJsonResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseContainerListFromJsonResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseObjectFromHeadersAndHttpContent;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseObjectInfoFromHeaders;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseObjectInfoListFromJsonResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ParseObjectMetadataFromHeaders;
|
||||
import org.jclouds.rackspace.cloudfiles.functions.ReturnTrueOn404FalseOn409;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListCdnContainerOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
@ -140,16 +141,15 @@ public interface CloudFilesClient {
|
|||
@ResponseParser(ParseContainerListFromJsonResponse.class)
|
||||
@QueryParams(keys = "format", values = "json")
|
||||
@Path("/")
|
||||
SortedSet<ContainerMetadata> listContainers(ListContainerOptions... options);
|
||||
Future<? extends SortedSet<ContainerMetadata>> listContainers(ListContainerOptions... options);
|
||||
|
||||
@POST
|
||||
@Path("{container}/{name}")
|
||||
boolean setObjectMetadata(@PathParam("container") String container,
|
||||
@PathParam("name") String name,
|
||||
boolean setObjectInfo(@PathParam("container") String container, @PathParam("name") String name,
|
||||
@BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> userMetadata);
|
||||
|
||||
@GET
|
||||
@ResponseParser(ParseContainerCDNMetadataListFromGsonResponse.class)
|
||||
@ResponseParser(ParseContainerCDNMetadataListFromJsonResponse.class)
|
||||
@QueryParams(keys = "format", values = "json")
|
||||
@Path("/")
|
||||
@Endpoint(CloudFilesCDN.class)
|
||||
|
@ -168,20 +168,20 @@ public interface CloudFilesClient {
|
|||
@Path("{container}")
|
||||
@ResponseParser(ParseCdnUriFromHeaders.class)
|
||||
@Endpoint(CloudFilesCDN.class)
|
||||
String enableCDN(@PathParam("container") String container,
|
||||
URI enableCDN(@PathParam("container") String container,
|
||||
@HeaderParam(CloudFilesHeaders.CDN_TTL) Long ttl);
|
||||
|
||||
@PUT
|
||||
@Path("{container}")
|
||||
@ResponseParser(ParseCdnUriFromHeaders.class)
|
||||
@Endpoint(CloudFilesCDN.class)
|
||||
String enableCDN(@PathParam("container") String container);
|
||||
URI enableCDN(@PathParam("container") String container);
|
||||
|
||||
@POST
|
||||
@Path("{container}")
|
||||
@ResponseParser(ParseCdnUriFromHeaders.class)
|
||||
@Endpoint(CloudFilesCDN.class)
|
||||
String updateCDN(@PathParam("container") String container,
|
||||
URI updateCDN(@PathParam("container") String container,
|
||||
@HeaderParam(CloudFilesHeaders.CDN_TTL) Long ttl);
|
||||
|
||||
@POST
|
||||
|
@ -222,18 +222,20 @@ public interface CloudFilesClient {
|
|||
@ResponseParser(ParseObjectFromHeadersAndHttpContent.class)
|
||||
@ExceptionParser(ThrowKeyNotFoundOn404.class)
|
||||
@Path("{container}/{name}")
|
||||
Future<CFObject> getObject(@PathParam("container") String container, @PathParam("name") String name,
|
||||
GetOptions... options);
|
||||
Future<CFObject> getObject(@PathParam("container") String container,
|
||||
@PathParam("name") String name, GetOptions... options);
|
||||
|
||||
@HEAD
|
||||
@ResponseParser(ParseObjectMetadataFromHeaders.class)
|
||||
@ResponseParser(ParseObjectInfoFromHeaders.class)
|
||||
@ExceptionParser(ThrowKeyNotFoundOn404.class)
|
||||
@Path("{container}/{name}")
|
||||
MutableObjectInfoWithMetadata getObjectInfo(@PathParam("container") String container, @PathParam("name") String name);
|
||||
MutableObjectInfoWithMetadata getObjectInfo(@PathParam("container") String container,
|
||||
@PathParam("name") String name);
|
||||
|
||||
@DELETE
|
||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
||||
@Path("{container}/{name}")
|
||||
Future<Void> removeObject(@PathParam("container") String container, @PathParam("name") String name);
|
||||
Future<Void> removeObject(@PathParam("container") String container,
|
||||
@PathParam("name") String name);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.blobstore.options.ListOptions.Builder.recursive;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModels;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.BoundedSortedSet;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.options.ListOptions;
|
||||
import org.jclouds.blobstore.strategy.ClearListStrategy;
|
||||
import org.jclouds.concurrent.FutureFunctionWrapper;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.logging.Logger.LoggerFactory;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.BlobToObjectGetOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ContainerToResourceList;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ContainerToResourceMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ListOptionsToListContainerOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
@ConsistencyModel(ConsistencyModels.STRICT)
|
||||
public class CloudFilesBlobStore implements BlobStore {
|
||||
private final CloudFilesClient connection;
|
||||
private final Blob.Factory blobFactory;
|
||||
private final LoggerFactory logFactory;
|
||||
private final ClearListStrategy clearContainerStrategy;
|
||||
private final ObjectToBlobMetadata object2BlobMd;
|
||||
private final ObjectToBlob object2Blob;
|
||||
private final BlobToObject blob2Object;
|
||||
private final ListOptionsToListContainerOptions container2ContainerListOptions;
|
||||
private final BlobToObjectGetOptions blob2ObjectGetOptions;
|
||||
private final ContainerToResourceMetadata container2ResourceMd;
|
||||
private final ContainerToResourceList container2ResourceList;
|
||||
private final ExecutorService service;
|
||||
|
||||
@Inject
|
||||
private CloudFilesBlobStore(CloudFilesClient connection, Blob.Factory blobFactory, LoggerFactory logFactory,
|
||||
ClearListStrategy clearContainerStrategy, ObjectToBlobMetadata object2BlobMd,
|
||||
ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
ListOptionsToListContainerOptions container2ContainerListOptions,
|
||||
BlobToObjectGetOptions blob2ObjectGetOptions,
|
||||
ContainerToResourceMetadata container2ResourceMd, ContainerToResourceList container2ResourceList,
|
||||
ExecutorService service) {
|
||||
this.connection = checkNotNull(connection, "connection");
|
||||
this.blobFactory = checkNotNull(blobFactory, "blobFactory");
|
||||
this.logFactory = checkNotNull(logFactory, "logFactory");
|
||||
this.clearContainerStrategy = checkNotNull(clearContainerStrategy, "clearContainerStrategy");
|
||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
||||
"container2ContainerListOptions");
|
||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
||||
this.container2ResourceList = checkNotNull(container2ResourceList, "container2ResourceList");
|
||||
this.service = checkNotNull(service, "service");
|
||||
}
|
||||
|
||||
protected <F, T> Future<T> wrapFuture(Future<? extends F> future, Function<F, T> function) {
|
||||
return new FutureFunctionWrapper<F, T>(future, function, logFactory.getLogger(function
|
||||
.getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation uses the CloudFiles HEAD Object command to return the result
|
||||
*/
|
||||
public BlobMetadata blobMetadata(String container, String key) {
|
||||
return object2BlobMd.apply(connection.getObjectInfo(container, key));
|
||||
}
|
||||
|
||||
public Future<Void> clearContainer(final String container) {
|
||||
return service.submit(new Callable<Void>() {
|
||||
|
||||
public Void call() throws Exception {
|
||||
clearContainerStrategy.execute(container, recursive());
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public Future<Boolean> createContainer(String container) {
|
||||
return connection.createContainer(container);
|
||||
}
|
||||
|
||||
public Future<Void> deleteContainer(final String container) {
|
||||
return service.submit(new Callable<Void>() {
|
||||
|
||||
public Void call() throws Exception {
|
||||
clearContainerStrategy.execute(container, recursive());
|
||||
connection.deleteContainerIfEmpty(container).get();
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public boolean exists(String container) {
|
||||
return connection.containerExists(container);
|
||||
}
|
||||
|
||||
public Future<Blob> getBlob(String container, String key,
|
||||
org.jclouds.blobstore.options.GetOptions... optionsList) {
|
||||
GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList);
|
||||
Future<CFObject> returnVal = connection.getObject(container, key, httpOptions);
|
||||
return wrapFuture(returnVal, object2Blob);
|
||||
}
|
||||
|
||||
public Future<? extends SortedSet<? extends ResourceMetadata>> list() {
|
||||
return wrapFuture(connection.listContainers(),
|
||||
new Function<SortedSet<ContainerMetadata>, SortedSet<? extends ResourceMetadata>>() {
|
||||
public SortedSet<? extends ResourceMetadata> apply(SortedSet<ContainerMetadata> from) {
|
||||
return Sets.newTreeSet(Iterables.transform(from, container2ResourceMd));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Future<? extends BoundedSortedSet<? extends ResourceMetadata>> list(String container,
|
||||
ListOptions... optionsList) {
|
||||
ListContainerOptions httpOptions = container2ContainerListOptions.apply(optionsList);
|
||||
Future<BoundedSortedSet<ObjectInfo>> returnVal = connection.listObjects(container, httpOptions);
|
||||
return wrapFuture(returnVal, container2ResourceList);
|
||||
}
|
||||
|
||||
public Future<String> putBlob(String container, Blob blob) {
|
||||
return connection.putObject(container, blob2Object.apply(blob));
|
||||
}
|
||||
|
||||
public Future<Void> removeBlob(String container, String key) {
|
||||
return connection.removeObject(container, key);
|
||||
}
|
||||
|
||||
public Blob newBlob() {
|
||||
return blobFactory.create(null);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContextBuilder;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
|
||||
import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Creates {@link CloudFilesBlobStoreContext} or {@link Injector} instances based on the most commonly
|
||||
* requested arguments.
|
||||
* <p/>
|
||||
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
|
||||
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
|
||||
*
|
||||
* @author Adrian Cole, Andrew Newdigate
|
||||
* @see CloudFilesBlobStoreContext
|
||||
*/
|
||||
public class CloudFilesBlobStoreContextBuilder extends BlobStoreContextBuilder<CloudFilesClient> {
|
||||
|
||||
public CloudFilesBlobStoreContextBuilder(Properties props) {
|
||||
super(new TypeLiteral<CloudFilesClient>() {
|
||||
}, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudFilesBlobStoreContextBuilder withExecutorService(ExecutorService service) {
|
||||
return (CloudFilesBlobStoreContextBuilder) super.withExecutorService(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudFilesBlobStoreContextBuilder withModules(Module... modules) {
|
||||
return (CloudFilesBlobStoreContextBuilder) super.withModules(modules);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addContextModule(List<Module> modules) {
|
||||
modules.add(new CloudFilesBlobStoreContextModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addClientModule(List<Module> modules) {
|
||||
modules.add(new RackspaceAuthenticationRestModule());
|
||||
modules.add(new CloudFilesRestClientModule());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
* Creates {@link CloudFilesBlobStoreContext} instances based on the most commonly requested
|
||||
* arguments.
|
||||
* <p/>
|
||||
* Note that Threadsafe objects will be bound as singletons to the Injector or Context provided.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* If no <code>Module</code>s are specified, the default {@link JDKLoggingModule logging} and
|
||||
* {@link JavaUrlHttpCommandExecutorServiceModule http transports} will be installed.
|
||||
*
|
||||
* @author Adrian Cole, Andrew Newdigate
|
||||
* @see CloudFilesBlobStoreContext
|
||||
*/
|
||||
public class CloudFilesBlobStoreContextFactory {
|
||||
public static BlobStoreContext<CloudFilesClient> createContext(Properties properties,
|
||||
Module... modules) {
|
||||
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
|
||||
properties).build()).withModules(modules).buildContext();
|
||||
}
|
||||
|
||||
public static BlobStoreContext<CloudFilesClient> createContext(String user,
|
||||
String key, Module... modules) {
|
||||
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
|
||||
user, key).build()).withModules(modules).buildContext();
|
||||
}
|
||||
|
||||
public static BlobStoreContext<CloudFilesClient> createContext(URI endpoint,
|
||||
String user, String key, Module... modules) {
|
||||
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
|
||||
user, key).withEndpoint(endpoint).build()).withModules(
|
||||
modules).buildContext();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesPropertiesBuilder;
|
||||
|
||||
/**
|
||||
* Builds properties used in CloudFiles Blob Stores
|
||||
*
|
||||
* @author Adrian Cole, Andrew Newdigate
|
||||
*/
|
||||
public class CloudFilesBlobStorePropertiesBuilder extends CloudFilesPropertiesBuilder {
|
||||
|
||||
public CloudFilesBlobStorePropertiesBuilder(String id, String secret) {
|
||||
super(id, secret);
|
||||
}
|
||||
|
||||
public CloudFilesBlobStorePropertiesBuilder(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* longest time a single synchronous operation can take before throwing an exception.
|
||||
*/
|
||||
public CloudFilesBlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
|
||||
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
|
||||
.toString(milliseconds));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.config;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.BlobMap;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.InputStreamMap;
|
||||
import org.jclouds.blobstore.config.BlobStoreMapModule;
|
||||
import org.jclouds.blobstore.config.BlobStoreObjectModule;
|
||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||
import org.jclouds.lifecycle.Closer;
|
||||
import org.jclouds.rackspace.CloudFiles;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStore;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CFObjectModule;
|
||||
import org.jclouds.rackspace.reference.RackspaceConstants;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the {@link CloudFilesBlobStoreContext}; requires {@link CloudFilesBlobStore} bound.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CloudFilesBlobStoreContextModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new BlobStoreObjectModule());
|
||||
install(new BlobStoreMapModule());
|
||||
install(new CFObjectModule());
|
||||
bind(BlobStore.class).to(CloudFilesBlobStore.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
BlobStoreContext<CloudFilesClient> provideContext(BlobMap.Factory blobMapFactory,
|
||||
InputStreamMap.Factory inputStreamMapFactory, Closer closer, BlobStore blobStore,
|
||||
CloudFilesClient defaultApi, @CloudFiles URI endPoint,
|
||||
@Named(RackspaceConstants.PROPERTY_RACKSPACE_USER) String account) {
|
||||
return new BlobStoreContextImpl<CloudFilesClient>(blobMapFactory, inputStreamMapFactory,
|
||||
closer, blobStore, defaultApi, endPoint, account);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,11 +13,11 @@ import com.google.common.base.Function;
|
|||
*/
|
||||
@Singleton
|
||||
public class BlobToObject implements Function<Blob, CFObject> {
|
||||
private final BlobToObjectInfo blob2ObjectMd;
|
||||
private final ResourceToObjectInfo blob2ObjectMd;
|
||||
private final CFObject.Factory objectProvider;
|
||||
|
||||
@Inject
|
||||
BlobToObject(BlobToObjectInfo blob2ObjectMd, CFObject.Factory objectProvider) {
|
||||
BlobToObject(ResourceToObjectInfo blob2ObjectMd, CFObject.Factory objectProvider) {
|
||||
this.blob2ObjectMd = blob2ObjectMd;
|
||||
this.objectProvider = objectProvider;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BlobToObjectGetOptions implements
|
||||
Function<org.jclouds.blobstore.options.GetOptions[], GetOptions> {
|
||||
public GetOptions apply(org.jclouds.blobstore.options.GetOptions[] from) {
|
||||
GetOptions httpOptions = new GetOptions();
|
||||
if (from.length != 0) {
|
||||
if (from[0].getIfMatch() != null) {
|
||||
httpOptions.ifETagMatches(from[0].getIfMatch());
|
||||
}
|
||||
if (from[0].getIfModifiedSince() != null) {
|
||||
httpOptions.ifModifiedSince(from[0].getIfModifiedSince());
|
||||
}
|
||||
if (from[0].getIfNoneMatch() != null) {
|
||||
httpOptions.ifETagDoesntMatch(from[0].getIfNoneMatch());
|
||||
}
|
||||
if (from[0].getIfUnmodifiedSince() != null) {
|
||||
httpOptions.ifUnmodifiedSince(from[0].getIfUnmodifiedSince());
|
||||
}
|
||||
for (String range : from[0].getRanges()) {
|
||||
String[] firstLast = range.split("\\-");
|
||||
httpOptions.range(Long.parseLong(firstLast[0]), Long.parseLong(firstLast[1]));
|
||||
}
|
||||
}
|
||||
return httpOptions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.BoundedSortedSet;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.domain.internal.BoundedTreeSet;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ContainerToResourceList implements
|
||||
Function<BoundedSortedSet<ObjectInfo>, BoundedSortedSet<? extends ResourceMetadata>> {
|
||||
private final ObjectToBlobMetadata object2blobMd;
|
||||
|
||||
@Inject
|
||||
public ContainerToResourceList(ObjectToBlobMetadata object2blobMd) {
|
||||
this.object2blobMd = object2blobMd;
|
||||
}
|
||||
|
||||
public BoundedSortedSet<? extends ResourceMetadata> apply(BoundedSortedSet<ObjectInfo> from) {
|
||||
return new BoundedTreeSet<ResourceMetadata>(Iterables.transform(Iterables.transform(from,
|
||||
object2blobMd), new Function<BlobMetadata, ResourceMetadata>() {
|
||||
public ResourceMetadata apply(BlobMetadata arg0) {
|
||||
return arg0;
|
||||
}
|
||||
}), from.getPath(), from.getMarker(), from.getMaxResults(), from.isTruncated());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.MutableResourceMetadata;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.domain.ResourceType;
|
||||
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerMetadata;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ContainerToResourceMetadata implements Function<ContainerMetadata, ResourceMetadata> {
|
||||
public ResourceMetadata apply(ContainerMetadata from) {
|
||||
MutableResourceMetadata to = new MutableResourceMetadataImpl();
|
||||
to.setName(from.getName());
|
||||
to.setType(ResourceType.CONTAINER);
|
||||
return to;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.options.ListOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ListContainerOptionsToListOptions implements
|
||||
Function<ListContainerOptions[], ListOptions> {
|
||||
public ListOptions apply(ListContainerOptions[] optionsList) {
|
||||
ListOptions options = new ListOptions();
|
||||
if (optionsList.length != 0) {
|
||||
if (optionsList[0].getPath() != null) {
|
||||
options.underPath(optionsList[0].getPath());
|
||||
}
|
||||
if (optionsList[0].getPrefix() != null) {
|
||||
options.underPath(optionsList[0].getPrefix());
|
||||
options.recursive();
|
||||
}
|
||||
if (optionsList[0].getMarker() != null) {
|
||||
options.afterMarker(optionsList[0].getMarker());
|
||||
}
|
||||
options.maxResults(optionsList[0].getMaxResults());
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.options.ListOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ListOptionsToListContainerOptions implements
|
||||
Function<ListOptions[], ListContainerOptions> {
|
||||
public ListContainerOptions apply(ListOptions[] optionsList) {
|
||||
ListContainerOptions options = new ListContainerOptions();
|
||||
if (optionsList.length != 0) {
|
||||
|
||||
if ((optionsList[0].getPath() == null) && (optionsList[0].isRecursive())) {
|
||||
options.withPrefix("");
|
||||
}
|
||||
if ((optionsList[0].getPath() == null) && (!optionsList[0].isRecursive())) {
|
||||
options.underPath("");
|
||||
}
|
||||
if ((optionsList[0].getPath() != null) && (optionsList[0].isRecursive())) {
|
||||
options.withPrefix(optionsList[0].getPath());
|
||||
}
|
||||
if ((optionsList[0].getPath() != null) && (!optionsList[0].isRecursive())) {
|
||||
options.underPath(optionsList[0].getPath());
|
||||
}
|
||||
if (optionsList[0].getMarker() != null) {
|
||||
options.afterMarker(optionsList[0].getMarker());
|
||||
}
|
||||
if (optionsList[0].getMaxResults() != null) {
|
||||
options.maxResults(optionsList[0].getMaxResults());
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,6 +7,7 @@ import org.jclouds.blobstore.domain.ResourceType;
|
|||
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -14,9 +15,8 @@ import com.google.common.base.Function;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ObjectToBlobMetadata implements
|
||||
Function<MutableObjectInfoWithMetadata, MutableBlobMetadata> {
|
||||
public MutableBlobMetadata apply(MutableObjectInfoWithMetadata from) {
|
||||
public class ObjectToBlobMetadata implements Function<ObjectInfo, MutableBlobMetadata> {
|
||||
public MutableBlobMetadata apply(ObjectInfo from) {
|
||||
MutableBlobMetadata to = new MutableBlobMetadataImpl();
|
||||
to.setContentMD5(from.getHash());
|
||||
if (from.getContentType() != null)
|
||||
|
@ -27,7 +27,8 @@ public class ObjectToBlobMetadata implements
|
|||
if (from.getBytes() != null)
|
||||
to.setSize(from.getBytes());
|
||||
to.setType(ResourceType.BLOB);
|
||||
to.setUserMetadata(from.getMetadata());
|
||||
if (from instanceof MutableObjectInfoWithMetadata)
|
||||
to.setUserMetadata(((MutableObjectInfoWithMetadata)from).getMetadata());
|
||||
if (from.getContentType() != null && from.getContentType().equals("application/directory")) {
|
||||
to.setType(ResourceType.RELATIVE_PATH);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.domain.ResourceType;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.internal.MutableObjectInfoWithMetadataImpl;
|
||||
|
||||
|
@ -12,11 +15,17 @@ import com.google.common.base.Function;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BlobToObjectInfo implements Function<BlobMetadata, MutableObjectInfoWithMetadata> {
|
||||
public MutableObjectInfoWithMetadata apply(BlobMetadata base) {
|
||||
public class ResourceToObjectInfo implements Function<ResourceMetadata, MutableObjectInfoWithMetadata> {
|
||||
public MutableObjectInfoWithMetadata apply(ResourceMetadata base) {
|
||||
MutableObjectInfoWithMetadata to = new MutableObjectInfoWithMetadataImpl();
|
||||
to.setContentType(base.getContentType());
|
||||
to.setHash(base.getContentMD5());
|
||||
if (base.getType() == ResourceType.BLOB){
|
||||
to.setContentType(((BlobMetadata)base).getContentType());
|
||||
to.setHash(((BlobMetadata)base).getContentMD5());
|
||||
} else if (base.getType() == ResourceType.RELATIVE_PATH){
|
||||
to.setContentType("application/directory");
|
||||
}
|
||||
if (base.getETag() != null && to.getHash() == null)
|
||||
to.setHash(HttpUtils.fromHexString(base.getETag()));
|
||||
to.setName(base.getName());
|
||||
to.setLastModified(base.getLastModified());
|
||||
if (base.getSize() != null)
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.BoundedSortedSet;
|
||||
import org.jclouds.blobstore.domain.ResourceMetadata;
|
||||
import org.jclouds.blobstore.domain.internal.BoundedTreeSet;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ResourceToObjectList implements
|
||||
Function<BoundedSortedSet<? extends ResourceMetadata>, BoundedSortedSet<ObjectInfo>> {
|
||||
private final ResourceToObjectInfo resource2ObjectMd;
|
||||
|
||||
@Inject
|
||||
public ResourceToObjectList(ResourceToObjectInfo resource2ObjectMd) {
|
||||
this.resource2ObjectMd = resource2ObjectMd;
|
||||
}
|
||||
|
||||
public BoundedSortedSet<ObjectInfo> apply(BoundedSortedSet<? extends ResourceMetadata> list) {
|
||||
|
||||
return new BoundedTreeSet<ObjectInfo>(Iterables.transform(list,
|
||||
new Function<ResourceMetadata, ObjectInfo>() {
|
||||
|
||||
public ObjectInfo apply(ResourceMetadata from) {
|
||||
return resource2ObjectMd.apply(from);
|
||||
}
|
||||
|
||||
}), list.getPath(), list.getMarker(), list.getMaxResults(), list.size() == list
|
||||
.getMaxResults());
|
||||
}
|
||||
}
|
|
@ -23,23 +23,28 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.domain;
|
||||
|
||||
import org.jclouds.blobstore.domain.internal.MutableResourceMetadataImpl;
|
||||
import java.net.URI;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Murty
|
||||
*
|
||||
*/
|
||||
public class ContainerCDNMetadata extends MutableResourceMetadataImpl {
|
||||
public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
|
||||
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = 8373435988423605652L;
|
||||
private long ttl;
|
||||
private String name;
|
||||
private boolean cdn_enabled;
|
||||
private String cdn_uri;
|
||||
private long ttl;
|
||||
private URI cdn_uri;
|
||||
private String referrer_acl;
|
||||
private String useragent_acl;
|
||||
private boolean log_retention;
|
||||
|
||||
public ContainerCDNMetadata(boolean cdnEnabled, long ttl, String cdnUri) {
|
||||
super();
|
||||
public ContainerCDNMetadata(String name, boolean cdnEnabled, long ttl, URI cdnUri) {
|
||||
this.name = name;
|
||||
this.cdn_enabled = cdnEnabled;
|
||||
this.ttl = ttl;
|
||||
this.cdn_uri = cdnUri;
|
||||
|
@ -52,41 +57,36 @@ public class ContainerCDNMetadata extends MutableResourceMetadataImpl {
|
|||
* Beware: The container name is not available from HEAD CDN responses and will be null. return
|
||||
* the name of the container to which these CDN settings apply.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return super.getName();
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setCdnUri(String cdnUri) {
|
||||
this.cdn_uri = cdnUri;
|
||||
}
|
||||
|
||||
public String getCdnUri() {
|
||||
public URI getCDNUri() {
|
||||
return cdn_uri;
|
||||
}
|
||||
|
||||
public void setTtl(long ttl) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
public long getTtl() {
|
||||
public long getTTL() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public void setCdnEnabled(boolean cdnEnabled) {
|
||||
this.cdn_enabled = cdnEnabled;
|
||||
public boolean isCDNEnabled() {
|
||||
return cdn_enabled;
|
||||
}
|
||||
|
||||
public boolean isCdnEnabled() {
|
||||
return cdn_enabled;
|
||||
public int compareTo(ContainerCDNMetadata o) {
|
||||
if (getName() == null)
|
||||
return -1;
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
int result = 1;
|
||||
result = prime * result + (cdn_enabled ? 1231 : 1237);
|
||||
result = prime * result + ((cdn_uri == null) ? 0 : cdn_uri.hashCode());
|
||||
result = prime * result + (log_retention ? 1231 : 1237);
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + (int) (ttl ^ (ttl >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class ContainerCDNMetadata extends MutableResourceMetadataImpl {
|
|||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!super.equals(obj))
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
|
@ -107,9 +107,25 @@ public class ContainerCDNMetadata extends MutableResourceMetadataImpl {
|
|||
return false;
|
||||
} else if (!cdn_uri.equals(other.cdn_uri))
|
||||
return false;
|
||||
if (ttl != other.ttl)
|
||||
if (log_retention != other.log_retention)
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getReferrerACL() {
|
||||
return referrer_acl;
|
||||
}
|
||||
|
||||
public String getUseragentACL() {
|
||||
return useragent_acl;
|
||||
}
|
||||
|
||||
public boolean isLogRetention() {
|
||||
return log_retention;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ package org.jclouds.rackspace.cloudfiles.functions;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesHeaders;
|
||||
|
@ -36,16 +38,14 @@ import com.google.common.base.Function;
|
|||
*
|
||||
* @author James Murty
|
||||
*/
|
||||
public class ParseCdnUriFromHeaders implements
|
||||
Function<HttpResponse, String> {
|
||||
public class ParseCdnUriFromHeaders implements Function<HttpResponse, URI> {
|
||||
|
||||
/**
|
||||
* parses the http response headers to provide the CDN URI string.
|
||||
*/
|
||||
public String apply(final HttpResponse from) {
|
||||
String cdnUri = checkNotNull(
|
||||
from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI),
|
||||
public URI apply(final HttpResponse from) {
|
||||
String cdnUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI),
|
||||
CloudFilesHeaders.CDN_URI);
|
||||
return cdnUri;
|
||||
return URI.create(cdnUri);
|
||||
}
|
||||
}
|
|
@ -25,10 +25,14 @@ package org.jclouds.rackspace.cloudfiles.functions;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesHeaders;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -38,14 +42,14 @@ import com.google.common.base.Function;
|
|||
* @author James Murty
|
||||
*/
|
||||
public class ParseContainerCDNMetadataFromHeaders implements
|
||||
Function<HttpResponse, ContainerCDNMetadata> {
|
||||
Function<HttpResponse, ContainerCDNMetadata>, InvocationContext {
|
||||
|
||||
private GeneratedHttpRequest<?> request;
|
||||
|
||||
/**
|
||||
* parses the http response headers to create a new {@link ContainerCDNMetadata} object.
|
||||
*/
|
||||
public ContainerCDNMetadata apply(final HttpResponse from) {
|
||||
// TODO: The container name is not returned as a header, hopefully one day it will be
|
||||
|
||||
String cdnUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI),
|
||||
CloudFilesHeaders.CDN_URI);
|
||||
String cdnTTL = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_TTL),
|
||||
|
@ -56,8 +60,12 @@ public class ParseContainerCDNMetadataFromHeaders implements
|
|||
// CDN is not, and has never, been enabled for this container.
|
||||
return null;
|
||||
} else {
|
||||
return new ContainerCDNMetadata(Boolean.parseBoolean(cdnEnabled), Long.parseLong(cdnTTL),
|
||||
cdnUri);
|
||||
return new ContainerCDNMetadata(request.getEndpoint().getPath(), Boolean
|
||||
.parseBoolean(cdnEnabled), Long.parseLong(cdnTTL), URI.create(cdnUri));
|
||||
}
|
||||
}
|
||||
|
||||
public void setContext(GeneratedHttpRequest<?> request) {
|
||||
this.request = request;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.functions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -31,6 +32,7 @@ import java.util.SortedSet;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
|
||||
|
@ -42,15 +44,23 @@ import com.google.gson.reflect.TypeToken;
|
|||
*
|
||||
* @author James Murty
|
||||
*/
|
||||
public class ParseContainerCDNMetadataListFromGsonResponse extends ParseJson<SortedSet<ContainerCDNMetadata>>
|
||||
public class ParseContainerCDNMetadataListFromJsonResponse extends ParseJson<SortedSet<ContainerCDNMetadata>>
|
||||
{
|
||||
|
||||
@Inject
|
||||
public ParseContainerCDNMetadataListFromGsonResponse(Gson gson) {
|
||||
public ParseContainerCDNMetadataListFromJsonResponse(Gson gson) {
|
||||
super(gson);
|
||||
}
|
||||
|
||||
public SortedSet<ContainerCDNMetadata> apply(InputStream stream) {
|
||||
String toParse;
|
||||
try {
|
||||
toParse = IOUtils.toString(stream);
|
||||
} catch (IOException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
// Ticket #1871 bad quoting on cdn uri
|
||||
stream = IOUtils.toInputStream(toParse.replaceAll("m,","m\","));
|
||||
Type listType = new TypeToken<SortedSet<ContainerCDNMetadata>>() {
|
||||
}.getType();
|
||||
try {
|
|
@ -45,11 +45,11 @@ import com.google.common.base.Function;
|
|||
public class ParseObjectFromHeadersAndHttpContent implements Function<HttpResponse, CFObject>,
|
||||
InvocationContext {
|
||||
|
||||
private final ParseObjectMetadataFromHeaders infoParser;
|
||||
private final ParseObjectInfoFromHeaders infoParser;
|
||||
private final CFObject.Factory objectProvider;
|
||||
|
||||
@Inject
|
||||
public ParseObjectFromHeadersAndHttpContent(ParseObjectMetadataFromHeaders infoParser,
|
||||
public ParseObjectFromHeadersAndHttpContent(ParseObjectInfoFromHeaders infoParser,
|
||||
CFObject.Factory objectProvider) {
|
||||
this.infoParser = infoParser;
|
||||
this.objectProvider = objectProvider;
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
|
|||
import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.BlobToObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
@ -41,16 +41,16 @@ import com.google.common.base.Function;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ParseObjectMetadataFromHeaders implements
|
||||
public class ParseObjectInfoFromHeaders implements
|
||||
Function<HttpResponse, MutableObjectInfoWithMetadata>, InvocationContext {
|
||||
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||
private final BlobToObjectInfo blobToObjectInfo;
|
||||
private final ResourceToObjectInfo blobToObjectInfo;
|
||||
|
||||
@Inject
|
||||
public ParseObjectMetadataFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||
BlobToObjectInfo blobToObjectMetadata) {
|
||||
public ParseObjectInfoFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||
ResourceToObjectInfo blobToObjectInfo) {
|
||||
this.blobMetadataParser = blobMetadataParser;
|
||||
this.blobToObjectInfo = blobToObjectMetadata;
|
||||
this.blobToObjectInfo = blobToObjectInfo;
|
||||
}
|
||||
|
||||
/**
|
|
@ -32,6 +32,7 @@ import static org.testng.Assert.fail;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -46,7 +47,6 @@ import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
|
|||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
|
@ -55,7 +55,6 @@ import org.jclouds.rackspace.cloudfiles.domain.MutableObjectInfoWithMetadata;
|
|||
import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListCdnContainerOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -68,25 +67,14 @@ import com.google.common.collect.Maps;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "cloudfiles.CloudFilesClientLiveTest")
|
||||
public class CloudFilesClientLiveTest {
|
||||
|
||||
private String bucketPrefix = BaseBlobStoreIntegrationTest.CONTAINER_PREFIX;
|
||||
CloudFilesClient connection;
|
||||
|
||||
@BeforeGroups(groups = { "live" })
|
||||
public void setupClient() {
|
||||
String account = System.getProperty("jclouds.test.user");
|
||||
String key = System.getProperty("jclouds.test.key");
|
||||
connection = CloudFilesContextFactory.createContext(account, key, new Log4JLoggingModule())
|
||||
.getApi();
|
||||
}
|
||||
public class CloudFilesClientLiveTest extends BaseBlobStoreIntegrationTest<CloudFilesClient> {
|
||||
|
||||
/**
|
||||
* this method overrides containerName to ensure it isn't found
|
||||
*/
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void deleteContainerIfEmptyNotFound() throws Exception {
|
||||
assert connection.deleteContainerIfEmpty("dbienf").get(10, TimeUnit.SECONDS);
|
||||
assert context.getApi().deleteContainerIfEmpty("dbienf").get(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -94,325 +82,329 @@ public class CloudFilesClientLiveTest {
|
|||
final long minimumTTL = 60 * 60; // The minimum TTL is 1 hour
|
||||
|
||||
// Create two new containers for testing
|
||||
final String containerNameWithCDN = bucketPrefix + ".testCDNOperationsContainerWithCDN";
|
||||
final String containerNameWithoutCDN = bucketPrefix + ".testCDNOperationsContainerWithoutCDN";
|
||||
assertTrue(connection.createContainer(containerNameWithCDN).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.createContainer(containerNameWithoutCDN).get(10, TimeUnit.SECONDS));
|
||||
|
||||
ContainerCDNMetadata cdnMetadata = null;
|
||||
|
||||
// Enable CDN with PUT for one container
|
||||
final String cdnUri = connection.enableCDN(containerNameWithCDN);
|
||||
assertTrue(cdnUri != null);
|
||||
assertTrue(cdnUri.startsWith("http://"));
|
||||
|
||||
// Confirm CDN is enabled via HEAD request and has default TTL
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCdnEnabled());
|
||||
assertEquals(cdnMetadata.getCdnUri(), cdnUri);
|
||||
final long initialTTL = cdnMetadata.getTtl();
|
||||
|
||||
final String containerNameWithCDN = getContainerName();
|
||||
final String containerNameWithoutCDN = getContainerName();
|
||||
try {
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithoutCDN);
|
||||
assert false : "should not exist";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
cdnMetadata = connection.getCDNMetadata("DoesNotExist");
|
||||
assert false : "should not exist";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
}
|
||||
ContainerCDNMetadata cdnMetadata = null;
|
||||
|
||||
// List CDN metadata for containers, and ensure all CDN info is available for enabled
|
||||
// container
|
||||
SortedSet<ContainerCDNMetadata> cdnMetadataList = connection.listCDNContainers();
|
||||
assertTrue(cdnMetadataList.size() >= 1);
|
||||
assertTrue(Iterables.any(cdnMetadataList, new Predicate<ContainerCDNMetadata>() {
|
||||
public boolean apply(ContainerCDNMetadata cdnMetadata) {
|
||||
return (cdnMetadata.getName().equals(containerNameWithCDN)
|
||||
&& cdnMetadata.isCdnEnabled() && cdnMetadata.getTtl() == initialTTL && cdnMetadata
|
||||
.getCdnUri().equals(cdnUri));
|
||||
// Enable CDN with PUT for one container
|
||||
final URI cdnUri = context.getApi().enableCDN(containerNameWithCDN);
|
||||
assertTrue(cdnUri != null);
|
||||
|
||||
// Confirm CDN is enabled via HEAD request and has default TTL
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCDNEnabled());
|
||||
assertEquals(cdnMetadata.getCDNUri(), cdnUri);
|
||||
final long initialTTL = cdnMetadata.getTTL();
|
||||
|
||||
try {
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithoutCDN);
|
||||
assert false : "should not exist";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
}
|
||||
}));
|
||||
|
||||
// Test listing with options
|
||||
cdnMetadataList = connection.listCDNContainers(ListCdnContainerOptions.Builder.enabledOnly());
|
||||
assertTrue(Iterables.all(cdnMetadataList, new Predicate<ContainerCDNMetadata>() {
|
||||
public boolean apply(ContainerCDNMetadata cdnMetadata) {
|
||||
return cdnMetadata.isCdnEnabled();
|
||||
try {
|
||||
cdnMetadata = context.getApi().getCDNMetadata("DoesNotExist");
|
||||
assert false : "should not exist";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
}
|
||||
}));
|
||||
|
||||
cdnMetadataList = connection.listCDNContainers(ListCdnContainerOptions.Builder.afterMarker(
|
||||
containerNameWithCDN.substring(0, containerNameWithCDN.length() - 1)).maxResults(1));
|
||||
assertEquals(cdnMetadataList.size(), 1);
|
||||
assertEquals(cdnMetadataList.first().getName(), containerNameWithCDN);
|
||||
// List CDN metadata for containers, and ensure all CDN info is available for enabled
|
||||
// container
|
||||
SortedSet<ContainerCDNMetadata> cdnMetadataList = context.getApi().listCDNContainers();
|
||||
assertTrue(cdnMetadataList.size() >= 1);
|
||||
|
||||
// Enable CDN with PUT for the same container, this time with a custom TTL
|
||||
long ttl = 4000;
|
||||
connection.enableCDN(containerNameWithCDN, ttl);
|
||||
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true,
|
||||
initialTTL, cdnUri)));
|
||||
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCdnEnabled());
|
||||
assertEquals(cdnMetadata.getTtl(), ttl);
|
||||
// Test listing with options
|
||||
cdnMetadataList = context.getApi().listCDNContainers(
|
||||
ListCdnContainerOptions.Builder.enabledOnly());
|
||||
assertTrue(Iterables.all(cdnMetadataList, new Predicate<ContainerCDNMetadata>() {
|
||||
public boolean apply(ContainerCDNMetadata cdnMetadata) {
|
||||
return cdnMetadata.isCDNEnabled();
|
||||
}
|
||||
}));
|
||||
|
||||
// Check POST by updating TTL settings
|
||||
ttl = minimumTTL;
|
||||
connection.updateCDN(containerNameWithCDN, minimumTTL);
|
||||
cdnMetadataList = context.getApi().listCDNContainers(
|
||||
ListCdnContainerOptions.Builder.afterMarker(
|
||||
containerNameWithCDN.substring(0, containerNameWithCDN.length() - 1))
|
||||
.maxResults(1));
|
||||
assertEquals(cdnMetadataList.size(), 1);
|
||||
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCdnEnabled());
|
||||
assertEquals(cdnMetadata.getTtl(), minimumTTL);
|
||||
// Enable CDN with PUT for the same container, this time with a custom TTL
|
||||
long ttl = 4000;
|
||||
context.getApi().enableCDN(containerNameWithCDN, ttl);
|
||||
|
||||
// Confirm that minimum allowed value for TTL is 3600, lower values are ignored.
|
||||
connection.updateCDN(containerNameWithCDN, 3599L);
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithCDN);
|
||||
assertEquals(cdnMetadata.getTtl(), minimumTTL); // Note that TTL is 3600 here, not 3599
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCDNEnabled());
|
||||
assertEquals(cdnMetadata.getTTL(), ttl);
|
||||
|
||||
// Disable CDN with POST
|
||||
assertTrue(connection.disableCDN(containerNameWithCDN));
|
||||
// Check POST by updating TTL settings
|
||||
ttl = minimumTTL;
|
||||
context.getApi().updateCDN(containerNameWithCDN, minimumTTL);
|
||||
|
||||
cdnMetadata = connection.getCDNMetadata(containerNameWithCDN);
|
||||
assertEquals(cdnMetadata.isCdnEnabled(), false);
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
|
||||
assertTrue(cdnMetadata.isCDNEnabled());
|
||||
assertEquals(cdnMetadata.getTTL(), minimumTTL);
|
||||
|
||||
// Delete test containers
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerNameWithCDN).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerNameWithoutCDN).get(10,
|
||||
TimeUnit.SECONDS));
|
||||
// Confirm that minimum allowed value for TTL is 3600, lower values are ignored.
|
||||
context.getApi().updateCDN(containerNameWithCDN, 3599L);
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
|
||||
assertEquals(cdnMetadata.getTTL(), minimumTTL); // Note that TTL is 3600 here, not 3599
|
||||
|
||||
// Disable CDN with POST
|
||||
assertTrue(context.getApi().disableCDN(containerNameWithCDN));
|
||||
|
||||
cdnMetadata = context.getApi().getCDNMetadata(containerNameWithCDN);
|
||||
assertEquals(cdnMetadata.isCDNEnabled(), false);
|
||||
} finally {
|
||||
recycleContainer(containerNameWithCDN);
|
||||
recycleContainer(containerNameWithoutCDN);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListOwnedContainers() throws Exception {
|
||||
SortedSet<ContainerMetadata> response = connection.listContainers();
|
||||
assertNotNull(response);
|
||||
long initialContainerCount = response.size();
|
||||
assertTrue(initialContainerCount >= 0);
|
||||
String containerPrefix = getContainerName();
|
||||
try {
|
||||
SortedSet<ContainerMetadata> response = context.getApi().listContainers().get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertNotNull(response);
|
||||
long initialContainerCount = response.size();
|
||||
assertTrue(initialContainerCount >= 0);
|
||||
|
||||
// Create test containers
|
||||
String[] containerJsr330 = new String[] { bucketPrefix + ".testListOwnedContainers1",
|
||||
bucketPrefix + ".testListOwnedContainers2" };
|
||||
assertTrue(connection.createContainer(containerJsr330[0]).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.createContainer(containerJsr330[1]).get(10, TimeUnit.SECONDS));
|
||||
// Create test containers
|
||||
String[] containerJsr330 = new String[] { containerPrefix + ".testListOwnedContainers1",
|
||||
containerPrefix + ".testListOwnedContainers2" };
|
||||
assertTrue(context.getApi().createContainer(containerJsr330[0]).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(context.getApi().createContainer(containerJsr330[1]).get(10, TimeUnit.SECONDS));
|
||||
|
||||
// Test default listing
|
||||
response = connection.listContainers();
|
||||
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
|
||||
// exist, this will fail
|
||||
// Test default listing
|
||||
response = context.getApi().listContainers().get(10, TimeUnit.SECONDS);
|
||||
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
|
||||
// exist, this will fail
|
||||
|
||||
// Test listing with options
|
||||
response = connection.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerJsr330[0].substring(0, containerJsr330[0].length() - 1)).maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), containerJsr330[0]);
|
||||
// Test listing with options
|
||||
response = context.getApi().listContainers(
|
||||
ListContainerOptions.Builder.afterMarker(
|
||||
containerJsr330[0].substring(0, containerJsr330[0].length() - 1))
|
||||
.maxResults(1)).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), containerJsr330[0]);
|
||||
|
||||
response = connection.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerJsr330[0]).maxResults(1));
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), containerJsr330[1]);
|
||||
response = context.getApi().listContainers(
|
||||
ListContainerOptions.Builder.afterMarker(containerJsr330[0]).maxResults(1)).get(
|
||||
10, TimeUnit.SECONDS);
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), containerJsr330[1]);
|
||||
|
||||
// Cleanup and test containers have been removed
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerJsr330[0]).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerJsr330[1]).get(10, TimeUnit.SECONDS));
|
||||
response = connection.listContainers();
|
||||
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
|
||||
// exist, this will fail
|
||||
// Cleanup and test containers have been removed
|
||||
assertTrue(context.getApi().deleteContainerIfEmpty(containerJsr330[0]).get(10,
|
||||
TimeUnit.SECONDS));
|
||||
assertTrue(context.getApi().deleteContainerIfEmpty(containerJsr330[1]).get(10,
|
||||
TimeUnit.SECONDS));
|
||||
response = context.getApi().listContainers().get(10, TimeUnit.SECONDS);
|
||||
// assertEquals(response.size(), initialContainerCount + 2);// if the containers already
|
||||
// exist, this will fail
|
||||
} finally {
|
||||
returnContainer(containerPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeadAccountMetadata() throws Exception {
|
||||
AccountMetadata metadata = connection.getAccountStatistics();
|
||||
assertNotNull(metadata);
|
||||
long initialContainerCount = metadata.getContainerCount();
|
||||
String containerPrefix = getContainerName();
|
||||
String containerName = containerPrefix + ".testHeadAccountMetadata";
|
||||
try {
|
||||
AccountMetadata metadata = context.getApi().getAccountStatistics();
|
||||
assertNotNull(metadata);
|
||||
long initialContainerCount = metadata.getContainerCount();
|
||||
|
||||
String containerName = bucketPrefix + ".testHeadAccountMetadata";
|
||||
assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(context.getApi().createContainer(containerName).get(10, TimeUnit.SECONDS));
|
||||
|
||||
metadata = connection.getAccountStatistics();
|
||||
assertNotNull(metadata);
|
||||
assertTrue(metadata.getContainerCount() >= initialContainerCount);
|
||||
metadata = context.getApi().getAccountStatistics();
|
||||
assertNotNull(metadata);
|
||||
assertTrue(metadata.getContainerCount() >= initialContainerCount);
|
||||
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerName).get(10, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteContainer() throws Exception {
|
||||
assertTrue(connection.deleteContainerIfEmpty("does-not-exist").get(10, TimeUnit.SECONDS));
|
||||
|
||||
String containerName = bucketPrefix + ".testDeleteContainer";
|
||||
assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerName).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(context.getApi().deleteContainerIfEmpty(containerName)
|
||||
.get(10, TimeUnit.SECONDS));
|
||||
} finally {
|
||||
returnContainer(containerPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutContainers() throws Exception {
|
||||
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
|
||||
SortedSet<ContainerMetadata> response = connection
|
||||
.listContainers(ListContainerOptions.Builder.afterMarker(
|
||||
containerName1.substring(0, containerName1.length() - 1)).maxResults(1));
|
||||
assertNotNull(response);
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), bucketPrefix + ".hello");
|
||||
|
||||
String containerName2 = bucketPrefix + "?should-be-illegal-question-char";
|
||||
String containerName = getContainerName();
|
||||
try {
|
||||
connection.createContainer(containerName2).get(10, TimeUnit.MILLISECONDS);
|
||||
fail("Should not be able to create container with illegal '?' character");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String containerName1 = containerName + ".hello";
|
||||
assertTrue(context.getApi().createContainer(containerName1).get(10, TimeUnit.SECONDS));
|
||||
// List only the container just created, using a marker with the container name less 1 char
|
||||
SortedSet<ContainerMetadata> response = context.getApi().listContainers(
|
||||
ListContainerOptions.Builder.afterMarker(
|
||||
containerName1.substring(0, containerName1.length() - 1)).maxResults(1))
|
||||
.get(10, TimeUnit.SECONDS);
|
||||
assertNotNull(response);
|
||||
assertEquals(response.size(), 1);
|
||||
assertEquals(response.first().getName(), containerName + ".hello");
|
||||
|
||||
// TODO: Should throw a specific exception, not UndeclaredThrowableException
|
||||
try {
|
||||
connection.createContainer(bucketPrefix + "/illegal-slash-char").get(10,
|
||||
TimeUnit.MILLISECONDS);
|
||||
fail("Should not be able to create container with illegal '/' character");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
String containerName2 = containerName + "?should-be-illegal-question-char";
|
||||
try {
|
||||
context.getApi().createContainer(containerName2).get(10, TimeUnit.MILLISECONDS);
|
||||
fail("Should not be able to create container with illegal '?' character");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerName1).get(10, TimeUnit.SECONDS));
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerName2).get(10, TimeUnit.SECONDS));
|
||||
// TODO: Should throw a specific exception, not UndeclaredThrowableException
|
||||
try {
|
||||
context.getApi().createContainer(containerName + "/illegal-slash-char").get(10,
|
||||
TimeUnit.MILLISECONDS);
|
||||
fail("Should not be able to create container with illegal '/' character");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
assertTrue(context.getApi().deleteContainerIfEmpty(containerName1).get(10,
|
||||
TimeUnit.SECONDS));
|
||||
assertTrue(context.getApi().deleteContainerIfEmpty(containerName2).get(10,
|
||||
TimeUnit.SECONDS));
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
}
|
||||
}
|
||||
|
||||
public void testListContainerPath() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
String containerName = bucketPrefix + ".testList";
|
||||
|
||||
String containerName = getContainerName();
|
||||
try {
|
||||
assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS));
|
||||
|
||||
String data = "foo";
|
||||
|
||||
connection.putObject(containerName, newCFObject(data, "foo")).get(10, TimeUnit.SECONDS);
|
||||
connection.putObject(containerName, newCFObject(data, "path/bar")).get(10, TimeUnit.SECONDS);
|
||||
context.getApi().putObject(containerName, newCFObject(data, "foo")).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
context.getApi().putObject(containerName, newCFObject(data, "path/bar")).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
|
||||
BoundedSortedSet<ObjectInfo> container = connection.listObjects(containerName,
|
||||
BoundedSortedSet<ObjectInfo> container = context.getApi().listObjects(containerName,
|
||||
underPath("")).get(10, TimeUnit.SECONDS);
|
||||
assert !container.isTruncated();
|
||||
assertEquals(container.size(), 1);
|
||||
assertEquals(container.first().getName(), "foo");
|
||||
container = connection.listObjects(containerName, underPath("path")).get(10,
|
||||
container = context.getApi().listObjects(containerName, underPath("path")).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assert !container.isTruncated();
|
||||
assertEquals(container.size(), 1);
|
||||
assertEquals(container.first().getName(), "path/bar");
|
||||
} finally {
|
||||
connection.removeObject(containerName, "foo").get(10, TimeUnit.SECONDS);
|
||||
connection.removeObject(containerName, "apps/foo").get(10, TimeUnit.SECONDS);
|
||||
|
||||
connection.deleteContainerIfEmpty(containerName).get(10, TimeUnit.SECONDS);
|
||||
returnContainer(containerName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObjectOperations() throws Exception {
|
||||
String containerName = bucketPrefix + ".testObjectOperations";
|
||||
|
||||
assertTrue(connection.createContainer(containerName).get(10, TimeUnit.SECONDS));
|
||||
|
||||
// Test PUT with string data, ETag hash, and a piece of metadata
|
||||
String data = "Here is my data";
|
||||
String key = "object";
|
||||
CFObject object = newCFObject(data, key);
|
||||
byte[] md5 = object.getInfo().getHash();
|
||||
String newEtag = connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo()
|
||||
.getHash()));
|
||||
|
||||
// Test HEAD of missing object
|
||||
String containerName = getContainerName();
|
||||
try {
|
||||
connection.getObjectInfo(containerName, "non-existent-object");
|
||||
assert false;
|
||||
} catch (KeyNotFoundException e) {
|
||||
// Test PUT with string data, ETag hash, and a piece of metadata
|
||||
String data = "Here is my data";
|
||||
String key = "object";
|
||||
CFObject object = newCFObject(data, key);
|
||||
byte[] md5 = object.getInfo().getHash();
|
||||
String newEtag = context.getApi().putObject(containerName, object).get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo().getHash()));
|
||||
|
||||
// Test HEAD of missing object
|
||||
try {
|
||||
context.getApi().getObjectInfo(containerName, "non-existent-object");
|
||||
assert false;
|
||||
} catch (KeyNotFoundException e) {
|
||||
}
|
||||
|
||||
// Test HEAD of object
|
||||
MutableObjectInfoWithMetadata metadata = context.getApi().getObjectInfo(containerName,
|
||||
object.getInfo().getName());
|
||||
// TODO assertEquals(metadata.getName(), object.getMetadata().getName());
|
||||
assertEquals(metadata.getBytes(), new Long(data.length()));
|
||||
assertEquals(metadata.getContentType(), "text/plain");
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo().getHash()));
|
||||
assertEquals(metadata.getHash(), HttpUtils.fromHexString(newEtag));
|
||||
assertEquals(metadata.getMetadata().entrySet().size(), 1);
|
||||
assertEquals(metadata.getMetadata().get("metadata"), "metadata-value");
|
||||
|
||||
// // Test POST to update object's metadata
|
||||
Map<String, String> userMetadata = Maps.newHashMap();
|
||||
userMetadata.put("New-Metadata-1", "value-1");
|
||||
userMetadata.put("New-Metadata-2", "value-2");
|
||||
assertTrue(context.getApi().setObjectInfo(containerName, object.getInfo().getName(),
|
||||
userMetadata));
|
||||
|
||||
// Test GET of missing object
|
||||
try {
|
||||
context.getApi().getObject(containerName, "non-existent-object").get(10,
|
||||
TimeUnit.SECONDS);
|
||||
assert false;
|
||||
} catch (KeyNotFoundException e) {
|
||||
}
|
||||
// Test GET of object (including updated metadata)
|
||||
CFObject getBlob = context.getApi().getObject(containerName, object.getInfo().getName())
|
||||
.get(120, TimeUnit.SECONDS);
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data);
|
||||
// TODO assertEquals(getBlob.getName(), object.getMetadata().getName());
|
||||
assertEquals(getBlob.getContentLength(), new Long(data.length()));
|
||||
assertEquals(getBlob.getInfo().getContentType(), "text/plain");
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils
|
||||
.toHexString(getBlob.getInfo().getHash()));
|
||||
assertEquals(HttpUtils.fromHexString(newEtag), getBlob.getInfo().getHash());
|
||||
assertEquals(getBlob.getInfo().getMetadata().entrySet().size(), 2);
|
||||
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-1"), "value-1");
|
||||
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-2"), "value-2");
|
||||
|
||||
// Test PUT with invalid ETag (as if object's data was corrupted in transit)
|
||||
String correctEtag = newEtag;
|
||||
String incorrectEtag = "0" + correctEtag.substring(1);
|
||||
object.getInfo().setHash(HttpUtils.fromHexString(incorrectEtag));
|
||||
try {
|
||||
context.getApi().putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
||||
} catch (Throwable e) {
|
||||
assertEquals(e.getCause().getClass(), HttpResponseException.class);
|
||||
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 422);
|
||||
}
|
||||
|
||||
// Test PUT chunked/streamed upload with data of "unknown" length
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
|
||||
CFObject blob = context.getApi().newCFObject();
|
||||
blob.getInfo().setName("chunked-object");
|
||||
blob.setData(bais);
|
||||
newEtag = context.getApi().putObject(containerName, blob).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils
|
||||
.toHexString(getBlob.getInfo().getHash()));
|
||||
|
||||
// Test GET with options
|
||||
// Non-matching ETag
|
||||
try {
|
||||
context.getApi().getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
assertEquals(e.getCause().getClass(), HttpResponseException.class);
|
||||
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 304);
|
||||
}
|
||||
|
||||
// Matching ETag
|
||||
getBlob = context.getApi().getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS);
|
||||
assertEquals(getBlob.getInfo().getHash(), HttpUtils.fromHexString(newEtag));
|
||||
getBlob = context.getApi().getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.startAt(8)).get(120, TimeUnit.SECONDS);
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8));
|
||||
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
}
|
||||
|
||||
// Test HEAD of object
|
||||
MutableObjectInfoWithMetadata metadata = connection.getObjectInfo(containerName, object.getInfo()
|
||||
.getName());
|
||||
// TODO assertEquals(metadata.getName(), object.getMetadata().getName());
|
||||
assertEquals(metadata.getBytes(), new Long(data.length()));
|
||||
assertEquals(metadata.getContentType(), "text/plain");
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(object.getInfo()
|
||||
.getHash()));
|
||||
assertEquals(metadata.getHash(), HttpUtils.fromHexString(newEtag));
|
||||
assertEquals(metadata.getMetadata().entrySet().size(), 1);
|
||||
assertEquals(metadata.getMetadata().get("metadata"), "metadata-value");
|
||||
|
||||
// // Test POST to update object's metadata
|
||||
Map<String, String> userMetadata = Maps.newHashMap();
|
||||
userMetadata.put("New-Metadata-1", "value-1");
|
||||
userMetadata.put("New-Metadata-2", "value-2");
|
||||
assertTrue(connection.setObjectMetadata(containerName, object.getInfo().getName(),
|
||||
userMetadata));
|
||||
|
||||
// Test GET of missing object
|
||||
try {
|
||||
connection.getObject(containerName, "non-existent-object").get(10, TimeUnit.SECONDS);
|
||||
assert false;
|
||||
} catch (KeyNotFoundException e) {
|
||||
}
|
||||
// Test GET of object (including updated metadata)
|
||||
CFObject getBlob = connection.getObject(containerName, object.getInfo().getName()).get(120,
|
||||
TimeUnit.SECONDS);
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data);
|
||||
// TODO assertEquals(getBlob.getName(), object.getMetadata().getName());
|
||||
assertEquals(getBlob.getContentLength(), new Long(data.length()));
|
||||
assertEquals(getBlob.getInfo().getContentType(), "text/plain");
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getInfo()
|
||||
.getHash()));
|
||||
assertEquals(HttpUtils.fromHexString(newEtag), getBlob.getInfo().getHash());
|
||||
assertEquals(getBlob.getInfo().getMetadata().entrySet().size(), 2);
|
||||
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-1"), "value-1");
|
||||
assertEquals(getBlob.getInfo().getMetadata().get("new-metadata-2"), "value-2");
|
||||
|
||||
// Test PUT with invalid ETag (as if object's data was corrupted in transit)
|
||||
String correctEtag = newEtag;
|
||||
String incorrectEtag = "0" + correctEtag.substring(1);
|
||||
object.getInfo().setHash(HttpUtils.fromHexString(incorrectEtag));
|
||||
try {
|
||||
connection.putObject(containerName, object).get(10, TimeUnit.SECONDS);
|
||||
} catch (Throwable e) {
|
||||
assertEquals(e.getCause().getClass(), HttpResponseException.class);
|
||||
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 422);
|
||||
}
|
||||
|
||||
// Test PUT chunked/streamed upload with data of "unknown" length
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(data.getBytes("UTF-8"));
|
||||
CFObject blob = connection.newCFObject();
|
||||
blob.getInfo().setName("chunked-object");
|
||||
blob.setData(bais);
|
||||
newEtag = connection.putObject(containerName, blob).get(10, TimeUnit.SECONDS);
|
||||
assertEquals(HttpUtils.toHexString(md5), HttpUtils.toHexString(getBlob.getInfo()
|
||||
.getHash()));
|
||||
|
||||
// Test GET with options
|
||||
// Non-matching ETag
|
||||
try {
|
||||
connection.getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.ifETagDoesntMatch(newEtag)).get(120, TimeUnit.SECONDS);
|
||||
} catch (Exception e) {
|
||||
assertEquals(e.getCause().getClass(), HttpResponseException.class);
|
||||
assertEquals(((HttpResponseException) e.getCause()).getResponse().getStatusCode(), 304);
|
||||
}
|
||||
|
||||
// Matching ETag
|
||||
getBlob = connection.getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.ifETagMatches(newEtag)).get(120, TimeUnit.SECONDS);
|
||||
assertEquals(getBlob.getInfo().getHash(), HttpUtils.fromHexString(newEtag));
|
||||
getBlob = connection.getObject(containerName, object.getInfo().getName(),
|
||||
GetOptions.Builder.startAt(8)).get(120, TimeUnit.SECONDS);
|
||||
assertEquals(IOUtils.toString((InputStream) getBlob.getData()), data.substring(8));
|
||||
|
||||
connection.removeObject(containerName, "object").get(10, TimeUnit.SECONDS);
|
||||
connection.removeObject(containerName, "chunked-object").get(10, TimeUnit.SECONDS);
|
||||
|
||||
assertTrue(connection.deleteContainerIfEmpty(containerName).get(10, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private CFObject newCFObject(String data, String key) throws IOException {
|
||||
CFObject object = connection.newCFObject();
|
||||
CFObject object = context.getApi().newCFObject();
|
||||
object.getInfo().setName(key);
|
||||
object.setData(data);
|
||||
object.generateMD5();
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.StubCloudFilesClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.internal.StubCloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants;
|
||||
import org.jclouds.rackspace.config.RackspaceAuthenticationRestModule;
|
||||
|
@ -72,7 +72,7 @@ public class CloudFilesContextBuilderTest {
|
|||
|
||||
public void testBuildContext() {
|
||||
RestContext<CloudFilesClient> context = newBuilder().withModules(
|
||||
new StubCloudFilesClientModule(), new StubRackspaceAuthenticationModule())
|
||||
new CloudFilesStubClientModule(), new StubRackspaceAuthenticationModule())
|
||||
.buildContext();
|
||||
assertEquals(context.getClass(), RestContextImpl.class);
|
||||
assertEquals(context.getApi().getClass(), StubCloudFilesClient.class);
|
||||
|
@ -81,7 +81,7 @@ public class CloudFilesContextBuilderTest {
|
|||
}
|
||||
|
||||
public void testBuildInjector() {
|
||||
Injector i = newBuilder().withModules(new StubCloudFilesClientModule(),
|
||||
Injector i = newBuilder().withModules(new CloudFilesStubClientModule(),
|
||||
new StubRackspaceAuthenticationModule()).buildInjector();
|
||||
assert i.getInstance(Key.get(new TypeLiteral<RestContext<CloudFilesClient>>() {
|
||||
})) != null;
|
||||
|
|
|
@ -27,9 +27,10 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import org.jclouds.concurrent.WithinThreadExecutorService;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesContextModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.StubCloudFilesClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.reference.CloudFilesConstants;
|
||||
import org.jclouds.rest.RestContext;
|
||||
import org.jclouds.rest.internal.RestContextImpl;
|
||||
|
@ -49,8 +50,8 @@ public class CloudFilesContextModuleTest {
|
|||
|
||||
Injector createInjector() {
|
||||
return Guice.createInjector(new ExecutorServiceModule(new WithinThreadExecutorService()),
|
||||
new StubCloudFilesClientModule(), new StubRackspaceAuthenticationModule(),
|
||||
new CloudFilesContextModule() {
|
||||
new CloudFilesStubClientModule(), new JDKLoggingModule(),
|
||||
new StubRackspaceAuthenticationModule(), new CloudFilesContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore;
|
||||
|
||||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.internal.BlobImpl;
|
||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesRestClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.internal.CFObjectImpl;
|
||||
import org.jclouds.rackspace.cloudfiles.internal.StubCloudFilesClient;
|
||||
import org.jclouds.rackspace.reference.RackspaceConstants;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* Tests behavior of modules configured in CloudFilesContextBuilder
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudfiles.CloudFilesContextBuilderTest")
|
||||
public class CloudFilesBlobStoreContextBuilderTest {
|
||||
|
||||
public void testNewBuilder() {
|
||||
CloudFilesBlobStoreContextBuilder builder = newBuilder();
|
||||
assertEquals(builder.getProperties().getProperty(PROPERTY_USER_METADATA_PREFIX),
|
||||
"X-Object-Meta-");
|
||||
assertEquals(builder.getProperties().getProperty(RackspaceConstants.PROPERTY_RACKSPACE_USER),
|
||||
"id");
|
||||
assertEquals(builder.getProperties().getProperty(RackspaceConstants.PROPERTY_RACKSPACE_KEY),
|
||||
"secret");
|
||||
}
|
||||
|
||||
private CloudFilesBlobStoreContextBuilder newBuilder() {
|
||||
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder("id",
|
||||
"secret").build()).withModules(new CloudFilesStubClientModule(),
|
||||
new StubRackspaceAuthenticationModule());
|
||||
}
|
||||
|
||||
public void testBuildContext() {
|
||||
BlobStoreContext<CloudFilesClient> context = newBuilder().buildContext();
|
||||
assertEquals(context.getClass(), BlobStoreContextImpl.class);
|
||||
assertEquals(context.getApi().getClass(), StubCloudFilesClient.class);
|
||||
assertEquals(context.getBlobStore().getClass(), CloudFilesBlobStore.class);
|
||||
assertEquals(context.getApi().newCFObject().getClass(), CFObjectImpl.class);
|
||||
assertEquals(context.getBlobStore().newBlob().getClass(), BlobImpl.class);
|
||||
assertEquals(context.getAccount(), "id");
|
||||
assertEquals(context.getEndPoint(), URI.create("http://localhost/rackspacestub/cloudfiles"));
|
||||
}
|
||||
|
||||
public void testBuildInjector() {
|
||||
Injector i = newBuilder().buildInjector();
|
||||
assert i.getInstance(Key.get(new TypeLiteral<BlobStoreContext<CloudFilesClient>>() {
|
||||
})) != null;
|
||||
assert i.getInstance(CFObject.class) != null;
|
||||
assert i.getInstance(Blob.class) != null;
|
||||
}
|
||||
|
||||
protected void testAddContextModule() {
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
CloudFilesBlobStoreContextBuilder builder = newBuilder();
|
||||
builder.addContextModule(modules);
|
||||
assertEquals(modules.size(), 1);
|
||||
assertEquals(modules.get(0).getClass(), CloudFilesBlobStoreContextModule.class);
|
||||
}
|
||||
|
||||
protected void addClientModule() {
|
||||
List<Module> modules = new ArrayList<Module>();
|
||||
CloudFilesBlobStoreContextBuilder builder = newBuilder();
|
||||
builder.addClientModule(modules);
|
||||
assertEquals(modules.size(), 1);
|
||||
assertEquals(modules.get(0).getClass(), CloudFilesRestClientModule.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.config;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
||||
import org.jclouds.concurrent.WithinThreadExecutorService;
|
||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
|
||||
import org.jclouds.rackspace.reference.RackspaceConstants;
|
||||
import org.jclouds.util.Jsr330;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudfiles.CloudFilesBlobStoreModuleTest")
|
||||
public class CloudFilesBlobStoreModuleTest {
|
||||
|
||||
Injector createInjector() {
|
||||
return Guice.createInjector(new ExecutorServiceModule(new WithinThreadExecutorService()),
|
||||
new JDKLoggingModule(), new CloudFilesStubClientModule(),
|
||||
new StubRackspaceAuthenticationModule(), new CloudFilesBlobStoreContextModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(
|
||||
Jsr330.named(RackspaceConstants.PROPERTY_RACKSPACE_USER)).to("user");
|
||||
bindConstant().annotatedWith(
|
||||
Jsr330.named(RackspaceConstants.PROPERTY_RACKSPACE_KEY)).to("key");
|
||||
bindConstant().annotatedWith(
|
||||
Jsr330.named(RackspaceConstants.PROPERTY_RACKSPACE_ENDPOINT)).to(
|
||||
"http://localhost");
|
||||
super.configure();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContextImpl() {
|
||||
BlobStoreContext<CloudFilesClient> context = createInjector().getInstance(
|
||||
Key.get(new TypeLiteral<BlobStoreContext<CloudFilesClient>>() {
|
||||
}));
|
||||
assertEquals(context.getClass(), BlobStoreContextImpl.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Murty
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "integration", "live" }, testName = "cloudfiles.CloudFilesBlobIntegrationTest")
|
||||
public class CloudFilesBlobIntegrationTest extends BaseBlobIntegrationTest<CloudFilesClient> {
|
||||
|
||||
@Override
|
||||
@Test(enabled = false)
|
||||
public void testGetTwoRanges() throws InterruptedException, ExecutionException,
|
||||
TimeoutException, IOException {
|
||||
// not supported in cloud files
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Murty
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "live" }, testName = "cloudfiles.CloudFilesBlobLiveTest")
|
||||
public class CloudFilesBlobLiveTest extends BaseBlobLiveTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "integration", "live" }, testName = "cloudfiles.CloudFilesBlobMapIntegrationTest")
|
||||
public class CloudFilesBlobMapIntegrationTest extends BaseBlobMapIntegrationTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author James Murty
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "integration", "live" }, testName = "cloudfiles.CloudFilesContainerIntegrationTest")
|
||||
public class CloudFilesContainerIntegrationTest extends BaseContainerIntegrationTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author James Murty
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "live" }, testName = "cloudfiles.CloudFilesContainerLiveTest")
|
||||
public class CloudFilesContainerLiveTest extends BaseContainerLiveTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "integration", "live" }, testName = "cloudfiles.CloudFilesInputStreamMapIntegrationTest")
|
||||
public class CloudFilesInputStreamMapIntegrationTest extends
|
||||
BaseInputStreamMapIntegrationTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = { "integration", "live" }, testName = "cloudfiles.CloudFilesServiceIntegrationTest")
|
||||
public class CloudFilesServiceIntegrationTest extends BaseServiceIntegrationTest<CloudFilesClient> {
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.integration.internal.BaseTestInitializer;
|
||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||
import org.jclouds.rackspace.StubRackspaceAuthenticationModule;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextBuilder;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStoreContextFactory;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.CloudFilesBlobStorePropertiesBuilder;
|
||||
import org.jclouds.rackspace.cloudfiles.config.CloudFilesStubClientModule;
|
||||
|
||||
import com.google.inject.Module;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CloudFilesTestInitializer extends BaseTestInitializer<CloudFilesClient> {
|
||||
|
||||
@Override
|
||||
protected BlobStoreContext<CloudFilesClient> createLiveContext(Module configurationModule,
|
||||
String url, String app, String account, String key) {
|
||||
return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder(
|
||||
account, key).relaxSSLHostname().build()).withModules(configurationModule,
|
||||
new Log4JLoggingModule()).buildContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlobStoreContext<CloudFilesClient> createStubContext() {
|
||||
return CloudFilesBlobStoreContextFactory.createContext("user", "pass",
|
||||
new StubRackspaceAuthenticationModule(), new CloudFilesStubClientModule());
|
||||
}
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ import com.google.inject.AbstractModule;
|
|||
import com.google.inject.TypeLiteral;
|
||||
|
||||
@ConfiguresRestClient
|
||||
public class StubCloudFilesClientModule extends AbstractModule {
|
||||
public class CloudFilesStubClientModule extends AbstractModule {
|
||||
// must be singleton for all threads and all objects or tests may fail;
|
||||
static final ConcurrentHashMap<String, ConcurrentMap<String, Blob>> map = new ConcurrentHashMap<String, ConcurrentMap<String, Blob>>();
|
||||
|
||||
|
@ -44,7 +44,6 @@ public class StubCloudFilesClientModule extends AbstractModule {
|
|||
|
||||
bind(new TypeLiteral<ConcurrentMap<String, ConcurrentMap<String, Blob>>>() {
|
||||
}).toInstance(map);
|
||||
|
||||
bind(new TypeLiteral<CloudFilesClient>() {
|
||||
}).to(new TypeLiteral<StubCloudFilesClient>() {
|
||||
}).asEagerSingleton();
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.http.functions.config.ParserModule;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ParseContainerCDNMetadataListFromJsonResponse}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudfiles.ParseContainerCDNMetadataListFromJsonResponseTest")
|
||||
public class ParseContainerCDNMetadataListFromJsonResponseTest {
|
||||
Injector i = Guice.createInjector(new ParserModule());
|
||||
|
||||
@Test
|
||||
public void testApplyInputStream() {
|
||||
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_cdn.json");
|
||||
List<ContainerCDNMetadata> expects = ImmutableList.of(
|
||||
|
||||
new ContainerCDNMetadata("adriancole-blobstore.testCDNOperationsContainerWithCDN", false,
|
||||
3600, URI.create("http://c0354712.cdn.cloudfiles.rackspacecloud.com")),
|
||||
new ContainerCDNMetadata("adriancole-blobstore5", true, 28800, URI
|
||||
.create("http://c0404671.cdn.cloudfiles.rackspacecloud.com")),
|
||||
new ContainerCDNMetadata("adriancole-cfcdnint.testCDNOperationsContainerWithCDN",
|
||||
false, 3600, URI
|
||||
.create("http://c0320431.cdn.cloudfiles.rackspacecloud.com")));
|
||||
ParseContainerCDNMetadataListFromJsonResponse parser = new ParseContainerCDNMetadataListFromJsonResponse(
|
||||
i.getInstance(Gson.class));
|
||||
assertEquals(parser.apply(is), expects);
|
||||
}
|
||||
|
||||
}
|
|
@ -47,8 +47,8 @@ import com.google.inject.util.Jsr330;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudfiles.ParseObjectMetadataFromHeadersTest")
|
||||
public class ParseObjectMetadataFromHeadersTest {
|
||||
@Test(groups = "unit", testName = "cloudfiles.ParseObjectInfoFromHeadersTest")
|
||||
public class ParseObjectInfoFromHeadersTest {
|
||||
Injector i = Guice.createInjector(new ParserModule(), new AbstractModule() {
|
||||
|
||||
@Override
|
||||
|
@ -60,7 +60,7 @@ public class ParseObjectMetadataFromHeadersTest {
|
|||
});
|
||||
|
||||
public void testEtagCaseIssue() {
|
||||
ParseObjectMetadataFromHeaders parser = i.getInstance(ParseObjectMetadataFromHeaders.class);
|
||||
ParseObjectInfoFromHeaders parser = i.getInstance(ParseObjectInfoFromHeaders.class);
|
||||
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/test")).atLeastOnce();
|
||||
replay(request);
|
|
@ -44,12 +44,12 @@ import com.google.inject.Guice;
|
|||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ParseBlobMetadataListFromJsonResponseTest}
|
||||
* Tests behavior of {@code ParseObjectInfoListFromJsonResponseTest}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudfiles.ParseBlobMetadataListFromJsonResponseTest")
|
||||
public class ParseBlobMetadataListFromJsonResponseTest {
|
||||
@Test(groups = "unit", testName = "cloudfiles.ParseObjectInfoListFromJsonResponseTest")
|
||||
public class ParseObjectInfoListFromJsonResponseTest {
|
||||
|
||||
Injector i = Guice.createInjector(new ParserModule());
|
||||
|
|
@ -23,13 +23,32 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudfiles.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BoundedSortedSet;
|
||||
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
||||
import org.jclouds.blobstore.integration.internal.StubBlobStore;
|
||||
import org.jclouds.blobstore.integration.internal.StubBlobStore.FutureBase;
|
||||
import org.jclouds.blobstore.options.ListOptions;
|
||||
import org.jclouds.concurrent.FutureFunctionWrapper;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.logging.Logger.LoggerFactory;
|
||||
import org.jclouds.rackspace.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ListContainerOptionsToListOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectInfo;
|
||||
import org.jclouds.rackspace.cloudfiles.blobstore.functions.ResourceToObjectList;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.AccountMetadata;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.CFObject;
|
||||
import org.jclouds.rackspace.cloudfiles.domain.ContainerCDNMetadata;
|
||||
|
@ -39,34 +58,72 @@ import org.jclouds.rackspace.cloudfiles.domain.ObjectInfo;
|
|||
import org.jclouds.rackspace.cloudfiles.options.ListCdnContainerOptions;
|
||||
import org.jclouds.rackspace.cloudfiles.options.ListContainerOptions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CloudFilesClient} which keeps all data in a local Map object.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class StubCloudFilesClient implements CloudFilesClient {
|
||||
private final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
|
||||
private final StubBlobStore blobStore;
|
||||
private final LoggerFactory logFactory;
|
||||
private final CFObject.Factory objectProvider;
|
||||
private final ObjectToBlob object2Blob;
|
||||
private final BlobToObject blob2Object;
|
||||
private final ResourceToObjectInfo blob2ObjectInfo;
|
||||
private final ListContainerOptionsToListOptions container2ContainerListOptions;
|
||||
private final ResourceToObjectList resource2ObjectList;
|
||||
|
||||
@Inject
|
||||
private StubCloudFilesClient(StubBlobStore blobStore, LoggerFactory logFactory,
|
||||
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
||||
CFObject.Factory objectProvider,
|
||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob,
|
||||
BlobToObject blob2Object, ResourceToObjectInfo blob2ObjectInfo,
|
||||
ListContainerOptionsToListOptions container2ContainerListOptions,
|
||||
ResourceToObjectList resource2ContainerList) {
|
||||
this.blobStore = blobStore;
|
||||
this.logFactory = logFactory;
|
||||
this.objectProvider = objectProvider;
|
||||
this.httpGetOptionsConverter = httpGetOptionsConverter;
|
||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.blob2ObjectInfo = checkNotNull(blob2ObjectInfo, "blob2ObjectInfo");
|
||||
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
||||
"container2ContainerListOptions");
|
||||
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
|
||||
}
|
||||
|
||||
protected <F, T> Future<T> wrapFuture(Future<? extends F> future, Function<F, T> function) {
|
||||
return new FutureFunctionWrapper<F, T>(future, function, logFactory.getLogger(function
|
||||
.getClass().getName()));
|
||||
}
|
||||
|
||||
public boolean containerExists(String container) {
|
||||
throw new UnsupportedOperationException();
|
||||
return blobStore.getContainerToBlobs().containsKey(container);
|
||||
}
|
||||
|
||||
public Future<Boolean> createContainer(String container) {
|
||||
throw new UnsupportedOperationException();
|
||||
return blobStore.createContainer(container);
|
||||
}
|
||||
|
||||
public Future<Boolean> deleteContainerIfEmpty(String container) {
|
||||
throw new UnsupportedOperationException();
|
||||
return blobStore.deleteContainerImpl(container);
|
||||
}
|
||||
|
||||
public boolean disableCDN(String container) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String enableCDN(String container, Long ttl) {
|
||||
public URI enableCDN(String container, Long ttl) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String enableCDN(String container) {
|
||||
public URI enableCDN(String container) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -79,44 +136,58 @@ public class StubCloudFilesClient implements CloudFilesClient {
|
|||
}
|
||||
|
||||
public Future<CFObject> getObject(String container, String key, GetOptions... options) {
|
||||
throw new UnsupportedOperationException();
|
||||
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
||||
return wrapFuture(blobStore.getBlob(container, key, getOptions), blob2Object);
|
||||
}
|
||||
|
||||
public MutableObjectInfoWithMetadata getObjectInfo(String container, String key) {
|
||||
throw new UnsupportedOperationException();
|
||||
return blob2ObjectInfo.apply(blobStore.blobMetadata(container, key));
|
||||
}
|
||||
|
||||
public SortedSet<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public SortedSet<ContainerMetadata> listContainers(ListContainerOptions... options) {
|
||||
throw new UnsupportedOperationException();
|
||||
public Future<? extends SortedSet<ContainerMetadata>> listContainers(
|
||||
ListContainerOptions... options) {
|
||||
return new FutureBase<SortedSet<ContainerMetadata>>() {
|
||||
|
||||
public SortedSet<ContainerMetadata> get() throws InterruptedException, ExecutionException {
|
||||
return Sets.newTreeSet(Iterables.transform(blobStore.getContainerToBlobs().keySet(),
|
||||
new Function<String, ContainerMetadata>() {
|
||||
public ContainerMetadata apply(String name) {
|
||||
return new ContainerMetadata(name, -1, -1);
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public Future<BoundedSortedSet<ObjectInfo>> listObjects(String container,
|
||||
ListContainerOptions... options) {
|
||||
throw new UnsupportedOperationException();
|
||||
ListContainerOptions... optionsList) {
|
||||
ListOptions options = container2ContainerListOptions.apply(optionsList);
|
||||
return wrapFuture(blobStore.list(container, options), resource2ObjectList);
|
||||
}
|
||||
|
||||
public Future<String> putObject(String container, CFObject object) {
|
||||
throw new UnsupportedOperationException();
|
||||
return blobStore.putBlob(container, object2Blob.apply(object));
|
||||
}
|
||||
|
||||
public Future<Void> removeObject(String container, String key) {
|
||||
return blobStore.removeBlob(container, key);
|
||||
}
|
||||
|
||||
public boolean setObjectInfo(String container, String key, Map<String, String> userMetadata) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean setObjectMetadata(String container, String key, Map<String, String> userMetadata) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String updateCDN(String container, Long ttl) {
|
||||
public URI updateCDN(String container, Long ttl) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public CFObject newCFObject() {
|
||||
throw new UnsupportedOperationException();
|
||||
return objectProvider.create(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
{"name":"adriancole-blobstore.testCDNOperationsContainerWithCDN","cdn_enabled":"false","ttl":3600,"cdn_uri":"http://c0354712.cdn.cloudfiles.rackspacecloud.com,"referrer_acl":"","useragent_acl":"", "log_retention":"false"},
|
||||
{"name":"adriancole-blobstore5","cdn_enabled":"true","ttl":28800,"cdn_uri":"http://c0404671.cdn.cloudfiles.rackspacecloud.com,"referrer_acl":"","useragent_acl":"", "log_retention":"false"},
|
||||
{"name":"adriancole-cfcdnint.testCDNOperationsContainerWithCDN","cdn_enabled":"false","ttl":3600,"cdn_uri":"http://c0320431.cdn.cloudfiles.rackspacecloud.com,"referrer_acl":"","useragent_acl":"", "log_retention":"false"}
|
||||
]
|
|
@ -40,7 +40,7 @@
|
|||
<module>core</module>
|
||||
</modules>
|
||||
<properties>
|
||||
<jclouds.test.initializer>org.jclouds.rackspace.cloudfiles.integration.CloudFilesTestInitializer</jclouds.test.initializer>
|
||||
<jclouds.test.initializer>org.jclouds.rackspace.cloudfiles.blobstore.integration.CloudFilesTestInitializer</jclouds.test.initializer>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
Loading…
Reference in New Issue