diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/CloudFilesClient.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/CloudFilesClient.java index 922cc3fb2e..688dcd2709 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/CloudFilesClient.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/CloudFilesClient.java @@ -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 listContainers(ListContainerOptions... options); + Future> 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 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 getObject(@PathParam("container") String container, @PathParam("name") String name, - GetOptions... options); + Future 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 removeObject(@PathParam("container") String container, @PathParam("name") String name); + Future removeObject(@PathParam("container") String container, + @PathParam("name") String name); } diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java new file mode 100644 index 0000000000..ef8d3f179c --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStore.java @@ -0,0 +1,181 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 Future wrapFuture(Future future, Function function) { + return new FutureFunctionWrapper(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 clearContainer(final String container) { + return service.submit(new Callable() { + + public Void call() throws Exception { + clearContainerStrategy.execute(container, recursive()); + return null; + } + + }); + } + + public Future createContainer(String container) { + return connection.createContainer(container); + } + + public Future deleteContainer(final String container) { + return service.submit(new Callable() { + + 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 getBlob(String container, String key, + org.jclouds.blobstore.options.GetOptions... optionsList) { + GetOptions httpOptions = blob2ObjectGetOptions.apply(optionsList); + Future returnVal = connection.getObject(container, key, httpOptions); + return wrapFuture(returnVal, object2Blob); + } + + public Future> list() { + return wrapFuture(connection.listContainers(), + new Function, SortedSet>() { + public SortedSet apply(SortedSet from) { + return Sets.newTreeSet(Iterables.transform(from, container2ResourceMd)); + } + }); + } + + public Future> list(String container, + ListOptions... optionsList) { + ListContainerOptions httpOptions = container2ContainerListOptions.apply(optionsList); + Future> returnVal = connection.listObjects(container, httpOptions); + return wrapFuture(returnVal, container2ResourceList); + } + + public Future putBlob(String container, Blob blob) { + return connection.putObject(container, blob2Object.apply(blob)); + } + + public Future removeBlob(String container, String key) { + return connection.removeObject(container, key); + } + + public Blob newBlob() { + return blobFactory.create(null); + } + +} diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilder.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilder.java new file mode 100755 index 0000000000..25c1eb2565 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilder.java @@ -0,0 +1,82 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules 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 { + + public CloudFilesBlobStoreContextBuilder(Properties props) { + super(new TypeLiteral() { + }, 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 modules) { + modules.add(new CloudFilesBlobStoreContextModule()); + } + + @Override + protected void addClientModule(List modules) { + modules.add(new RackspaceAuthenticationRestModule()); + modules.add(new CloudFilesRestClientModule()); + } +} diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextFactory.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextFactory.java new file mode 100755 index 0000000000..6d2143ca0d --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextFactory.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + *

+ * Note that Threadsafe objects will be bound as singletons to the Injector or Context provided. + *

+ *

+ * If no Modules 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 createContext(Properties properties, + Module... modules) { + return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder( + properties).build()).withModules(modules).buildContext(); + } + + public static BlobStoreContext createContext(String user, + String key, Module... modules) { + return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder( + user, key).build()).withModules(modules).buildContext(); + } + + public static BlobStoreContext createContext(URI endpoint, + String user, String key, Module... modules) { + return new CloudFilesBlobStoreContextBuilder(new CloudFilesBlobStorePropertiesBuilder( + user, key).withEndpoint(endpoint).build()).withModules( + modules).buildContext(); + } +} diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStorePropertiesBuilder.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStorePropertiesBuilder.java new file mode 100644 index 0000000000..7231585be5 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStorePropertiesBuilder.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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; + } + +} diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java new file mode 100755 index 0000000000..76b82949fb --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreContextModule.java @@ -0,0 +1,73 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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(blobMapFactory, inputStreamMapFactory, + closer, blobStore, defaultApi, endPoint, account); + } + +} diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java index c94dfb85cb..23b0012be3 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObject.java @@ -13,11 +13,11 @@ import com.google.common.base.Function; */ @Singleton public class BlobToObject implements Function { - 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; } diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectGetOptions.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectGetOptions.java new file mode 100644 index 0000000000..dd53a3e691 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectGetOptions.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + 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; + } +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceList.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceList.java new file mode 100644 index 0000000000..297962bee3 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceList.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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> { + private final ObjectToBlobMetadata object2blobMd; + + @Inject + public ContainerToResourceList(ObjectToBlobMetadata object2blobMd) { + this.object2blobMd = object2blobMd; + } + + public BoundedSortedSet apply(BoundedSortedSet from) { + return new BoundedTreeSet(Iterables.transform(Iterables.transform(from, + object2blobMd), new Function() { + public ResourceMetadata apply(BlobMetadata arg0) { + return arg0; + } + }), from.getPath(), from.getMarker(), from.getMaxResults(), from.isTruncated()); + + } +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceMetadata.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceMetadata.java new file mode 100644 index 0000000000..a773fb498c --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ContainerToResourceMetadata.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + public ResourceMetadata apply(ContainerMetadata from) { + MutableResourceMetadata to = new MutableResourceMetadataImpl(); + to.setName(from.getName()); + to.setType(ResourceType.CONTAINER); + return to; + } +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListContainerOptionsToListOptions.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListContainerOptionsToListOptions.java new file mode 100644 index 0000000000..20fd1b8a57 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListContainerOptionsToListOptions.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + 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; + } + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListOptionsToListContainerOptions.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListOptionsToListContainerOptions.java new file mode 100644 index 0000000000..ef5f651700 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ListOptionsToListContainerOptions.java @@ -0,0 +1,65 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + 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; + } + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java index d9ae838e92..8e0f7981b8 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ObjectToBlobMetadata.java @@ -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 { - public MutableBlobMetadata apply(MutableObjectInfoWithMetadata from) { +public class ObjectToBlobMetadata implements Function { + 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); } diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectInfo.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectInfo.java similarity index 50% rename from rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectInfo.java rename to rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectInfo.java index 3c6b34082f..85f48268a9 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/BlobToObjectInfo.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectInfo.java @@ -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 { - public MutableObjectInfoWithMetadata apply(BlobMetadata base) { +public class ResourceToObjectInfo implements Function { + 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) diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectList.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectList.java new file mode 100644 index 0000000000..7ae86888d9 --- /dev/null +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/blobstore/functions/ResourceToObjectList.java @@ -0,0 +1,62 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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> { + private final ResourceToObjectInfo resource2ObjectMd; + + @Inject + public ResourceToObjectList(ResourceToObjectInfo resource2ObjectMd) { + this.resource2ObjectMd = resource2ObjectMd; + } + + public BoundedSortedSet apply(BoundedSortedSet list) { + + return new BoundedTreeSet(Iterables.transform(list, + new Function() { + + public ObjectInfo apply(ResourceMetadata from) { + return resource2ObjectMd.apply(from); + } + + }), list.getPath(), list.getMarker(), list.getMaxResults(), list.size() == list + .getMaxResults()); + } +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/domain/ContainerCDNMetadata.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/domain/ContainerCDNMetadata.java index fa3380defa..496c771a36 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/domain/ContainerCDNMetadata.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/domain/ContainerCDNMetadata.java @@ -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 { /** 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; + } } diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseCdnUriFromHeaders.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseCdnUriFromHeaders.java index 6fec2dc721..5f43d980aa 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseCdnUriFromHeaders.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseCdnUriFromHeaders.java @@ -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 { +public class ParseCdnUriFromHeaders implements Function { /** * 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); } } \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataFromHeaders.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataFromHeaders.java index b56892a89c..fc23218f0f 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataFromHeaders.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataFromHeaders.java @@ -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 { + Function, 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; + } } \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromGsonResponse.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponse.java similarity index 81% rename from rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromGsonResponse.java rename to rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponse.java index 6c57821117..e5a9da2533 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromGsonResponse.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponse.java @@ -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> +public class ParseContainerCDNMetadataListFromJsonResponse extends ParseJson> { @Inject - public ParseContainerCDNMetadataListFromGsonResponse(Gson gson) { + public ParseContainerCDNMetadataListFromJsonResponse(Gson gson) { super(gson); } public SortedSet 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>() { }.getType(); try { diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectFromHeadersAndHttpContent.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectFromHeadersAndHttpContent.java index cfb941c54e..94662fee2d 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectFromHeadersAndHttpContent.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectFromHeadersAndHttpContent.java @@ -45,11 +45,11 @@ import com.google.common.base.Function; public class ParseObjectFromHeadersAndHttpContent implements Function, 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; diff --git a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeaders.java b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeaders.java similarity index 86% rename from rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeaders.java rename to rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeaders.java index 5c4c292f0a..4c82ff0c35 100644 --- a/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeaders.java +++ b/rackspace/cloudfiles/core/src/main/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeaders.java @@ -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, 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; } /** diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java index 1f0227c6b8..085a81aba8 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesClientLiveTest.java @@ -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 { /** * 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 cdnMetadataList = connection.listCDNContainers(); - assertTrue(cdnMetadataList.size() >= 1); - assertTrue(Iterables.any(cdnMetadataList, new Predicate() { - 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() { - 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 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() { + 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 response = connection.listContainers(); - assertNotNull(response); - long initialContainerCount = response.size(); - assertTrue(initialContainerCount >= 0); + String containerPrefix = getContainerName(); + try { + SortedSet 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 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 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 container = connection.listObjects(containerName, + BoundedSortedSet 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 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 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(); diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextBuilderTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextBuilderTest.java index 291ad50d44..d45d21a9d2 100755 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextBuilderTest.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextBuilderTest.java @@ -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 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>() { })) != null; diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextModuleTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextModuleTest.java index 0c25019c99..a070a5c94b 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextModuleTest.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/CloudFilesContextModuleTest.java @@ -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( diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilderTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilderTest.java new file mode 100644 index 0000000000..89fda8f42e --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/CloudFilesBlobStoreContextBuilderTest.java @@ -0,0 +1,112 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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>() { + })) != null; + assert i.getInstance(CFObject.class) != null; + assert i.getInstance(Blob.class) != null; + } + + protected void testAddContextModule() { + List modules = new ArrayList(); + CloudFilesBlobStoreContextBuilder builder = newBuilder(); + builder.addContextModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), CloudFilesBlobStoreContextModule.class); + } + + protected void addClientModule() { + List modules = new ArrayList(); + CloudFilesBlobStoreContextBuilder builder = newBuilder(); + builder.addClientModule(modules); + assertEquals(modules.size(), 1); + assertEquals(modules.get(0).getClass(), CloudFilesRestClientModule.class); + } + +} diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreModuleTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreModuleTest.java new file mode 100755 index 0000000000..7cc2236780 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/config/CloudFilesBlobStoreModuleTest.java @@ -0,0 +1,77 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 context = createInjector().getInstance( + Key.get(new TypeLiteral>() { + })); + assertEquals(context.getClass(), BlobStoreContextImpl.class); + } + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobIntegrationTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobIntegrationTest.java new file mode 100755 index 0000000000..616def9be4 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobIntegrationTest.java @@ -0,0 +1,49 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + @Override + @Test(enabled = false) + public void testGetTwoRanges() throws InterruptedException, ExecutionException, + TimeoutException, IOException { + // not supported in cloud files + } + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobLiveTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobLiveTest.java new file mode 100644 index 0000000000..eea21fabed --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobLiveTest.java @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobMapIntegrationTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobMapIntegrationTest.java new file mode 100644 index 0000000000..6278abfada --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesBlobMapIntegrationTest.java @@ -0,0 +1,36 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerIntegrationTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerIntegrationTest.java new file mode 100755 index 0000000000..a73c98d465 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerIntegrationTest.java @@ -0,0 +1,37 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerLiveTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerLiveTest.java new file mode 100644 index 0000000000..24db19a90d --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesContainerLiveTest.java @@ -0,0 +1,37 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesInputStreamMapIntegrationTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesInputStreamMapIntegrationTest.java new file mode 100644 index 0000000000..c688b51130 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesInputStreamMapIntegrationTest.java @@ -0,0 +1,37 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesServiceIntegrationTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesServiceIntegrationTest.java new file mode 100644 index 0000000000..90e1ac56c3 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesServiceIntegrationTest.java @@ -0,0 +1,36 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesTestInitializer.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesTestInitializer.java new file mode 100644 index 0000000000..cb33918c11 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/blobstore/integration/CloudFilesTestInitializer.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 { + + @Override + protected BlobStoreContext 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 createStubContext() { + return CloudFilesBlobStoreContextFactory.createContext("user", "pass", + new StubRackspaceAuthenticationModule(), new CloudFilesStubClientModule()); + } + +} \ No newline at end of file diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/StubCloudFilesClientModule.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/CloudFilesStubClientModule.java similarity index 96% rename from rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/StubCloudFilesClientModule.java rename to rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/CloudFilesStubClientModule.java index ac5d58f386..f46aed8d90 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/StubCloudFilesClientModule.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/config/CloudFilesStubClientModule.java @@ -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> map = new ConcurrentHashMap>(); @@ -44,7 +44,6 @@ public class StubCloudFilesClientModule extends AbstractModule { bind(new TypeLiteral>>() { }).toInstance(map); - bind(new TypeLiteral() { }).to(new TypeLiteral() { }).asEagerSingleton(); diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponseTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponseTest.java new file mode 100644 index 0000000000..ca27207c9d --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseContainerCDNMetadataListFromJsonResponseTest.java @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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); + } + +} diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeadersTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeadersTest.java similarity index 92% rename from rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeadersTest.java rename to rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeadersTest.java index 426d54fac2..461ef57f47 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectMetadataFromHeadersTest.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoFromHeadersTest.java @@ -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); diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseBlobMetadataListFromJsonResponseTest.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoListFromJsonResponseTest.java similarity index 93% rename from rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseBlobMetadataListFromJsonResponseTest.java rename to rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoListFromJsonResponseTest.java index 1712d6bc31..4e6f89e2f0 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseBlobMetadataListFromJsonResponseTest.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseObjectInfoListFromJsonResponseTest.java @@ -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()); diff --git a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/internal/StubCloudFilesClient.java b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/internal/StubCloudFilesClient.java index 061f6060b6..06df580c29 100644 --- a/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/internal/StubCloudFilesClient.java +++ b/rackspace/cloudfiles/core/src/test/java/org/jclouds/rackspace/cloudfiles/internal/StubCloudFilesClient.java @@ -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> 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 Future wrapFuture(Future future, Function function) { + return new FutureFunctionWrapper(future, function, logFactory.getLogger(function + .getClass().getName())); + } public boolean containerExists(String container) { - throw new UnsupportedOperationException(); + return blobStore.getContainerToBlobs().containsKey(container); } public Future createContainer(String container) { - throw new UnsupportedOperationException(); + return blobStore.createContainer(container); } public Future 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 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 listCDNContainers(ListCdnContainerOptions... options) { throw new UnsupportedOperationException(); } - public SortedSet listContainers(ListContainerOptions... options) { - throw new UnsupportedOperationException(); + public Future> listContainers( + ListContainerOptions... options) { + return new FutureBase>() { + + public SortedSet get() throws InterruptedException, ExecutionException { + return Sets.newTreeSet(Iterables.transform(blobStore.getContainerToBlobs().keySet(), + new Function() { + public ContainerMetadata apply(String name) { + return new ContainerMetadata(name, -1, -1); + } + + })); + } + }; } public Future> listObjects(String container, - ListContainerOptions... options) { - throw new UnsupportedOperationException(); + ListContainerOptions... optionsList) { + ListOptions options = container2ContainerListOptions.apply(optionsList); + return wrapFuture(blobStore.list(container, options), resource2ObjectList); } public Future putObject(String container, CFObject object) { - throw new UnsupportedOperationException(); + return blobStore.putBlob(container, object2Blob.apply(object)); } public Future removeObject(String container, String key) { + return blobStore.removeBlob(container, key); + } + + public boolean setObjectInfo(String container, String key, Map userMetadata) { throw new UnsupportedOperationException(); } - public boolean setObjectMetadata(String container, String key, Map 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); } } diff --git a/rackspace/cloudfiles/core/src/test/resources/test_list_cdn.json b/rackspace/cloudfiles/core/src/test/resources/test_list_cdn.json new file mode 100644 index 0000000000..5bf462d7d5 --- /dev/null +++ b/rackspace/cloudfiles/core/src/test/resources/test_list_cdn.json @@ -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"} +] \ No newline at end of file diff --git a/rackspace/cloudfiles/pom.xml b/rackspace/cloudfiles/pom.xml index 4bf21a8caf..3ea7eb48d6 100644 --- a/rackspace/cloudfiles/pom.xml +++ b/rackspace/cloudfiles/pom.xml @@ -40,7 +40,7 @@ core - org.jclouds.rackspace.cloudfiles.integration.CloudFilesTestInitializer + org.jclouds.rackspace.cloudfiles.blobstore.integration.CloudFilesTestInitializer