mirror of https://github.com/apache/jclouds.git
enforced blobs must have uri, container, and can have publicAccess
This commit is contained in:
parent
fc8bb96363
commit
53c735fdff
|
@ -51,6 +51,7 @@ import org.jclouds.blobstore.domain.PageSet;
|
|||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
|
@ -258,4 +259,12 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.jclouds.blobstore.domain.PageSet;
|
|||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
|
@ -225,4 +226,10 @@ public class AtmosBlobStore extends BaseBlobStore {
|
|||
sync.deletePath(container + "/" + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,8 @@ import org.jclouds.io.payloads.BaseMutableContentMetadata;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
|
@ -61,10 +61,11 @@ public class DirectoryEntryListToResourceMetadataList implements
|
|||
StorageType type = from.getType() == FileType.DIRECTORY ? StorageType.FOLDER : StorageType.BLOB;
|
||||
if (type == StorageType.FOLDER)
|
||||
return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation
|
||||
.get(), null, null, null, Maps.<String, String> newHashMap());
|
||||
.get(), null, null, null,ImmutableMap.<String,String>of());
|
||||
else
|
||||
return new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(),
|
||||
null, null, null, Maps.<String, String> newHashMap(), new BaseMutableContentMetadata());
|
||||
null, null, null,ImmutableMap.<String,String>of(), null,
|
||||
null, new BaseMutableContentMetadata());
|
||||
}
|
||||
|
||||
}), from.getToken());
|
||||
|
|
|
@ -33,7 +33,7 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.blobstore.functions.ThrowContainerNotFoundOn404;
|
||||
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
|
||||
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.jclouds.cloudfiles.functions.ParseCdnUriFromHeaders;
|
||||
import org.jclouds.cloudfiles.functions.ParseContainerCDNMetadataFromHeaders;
|
||||
|
@ -86,7 +86,7 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
|
|||
*/
|
||||
@HEAD
|
||||
@ResponseParser(ParseContainerCDNMetadataFromHeaders.class)
|
||||
@ExceptionParser(ThrowContainerNotFoundOn404.class)
|
||||
@ExceptionParser(ReturnNullOnContainerNotFound.class)
|
||||
@Path("/{container}")
|
||||
@Endpoint(CDNManagement.class)
|
||||
ListenableFuture<ContainerCDNMetadata> getCDNMetadata(@PathParam("container") String container);
|
||||
|
|
|
@ -23,10 +23,10 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContextBuilder;
|
||||
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
|
||||
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
||||
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
@ -44,8 +44,7 @@ import com.google.inject.Module;
|
|||
* @author Adrian Cole, Andrew Newdigate
|
||||
* @see CloudFilesBlobStoreContext
|
||||
*/
|
||||
public class CloudFilesContextBuilder extends
|
||||
BlobStoreContextBuilder<CloudFilesClient, CloudFilesAsyncClient> {
|
||||
public class CloudFilesContextBuilder extends BlobStoreContextBuilder<CloudFilesClient, CloudFilesAsyncClient> {
|
||||
|
||||
public CloudFilesContextBuilder(Properties props) {
|
||||
super(CloudFilesClient.class, CloudFilesAsyncClient.class, props);
|
||||
|
@ -53,7 +52,7 @@ public class CloudFilesContextBuilder extends
|
|||
|
||||
@Override
|
||||
protected void addContextModule(List<Module> modules) {
|
||||
modules.add(new SwiftBlobStoreContextModule());
|
||||
modules.add(new CloudFilesBlobStoreContextModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.cloudfiles.blobstore;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.cloudfiles.CloudFilesAsyncClient;
|
||||
import org.jclouds.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.cloudfiles.blobstore.functions.EnableCDNAndCache;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.concurrent.Futures;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.BlobStoreListContainerOptionsToListContainerOptions;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceList;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceMetadata;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CloudFilesAsyncBlobStore extends SwiftAsyncBlobStore {
|
||||
private final EnableCDNAndCache enableCDNAndCache;
|
||||
|
||||
@Inject
|
||||
protected CloudFilesAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, CloudFilesClient sync, CloudFilesAsyncClient async,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, EnableCDNAndCache enableCDNAndCache) {
|
||||
super(context, blobUtils, service, defaultLocation, locations, sync, async, container2ResourceMd,
|
||||
container2ContainerListOptions, container2ResourceList, object2Blob, blob2Object, object2BlobMd,
|
||||
blob2ObjectGetOptions, fetchBlobMetadataProvider);
|
||||
this.enableCDNAndCache = enableCDNAndCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, final String container,
|
||||
CreateContainerOptions options) {
|
||||
|
||||
ListenableFuture<Boolean> returnVal = createContainerInLocation(location, container);
|
||||
if (options.isPublicRead())
|
||||
return Futures.compose(createContainerInLocation(location, container), new Function<Boolean, Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean apply(Boolean input) {
|
||||
if (Boolean.TRUE.equals(input)) {
|
||||
return enableCDNAndCache.apply(container) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}, service);
|
||||
return returnVal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.jclouds.cloudfiles.blobstore;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.cloudfiles.blobstore.functions.EnableCDNAndCache;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.openstack.swift.CommonSwiftClient;
|
||||
import org.jclouds.openstack.swift.blobstore.SwiftBlobStore;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.BlobStoreListContainerOptionsToListContainerOptions;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceList;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceMetadata;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CloudFilesBlobStore extends SwiftBlobStore {
|
||||
|
||||
private EnableCDNAndCache enableCDNAndCache;
|
||||
|
||||
@Inject
|
||||
protected CloudFilesBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, EnableCDNAndCache enableCDNAndCache) {
|
||||
super(context, blobUtils, defaultLocation, locations, sync, container2ResourceMd, container2ContainerListOptions,
|
||||
container2ResourceList, object2Blob, blob2Object, object2BlobMd, blob2ObjectGetOptions,
|
||||
fetchBlobMetadataProvider);
|
||||
this.enableCDNAndCache = enableCDNAndCache;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
|
||||
try {
|
||||
return createContainerInLocation(location, container);
|
||||
} finally {
|
||||
if (options.isPublicRead())
|
||||
enableCDNAndCache.apply(container);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.cloudfiles.blobstore.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.cloudfiles.blobstore.CloudFilesAsyncBlobStore;
|
||||
import org.jclouds.cloudfiles.blobstore.CloudFilesBlobStore;
|
||||
import org.jclouds.cloudfiles.blobstore.functions.CloudFilesObjectToBlobMetadata;
|
||||
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
|
||||
import org.jclouds.openstack.swift.blobstore.SwiftBlobStore;
|
||||
import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CloudFilesBlobStoreContextModule extends SwiftBlobStoreContextModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Map<String, URI> cdnContainer(final CloudFilesClient client) {
|
||||
return new MapMaker().expireAfterWrite(30, TimeUnit.SECONDS).makeComputingMap(new Function<String, URI>() {
|
||||
public URI apply(String container) {
|
||||
ContainerCDNMetadata md = client.getCDNMetadata(container);
|
||||
return md != null ? md.getCDNUri() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getCDNMetadata()";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
bind(SwiftBlobStore.class).to(CloudFilesBlobStore.class);
|
||||
bind(SwiftAsyncBlobStore.class).to(CloudFilesAsyncBlobStore.class);
|
||||
bind(ObjectToBlobMetadata.class).to(CloudFilesObjectToBlobMetadata.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.cloudfiles.blobstore.functions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class CloudFilesObjectToBlobMetadata extends ObjectToBlobMetadata {
|
||||
private final PublicUriForObjectInfo publicUriForObjectInfo;
|
||||
|
||||
@Inject
|
||||
public CloudFilesObjectToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
||||
PublicUriForObjectInfo publicUriForObjectInfo) {
|
||||
super(ifDirectoryReturnName);
|
||||
this.publicUriForObjectInfo = publicUriForObjectInfo;
|
||||
}
|
||||
|
||||
public MutableBlobMetadata apply(ObjectInfo from) {
|
||||
if (from == null)
|
||||
return null;
|
||||
MutableBlobMetadata to = super.apply(from);
|
||||
to.setPublicUri(publicUriForObjectInfo.apply(from));
|
||||
return to;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.cloudfiles.blobstore.functions;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.cloudfiles.CloudFilesClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class EnableCDNAndCache implements Function<String, URI> {
|
||||
private final Map<String, URI> cdnContainer;
|
||||
private final CloudFilesClient sync;
|
||||
|
||||
@Inject
|
||||
public EnableCDNAndCache(CloudFilesClient sync, Map<String, URI> cdnContainer) {
|
||||
this.sync = sync;
|
||||
this.cdnContainer = cdnContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI apply(String input) {
|
||||
URI uri = sync.enableCDN(input);
|
||||
cdnContainer.put(input, uri);
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.cloudfiles.blobstore.functions;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class PublicUriForObjectInfo implements Function<ObjectInfo, URI> {
|
||||
private final Map<String, URI> cdnContainer;
|
||||
private final Provider<UriBuilder> uriBuilders;
|
||||
|
||||
@Inject
|
||||
public PublicUriForObjectInfo(Map<String, URI> cdnContainer, Provider<UriBuilder> uriBuilders) {
|
||||
this.cdnContainer = cdnContainer;
|
||||
this.uriBuilders = uriBuilders;
|
||||
}
|
||||
|
||||
public URI apply(ObjectInfo from) {
|
||||
if (from == null)
|
||||
return null;
|
||||
try {
|
||||
return uriBuilders.get().uri(cdnContainer.get(from.getContainer())).path(from.getName()).replaceQuery("")
|
||||
.build();
|
||||
} catch (NullPointerException e) {
|
||||
// MapMaker constructed maps are not allowed to return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ package org.jclouds.cloudfiles.domain;
|
|||
|
||||
import java.net.URI;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Murty
|
||||
|
@ -79,11 +78,7 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -96,22 +91,11 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ContainerCDNMetadata other = (ContainerCDNMetadata) obj;
|
||||
if (cdn_enabled != other.cdn_enabled)
|
||||
return false;
|
||||
if (cdn_uri == null) {
|
||||
if (other.cdn_uri != null)
|
||||
return false;
|
||||
} else if (!cdn_uri.equals(other.cdn_uri))
|
||||
return false;
|
||||
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;
|
||||
if (ttl != other.ttl)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -129,8 +113,8 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ContainerCDNMetadata [cdn_enabled=" + cdn_enabled + ", cdn_uri=" + cdn_uri
|
||||
+ ", log_retention=" + log_retention + ", name=" + name + ", referrer_acl="
|
||||
+ referrer_acl + ", ttl=" + ttl + ", useragent_acl=" + useragent_acl + "]";
|
||||
return String.format(
|
||||
"[name=%s, cdn_uri=%s, cdn_enabled=%s, log_retention=%s, referrer_acl=%s, ttl=%s, useragent_acl=%s]",
|
||||
name, cdn_uri, cdn_enabled, log_retention, referrer_acl, ttl, useragent_acl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,8 @@ import static org.testng.Assert.assertTrue;
|
|||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
|
||||
import org.jclouds.cloudfiles.options.ListCdnContainerOptions;
|
||||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.openstack.swift.CommonSwiftClientLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -74,28 +72,21 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
|
|||
assertTrue(cdnMetadata.isCDNEnabled());
|
||||
|
||||
assertEquals(cdnMetadata.getCDNUri(), cdnUri);
|
||||
final long initialTTL = cdnMetadata.getTTL();
|
||||
|
||||
|
||||
cdnMetadata = getApi().getCDNMetadata(containerNameWithoutCDN);
|
||||
assert cdnMetadata == null || !cdnMetadata.isCDNEnabled() : containerNameWithoutCDN
|
||||
+ " should not have metadata";
|
||||
|
||||
try {
|
||||
cdnMetadata = getApi().getCDNMetadata(containerNameWithoutCDN);
|
||||
assert cdnMetadata == null || !cdnMetadata.isCDNEnabled() : containerNameWithoutCDN
|
||||
+ " should not have metadata";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
} catch (HttpResponseException e) {
|
||||
}
|
||||
assert getApi().getCDNMetadata("DoesNotExist") == null;
|
||||
|
||||
try {
|
||||
cdnMetadata = getApi().getCDNMetadata("DoesNotExist");
|
||||
assert false : "should not exist";
|
||||
} catch (ContainerNotFoundException e) {
|
||||
} catch (HttpResponseException e) {
|
||||
}
|
||||
// List CDN metadata for containers, and ensure all CDN info is
|
||||
// available for enabled
|
||||
// container
|
||||
Set<ContainerCDNMetadata> cdnMetadataList = getApi().listCDNContainers();
|
||||
assertTrue(cdnMetadataList.size() >= 1);
|
||||
|
||||
final long initialTTL = cdnMetadata.getTTL();
|
||||
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true, initialTTL, cdnUri)));
|
||||
|
||||
// Test listing with options
|
||||
|
|
|
@ -79,6 +79,7 @@ import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.GetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||
|
@ -660,10 +661,17 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
String eTag = CryptoStreams.hex(object.getPayload().getContentMetadata().getContentMD5());
|
||||
return eTag;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ListenableFuture<String> putBlobMultipart(String container, Blob blob) {
|
||||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.jclouds.s3.blobstore;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
|
@ -30,19 +31,6 @@ import javax.inject.Provider;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.util.S3Utils;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
|
@ -51,6 +39,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
|
@ -58,6 +47,25 @@ import org.jclouds.collect.Memoized;
|
|||
import org.jclouds.concurrent.Futures;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.s3.S3AsyncClient;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
|
||||
import org.jclouds.s3.domain.AccessControlList.Permission;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.util.S3Utils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -81,15 +89,16 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
private final BlobToObject blob2Object;
|
||||
private final ObjectToBlobMetadata object2BlobMd;
|
||||
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
|
||||
private final Map<String, AccessControlList> bucketAcls;
|
||||
|
||||
@Inject
|
||||
protected S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, S3AsyncClient async, S3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, S3AsyncClient async, S3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, Map<String, AccessControlList> bucketAcls) {
|
||||
super(context, blobUtils, service, defaultLocation, locations);
|
||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||
this.async = checkNotNull(async, "async");
|
||||
|
@ -101,6 +110,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
|
||||
this.bucketAcls = checkNotNull(bucketAcls, "bucketAcls");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,11 +119,11 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||
return Futures.compose(async.listOwnedBuckets(),
|
||||
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, bucket2ResourceMd), null);
|
||||
}
|
||||
}, service);
|
||||
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, bucket2ResourceMd), null);
|
||||
}
|
||||
}, service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,8 +147,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
*/
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) {
|
||||
location = location != null ? location : defaultLocation.get();
|
||||
return async.putBucketInRegion(location.getId(), container);
|
||||
return createContainerInLocation(location, container, CreateContainerOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,9 +162,9 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
|
||||
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
|
||||
ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, bucket2ResourceList,
|
||||
service);
|
||||
service);
|
||||
return (options.isDetailed()) ? Futures.compose(list,
|
||||
fetchBlobMetadataProvider.get().setContainerName(container), service) : list;
|
||||
fetchBlobMetadataProvider.get().setContainerName(container), service) : list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +231,11 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
*/
|
||||
@Override
|
||||
public ListenableFuture<String> putBlob(String container, Blob blob) {
|
||||
return async.putObject(container, blob2Object.apply(blob));
|
||||
PutObjectOptions options = new PutObjectOptions();
|
||||
AccessControlList acl = bucketAcls.get(container);
|
||||
if (acl != null && acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
|
||||
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
return async.putObject(container, blob2Object.apply(blob), options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,4 +256,14 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
PutBucketOptions putBucketOptions = new PutBucketOptions();
|
||||
if (options.isPublicRead())
|
||||
putBucketOptions.withBucketAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
location = location != null ? location : defaultLocation.get();
|
||||
return async.putBucketInRegion(location.getId(), container, putBucketOptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,22 +21,13 @@ package org.jclouds.s3.blobstore;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.util.S3Utils;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
|
@ -45,12 +36,29 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
import org.jclouds.s3.S3Client;
|
||||
import org.jclouds.s3.blobstore.functions.BlobToObject;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceList;
|
||||
import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
||||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CannedAccessPolicy;
|
||||
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
|
||||
import org.jclouds.s3.domain.AccessControlList.Permission;
|
||||
import org.jclouds.s3.options.ListBucketOptions;
|
||||
import org.jclouds.s3.options.PutBucketOptions;
|
||||
import org.jclouds.s3.options.PutObjectOptions;
|
||||
import org.jclouds.s3.util.S3Utils;
|
||||
import org.jclouds.util.Assertions;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -72,6 +80,7 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
private final ObjectToBlobMetadata object2BlobMd;
|
||||
private final BlobToHttpGetOptions blob2ObjectGetOptions;
|
||||
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
|
||||
private final Map<String, AccessControlList> bucketAcls;
|
||||
|
||||
@Inject
|
||||
protected S3BlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||
|
@ -79,7 +88,7 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, Map<String, AccessControlList> bucketAcls) {
|
||||
super(context, blobUtils, defaultLocation, locations);
|
||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||
this.sync = checkNotNull(sync, "sync");
|
||||
|
@ -90,6 +99,7 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
|
||||
this.bucketAcls = checkNotNull(bucketAcls, "bucketAcls");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,8 +135,7 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
*/
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container) {
|
||||
location = location != null ? location : defaultLocation.get();
|
||||
return sync.putBucketInRegion(location.getId(), container);
|
||||
return createContainerInLocation(location, container, CreateContainerOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +231,11 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
*/
|
||||
@Override
|
||||
public String putBlob(String container, Blob blob) {
|
||||
return sync.putObject(container, blob2Object.apply(blob));
|
||||
PutObjectOptions options = new PutObjectOptions();
|
||||
AccessControlList acl = bucketAcls.get(container);
|
||||
if (acl != null && acl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
|
||||
options.withAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
return sync.putObject(container, blob2Object.apply(blob), options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -257,4 +270,13 @@ public class S3BlobStore extends BaseBlobStore {
|
|||
protected boolean deleteAndVerifyContainerGone(final String container) {
|
||||
return S3Utils.deleteAndVerifyContainerGone(sync, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
|
||||
PutBucketOptions putBucketOptions = new PutBucketOptions();
|
||||
if (options.isPublicRead())
|
||||
putBucketOptions.withBucketAcl(CannedAccessPolicy.PUBLIC_READ);
|
||||
location = location != null ? location : defaultLocation.get();
|
||||
return sync.putBucketInRegion(location.getId(), container, putBucketOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
package org.jclouds.s3.blobstore.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
import org.jclouds.blobstore.BlobRequestSigner;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
|
@ -34,10 +39,13 @@ import org.jclouds.s3.blobstore.S3AsyncBlobStore;
|
|||
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
|
||||
import org.jclouds.s3.blobstore.S3BlobStore;
|
||||
import org.jclouds.s3.blobstore.functions.LocationFromBucketLocation;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
|
@ -70,5 +78,19 @@ public class S3BlobStoreContextModule extends AbstractModule {
|
|||
}).to(LocationFromBucketLocation.class);
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Map<String, AccessControlList> bucketAcls(final S3Client client) {
|
||||
return new MapMaker().expireAfterWrite(30, TimeUnit.SECONDS).makeComputingMap(
|
||||
new Function<String, AccessControlList>() {
|
||||
public AccessControlList apply(String bucketName) {
|
||||
return client.getBucketACL(bucketName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getBucketAcl()";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,29 +19,36 @@
|
|||
|
||||
package org.jclouds.s3.blobstore.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
import org.jclouds.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.s3.domain.internal.MutableObjectMetadataImpl;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjectMetadata> {
|
||||
public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjectMetadata>,
|
||||
InvocationContext<BlobToObjectMetadata> {
|
||||
private String bucket;
|
||||
|
||||
public MutableObjectMetadata apply(BlobMetadata from) {
|
||||
if (from == null)
|
||||
return null;
|
||||
MutableObjectMetadata to = new MutableObjectMetadataImpl();
|
||||
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
|
||||
to.setUri(from.getUri());
|
||||
to.setETag(from.getETag());
|
||||
to.setKey(from.getName());
|
||||
to.setBucket(bucket);
|
||||
to.setLastModified(from.getLastModified());
|
||||
if (from.getUserMetadata() != null) {
|
||||
for (Entry<String, String> entry : from.getUserMetadata().entrySet())
|
||||
|
@ -49,4 +56,16 @@ public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjec
|
|||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlobToObjectMetadata setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
|
||||
return setBucket(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
|
||||
}
|
||||
|
||||
private BlobToObjectMetadata setBucket(String bucket) {
|
||||
this.bucket = bucket;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||
import org.jclouds.s3.domain.S3Object;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
|
|
@ -19,15 +19,20 @@
|
|||
|
||||
package org.jclouds.s3.blobstore.functions;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageType;
|
||||
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
|
||||
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
|
||||
import org.jclouds.s3.domain.AccessControlList.Permission;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -37,10 +42,13 @@ import com.google.common.base.Function;
|
|||
@Singleton
|
||||
public class ObjectToBlobMetadata implements Function<ObjectMetadata, MutableBlobMetadata> {
|
||||
private final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||
private final Map<String, AccessControlList> bucketAcls;
|
||||
|
||||
@Inject
|
||||
public ObjectToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName) {
|
||||
public ObjectToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
||||
Map<String, AccessControlList> bucketAcls) {
|
||||
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
||||
this.bucketAcls = bucketAcls;
|
||||
}
|
||||
|
||||
public MutableBlobMetadata apply(ObjectMetadata from) {
|
||||
|
@ -48,6 +56,15 @@ public class ObjectToBlobMetadata implements Function<ObjectMetadata, MutableBlo
|
|||
return null;
|
||||
MutableBlobMetadata to = new MutableBlobMetadataImpl();
|
||||
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
|
||||
try {
|
||||
AccessControlList bucketAcl = bucketAcls.get(from.getBucket());
|
||||
if (bucketAcl.hasPermission(GroupGranteeURI.ALL_USERS, Permission.READ))
|
||||
to.setPublicUri(from.getUri());
|
||||
} catch (NullPointerException e) {
|
||||
// MapMaker cannot return null, but a call to get acls can
|
||||
}
|
||||
to.setUri(from.getUri());
|
||||
to.setContainer(from.getBucket());
|
||||
to.setETag(from.getETag());
|
||||
to.setName(from.getKey());
|
||||
to.setLastModified(from.getLastModified());
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.s3.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -50,6 +51,8 @@ public interface MutableObjectMetadata extends ObjectMetadata {
|
|||
*/
|
||||
void setKey(String key);
|
||||
|
||||
void setBucket(String bucket);
|
||||
|
||||
/**
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
|
||||
* The owner of a bucket or object cannot be changed. However, if the object is overwritten by
|
||||
|
@ -80,4 +83,6 @@ public interface MutableObjectMetadata extends ObjectMetadata {
|
|||
|
||||
void setUserMetadata(Map<String, String> userMetadata);
|
||||
|
||||
void setUri(URI uri);
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.s3.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -50,6 +51,10 @@ public interface ObjectMetadata extends Comparable<ObjectMetadata> {
|
|||
*/
|
||||
String getKey();
|
||||
|
||||
String getBucket();
|
||||
|
||||
URI getUri();
|
||||
|
||||
/**
|
||||
* Every bucket and object in Amazon S3 has an owner, the user that created the bucket or object.
|
||||
* The owner of a bucket or object cannot be changed. However, if the object is overwritten by
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.io.ContentMetadataBuilder;
|
||||
|
@ -38,19 +40,49 @@ public class ObjectMetadataBuilder {
|
|||
return new ObjectMetadataBuilder();
|
||||
}
|
||||
|
||||
private final ContentMetadataBuilder contentMetadataBuilder = new ContentMetadataBuilder().contentType("binary/octet-stream");
|
||||
private final ContentMetadataBuilder contentMetadataBuilder = new ContentMetadataBuilder()
|
||||
.contentType("binary/octet-stream");
|
||||
|
||||
private String key;
|
||||
private StorageClass storageClass;
|
||||
private String bucket;
|
||||
private URI uri;
|
||||
private StorageClass storageClass = StorageClass.STANDARD;
|
||||
private String cacheControl;
|
||||
private Date lastModified;
|
||||
private String eTag;
|
||||
private CanonicalUser owner;
|
||||
private Map<String, String> userMetadata = ImmutableMap.of();
|
||||
|
||||
|
||||
|
||||
public ObjectMetadataBuilder key(String key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder bucket(String bucket) {
|
||||
this.bucket = bucket;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder owner(CanonicalUser owner) {
|
||||
this.owner = owner;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder eTag(String eTag) {
|
||||
this.eTag = eTag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder uri(URI uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder lastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectMetadataBuilder storageClass(StorageClass storageClass) {
|
||||
this.storageClass = storageClass;
|
||||
return this;
|
||||
|
@ -98,7 +130,6 @@ public class ObjectMetadataBuilder {
|
|||
public ObjectMetadataBuilder contentType(String contentType) {
|
||||
contentMetadataBuilder.contentType(contentType);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public ObjectMetadata build() {
|
||||
|
@ -106,8 +137,13 @@ public class ObjectMetadataBuilder {
|
|||
toReturn.setContentMetadata(BaseMutableContentMetadata.fromContentMetadata(contentMetadataBuilder.build()));
|
||||
toReturn.setCacheControl(cacheControl);
|
||||
toReturn.setKey(key);
|
||||
toReturn.setBucket(bucket);
|
||||
toReturn.setUri(uri);
|
||||
toReturn.setETag(eTag);
|
||||
toReturn.setOwner(owner);
|
||||
toReturn.setStorageClass(storageClass);
|
||||
toReturn.setUserMetadata(userMetadata);
|
||||
toReturn.setLastModified(lastModified);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,19 @@
|
|||
|
||||
package org.jclouds.s3.domain.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.io.ContentMetadata;
|
||||
import org.jclouds.io.payloads.BaseImmutableContentMetadata;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Returns the metadata parsable from a bucket listing
|
||||
|
@ -41,29 +44,38 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
private static final long serialVersionUID = -4415449798024051115L;
|
||||
|
||||
private final String key;
|
||||
private final String bucket;
|
||||
private final URI uri;
|
||||
private final Date lastModified;
|
||||
private final String eTag;
|
||||
private final CanonicalUser owner;
|
||||
private final StorageClass storageClass;
|
||||
private final String cacheControl;
|
||||
private final Map<String, String> userMetadata;
|
||||
private final ContentMetadata contentMetadata;
|
||||
|
||||
public BucketListObjectMetadata(String key, Date lastModified, String eTag, byte[] md5, long contentLength,
|
||||
CanonicalUser owner, StorageClass storageClass) {
|
||||
this.key = key;
|
||||
public BucketListObjectMetadata(String key, String bucket, URI uri, Date lastModified, String eTag, byte[] md5,
|
||||
long contentLength, CanonicalUser owner, StorageClass storageClass) {
|
||||
this.key = checkNotNull(key, "key");
|
||||
this.bucket = checkNotNull(bucket, "bucket");
|
||||
this.uri = checkNotNull(uri, "uri");
|
||||
this.lastModified = lastModified;
|
||||
this.eTag = eTag;
|
||||
this.owner = owner;
|
||||
this.contentMetadata = new BaseImmutableContentMetadata(null, contentLength, md5, null, null, null);
|
||||
this.storageClass = storageClass;
|
||||
this.cacheControl = null;
|
||||
this.userMetadata = Maps.newHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
@ -71,6 +83,15 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getBucket() {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public CanonicalUser getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
@ -78,6 +99,7 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public StorageClass getStorageClass() {
|
||||
return storageClass;
|
||||
}
|
||||
|
@ -85,13 +107,15 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getCacheControl() {
|
||||
return cacheControl;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
@ -99,6 +123,7 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getETag() {
|
||||
return eTag;
|
||||
}
|
||||
|
@ -106,15 +131,17 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ObjectMetadata o) {
|
||||
return (this == o) ? 0 : getKey().compareTo(o.getKey());
|
||||
return (this == o) ? 0 : getUri().compareTo(o.getUri());
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getUserMetadata() {
|
||||
return userMetadata;
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -129,14 +156,7 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
|
||||
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
|
||||
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
|
||||
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
|
||||
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
|
||||
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -149,47 +169,19 @@ public class BucketListObjectMetadata implements Serializable, ObjectMetadata {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BucketListObjectMetadata other = (BucketListObjectMetadata) obj;
|
||||
if (cacheControl == null) {
|
||||
if (other.cacheControl != null)
|
||||
if (uri == null) {
|
||||
if (other.uri != null)
|
||||
return false;
|
||||
} else if (!cacheControl.equals(other.cacheControl))
|
||||
return false;
|
||||
if (contentMetadata == null) {
|
||||
if (other.contentMetadata != null)
|
||||
return false;
|
||||
} else if (!contentMetadata.equals(other.contentMetadata))
|
||||
return false;
|
||||
if (eTag == null) {
|
||||
if (other.eTag != null)
|
||||
return false;
|
||||
} else if (!eTag.equals(other.eTag))
|
||||
return false;
|
||||
if (key == null) {
|
||||
if (other.key != null)
|
||||
return false;
|
||||
} else if (!key.equals(other.key))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (owner == null) {
|
||||
if (other.owner != null)
|
||||
return false;
|
||||
} else if (!owner.equals(other.owner))
|
||||
return false;
|
||||
if (storageClass == null) {
|
||||
if (other.storageClass != null)
|
||||
return false;
|
||||
} else if (!storageClass.equals(other.storageClass))
|
||||
return false;
|
||||
if (userMetadata == null) {
|
||||
if (other.userMetadata != null)
|
||||
return false;
|
||||
} else if (!userMetadata.equals(other.userMetadata))
|
||||
} else if (!uri.equals(other.uri))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"[uri=%s, key=%s, bucket=%s, contentMetadata=%s, eTag=%s, lastModified=%s, owner=%s, storageClass=%s]",
|
||||
uri, key, bucket, contentMetadata, eTag, lastModified, owner, storageClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,13 +20,16 @@
|
|||
package org.jclouds.s3.domain.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.io.ContentMetadata;
|
||||
import org.jclouds.io.payloads.BaseImmutableContentMetadata;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
* Returns the metadata parsable from a bucket listing
|
||||
|
@ -38,57 +41,68 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
|
|||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -4415449798024051115L;
|
||||
|
||||
private final String key;
|
||||
private final Date lastModified;
|
||||
private final String eTag;
|
||||
private final CanonicalUser owner;
|
||||
private final StorageClass storageClass;
|
||||
private final String cacheControl;
|
||||
private final Map<String, String> userMetadata;
|
||||
private final BaseImmutableContentMetadata contentMetadata;
|
||||
|
||||
public CopyObjectResult(Date lastModified, String eTag) {
|
||||
this.key = null;
|
||||
this.lastModified = lastModified;
|
||||
this.eTag = eTag;
|
||||
this.owner = null;
|
||||
this.storageClass = StorageClass.STANDARD;
|
||||
this.contentMetadata = new BaseImmutableContentMetadata(null, null, null, null, null, null);
|
||||
this.cacheControl = null;
|
||||
this.userMetadata = null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getBucket() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public CanonicalUser getOwner() {
|
||||
return owner;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public StorageClass getStorageClass() {
|
||||
return storageClass;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getCacheControl() {
|
||||
return cacheControl;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
@ -96,6 +110,7 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getETag() {
|
||||
return eTag;
|
||||
}
|
||||
|
@ -103,15 +118,17 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ObjectMetadata o) {
|
||||
return (this == o) ? 0 : getKey().compareTo(o.getKey());
|
||||
return (this == o) ? 0 : getETag().compareTo(o.getETag());
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getUserMetadata() {
|
||||
return userMetadata;
|
||||
return ImmutableMap.of();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,14 +143,8 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
|
||||
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
|
||||
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
|
||||
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
|
||||
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -146,47 +157,22 @@ public class CopyObjectResult implements Serializable, ObjectMetadata {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CopyObjectResult other = (CopyObjectResult) obj;
|
||||
if (cacheControl == null) {
|
||||
if (other.cacheControl != null)
|
||||
return false;
|
||||
} else if (!cacheControl.equals(other.cacheControl))
|
||||
return false;
|
||||
if (contentMetadata == null) {
|
||||
if (other.contentMetadata != null)
|
||||
return false;
|
||||
} else if (!contentMetadata.equals(other.contentMetadata))
|
||||
return false;
|
||||
if (eTag == null) {
|
||||
if (other.eTag != null)
|
||||
return false;
|
||||
} else if (!eTag.equals(other.eTag))
|
||||
return false;
|
||||
if (key == null) {
|
||||
if (other.key != null)
|
||||
return false;
|
||||
} else if (!key.equals(other.key))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (owner == null) {
|
||||
if (other.owner != null)
|
||||
return false;
|
||||
} else if (!owner.equals(other.owner))
|
||||
return false;
|
||||
if (storageClass == null) {
|
||||
if (other.storageClass != null)
|
||||
return false;
|
||||
} else if (!storageClass.equals(other.storageClass))
|
||||
return false;
|
||||
if (userMetadata == null) {
|
||||
if (other.userMetadata != null)
|
||||
return false;
|
||||
} else if (!userMetadata.equals(other.userMetadata))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[eTag=%s, lastModified=%s]", eTag, lastModified);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,15 +20,16 @@
|
|||
package org.jclouds.s3.domain.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.io.MutableContentMetadata;
|
||||
import org.jclouds.io.payloads.BaseMutableContentMetadata;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.MutableObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
|
@ -43,6 +44,8 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
private static final long serialVersionUID = -4648755473986695062L;
|
||||
|
||||
private String key;
|
||||
private String bucket;
|
||||
private URI uri;
|
||||
private Date lastModified;
|
||||
private String eTag;
|
||||
private CanonicalUser owner;
|
||||
|
@ -60,11 +63,15 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
this.storageClass = StorageClass.STANDARD;
|
||||
this.contentMetadata = new BaseMutableContentMetadata();
|
||||
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
|
||||
this.key = from.getKey();
|
||||
this.uri = from.getUri();
|
||||
this.bucket = from.getBucket();
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
@ -72,6 +79,31 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getBucket() {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public CanonicalUser getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
@ -79,6 +111,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public StorageClass getStorageClass() {
|
||||
return storageClass;
|
||||
}
|
||||
|
@ -86,6 +119,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getCacheControl() {
|
||||
return cacheControl;
|
||||
}
|
||||
|
@ -93,6 +127,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
@ -100,6 +135,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getETag() {
|
||||
return eTag;
|
||||
}
|
||||
|
@ -107,6 +143,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ObjectMetadata o) {
|
||||
return (this == o) ? 0 : getKey().compareTo(o.getKey());
|
||||
}
|
||||
|
@ -114,6 +151,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getUserMetadata() {
|
||||
return userMetadata;
|
||||
}
|
||||
|
@ -121,6 +159,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setCacheControl(String cacheControl) {
|
||||
this.cacheControl = cacheControl;
|
||||
}
|
||||
|
@ -128,6 +167,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setETag(String eTag) {
|
||||
this.eTag = eTag;
|
||||
}
|
||||
|
@ -135,6 +175,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
@ -142,6 +183,15 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBucket(String bucket) {
|
||||
this.bucket = bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setLastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
@ -149,6 +199,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setOwner(CanonicalUser owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
@ -156,6 +207,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setStorageClass(StorageClass storageClass) {
|
||||
this.storageClass = storageClass;
|
||||
}
|
||||
|
@ -163,6 +215,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setUserMetadata(Map<String, String> userMetadata) {
|
||||
this.userMetadata = userMetadata;
|
||||
}
|
||||
|
@ -187,14 +240,7 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((cacheControl == null) ? 0 : cacheControl.hashCode());
|
||||
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
|
||||
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
|
||||
result = prime * result + ((storageClass == null) ? 0 : storageClass.hashCode());
|
||||
result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode());
|
||||
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -207,54 +253,21 @@ public class MutableObjectMetadataImpl implements Serializable, MutableObjectMet
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MutableObjectMetadataImpl other = (MutableObjectMetadataImpl) obj;
|
||||
if (cacheControl == null) {
|
||||
if (other.cacheControl != null)
|
||||
if (uri == null) {
|
||||
if (other.uri != null)
|
||||
return false;
|
||||
} else if (!cacheControl.equals(other.cacheControl))
|
||||
return false;
|
||||
if (contentMetadata == null) {
|
||||
if (other.contentMetadata != null)
|
||||
return false;
|
||||
} else if (!contentMetadata.equals(other.contentMetadata))
|
||||
return false;
|
||||
if (eTag == null) {
|
||||
if (other.eTag != null)
|
||||
return false;
|
||||
} else if (!eTag.equals(other.eTag))
|
||||
return false;
|
||||
if (key == null) {
|
||||
if (other.key != null)
|
||||
return false;
|
||||
} else if (!key.equals(other.key))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (owner == null) {
|
||||
if (other.owner != null)
|
||||
return false;
|
||||
} else if (!owner.equals(other.owner))
|
||||
return false;
|
||||
if (storageClass == null) {
|
||||
if (other.storageClass != null)
|
||||
return false;
|
||||
} else if (!storageClass.equals(other.storageClass))
|
||||
return false;
|
||||
if (userMetadata == null) {
|
||||
if (other.userMetadata != null)
|
||||
return false;
|
||||
} else if (!userMetadata.equals(other.userMetadata))
|
||||
} else if (!uri.equals(other.uri))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[key=" + key + ", cacheControl=" + cacheControl + ", contentMetadata=" + contentMetadata + ", eTag="
|
||||
+ eTag + ", lastModified=" + lastModified + ", owner=" + owner + ", storageClass=" + storageClass
|
||||
+ ", userMetadata=" + userMetadata + "]";
|
||||
return String
|
||||
.format(
|
||||
"[key=%s, bucket=%s, uri=%s, eTag=%s, cacheControl=%s, contentMetadata=%s, lastModified=%s, owner=%s, storageClass=%s, userMetadata=%s]",
|
||||
key, bucket, uri, eTag, cacheControl, contentMetadata, lastModified, owner, storageClass,
|
||||
userMetadata);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
|
|||
S3Object object = objectProvider.create(metadata);
|
||||
object.getAllHeaders().putAll(from.getHeaders());
|
||||
object.setPayload(from.getPayload());
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ public class ParseObjectMetadataFromHeaders implements Function<HttpResponse, Mu
|
|||
@Override
|
||||
public ParseObjectMetadataFromHeaders setContext(HttpRequest request) {
|
||||
blobMetadataParser.setContext(request);
|
||||
blobToObjectMetadata.setContext(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
@ -79,11 +81,11 @@ public class AccessControlListHandler extends ParseSax.HandlerWithResult<AccessC
|
|||
}
|
||||
|
||||
else if (qName.equals("ID") || qName.equals("EmailAddress") || qName.equals("URI")) {
|
||||
currentId = currentText.toString().trim();
|
||||
currentId = currentOrNull(currentText);
|
||||
} else if (qName.equals("DisplayName")) {
|
||||
currentDisplayName = currentText.toString().trim();
|
||||
currentDisplayName = currentOrNull(currentText);
|
||||
} else if (qName.equals("Permission")) {
|
||||
currentPermission = currentText.toString().trim();
|
||||
currentPermission = currentOrNull(currentText);
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -68,9 +70,9 @@ public class BucketLoggingHandler extends ParseSax.HandlerWithResult<BucketLoggi
|
|||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("TargetBucket")) {
|
||||
this.targetBucket = currentText.toString().trim();
|
||||
this.targetBucket = currentOrNull(currentText);
|
||||
} else if (qName.equals("TargetPrefix")) {
|
||||
this.targetPrefix = currentText.toString().trim();
|
||||
this.targetPrefix = currentOrNull(currentText);
|
||||
} else if (qName.equals("Grantee")) {
|
||||
if ("AmazonCustomerByEmail".equals(currentGranteeType)) {
|
||||
currentGrantee = new EmailAddressGrantee(currentId);
|
||||
|
@ -82,11 +84,11 @@ public class BucketLoggingHandler extends ParseSax.HandlerWithResult<BucketLoggi
|
|||
} else if (qName.equals("Grant")) {
|
||||
targetGrants.add(new Grant(currentGrantee, currentPermission));
|
||||
} else if (qName.equals("ID") || qName.equals("EmailAddress") || qName.equals("URI")) {
|
||||
currentId = currentText.toString().trim();
|
||||
currentId = currentOrNull(currentText);
|
||||
} else if (qName.equals("DisplayName")) {
|
||||
currentDisplayName = currentText.toString().trim();
|
||||
currentDisplayName = currentOrNull(currentText);
|
||||
} else if (qName.equals("Permission")) {
|
||||
currentPermission = currentText.toString().trim();
|
||||
currentPermission = currentOrNull(currentText);
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -51,9 +53,9 @@ public class CopyObjectHandler extends ParseSax.HandlerWithResult<ObjectMetadata
|
|||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("ETag")) {
|
||||
this.currentETag = currentText.toString().trim();
|
||||
this.currentETag = currentOrNull(currentText);
|
||||
} else if (qName.equals("LastModified")) {
|
||||
this.currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
|
||||
this.currentLastModified = dateParser.iso8601DateParse(currentOrNull(currentText));
|
||||
} else if (qName.equals("CopyObjectResult")) {
|
||||
metadata = new CopyObjectResult(currentLastModified, currentETag);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -62,15 +64,15 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<Set<Buck
|
|||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("ID")) { // owner stuff
|
||||
currentOwner = new CanonicalUser(currentText.toString().trim());
|
||||
currentOwner = new CanonicalUser(currentOrNull(currentText));
|
||||
} else if (qName.equals("DisplayName")) {
|
||||
currentOwner.setDisplayName(currentText.toString().trim());
|
||||
currentOwner.setDisplayName(currentOrNull(currentText));
|
||||
} else if (qName.equals("Bucket")) {
|
||||
buckets.add(new BucketMetadata(currentName, currentCreationDate, currentOwner));
|
||||
} else if (qName.equals("Name")) {
|
||||
currentName = currentText.toString().trim();
|
||||
currentName = currentOrNull(currentText);
|
||||
} else if (qName.equals("CreationDate")) {
|
||||
currentCreationDate = dateParser.iso8601DateParse(currentText.toString().trim());
|
||||
currentCreationDate = dateParser.iso8601DateParse(currentOrNull(currentText));
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -19,24 +19,25 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
|
||||
import org.jclouds.s3.domain.internal.BucketListObjectMetadata;
|
||||
import org.jclouds.s3.domain.internal.ListBucketResponseImpl;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
||||
import org.jclouds.s3.domain.internal.ListBucketResponseImpl;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
|
||||
/**
|
||||
* Parses the following XML document:
|
||||
|
@ -49,11 +50,14 @@ import com.google.common.collect.Sets;
|
|||
* />
|
||||
*/
|
||||
public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResponse> {
|
||||
private Set<ObjectMetadata> contents;
|
||||
private Set<String> commonPrefixes;
|
||||
private Builder<ObjectMetadata> contents = ImmutableSet.<ObjectMetadata> builder();
|
||||
private Builder<String> commonPrefixes = ImmutableSet.<String> builder();
|
||||
private CanonicalUser currentOwner;
|
||||
private StringBuilder currentText = new StringBuilder();
|
||||
|
||||
private ObjectMetadataBuilder builder = new ObjectMetadataBuilder();
|
||||
|
||||
private final Provider<UriBuilder> uriBuilders;
|
||||
private final DateService dateParser;
|
||||
|
||||
private String bucketName;
|
||||
|
@ -64,25 +68,19 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
|
|||
private boolean isTruncated;
|
||||
|
||||
@Inject
|
||||
public ListBucketHandler(DateService dateParser) {
|
||||
public ListBucketHandler(DateService dateParser, Provider<UriBuilder> uriBuilders) {
|
||||
this.dateParser = dateParser;
|
||||
this.contents = Sets.newLinkedHashSet();
|
||||
this.commonPrefixes = Sets.newLinkedHashSet();
|
||||
this.uriBuilders = uriBuilders;
|
||||
}
|
||||
|
||||
public ListBucketResponse getResult() {
|
||||
return new ListBucketResponseImpl(bucketName, contents, prefix, marker,
|
||||
return new ListBucketResponseImpl(bucketName, contents.build(), prefix, marker,
|
||||
(isTruncated && nextMarker == null) ? currentKey : nextMarker, maxResults, delimiter, isTruncated,
|
||||
commonPrefixes);
|
||||
commonPrefixes.build());
|
||||
}
|
||||
|
||||
private boolean inCommonPrefixes;
|
||||
private String currentKey;
|
||||
private Date currentLastModified;
|
||||
private String currentETag;
|
||||
private byte[] currentMD5;
|
||||
private long currentSize;
|
||||
private StorageClass currentStorageClass;
|
||||
private String nextMarker;
|
||||
|
||||
public void startElement(String uri, String name, String qName, Attributes attrs) {
|
||||
|
@ -93,45 +91,48 @@ public class ListBucketHandler extends ParseSax.HandlerWithResult<ListBucketResp
|
|||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
if (qName.equals("ID")) {
|
||||
currentOwner = new CanonicalUser(currentText.toString().trim());
|
||||
currentOwner = new CanonicalUser(currentOrNull(currentText));
|
||||
} else if (qName.equals("DisplayName")) {
|
||||
currentOwner.setDisplayName(currentText.toString().trim());
|
||||
currentOwner.setDisplayName(currentOrNull(currentText));
|
||||
} else if (qName.equals("Key")) { // content stuff
|
||||
currentKey = currentText.toString().trim();
|
||||
currentKey = currentOrNull(currentText);
|
||||
builder.key(currentKey);
|
||||
builder.uri(uriBuilders.get().uri(getRequest().getEndpoint()).path(currentKey).replaceQuery("").build());
|
||||
} else if (qName.equals("LastModified")) {
|
||||
currentLastModified = dateParser.iso8601DateParse(currentText.toString().trim());
|
||||
builder.lastModified(dateParser.iso8601DateParse(currentOrNull(currentText)));
|
||||
} else if (qName.equals("ETag")) {
|
||||
currentETag = currentText.toString().trim();
|
||||
currentMD5 = CryptoStreams.hex(Strings2.replaceAll(currentETag, '"', ""));
|
||||
String currentETag = currentOrNull(currentText);
|
||||
builder.eTag(currentETag);
|
||||
builder.contentMD5(CryptoStreams.hex(Strings2.replaceAll(currentETag, '"', "")));
|
||||
} else if (qName.equals("Size")) {
|
||||
currentSize = new Long(currentText.toString().trim());
|
||||
builder.contentLength(new Long(currentOrNull(currentText)));
|
||||
} else if (qName.equals("Owner")) {
|
||||
builder.owner(currentOwner);
|
||||
currentOwner = null;
|
||||
} else if (qName.equals("StorageClass")) {
|
||||
currentStorageClass = ObjectMetadata.StorageClass.valueOf(currentText.toString().trim());
|
||||
builder.storageClass(ObjectMetadata.StorageClass.valueOf(currentOrNull(currentText)));
|
||||
} else if (qName.equals("Contents")) {
|
||||
contents.add(new BucketListObjectMetadata(currentKey, currentLastModified, currentETag, currentMD5,
|
||||
currentSize, currentOwner, currentStorageClass));
|
||||
contents.add(builder.build());
|
||||
builder = new ObjectMetadataBuilder().bucket(bucketName);
|
||||
} else if (qName.equals("Name")) {
|
||||
this.bucketName = currentText.toString().trim();
|
||||
this.bucketName = currentOrNull(currentText);
|
||||
builder.bucket(bucketName);
|
||||
} else if (qName.equals("Prefix")) {
|
||||
String prefix = currentText.toString().trim();
|
||||
String prefix = currentOrNull(currentText);
|
||||
if (inCommonPrefixes)
|
||||
commonPrefixes.add(prefix);
|
||||
else
|
||||
this.prefix = prefix;
|
||||
} else if (qName.equals("Delimiter")) {
|
||||
if (!currentText.toString().equals(""))
|
||||
this.delimiter = currentText.toString().trim();
|
||||
this.delimiter = currentOrNull(currentText);
|
||||
} else if (qName.equals("Marker")) {
|
||||
if (!currentText.toString().equals(""))
|
||||
this.marker = currentText.toString().trim();
|
||||
this.marker = currentOrNull(currentText);
|
||||
} else if (qName.equals("NextMarker")) {
|
||||
if (!currentText.toString().equals(""))
|
||||
this.nextMarker = currentText.toString().trim();
|
||||
this.nextMarker = currentOrNull(currentText);
|
||||
} else if (qName.equals("MaxKeys")) {
|
||||
this.maxResults = Integer.parseInt(currentText.toString().trim());
|
||||
this.maxResults = Integer.parseInt(currentOrNull(currentText));
|
||||
} else if (qName.equals("IsTruncated")) {
|
||||
this.isTruncated = Boolean.parseBoolean(currentText.toString().trim());
|
||||
this.isTruncated = Boolean.parseBoolean(currentOrNull(currentText));
|
||||
}
|
||||
currentText = new StringBuilder();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
||||
|
@ -39,7 +41,7 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String
|
|||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
region = fromValue(currentText.toString().trim());
|
||||
region = fromValue(currentOrNull(currentText));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,14 +50,8 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String
|
|||
* {@code US_STANDARD} is returned as "" xml documents.
|
||||
*/
|
||||
public static String fromValue(String v) {
|
||||
if (v.equals(""))
|
||||
if (v == null || "".equals(v))
|
||||
return Region.US_STANDARD;
|
||||
if (v.equals(Region.EU))
|
||||
return Region.EU;
|
||||
else if (v.equals(Region.US_WEST_1))
|
||||
return Region.US_WEST_1;
|
||||
else if (v.equals(Region.AP_SOUTHEAST_1))
|
||||
return Region.AP_SOUTHEAST_1;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.s3.xml;
|
||||
|
||||
import static org.jclouds.util.SaxUtils.currentOrNull;
|
||||
|
||||
import org.jclouds.s3.domain.Payer;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
|
||||
|
@ -39,7 +41,7 @@ public class PayerHandler extends ParseSax.HandlerWithResult<Payer> {
|
|||
}
|
||||
|
||||
public void endElement(String uri, String name, String qName) {
|
||||
constraint = Payer.fromValue(currentText.toString().trim());
|
||||
constraint = Payer.fromValue(currentOrNull(currentText));
|
||||
}
|
||||
|
||||
public void characters(char ch[], int start, int length) {
|
||||
|
|
|
@ -22,19 +22,20 @@ package org.jclouds.s3.xml;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
|
||||
import org.jclouds.s3.domain.internal.BucketListObjectMetadata;
|
||||
import org.jclouds.s3.domain.internal.ListBucketResponseImpl;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.BaseHandlerTest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadataBuilder;
|
||||
import org.jclouds.s3.domain.internal.ListBucketResponseImpl;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
@ -63,59 +64,68 @@ public class ListBucketHandlerTest extends BaseHandlerTest {
|
|||
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/list_bucket.xml");
|
||||
|
||||
ListBucketResponse result = createParser().parse(is);
|
||||
|
||||
CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0",
|
||||
"ferncam");
|
||||
ListBucketResponse expected = new ListBucketResponseImpl("adriancole.org.jclouds.s3.amazons3testdelimiter",
|
||||
ImmutableList.of(
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/0", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:08.000Z"), "\"c82e6a0025c31c5de5947fda62ac51ab\"",
|
||||
CryptoStreams.hex("c82e6a0025c31c5de5947fda62ac51ab"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/1", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"944fab2c5a9a6bacf07db5e688310d7a\"",
|
||||
CryptoStreams.hex("944fab2c5a9a6bacf07db5e688310d7a"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/2", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"a227b8888045c8fd159fb495214000f0\"",
|
||||
CryptoStreams.hex("a227b8888045c8fd159fb495214000f0"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/3", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"c9caa76c3dec53e2a192608ce73eef03\"",
|
||||
CryptoStreams.hex("c9caa76c3dec53e2a192608ce73eef03"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/4", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"1ce5d0dcc6154a647ea90c7bdf82a224\"",
|
||||
CryptoStreams.hex("1ce5d0dcc6154a647ea90c7bdf82a224"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/5", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:09.000Z"), "\"79433524d87462ee05708a8ef894ed55\"",
|
||||
CryptoStreams.hex("79433524d87462ee05708a8ef894ed55"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/6", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"dd00a060b28ddca8bc5a21a49e306f67\"",
|
||||
CryptoStreams.hex("dd00a060b28ddca8bc5a21a49e306f67"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/7", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"8cd06eca6e819a927b07a285d750b100\"",
|
||||
CryptoStreams.hex("8cd06eca6e819a927b07a285d750b100"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/8", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"174495094d0633b92cbe46603eee6bad\"",
|
||||
CryptoStreams.hex("174495094d0633b92cbe46603eee6bad"), 8, owner, StorageClass.STANDARD),
|
||||
(ObjectMetadata) new BucketListObjectMetadata("apps/9", dateService
|
||||
.iso8601DateParse("2009-05-07T18:27:10.000Z"), "\"cd8a19b26fea8a827276df0ad11c580d\"",
|
||||
CryptoStreams.hex("cd8a19b26fea8a827276df0ad11c580d"), 8, owner, StorageClass.STANDARD)),
|
||||
"apps/", null, null, 1000, null, false, new TreeSet<String>());
|
||||
"ferncam");
|
||||
String bucket = "adriancole.org.jclouds.aws.s3.amazons3testdelimiter";
|
||||
ListBucketResponse expected = new ListBucketResponseImpl(bucket, ImmutableList.<ObjectMetadata> of(
|
||||
new ObjectMetadataBuilder().key("apps/0").bucket(bucket).uri(URI.create("http://bucket.com/apps/0"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:08.000Z")).eTag(
|
||||
"\"c82e6a0025c31c5de5947fda62ac51ab\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("c82e6a0025c31c5de5947fda62ac51ab")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/1").bucket(bucket).uri(URI.create("http://bucket.com/apps/1"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:09.000Z")).eTag(
|
||||
"\"944fab2c5a9a6bacf07db5e688310d7a\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("944fab2c5a9a6bacf07db5e688310d7a")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/2").bucket(bucket).uri(URI.create("http://bucket.com/apps/2"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:09.000Z")).eTag(
|
||||
"\"a227b8888045c8fd159fb495214000f0\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("a227b8888045c8fd159fb495214000f0")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/3").bucket(bucket).uri(URI.create("http://bucket.com/apps/3"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:09.000Z")).eTag(
|
||||
"\"c9caa76c3dec53e2a192608ce73eef03\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("c9caa76c3dec53e2a192608ce73eef03")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/4").bucket(bucket).uri(URI.create("http://bucket.com/apps/4"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:09.000Z")).eTag(
|
||||
"\"1ce5d0dcc6154a647ea90c7bdf82a224\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("1ce5d0dcc6154a647ea90c7bdf82a224")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/5").bucket(bucket).uri(URI.create("http://bucket.com/apps/5"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:09.000Z")).eTag(
|
||||
"\"79433524d87462ee05708a8ef894ed55\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("79433524d87462ee05708a8ef894ed55")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/6").bucket(bucket).uri(URI.create("http://bucket.com/apps/6"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:10.000Z")).eTag(
|
||||
"\"dd00a060b28ddca8bc5a21a49e306f67\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("dd00a060b28ddca8bc5a21a49e306f67")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/7").bucket(bucket).uri(URI.create("http://bucket.com/apps/7"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:10.000Z")).eTag(
|
||||
"\"8cd06eca6e819a927b07a285d750b100\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("8cd06eca6e819a927b07a285d750b100")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/8").bucket(bucket).uri(URI.create("http://bucket.com/apps/8"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:10.000Z")).eTag(
|
||||
"\"174495094d0633b92cbe46603eee6bad\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("174495094d0633b92cbe46603eee6bad")).contentLength(8l).build(),
|
||||
new ObjectMetadataBuilder().key("apps/9").bucket(bucket).uri(URI.create("http://bucket.com/apps/9"))
|
||||
.lastModified(dateService.iso8601DateParse("2009-05-07T18:27:10.000Z")).eTag(
|
||||
"\"cd8a19b26fea8a827276df0ad11c580d\"").owner(owner).contentMD5(
|
||||
CryptoStreams.hex("cd8a19b26fea8a827276df0ad11c580d")).contentLength(8l).build()),
|
||||
"apps/", null, null, 1000, null, false, new TreeSet<String>());
|
||||
|
||||
ListBucketResponse result = (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class))
|
||||
.parse(is);
|
||||
|
||||
assertEquals(result, expected);
|
||||
assertEquals(result.toString(), expected.toString());
|
||||
}
|
||||
|
||||
ParseSax<ListBucketResponse> createParser() {
|
||||
ParseSax<ListBucketResponse> parser = (ParseSax<ListBucketResponse>) factory.create(injector
|
||||
.getInstance(ListBucketHandler.class));
|
||||
return parser;
|
||||
return factory.create(injector.getInstance(ListBucketHandler.class)).setContext(
|
||||
HttpRequest.builder().method("GET").endpoint(URI.create("http://bucket.com")).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListMyBucketsWithDelimiterSlashAndCommonPrefixesAppsSlash() throws HttpException {
|
||||
|
||||
ListBucketResponse bucket = createParser().parse(
|
||||
Strings2.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
|
||||
Strings2.toInputStream(listBucketWithSlashDelimiterAndCommonPrefixApps));
|
||||
assertEquals(bucket.getCommonPrefixes().iterator().next(), "apps/");
|
||||
assertEquals(bucket.getDelimiter(), "/");
|
||||
assert bucket.getMarker() == null;
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.testng.Assert.assertEquals;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
@ -30,16 +31,19 @@ import java.util.concurrent.CompletionService;
|
|||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.PerformanceTest;
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.config.SaxParserModule;
|
||||
import org.jclouds.s3.domain.BucketMetadata;
|
||||
import org.jclouds.s3.domain.CanonicalUser;
|
||||
import org.jclouds.s3.domain.ListBucketResponse;
|
||||
import org.jclouds.s3.domain.ObjectMetadata;
|
||||
import org.jclouds.s3.domain.ObjectMetadata.StorageClass;
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.config.SaxParserModule;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
|
@ -49,13 +53,14 @@ import org.xml.sax.SAXException;
|
|||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.sun.jersey.api.uri.UriBuilderImpl;
|
||||
|
||||
/**
|
||||
* Tests parsing of S3 responses
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
//NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||
@Test(groups = "performance", sequential = true, timeOut = 2 * 60 * 1000, testName = "S3ParserTest")
|
||||
public class S3ParserTest extends PerformanceTest {
|
||||
Injector injector = null;
|
||||
|
@ -63,7 +68,12 @@ public class S3ParserTest extends PerformanceTest {
|
|||
|
||||
@BeforeTest
|
||||
protected void setUpInjector() {
|
||||
injector = Guice.createInjector(new SaxParserModule());
|
||||
injector = Guice.createInjector(new SaxParserModule() {
|
||||
public void configure() {
|
||||
super.configure();
|
||||
bind(UriBuilder.class).to(UriBuilderImpl.class);
|
||||
}
|
||||
});
|
||||
factory = injector.getInstance(ParseSax.Factory.class);
|
||||
assert factory != null;
|
||||
}
|
||||
|
@ -140,7 +150,8 @@ public class S3ParserTest extends PerformanceTest {
|
|||
}
|
||||
|
||||
private ListBucketResponse runParseListContainerResult() throws HttpException {
|
||||
return (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class)).parse(
|
||||
return (ListBucketResponse) factory.create(injector.getInstance(ListBucketHandler.class)).setContext(
|
||||
HttpRequest.builder().method("GET").endpoint(URI.create("http://bucket.com")).build()).parse(
|
||||
Strings2.toInputStream(listContainerResult));
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
|
@ -82,14 +83,14 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
|
||||
|
||||
@Inject
|
||||
SwiftAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync, CommonSwiftAsyncClient async,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||
protected SwiftAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync,
|
||||
CommonSwiftAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
|
||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||
super(context, blobUtils, service, defaultLocation, locations);
|
||||
this.sync = sync;
|
||||
this.async = async;
|
||||
|
@ -109,11 +110,12 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||
return Futures.compose(async.listContainers(),
|
||||
new Function<Set<ContainerMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<ContainerMetadata> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), null);
|
||||
}
|
||||
}, service);
|
||||
new Function<Set<ContainerMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
||||
Set<ContainerMetadata> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), null);
|
||||
}
|
||||
}, service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,12 +146,12 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
|
||||
org.jclouds.openstack.swift.options.ListContainerOptions httpOptions = container2ContainerListOptions
|
||||
.apply(options);
|
||||
.apply(options);
|
||||
ListenableFuture<PageSet<ObjectInfo>> returnVal = async.listObjects(container, httpOptions);
|
||||
ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, container2ResourceList,
|
||||
service);
|
||||
service);
|
||||
return options.isDetailed() ? Futures.compose(list, fetchBlobMetadataProvider.get().setContainerName(container),
|
||||
service) : list;
|
||||
service) : list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,14 +178,14 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
||||
return Futures.compose(async.getObjectInfo(container, key),
|
||||
new Function<MutableObjectInfoWithMetadata, BlobMetadata>() {
|
||||
new Function<MutableObjectInfoWithMetadata, BlobMetadata>() {
|
||||
|
||||
@Override
|
||||
public BlobMetadata apply(MutableObjectInfoWithMetadata from) {
|
||||
return object2BlobMd.apply(from);
|
||||
}
|
||||
@Override
|
||||
public BlobMetadata apply(MutableObjectInfoWithMetadata from) {
|
||||
return object2BlobMd.apply(from);
|
||||
}
|
||||
|
||||
}, service);
|
||||
}, service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,4 +241,11 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
|
@ -72,7 +73,7 @@ public class SwiftBlobStore extends BaseBlobStore {
|
|||
private final Provider<FetchBlobMetadata> fetchBlobMetadataProvider;
|
||||
|
||||
@Inject
|
||||
SwiftBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||
protected SwiftBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
|
||||
|
@ -226,4 +227,11 @@ public class SwiftBlobStore extends BaseBlobStore {
|
|||
sync.deleteContainerIfEmpty(container);
|
||||
return !sync.containerExists(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,8 +54,9 @@ public class ObjectToBlobMetadata implements Function<ObjectInfo, MutableBlobMet
|
|||
if (from.getHash() != null)
|
||||
to.setETag(CryptoStreams.hex(from.getHash()));
|
||||
to.setName(from.getName());
|
||||
if (from.getBytes() != null)
|
||||
to.getContentMetadata().setContentLength(from.getBytes());
|
||||
to.setContainer(from.getContainer());
|
||||
to.setUri(from.getUri());
|
||||
to.getContentMetadata().setContentLength(from.getBytes());
|
||||
if (from.getLastModified() != null)
|
||||
to.setLastModified(from.getLastModified());
|
||||
if (from instanceof MutableObjectInfoWithMetadata)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.openstack.swift.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -44,6 +45,10 @@ public interface MutableObjectInfoWithMetadata extends ObjectInfo {
|
|||
|
||||
void setContentType(String contentType);
|
||||
|
||||
void setContainer(String container);
|
||||
|
||||
void setUri(URI uri);
|
||||
|
||||
Map<String, String> getMetadata();
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.openstack.swift.domain;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +29,8 @@ import java.util.Date;
|
|||
*/
|
||||
public interface ObjectInfo extends Comparable<ObjectInfo> {
|
||||
|
||||
URI getUri();
|
||||
|
||||
String getName();
|
||||
|
||||
byte[] getHash();
|
||||
|
@ -38,4 +41,6 @@ public interface ObjectInfo extends Comparable<ObjectInfo> {
|
|||
|
||||
Date getLastModified();
|
||||
|
||||
String getContainer();
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.openstack.swift.domain.internal;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -63,7 +64,8 @@ public class DelegatingMutableObjectInfoWithMetadata extends BaseMutableContentM
|
|||
|
||||
@Override
|
||||
public void setContentLength(Long bytes) {
|
||||
delegate.setBytes(bytes);
|
||||
if (bytes != null)
|
||||
delegate.setBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,7 +109,7 @@ public class DelegatingMutableObjectInfoWithMetadata extends BaseMutableContentM
|
|||
|
||||
@Override
|
||||
public Long getBytes() {
|
||||
return delegate.getBytes();
|
||||
return delegate.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,4 +131,24 @@ public class DelegatingMutableObjectInfoWithMetadata extends BaseMutableContentM
|
|||
public int compareTo(ObjectInfo o) {
|
||||
return delegate.compareTo(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContainer(String container) {
|
||||
delegate.setContainer(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return delegate.getContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUri(URI uri) {
|
||||
delegate.setUri(uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return delegate.getUri();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.openstack.swift.domain.internal;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
@ -37,44 +38,82 @@ import com.google.common.collect.Maps;
|
|||
*/
|
||||
public class MutableObjectInfoWithMetadataImpl implements MutableObjectInfoWithMetadata {
|
||||
private String name;
|
||||
private String container;
|
||||
private URI uri;
|
||||
private Long bytes;
|
||||
private byte[] hash;
|
||||
private String contentType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
private Date lastModified;
|
||||
private final Map<String, String> metadata = Maps.newHashMap();
|
||||
private final Map<String, String> metadata = Maps.newLinkedHashMap();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setBytes(Long bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setHash(byte[] hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Long getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public byte[] getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
@ -83,11 +122,7 @@ public class MutableObjectInfoWithMetadataImpl implements MutableObjectInfoWithM
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((bytes == null) ? 0 : bytes.hashCode());
|
||||
result = prime * result + ((contentType == null) ? 0 : contentType.hashCode());
|
||||
result = prime * result + Arrays.hashCode(hash);
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||
result = prime * result + ((container == null) ? 0 : container.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -101,27 +136,10 @@ public class MutableObjectInfoWithMetadataImpl implements MutableObjectInfoWithM
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MutableObjectInfoWithMetadataImpl other = (MutableObjectInfoWithMetadataImpl) obj;
|
||||
if (bytes == null) {
|
||||
if (other.bytes != null)
|
||||
if (container == null) {
|
||||
if (other.container != null)
|
||||
return false;
|
||||
} else if (!bytes.equals(other.bytes))
|
||||
return false;
|
||||
if (contentType == null) {
|
||||
if (other.contentType != null)
|
||||
return false;
|
||||
} else if (!contentType.equals(other.contentType))
|
||||
return false;
|
||||
if (!Arrays.equals(hash, other.hash))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (metadata == null) {
|
||||
if (other.metadata != null)
|
||||
return false;
|
||||
} else if (!metadata.equals(other.metadata))
|
||||
} else if (!container.equals(other.container))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
|
@ -131,16 +149,60 @@ public class MutableObjectInfoWithMetadataImpl implements MutableObjectInfoWithM
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(ObjectInfo o) {
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setLastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setContainer(String container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[name=%s, container=%s, uri=%s, bytes=%s, contentType=%s, lastModified=%s, hash=%s]", name,
|
||||
container, uri, bytes, contentType, lastModified, Arrays.toString(hash));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,56 +19,159 @@
|
|||
|
||||
package org.jclouds.openstack.swift.domain.internal;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import org.jclouds.openstack.swift.domain.ObjectInfo;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class ObjectInfoImpl implements ObjectInfo {
|
||||
String name;
|
||||
byte[] hash;
|
||||
long bytes;
|
||||
String content_type;
|
||||
Date last_modified;
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String name;
|
||||
private String container;
|
||||
private URI uri;
|
||||
private byte[] hash;
|
||||
private Long bytes;
|
||||
private String contentType;
|
||||
private Date lastModified;
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder container(String container) {
|
||||
this.container = container;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder uri(URI uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hash(byte[] hash) {
|
||||
this.hash = hash;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder bytes(Long bytes) {
|
||||
this.bytes = bytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder contentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder lastModified(Date lastModified) {
|
||||
this.lastModified = lastModified;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ObjectInfoImpl build() {
|
||||
return new ObjectInfoImpl(name, uri, container, hash, bytes, contentType, lastModified);
|
||||
}
|
||||
|
||||
public Builder fromObjectInfo(ObjectInfo in) {
|
||||
return name(in.getName()).container(in.getContainer()).uri(uri).hash(in.getHash()).bytes(in.getBytes())
|
||||
.contentType(in.getContentType()).lastModified(in.getLastModified());
|
||||
}
|
||||
}
|
||||
|
||||
private String name;
|
||||
private String container;
|
||||
private URI uri;
|
||||
private byte[] hash;
|
||||
private Long bytes;
|
||||
@SerializedName("content_type")
|
||||
private String contentType;
|
||||
@SerializedName("last_modified")
|
||||
private Date lastModified;
|
||||
|
||||
public ObjectInfoImpl(String name, URI uri, String container, byte[] hash, Long bytes, String contentType,
|
||||
Date lastModified) {
|
||||
this.name = name;
|
||||
this.container = container;
|
||||
this.uri = uri;
|
||||
this.hash = hash;
|
||||
this.bytes = bytes;
|
||||
this.contentType = contentType;
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
ObjectInfoImpl() {
|
||||
|
||||
}
|
||||
|
||||
public int compareTo(ObjectInfoImpl o) {
|
||||
return (this == o) ? 0 : name.compareTo(o.name);
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Long getBytes() {
|
||||
return bytes;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return content_type;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public byte[] getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public Date getLastModified() {
|
||||
return last_modified;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Long getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Date getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (bytes ^ (bytes >>> 32));
|
||||
result = prime * result
|
||||
+ ((content_type == null) ? 0 : content_type.hashCode());
|
||||
result = prime * result + Arrays.hashCode(hash);
|
||||
result = prime * result
|
||||
+ ((last_modified == null) ? 0 : last_modified.hashCode());
|
||||
result = prime * result + ((container == null) ? 0 : container.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -82,19 +185,10 @@ public class ObjectInfoImpl implements ObjectInfo {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ObjectInfoImpl other = (ObjectInfoImpl) obj;
|
||||
if (bytes != other.bytes)
|
||||
return false;
|
||||
if (content_type == null) {
|
||||
if (other.content_type != null)
|
||||
if (container == null) {
|
||||
if (other.container != null)
|
||||
return false;
|
||||
} else if (!content_type.equals(other.content_type))
|
||||
return false;
|
||||
if (!Arrays.equals(hash, other.hash))
|
||||
return false;
|
||||
if (last_modified == null) {
|
||||
if (other.last_modified != null)
|
||||
return false;
|
||||
} else if (!last_modified.equals(other.last_modified))
|
||||
} else if (!container.equals(other.container))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
|
@ -104,15 +198,19 @@ public class ObjectInfoImpl implements ObjectInfo {
|
|||
return true;
|
||||
}
|
||||
|
||||
public int compareTo(ObjectInfo o) {
|
||||
return (this == o) ? 0 : getName().compareTo(o.getName());
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[name=%s, container=%s, uri=%s, bytes=%s, contentType=%s, lastModified=%s, hash=%s]", name,
|
||||
container, uri, bytes, contentType, lastModified, Arrays.toString(hash));
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return builder().fromObjectInfo(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ObjectInfoImpl [bytes=" + bytes + ", content_flavor="
|
||||
+ content_type + ", hash=" + Arrays.asList(hash)
|
||||
+ ", last_modified=" + last_modified.getTime() + ", name=" + name
|
||||
+ "]";
|
||||
public int compareTo(ObjectInfo o) {
|
||||
return name.compareTo(o.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.openstack.swift.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -31,6 +32,7 @@ import org.jclouds.http.HttpResponse;
|
|||
import org.jclouds.openstack.swift.blobstore.functions.ResourceToObjectInfo;
|
||||
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -43,6 +45,7 @@ public class ParseObjectInfoFromHeaders implements Function<HttpResponse, Mutabl
|
|||
InvocationContext<ParseObjectInfoFromHeaders> {
|
||||
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||
private final ResourceToObjectInfo blobToObjectInfo;
|
||||
private String container;
|
||||
|
||||
@Inject
|
||||
public ParseObjectInfoFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||
|
@ -58,6 +61,8 @@ public class ParseObjectInfoFromHeaders implements Function<HttpResponse, Mutabl
|
|||
BlobMetadata base = blobMetadataParser.apply(from);
|
||||
MutableObjectInfoWithMetadata to = blobToObjectInfo.apply(base);
|
||||
to.setBytes(attemptToParseSizeAndRangeFromHeaders(from));
|
||||
to.setContainer(container);
|
||||
to.setUri(base.getUri());
|
||||
String eTagHeader = from.getFirstHeaderOrNull("Etag");
|
||||
if (eTagHeader != null) {
|
||||
to.setHash(CryptoStreams.hex(eTagHeader));
|
||||
|
@ -68,6 +73,12 @@ public class ParseObjectInfoFromHeaders implements Function<HttpResponse, Mutabl
|
|||
@Override
|
||||
public ParseObjectInfoFromHeaders setContext(HttpRequest request) {
|
||||
blobMetadataParser.setContext(request);
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
|
||||
return setContainer(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
|
||||
}
|
||||
|
||||
private ParseObjectInfoFromHeaders setContainer(String container) {
|
||||
this.container = container;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.lang.reflect.Type;
|
|||
import java.util.SortedSet;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
|
@ -51,14 +53,18 @@ import com.google.inject.TypeLiteral;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<ObjectInfo>> implements InvocationContext<ParseObjectInfoListFromJsonResponse> {
|
||||
public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<ObjectInfo>> implements
|
||||
InvocationContext<ParseObjectInfoListFromJsonResponse> {
|
||||
private final Provider<UriBuilder> uriBuilders;
|
||||
|
||||
private GeneratedHttpRequest<?> request;
|
||||
private String container;
|
||||
|
||||
@Inject
|
||||
public ParseObjectInfoListFromJsonResponse(Json json) {
|
||||
public ParseObjectInfoListFromJsonResponse(Json json, Provider<UriBuilder> uriBuilders) {
|
||||
super(json, new TypeLiteral<PageSet<ObjectInfo>>() {
|
||||
});
|
||||
this.uriBuilders = uriBuilders;
|
||||
}
|
||||
|
||||
public PageSet<ObjectInfo> apply(InputStream stream) {
|
||||
|
@ -66,7 +72,7 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
|
|||
checkState(request.getArgs() != null, "request.getArgs() should be initialized at this point");
|
||||
checkArgument(request.getArgs().get(0) instanceof String, "arg[0] must be a container name");
|
||||
checkArgument(request.getArgs().get(1) instanceof ListContainerOptions[],
|
||||
"arg[1] must be an array of ListContainerOptions");
|
||||
"arg[1] must be an array of ListContainerOptions");
|
||||
ListContainerOptions[] optionsList = (ListContainerOptions[]) request.getArgs().get(1);
|
||||
ListContainerOptions options = optionsList.length > 0 ? optionsList[0] : ListContainerOptions.NONE;
|
||||
Type listType = new TypeToken<SortedSet<ObjectInfoImpl>>() {
|
||||
|
@ -75,11 +81,13 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
|
|||
try {
|
||||
SortedSet<ObjectInfoImpl> list = apply(stream, listType);
|
||||
SortedSet<ObjectInfo> returnVal = Sets.newTreeSet(Iterables.transform(list,
|
||||
new Function<ObjectInfoImpl, ObjectInfo>() {
|
||||
public ObjectInfo apply(ObjectInfoImpl from) {
|
||||
return from;
|
||||
}
|
||||
}));
|
||||
new Function<ObjectInfoImpl, ObjectInfo>() {
|
||||
public ObjectInfo apply(ObjectInfoImpl from) {
|
||||
return from.toBuilder().container(container).uri(
|
||||
uriBuilders.get().uri(request.getEndpoint()).path(from.getName()).replaceQuery("")
|
||||
.build()).build();
|
||||
}
|
||||
}));
|
||||
boolean truncated = options.getMaxResults() == returnVal.size();
|
||||
String marker = truncated ? returnVal.last().getName() : null;
|
||||
return new PageSetImpl<ObjectInfo>(returnVal, marker);
|
||||
|
@ -92,6 +100,11 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
|
|||
public ParseObjectInfoListFromJsonResponse setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
|
||||
this.request = (GeneratedHttpRequest<?>) request;
|
||||
return setContainer(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
|
||||
}
|
||||
|
||||
private ParseObjectInfoListFromJsonResponse setContainer(String container) {
|
||||
this.container = container;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@ import static org.easymock.classextension.EasyMock.replay;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
|
@ -39,10 +42,11 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.sun.jersey.api.uri.UriBuilderImpl;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ParseObjectInfoListFromJsonResponse}
|
||||
|
@ -57,34 +61,31 @@ public class ParseObjectInfoListFromJsonResponseTest {
|
|||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
bind(UriBuilder.class).to(UriBuilderImpl.class);
|
||||
}
|
||||
|
||||
}, new GsonModule());
|
||||
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_container.json");
|
||||
Set<ObjectInfo> expects = Sets.newLinkedHashSet();
|
||||
ObjectInfoImpl one = i.getInstance(ObjectInfoImpl.class);
|
||||
one.name = "test_obj_1";
|
||||
one.hash = CryptoStreams.hex("4281c348eaf83e70ddce0e07221c3d28");
|
||||
one.bytes = 14l;
|
||||
one.content_type = "application/octet-stream";
|
||||
one.last_modified = new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z");
|
||||
expects.add(one);
|
||||
ObjectInfoImpl two = i.getInstance(ObjectInfoImpl.class);
|
||||
two.name = ("test_obj_2");
|
||||
two.hash = CryptoStreams.hex("b039efe731ad111bc1b0ef221c3849d0");
|
||||
two.bytes = (64l);
|
||||
two.content_type = ("application/octet-stream");
|
||||
two.last_modified = (new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z"));
|
||||
expects.add(two);
|
||||
Set<ObjectInfo> expects = ImmutableSet.<ObjectInfo> of(ObjectInfoImpl.builder().container("container").name(
|
||||
"test_obj_1").uri(URI.create("http://localhost/foo/test_obj_1")).hash(
|
||||
CryptoStreams.hex("4281c348eaf83e70ddce0e07221c3d28")).bytes(14l)
|
||||
.contentType("application/octet-stream").lastModified(
|
||||
new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z")).build(),
|
||||
ObjectInfoImpl.builder().container("container").name("test_obj_2").uri(
|
||||
URI.create("http://localhost/foo/test_obj_2")).hash(
|
||||
CryptoStreams.hex("b039efe731ad111bc1b0ef221c3849d0")).bytes(64l).contentType(
|
||||
"application/octet-stream").lastModified(
|
||||
new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z")).build());
|
||||
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
|
||||
ListContainerOptions options = new ListContainerOptions();
|
||||
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/foo")).atLeastOnce();
|
||||
expect(request.getArgs()).andReturn(
|
||||
ImmutableList.<Object> of("containter", new ListContainerOptions[] { options })).atLeastOnce();
|
||||
ImmutableList.<Object> of("container", new ListContainerOptions[] { options })).atLeastOnce();
|
||||
replay(request);
|
||||
ParseObjectInfoListFromJsonResponse parser = i.getInstance(ParseObjectInfoListFromJsonResponse.class);
|
||||
parser.setContext(request);
|
||||
assertEquals(parser.apply(is), expects);
|
||||
assertEquals(parser.apply(is).toString(), expects.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.blobstore.domain.BlobBuilder;
|
|||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.GetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
|
@ -77,6 +78,12 @@ public interface AsyncBlobStore {
|
|||
*/
|
||||
ListenableFuture<Boolean> createContainerInLocation(@Nullable Location location, String container);
|
||||
|
||||
/**
|
||||
* @see BlobStore#createContainerInLocation(Location,String,CreateContainerOptions)
|
||||
*/
|
||||
ListenableFuture<Boolean> createContainerInLocation(@Nullable Location location, String container,
|
||||
CreateContainerOptions options);
|
||||
|
||||
/**
|
||||
* @see BlobStore#list(String)
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.blobstore.domain.BlobBuilder;
|
|||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.GetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
|
@ -100,6 +101,14 @@ public interface BlobStore {
|
|||
*/
|
||||
boolean createContainerInLocation(@Nullable Location location, String container);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param options
|
||||
* controls default access control
|
||||
* @see #createContainerInLocation(Location,String)
|
||||
*/
|
||||
boolean createContainerInLocation(@Nullable Location location, String container, CreateContainerOptions options);
|
||||
|
||||
/**
|
||||
* Lists all resources in a container non-recursive.
|
||||
*
|
||||
|
|
|
@ -50,10 +50,10 @@ import java.util.Collections;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -61,21 +61,24 @@ import java.util.concurrent.ExecutorService;
|
|||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.MutableStorageMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageType;
|
||||
import org.jclouds.blobstore.domain.Blob.Factory;
|
||||
import org.jclouds.blobstore.domain.internal.MutableStorageMetadataImpl;
|
||||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.GetOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.strategy.IfDirectoryReturnNameStrategy;
|
||||
|
@ -91,6 +94,7 @@ import org.jclouds.http.HttpResponse;
|
|||
import org.jclouds.http.HttpResponseException;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.options.HttpRequestOptions;
|
||||
import org.jclouds.io.ContentMetadata;
|
||||
import org.jclouds.io.MutableContentMetadata;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
|
@ -117,6 +121,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
protected final DateService dateService;
|
||||
protected final Crypto crypto;
|
||||
protected final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
|
||||
protected final Provider<UriBuilder> uriBuilders;
|
||||
protected final ConcurrentMap<String, Location> containerToLocation;
|
||||
protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
|
||||
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||
|
@ -124,16 +129,18 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
|
||||
@Inject
|
||||
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService, Crypto crypto,
|
||||
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
||||
ConcurrentMap<String, Location> containerToLocation, HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Factory blobFactory, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs, Provider<UriBuilder> uriBuilders,
|
||||
ConcurrentMap<String, Location> containerToLocation,
|
||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Factory blobFactory, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
super(context, blobUtils, service, defaultLocation, locations);
|
||||
this.blobFactory = blobFactory;
|
||||
this.dateService = dateService;
|
||||
this.crypto = crypto;
|
||||
this.containerToBlobs = containerToBlobs;
|
||||
this.uriBuilders = uriBuilders;
|
||||
this.containerToLocation = containerToLocation;
|
||||
this.httpGetOptionsConverter = httpGetOptionsConverter;
|
||||
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
||||
|
@ -152,21 +159,21 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return immediateFailedFuture(cnfe(container));
|
||||
|
||||
SortedSet<StorageMetadata> contents = newTreeSet(transform(realContents.keySet(),
|
||||
new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String key) {
|
||||
Blob oldBlob = realContents.get(key);
|
||||
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
|
||||
+ container);
|
||||
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
|
||||
MutableBlobMetadata md = copy(oldBlob.getMetadata());
|
||||
String directoryName = ifDirectoryReturnName.execute(md);
|
||||
if (directoryName != null) {
|
||||
md.setName(directoryName);
|
||||
md.setType(StorageType.RELATIVE_PATH);
|
||||
new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String key) {
|
||||
Blob oldBlob = realContents.get(key);
|
||||
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
|
||||
+ container);
|
||||
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
|
||||
MutableBlobMetadata md = copy(oldBlob.getMetadata());
|
||||
String directoryName = ifDirectoryReturnName.execute(md);
|
||||
if (directoryName != null) {
|
||||
md.setName(directoryName);
|
||||
md.setType(StorageType.RELATIVE_PATH);
|
||||
}
|
||||
return md;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
if (options.getMarker() != null) {
|
||||
final String finalMarker = options.getMarker();
|
||||
|
@ -210,15 +217,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
|
||||
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
|
||||
|
||||
Iterables.<StorageMetadata> addAll(contents,
|
||||
transform(commonPrefixes, new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String o) {
|
||||
MutableStorageMetadata md = new MutableStorageMetadataImpl();
|
||||
md.setType(StorageType.RELATIVE_PATH);
|
||||
md.setName(o);
|
||||
return md;
|
||||
}
|
||||
}));
|
||||
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
|
||||
new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String o) {
|
||||
MutableStorageMetadata md = new MutableStorageMetadataImpl();
|
||||
md.setType(StorageType.RELATIVE_PATH);
|
||||
md.setName(o);
|
||||
return md;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// trim metadata, if the response isn't supposed to be detailed.
|
||||
|
@ -229,13 +236,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
}
|
||||
|
||||
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
|
||||
marker));
|
||||
marker));
|
||||
|
||||
}
|
||||
|
||||
private ContainerNotFoundException cnfe(final String name) {
|
||||
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
|
||||
.keySet()));
|
||||
.keySet()));
|
||||
}
|
||||
|
||||
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
||||
|
@ -333,15 +340,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
|
||||
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String name) {
|
||||
MutableStorageMetadata cmd = create();
|
||||
cmd.setName(name);
|
||||
cmd.setType(StorageType.CONTAINER);
|
||||
cmd.setLocation(getContainerToLocation().get(name));
|
||||
return cmd;
|
||||
}
|
||||
}), null));
|
||||
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
|
||||
public StorageMetadata apply(String name) {
|
||||
MutableStorageMetadata cmd = create();
|
||||
cmd.setName(name);
|
||||
cmd.setType(StorageType.CONTAINER);
|
||||
cmd.setLocation(getContainerToLocation().get(name));
|
||||
return cmd;
|
||||
}
|
||||
}), null));
|
||||
}
|
||||
|
||||
protected MutableStorageMetadata create() {
|
||||
|
@ -365,7 +372,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
*/
|
||||
public ListenableFuture<Void> createContainerInLocationIfAbsent(final Location location, final String name) {
|
||||
ConcurrentMap<String, Blob> container = getContainerToBlobs().putIfAbsent(name,
|
||||
new ConcurrentHashMap<String, Blob>());
|
||||
new ConcurrentHashMap<String, Blob>());
|
||||
if (container == null) {
|
||||
getContainerToLocation().put(name, location != null ? location : defaultLocation.get());
|
||||
return immediateFuture((Void) null);
|
||||
|
@ -495,7 +502,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
new IllegalStateException("containerName not found: " + containerName);
|
||||
}
|
||||
|
||||
Blob blob = createUpdatedCopyOfBlob(in);
|
||||
Blob blob = createUpdatedCopyOfBlobInContainer(containerName, in);
|
||||
|
||||
container.put(blob.getMetadata().getName(), blob);
|
||||
|
||||
|
@ -508,22 +515,22 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
new IllegalStateException("containerName not found: " + containerName);
|
||||
}
|
||||
|
||||
Blob blob = createUpdatedCopyOfBlob(in);
|
||||
Blob blob = createUpdatedCopyOfBlobInContainer(containerName, in);
|
||||
|
||||
Blob old = container.put(blob.getMetadata().getName(), blob);
|
||||
|
||||
return immediateFuture(old);
|
||||
}
|
||||
|
||||
protected Blob createUpdatedCopyOfBlob(Blob in) {
|
||||
protected Blob createUpdatedCopyOfBlobInContainer(String containerName, Blob in) {
|
||||
checkNotNull(in, "blob");
|
||||
checkNotNull(in.getPayload(), "blob.payload");
|
||||
ByteArrayPayload payload = (in.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(in
|
||||
.getPayload()) : null;
|
||||
.getPayload()) : null;
|
||||
if (payload == null)
|
||||
payload = (in.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(in.getPayload())
|
||||
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class.cast(
|
||||
in.getPayload()).getDelegate()) : null : null;
|
||||
.getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(DelegatingPayload.class
|
||||
.cast(in.getPayload()).getDelegate()) : null : null;
|
||||
try {
|
||||
if (payload == null || !(payload instanceof ByteArrayPayload)) {
|
||||
MutableContentMetadata oldMd = in.getPayload().getContentMetadata();
|
||||
|
@ -540,12 +547,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
}
|
||||
Blob blob = blobFactory.create(copy(in.getMetadata()));
|
||||
blob.setPayload(payload);
|
||||
blob.getMetadata().setContainer(containerName);
|
||||
blob.getMetadata().setUri(
|
||||
uriBuilders.get().scheme("mem").host(containerName).path(in.getMetadata().getName()).build());
|
||||
blob.getMetadata().setLastModified(new Date());
|
||||
String eTag = CryptoStreams.hex(payload.getContentMetadata().getContentMD5());
|
||||
blob.getMetadata().setETag(eTag);
|
||||
// Set HTTP headers to match metadata
|
||||
blob.getAllHeaders().replaceValues(HttpHeaders.LAST_MODIFIED,
|
||||
Collections.singleton(dateService.rfc822DateFormat(blob.getMetadata().getLastModified())));
|
||||
Collections.singleton(dateService.rfc822DateFormat(blob.getMetadata().getLastModified())));
|
||||
blob.getAllHeaders().replaceValues(HttpHeaders.ETAG, Collections.singleton(eTag));
|
||||
copyPayloadHeadersToBlob(payload, blob);
|
||||
blob.getAllHeaders().putAll(Multimaps.forMap(blob.getMetadata().getUserMetadata()));
|
||||
|
@ -593,7 +603,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
if (object.getMetadata().getLastModified().before(modifiedSince)) {
|
||||
HttpResponse response = new HttpResponse(304, null, null);
|
||||
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", object
|
||||
.getMetadata().getLastModified(), modifiedSince), null, response));
|
||||
.getMetadata().getLastModified(), modifiedSince), null, response));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -602,7 +612,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
|
||||
HttpResponse response = new HttpResponse(412, null, null);
|
||||
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", object
|
||||
.getMetadata().getLastModified(), unmodifiedSince), null, response));
|
||||
.getMetadata().getLastModified(), unmodifiedSince), null, response));
|
||||
}
|
||||
}
|
||||
Blob returnVal = copyBlob(object);
|
||||
|
@ -633,7 +643,10 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
}
|
||||
|
||||
}
|
||||
ContentMetadata cmd = returnVal.getPayload().getContentMetadata();
|
||||
returnVal.setPayload(out.toByteArray());
|
||||
HttpUtils.copy(cmd, returnVal.getPayload().getContentMetadata());
|
||||
returnVal.getPayload().getContentMetadata().setContentLength(new Long(out.toByteArray().length));
|
||||
}
|
||||
checkNotNull(returnVal.getPayload(), "payload " + returnVal);
|
||||
return immediateFuture(returnVal);
|
||||
|
@ -681,4 +694,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
if (options.isPublicRead())
|
||||
throw new UnsupportedOperationException("publicRead");
|
||||
return createContainerInLocation(location, container);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
package org.jclouds.blobstore.domain;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.blobstore.domain.internal.BlobMetadataImpl;
|
||||
import org.jclouds.io.ContentMetadata;
|
||||
|
||||
|
@ -31,5 +35,20 @@ import com.google.inject.ImplementedBy;
|
|||
*/
|
||||
@ImplementedBy(BlobMetadataImpl.class)
|
||||
public interface BlobMetadata extends StorageMetadata {
|
||||
/**
|
||||
* If the blob is publicly readable, what is the URI one can access it at.
|
||||
*
|
||||
* @return uri, or null, if not readable
|
||||
*/
|
||||
@Nullable
|
||||
URI getPublicUri();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the container holding this blob
|
||||
*/
|
||||
@Nullable
|
||||
String getContainer();
|
||||
|
||||
ContentMetadata getContentMetadata();
|
||||
}
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
package org.jclouds.blobstore.domain;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
|
||||
import org.jclouds.io.MutableContentMetadata;
|
||||
|
||||
|
@ -31,8 +35,24 @@ import com.google.inject.ImplementedBy;
|
|||
*/
|
||||
@ImplementedBy(MutableBlobMetadataImpl.class)
|
||||
public interface MutableBlobMetadata extends BlobMetadata, MutableStorageMetadata {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
MutableContentMetadata getContentMetadata();
|
||||
|
||||
/**
|
||||
* @see BlobMetadata#getContentMetadata
|
||||
*/
|
||||
void setContentMetadata(MutableContentMetadata md);
|
||||
|
||||
/**
|
||||
* @see BlobMetadata#getPublicUri
|
||||
*/
|
||||
void setPublicUri(@Nullable URI publicUri);
|
||||
|
||||
/**
|
||||
* @see BlobMetadata#getContainer
|
||||
*/
|
||||
void setContainer(@Nullable String container);
|
||||
}
|
|
@ -42,14 +42,35 @@ import org.jclouds.io.ContentMetadata;
|
|||
public class BlobMetadataImpl extends StorageMetadataImpl implements Serializable, BlobMetadata {
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -5932618957134612231L;
|
||||
private final URI publicUri;
|
||||
private final String container;
|
||||
private final ContentMetadata contentMetadata;
|
||||
|
||||
public BlobMetadataImpl(String id, String name, @Nullable Location location, URI uri, String eTag,
|
||||
Date lastModified, Map<String, String> userMetadata, ContentMetadata contentMetadata) {
|
||||
Date lastModified, Map<String, String> userMetadata, @Nullable URI publicUri, @Nullable String container,
|
||||
ContentMetadata contentMetadata) {
|
||||
super(StorageType.BLOB, id, name, location, uri, eTag, lastModified, userMetadata);
|
||||
this.publicUri = publicUri;
|
||||
this.container = container;
|
||||
this.contentMetadata = checkNotNull(contentMetadata, "contentMetadata");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getPublicUri() {
|
||||
return publicUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.blobstore.domain.internal;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
|
@ -36,9 +38,10 @@ public class MutableBlobMetadataImpl extends MutableStorageMetadataImpl implemen
|
|||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -5932618957134612231L;
|
||||
private MutableContentMetadata contentMetadata;
|
||||
private URI publicUri;
|
||||
private String container;
|
||||
|
||||
public MutableBlobMetadataImpl() {
|
||||
super();
|
||||
this.setType(StorageType.BLOB);
|
||||
this.contentMetadata = new BaseMutableContentMetadata();
|
||||
}
|
||||
|
@ -47,6 +50,8 @@ public class MutableBlobMetadataImpl extends MutableStorageMetadataImpl implemen
|
|||
super(from);
|
||||
this.contentMetadata = new BaseMutableContentMetadata();
|
||||
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
|
||||
this.publicUri = from.getPublicUri();
|
||||
this.container = from.getContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,4 +70,36 @@ public class MutableBlobMetadataImpl extends MutableStorageMetadataImpl implemen
|
|||
this.contentMetadata = contentMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setPublicUri(URI publicUri) {
|
||||
this.publicUri = publicUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public URI getPublicUri() {
|
||||
return publicUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setContainer(String container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX;
|
||||
import static org.jclouds.blobstore.util.BlobStoreUtils.getNameFor;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -54,6 +55,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
|
|||
private final Provider<MutableBlobMetadata> metadataFactory;
|
||||
|
||||
private String name;
|
||||
private URI endpoint;
|
||||
|
||||
@Inject
|
||||
public ParseSystemAndUserMetadataFromHeaders(Provider<MutableBlobMetadata> metadataFactory, DateService dateParser,
|
||||
|
@ -69,6 +71,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
|
|||
|
||||
MutableBlobMetadata to = metadataFactory.get();
|
||||
to.setName(name);
|
||||
to.setUri(endpoint);
|
||||
if (from.getPayload() != null)
|
||||
HttpUtils.copy(from.getPayload().getContentMetadata(), to.getContentMetadata());
|
||||
addETagTo(from, to);
|
||||
|
@ -115,6 +118,7 @@ public class ParseSystemAndUserMetadataFromHeaders implements Function<HttpRespo
|
|||
}
|
||||
|
||||
public ParseSystemAndUserMetadataFromHeaders setContext(HttpRequest request) {
|
||||
this.endpoint = request.getEndpoint();
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
|
||||
return setName(getNameFor(GeneratedHttpRequest.class.cast(request)));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.blobstore.options;
|
||||
|
||||
/**
|
||||
* Contains options supported in the list container operation. <h2>
|
||||
* Usage</h2> The recommended way to instantiate a CreateOptions object is to statically import
|
||||
* CreateContainerOptions.* and invoke a static creation method followed by an instance mutator (if
|
||||
* needed):
|
||||
* <p/>
|
||||
* <code>
|
||||
* import static org.jclouds.blobstore.options.CreateContainerOptions.Builder.*
|
||||
* <p/>
|
||||
* BlobStore connection = // get connection
|
||||
* Future<CreateResponse<ResourceMetadata>> list = connection.list("container",inDirectory("home/users").maxResults(1000));
|
||||
* <code>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CreateContainerOptions implements Cloneable {
|
||||
|
||||
public static final ImmutableCreateContainerOptions NONE = new ImmutableCreateContainerOptions(
|
||||
new CreateContainerOptions());
|
||||
|
||||
private boolean publicRead;
|
||||
|
||||
public CreateContainerOptions() {
|
||||
}
|
||||
|
||||
CreateContainerOptions(boolean publicRead) {
|
||||
this.publicRead = publicRead;
|
||||
}
|
||||
|
||||
public static class ImmutableCreateContainerOptions extends CreateContainerOptions {
|
||||
private final CreateContainerOptions delegate;
|
||||
|
||||
public ImmutableCreateContainerOptions(CreateContainerOptions delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublicRead() {
|
||||
return delegate.isPublicRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateContainerOptions publicRead() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateContainerOptions clone() {
|
||||
return delegate.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isPublicRead() {
|
||||
return publicRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* return a listing of all objects inside the store, publicReadly.
|
||||
*/
|
||||
public CreateContainerOptions publicRead() {
|
||||
// checkArgument(path == null, "path and publicRead combination currently not supported");
|
||||
this.publicRead = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see CreateContainerOptions#publicRead()
|
||||
*/
|
||||
public static CreateContainerOptions publicRead() {
|
||||
CreateContainerOptions options = new CreateContainerOptions();
|
||||
return options.publicRead();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateContainerOptions clone() {
|
||||
return new CreateContainerOptions(publicRead);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[publicRead=" + publicRead + "]";
|
||||
}
|
||||
}
|
|
@ -49,11 +49,11 @@ import javax.ws.rs.core.MediaType;
|
|||
|
||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobBuilder.PayloadBlobBuilder;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.PageSet;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageType;
|
||||
import org.jclouds.blobstore.domain.BlobBuilder.PayloadBlobBuilder;
|
||||
import org.jclouds.concurrent.Futures;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
|
@ -99,7 +99,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
|
||||
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
|
||||
.getResourceAsStream("/const.txt.gz")));
|
||||
.getResourceAsStream("/const.txt.gz")));
|
||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
|
||||
|
||||
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
|
||||
|
@ -114,178 +114,181 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
@Test(groups = { "integration", "live" })
|
||||
public void testBigFileGets() throws InterruptedException, IOException {
|
||||
final String expectedContentDisposition = "attachment; filename=constit.txt";
|
||||
String containerName = getContainerName();
|
||||
final String container = getContainerName();
|
||||
try {
|
||||
String key = "constitution.txt";
|
||||
final String name = "constitution.txt";
|
||||
|
||||
uploadConstitution(containerName, key, expectedContentDisposition);
|
||||
uploadConstitution(container, name, expectedContentDisposition);
|
||||
Map<Integer, Future<?>> responses = Maps.newHashMap();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
||||
responses.put(i,
|
||||
Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key), new Function<Blob, Void>() {
|
||||
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(container, name),
|
||||
new Function<Blob, Void>() {
|
||||
|
||||
@Override
|
||||
public Void apply(Blob from) {
|
||||
try {
|
||||
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
|
||||
checkContentDisposition(from, expectedContentDisposition);
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
@Override
|
||||
public Void apply(Blob from) {
|
||||
try {
|
||||
validateMetadata(from.getMetadata(), container, name);
|
||||
assertEquals(CryptoStreams.md5(from.getPayload()), oneHundredOneConstitutionsMD5);
|
||||
checkContentDisposition(from, expectedContentDisposition);
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}, this.exec));
|
||||
}, this.exec));
|
||||
}
|
||||
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
|
||||
"get constitution");
|
||||
"get constitution");
|
||||
assert exceptions.size() == 0 : exceptions;
|
||||
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void uploadConstitution(String containerName, String key, String contentDisposition) throws IOException {
|
||||
private void uploadConstitution(String container, String name, String contentDisposition) throws IOException {
|
||||
context.getBlobStore().putBlob(
|
||||
containerName,
|
||||
context.getBlobStore().blobBuilder(key).payload(oneHundredOneConstitutions.getInput())
|
||||
.contentType("text/plain").contentMD5(oneHundredOneConstitutionsMD5)
|
||||
.contentLength(oneHundredOneConstitutionsLength).contentDisposition(contentDisposition).build());
|
||||
container,
|
||||
context.getBlobStore().blobBuilder(name).payload(oneHundredOneConstitutions.getInput()).contentType(
|
||||
"text/plain").contentMD5(oneHundredOneConstitutionsMD5).contentLength(
|
||||
oneHundredOneConstitutionsLength).contentDisposition(contentDisposition).build());
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetIfModifiedSince() throws InterruptedException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
String key = "apples";
|
||||
String name = "apples";
|
||||
|
||||
Date before = new Date(System.currentTimeMillis() - 1000);
|
||||
// first create the blob
|
||||
addObjectAndValidateContent(containerName, key);
|
||||
addObjectAndValidateContent(container, name);
|
||||
// now, modify it
|
||||
addObjectAndValidateContent(containerName, key);
|
||||
addObjectAndValidateContent(container, name);
|
||||
Date after = new Date(System.currentTimeMillis() + 1000);
|
||||
|
||||
context.getBlobStore().getBlob(containerName, key, ifModifiedSince(before));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifModifiedSince(before));
|
||||
validateContent(container, name);
|
||||
|
||||
try {
|
||||
context.getBlobStore().getBlob(containerName, key, ifModifiedSince(after));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifModifiedSince(after));
|
||||
validateContent(container, name);
|
||||
} catch (HttpResponseException ex) {
|
||||
assertEquals(ex.getResponse().getStatusCode(), 304);
|
||||
}
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetIfUnmodifiedSince() throws InterruptedException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
String key = "apples";
|
||||
String name = "apples";
|
||||
|
||||
Date before = new Date(System.currentTimeMillis() - 1000);
|
||||
addObjectAndValidateContent(containerName, key);
|
||||
addObjectAndValidateContent(container, name);
|
||||
Date after = new Date(System.currentTimeMillis() + 1000);
|
||||
|
||||
context.getBlobStore().getBlob(containerName, key, ifUnmodifiedSince(after));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifUnmodifiedSince(after));
|
||||
validateContent(container, name);
|
||||
|
||||
try {
|
||||
context.getBlobStore().getBlob(containerName, key, ifUnmodifiedSince(before));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifUnmodifiedSince(before));
|
||||
validateContent(container, name);
|
||||
} catch (HttpResponseException ex) {
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetIfMatch() throws InterruptedException, UnsupportedEncodingException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
String key = "apples";
|
||||
String name = "apples";
|
||||
|
||||
String goodETag = addObjectAndValidateContent(containerName, key);
|
||||
String goodETag = addObjectAndValidateContent(container, name);
|
||||
|
||||
context.getBlobStore().getBlob(containerName, key, ifETagMatches(goodETag));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifETagMatches(goodETag));
|
||||
validateContent(container, name);
|
||||
|
||||
try {
|
||||
context.getBlobStore().getBlob(containerName, key, ifETagMatches("powerfrisbee"));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifETagMatches("powerfrisbee"));
|
||||
validateContent(container, name);
|
||||
} catch (HttpResponseException ex) {
|
||||
assertEquals(ex.getResponse().getStatusCode(), 412);
|
||||
}
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetIfNoneMatch() throws InterruptedException, UnsupportedEncodingException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
String key = "apples";
|
||||
String name = "apples";
|
||||
|
||||
String goodETag = addObjectAndValidateContent(containerName, key);
|
||||
String goodETag = addObjectAndValidateContent(container, name);
|
||||
|
||||
context.getBlobStore().getBlob(containerName, key, ifETagDoesntMatch("powerfrisbee"));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifETagDoesntMatch("powerfrisbee"));
|
||||
validateContent(container, name);
|
||||
|
||||
try {
|
||||
context.getBlobStore().getBlob(containerName, key, ifETagDoesntMatch(goodETag));
|
||||
validateContent(containerName, key);
|
||||
context.getBlobStore().getBlob(container, name, ifETagDoesntMatch(goodETag));
|
||||
validateContent(container, name);
|
||||
} catch (HttpResponseException ex) {
|
||||
assertEquals(ex.getResponse().getStatusCode(), 304);
|
||||
}
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetRange() throws InterruptedException, IOException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
String key = "apples";
|
||||
String name = "apples";
|
||||
|
||||
addObjectAndValidateContent(containerName, key);
|
||||
Blob blob1 = context.getBlobStore().getBlob(containerName, key, range(0, 5));
|
||||
addObjectAndValidateContent(container, name);
|
||||
Blob blob1 = context.getBlobStore().getBlob(container, name, range(0, 5));
|
||||
validateMetadata(blob1.getMetadata(), container, name);
|
||||
assertEquals(getContentAsStringOrNullAndClose(blob1), TEST_STRING.substring(0, 6));
|
||||
|
||||
Blob blob2 = context.getBlobStore().getBlob(containerName, key, range(6, TEST_STRING.length()));
|
||||
Blob blob2 = context.getBlobStore().getBlob(container, name, range(6, TEST_STRING.length()));
|
||||
validateMetadata(blob2.getMetadata(), container, name);
|
||||
assertEquals(getContentAsStringOrNullAndClose(blob2), TEST_STRING.substring(6, TEST_STRING.length()));
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testGetTwoRanges() throws InterruptedException, IOException {
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
String key = "apples";
|
||||
|
||||
addObjectAndValidateContent(containerName, key);
|
||||
Blob blob = context.getBlobStore().getBlob(containerName, key, range(0, 5).range(6, TEST_STRING.length()));
|
||||
String name = "apples";
|
||||
|
||||
addObjectAndValidateContent(container, name);
|
||||
Blob blob = context.getBlobStore().getBlob(container, name, range(0, 5).range(6, TEST_STRING.length()));
|
||||
validateMetadata(blob.getMetadata(), container, name);
|
||||
assertEquals(getContentAsStringOrNullAndClose(blob), TEST_STRING);
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,13 +296,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
// public void testGetTail() throws InterruptedException, ExecutionException,
|
||||
// TimeoutException,
|
||||
// IOException {
|
||||
// String containerName = getContainerName();
|
||||
// String container = getContainerName();
|
||||
// try {
|
||||
//
|
||||
// String key = "apples";
|
||||
// String name = "apples";
|
||||
//
|
||||
// addObjectAndValidateContent(containerName, key);
|
||||
// Blob blob = context.getBlobStore().getBlob(containerName, key,
|
||||
// addObjectAndValidateContent(container, name);
|
||||
// Blob blob = context.getBlobStore().getBlob(container, name,
|
||||
// tail(5)).get(30,
|
||||
// TimeUnit.SECONDS);
|
||||
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob), TEST_STRING
|
||||
|
@ -307,7 +310,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
// assertEquals(blob.getContentLength(), 5);
|
||||
// assertEquals(blob.getMetadata().getSize(), TEST_STRING.length());
|
||||
// } finally {
|
||||
// returnContainer(containerName);
|
||||
// returnContainer(container);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
@ -316,12 +319,12 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
// ExecutionException,
|
||||
// TimeoutException,
|
||||
// IOException {
|
||||
// String containerName = getContainerName();
|
||||
// String container = getContainerName();
|
||||
// try {
|
||||
// String key = "apples";
|
||||
// String name = "apples";
|
||||
//
|
||||
// addObjectAndValidateContent(containerName, key);
|
||||
// Blob blob = context.getBlobStore().getBlob(containerName, key,
|
||||
// addObjectAndValidateContent(container, name);
|
||||
// Blob blob = context.getBlobStore().getBlob(container, name,
|
||||
// startAt(5)).get(30,
|
||||
// TimeUnit.SECONDS);
|
||||
// assertEquals(BlobStoreUtils.getContentAsStringAndClose(blob),
|
||||
|
@ -330,71 +333,69 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
// assertEquals(blob.getContentLength(), TEST_STRING.length() - 5);
|
||||
// assertEquals(blob.getMetadata().getSize(), TEST_STRING.length());
|
||||
// } finally {
|
||||
// returnContainer(containerName);
|
||||
// returnContainer(container);
|
||||
// }
|
||||
// }
|
||||
|
||||
private String addObjectAndValidateContent(String sourcecontainerName, String sourceKey) throws InterruptedException {
|
||||
String eTag = addBlobToContainer(sourcecontainerName, sourceKey);
|
||||
validateContent(sourcecontainerName, sourceKey);
|
||||
private String addObjectAndValidateContent(String sourcecontainer, String sourceKey) throws InterruptedException {
|
||||
String eTag = addBlobToContainer(sourcecontainer, sourceKey);
|
||||
validateContent(sourcecontainer, sourceKey);
|
||||
return eTag;
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void deleteObjectNotFound() throws InterruptedException {
|
||||
String containerName = getContainerName();
|
||||
String key = "test";
|
||||
String container = getContainerName();
|
||||
String name = "test";
|
||||
try {
|
||||
context.getBlobStore().removeBlob(containerName, key);
|
||||
context.getBlobStore().removeBlob(container, name);
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void blobNotFound() throws InterruptedException {
|
||||
String containerName = getContainerName();
|
||||
String key = "test";
|
||||
String container = getContainerName();
|
||||
String name = "test";
|
||||
try {
|
||||
assert !context.getBlobStore().blobExists(containerName, key);
|
||||
assert !context.getBlobStore().blobExists(container, name);
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "delete")
|
||||
public Object[][] createData() {
|
||||
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
|
||||
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
|
||||
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
|
||||
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" }, dataProvider = "delete")
|
||||
public void deleteObject(String key) throws InterruptedException {
|
||||
String containerName = getContainerName();
|
||||
public void deleteObject(String name) throws InterruptedException {
|
||||
String container = getContainerName();
|
||||
try {
|
||||
addBlobToContainer(containerName, key, key, MediaType.TEXT_PLAIN);
|
||||
context.getBlobStore().removeBlob(containerName, key);
|
||||
assertContainerEmptyDeleting(containerName, key);
|
||||
addBlobToContainer(container, name, name, MediaType.TEXT_PLAIN);
|
||||
context.getBlobStore().removeBlob(container, name);
|
||||
assertContainerEmptyDeleting(container, name);
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertContainerEmptyDeleting(String containerName, String key) {
|
||||
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
|
||||
new Predicate<StorageMetadata>() {
|
||||
private void assertContainerEmptyDeleting(String container, String name) {
|
||||
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(container),
|
||||
new Predicate<StorageMetadata>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(StorageMetadata input) {
|
||||
return input.getType() == StorageType.BLOB;
|
||||
}
|
||||
@Override
|
||||
public boolean apply(StorageMetadata input) {
|
||||
return input.getType() == StorageType.BLOB;
|
||||
}
|
||||
|
||||
});
|
||||
assertEquals(
|
||||
Iterables.size(listing),
|
||||
0,
|
||||
String.format("deleting %s, we still have %s blobs left in container %s, using encoding %s", key,
|
||||
Iterables.size(listing), containerName, LOCAL_ENCODING));
|
||||
});
|
||||
assertEquals(Iterables.size(listing), 0, String.format(
|
||||
"deleting %s, we still have %s blobs left in container %s, using encoding %s", name, Iterables
|
||||
.size(listing), container, LOCAL_ENCODING));
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
|
@ -414,60 +415,63 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
String realObject = Strings2.toStringAndClose(new FileInputStream("pom.xml"));
|
||||
|
||||
return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
|
||||
{ "string", "text/xml", realObject, realObject },
|
||||
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
|
||||
{ "string", "text/xml", realObject, realObject },
|
||||
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
|
||||
public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException,
|
||||
IOException {
|
||||
PayloadBlobBuilder blobBuilder = context.getBlobStore().blobBuilder(key).payload(Payloads.newPayload(content))
|
||||
.contentType(type);
|
||||
public void testPutObject(String name, String type, Object content, Object realObject) throws InterruptedException,
|
||||
IOException {
|
||||
PayloadBlobBuilder blobBuilder = context.getBlobStore().blobBuilder(name).payload(Payloads.newPayload(content))
|
||||
.contentType(type);
|
||||
addContentMetadata(blobBuilder);
|
||||
if (content instanceof InputStream) {
|
||||
blobBuilder.calculateMD5();
|
||||
}
|
||||
Blob blob = blobBuilder.build();
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
assertNotNull(context.getBlobStore().putBlob(containerName, blob));
|
||||
blob = context.getBlobStore().getBlob(containerName, blob.getMetadata().getName());
|
||||
assertNotNull(context.getBlobStore().putBlob(container, blob));
|
||||
blob = context.getBlobStore().getBlob(container, blob.getMetadata().getName());
|
||||
validateMetadata(blob.getMetadata(), container, name);
|
||||
checkContentMetadata(blob);
|
||||
|
||||
String returnedString = getContentAsStringOrNullAndClose(blob);
|
||||
assertEquals(returnedString, realObject);
|
||||
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
|
||||
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(container);
|
||||
assert set.size() == 1 : set;
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testPutObjectStream() throws InterruptedException, IOException, ExecutionException {
|
||||
PayloadBlobBuilder blobBuilder = context.getBlobStore().blobBuilder("streaming").payload(new StreamingPayload(new WriteTo() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
outstream.write("foo".getBytes());
|
||||
}
|
||||
}));
|
||||
PayloadBlobBuilder blobBuilder = context.getBlobStore().blobBuilder("streaming").payload(
|
||||
new StreamingPayload(new WriteTo() {
|
||||
@Override
|
||||
public void writeTo(OutputStream outstream) throws IOException {
|
||||
outstream.write("foo".getBytes());
|
||||
}
|
||||
}));
|
||||
addContentMetadata(blobBuilder);
|
||||
|
||||
|
||||
Blob blob = blobBuilder.build();
|
||||
|
||||
String containerName = getContainerName();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
|
||||
assertNotNull(context.getBlobStore().putBlob(containerName, blob));
|
||||
assertNotNull(context.getBlobStore().putBlob(container, blob));
|
||||
|
||||
blob = context.getBlobStore().getBlob(containerName, blob.getMetadata().getName());
|
||||
blob = context.getBlobStore().getBlob(container, blob.getMetadata().getName());
|
||||
String returnedString = getContentAsStringOrNullAndClose(blob);
|
||||
assertEquals(returnedString, "foo");
|
||||
validateMetadata(blob.getMetadata(), container, blob.getMetadata().getName());
|
||||
checkContentMetadata(blob);
|
||||
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(containerName);
|
||||
PageSet<? extends StorageMetadata> set = context.getBlobStore().list(container);
|
||||
assert set.size() == 1 : set;
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,31 +491,31 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
|
||||
protected void checkContentType(Blob blob, String contentType) {
|
||||
assert blob.getPayload().getContentMetadata().getContentType().startsWith(contentType) : blob.getPayload()
|
||||
.getContentMetadata().getContentType();
|
||||
.getContentMetadata().getContentType();
|
||||
assert blob.getMetadata().getContentMetadata().getContentType().startsWith(contentType) : blob.getMetadata()
|
||||
.getContentMetadata().getContentType();
|
||||
.getContentMetadata().getContentType();
|
||||
}
|
||||
|
||||
protected void checkContentDisposition(Blob blob, String contentDisposition) {
|
||||
assert blob.getPayload().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
|
||||
.getPayload().getContentMetadata().getContentDisposition();
|
||||
.getPayload().getContentMetadata().getContentDisposition();
|
||||
assert blob.getMetadata().getContentMetadata().getContentDisposition().startsWith(contentDisposition) : blob
|
||||
.getMetadata().getContentMetadata().getContentDisposition();
|
||||
.getMetadata().getContentMetadata().getContentDisposition();
|
||||
|
||||
}
|
||||
|
||||
protected void checkContentEncoding(Blob blob, String contentEncoding) {
|
||||
assert (blob.getPayload().getContentMetadata().getContentEncoding().indexOf(contentEncoding) != -1) : blob
|
||||
.getPayload().getContentMetadata().getContentEncoding();
|
||||
.getPayload().getContentMetadata().getContentEncoding();
|
||||
assert (blob.getMetadata().getContentMetadata().getContentEncoding().indexOf(contentEncoding) != -1) : blob
|
||||
.getMetadata().getContentMetadata().getContentEncoding();
|
||||
.getMetadata().getContentMetadata().getContentEncoding();
|
||||
}
|
||||
|
||||
protected void checkContentLanguage(Blob blob, String contentLanguage) {
|
||||
assert blob.getPayload().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
|
||||
.getPayload().getContentMetadata().getContentLanguage();
|
||||
.getPayload().getContentMetadata().getContentLanguage();
|
||||
assert blob.getMetadata().getContentMetadata().getContentLanguage().startsWith(contentLanguage) : blob
|
||||
.getMetadata().getContentMetadata().getContentLanguage();
|
||||
.getMetadata().getContentMetadata().getContentLanguage();
|
||||
}
|
||||
|
||||
protected volatile static Crypto crypto;
|
||||
|
@ -527,40 +531,41 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testMetadata() throws InterruptedException, IOException {
|
||||
String key = "hello";
|
||||
String name = "hello";
|
||||
// NOTE all metadata in jclouds comes out as lowercase, in an effort to
|
||||
// normalize the
|
||||
// providers.
|
||||
Blob blob = context.getBlobStore().blobBuilder(key).userMetadata(ImmutableMap.of("Adrian", "powderpuff"))
|
||||
.payload(TEST_STRING).contentType(MediaType.TEXT_PLAIN).calculateMD5().build();
|
||||
String containerName = getContainerName();
|
||||
Blob blob = context.getBlobStore().blobBuilder(name).userMetadata(ImmutableMap.of("Adrian", "powderpuff"))
|
||||
.payload(TEST_STRING).contentType(MediaType.TEXT_PLAIN).calculateMD5().build();
|
||||
String container = getContainerName();
|
||||
try {
|
||||
assertNull(context.getBlobStore().blobMetadata(containerName, "powderpuff"));
|
||||
assertNull(context.getBlobStore().blobMetadata(container, "powderpuff"));
|
||||
|
||||
addBlobToContainer(containerName, blob);
|
||||
Blob newObject = validateContent(containerName, key);
|
||||
addBlobToContainer(container, blob);
|
||||
Blob newObject = validateContent(container, name);
|
||||
|
||||
BlobMetadata metadata = newObject.getMetadata();
|
||||
|
||||
validateMetadata(metadata);
|
||||
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
||||
validateMetadata(metadata, container, name);
|
||||
validateMetadata(context.getBlobStore().blobMetadata(container, name));
|
||||
|
||||
// write 2 items with the same key to ensure that provider doesn't
|
||||
// write 2 items with the same name to ensure that provider doesn't
|
||||
// accept dupes
|
||||
blob.getMetadata().getUserMetadata().put("Adrian", "wonderpuff");
|
||||
blob.getMetadata().getUserMetadata().put("Adrian", "powderpuff");
|
||||
|
||||
addBlobToContainer(containerName, blob);
|
||||
validateMetadata(context.getBlobStore().blobMetadata(containerName, key));
|
||||
addBlobToContainer(container, blob);
|
||||
validateMetadata(context.getBlobStore().blobMetadata(container, name));
|
||||
|
||||
} finally {
|
||||
returnContainer(containerName);
|
||||
returnContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateMetadata(BlobMetadata metadata) throws IOException {
|
||||
assert metadata.getContentMetadata().getContentType().startsWith("text/plain") : metadata.getContentMetadata()
|
||||
.getContentType();
|
||||
.getContentType();
|
||||
assertEquals(metadata.getContentMetadata().getContentLength(), new Long(TEST_STRING.length()));
|
||||
assertEquals(metadata.getUserMetadata().get("adrian"), "powderpuff");
|
||||
checkMD5(metadata);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.jclouds.blobstore.integration.internal;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Throwables.propagateIfPossible;
|
||||
import static org.jclouds.blobstore.util.BlobStoreUtils.getContentAsStringOrNullAndClose;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
|
@ -40,6 +41,7 @@ import javax.ws.rs.core.MediaType;
|
|||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageType;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
|
@ -62,13 +64,13 @@ public class BaseBlobStoreIntegrationTest {
|
|||
protected static final String TEST_STRING = String.format(XML_STRING_FORMAT, "apple");
|
||||
|
||||
protected Map<String, String> fiveStrings = ImmutableMap.of("one", String.format(XML_STRING_FORMAT, "apple"), "two",
|
||||
String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four",
|
||||
String.format(XML_STRING_FORMAT, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma"));
|
||||
String.format(XML_STRING_FORMAT, "bear"), "three", String.format(XML_STRING_FORMAT, "candy"), "four",
|
||||
String.format(XML_STRING_FORMAT, "dogma"), "five", String.format(XML_STRING_FORMAT, "emma"));
|
||||
|
||||
protected Map<String, String> fiveStringsUnderPath = ImmutableMap.of("path/1",
|
||||
String.format(XML_STRING_FORMAT, "apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3",
|
||||
String.format(XML_STRING_FORMAT, "candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5",
|
||||
String.format(XML_STRING_FORMAT, "emma"));
|
||||
protected Map<String, String> fiveStringsUnderPath = ImmutableMap.of("path/1", String.format(XML_STRING_FORMAT,
|
||||
"apple"), "path/2", String.format(XML_STRING_FORMAT, "bear"), "path/3", String.format(XML_STRING_FORMAT,
|
||||
"candy"), "path/4", String.format(XML_STRING_FORMAT, "dogma"), "path/5", String.format(XML_STRING_FORMAT,
|
||||
"emma"));
|
||||
|
||||
public static long INCONSISTENCY_WINDOW = 10000;
|
||||
protected static volatile AtomicInteger containerIndex = new AtomicInteger(0);
|
||||
|
@ -92,7 +94,7 @@ public class BaseBlobStoreIntegrationTest {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
private BlobStoreContext getCloudResources(ITestContext testContext) throws ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException, Exception {
|
||||
InstantiationException, IllegalAccessException, Exception {
|
||||
String initializerClass = checkNotNull(System.getProperty("test.initializer"), "test.initializer");
|
||||
Class<BaseTestInitializer> clazz = (Class<BaseTestInitializer>) Class.forName(initializerClass);
|
||||
BaseTestInitializer initializer = clazz.newInstance();
|
||||
|
@ -125,7 +127,7 @@ public class BaseBlobStoreIntegrationTest {
|
|||
private static volatile boolean initialized = false;
|
||||
|
||||
protected void createContainersSharedByAllThreads(BlobStoreContext context, ITestContext testContext)
|
||||
throws Exception {
|
||||
throws Exception {
|
||||
while (!initialized) {
|
||||
synchronized (BaseBlobStoreIntegrationTest.class) {
|
||||
if (!initialized) {
|
||||
|
@ -176,12 +178,12 @@ public class BaseBlobStoreIntegrationTest {
|
|||
try {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
Iterable<? extends StorageMetadata> testContainers = Iterables.filter(context.getBlobStore().list(),
|
||||
new Predicate<StorageMetadata>() {
|
||||
public boolean apply(StorageMetadata input) {
|
||||
return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER)
|
||||
&& input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());
|
||||
}
|
||||
});
|
||||
new Predicate<StorageMetadata>() {
|
||||
public boolean apply(StorageMetadata input) {
|
||||
return (input.getType() == StorageType.CONTAINER || input.getType() == StorageType.FOLDER)
|
||||
&& input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());
|
||||
}
|
||||
});
|
||||
for (StorageMetadata container : testContainers) {
|
||||
deleteContainerOrWarnIfUnable(context, container.getName());
|
||||
}
|
||||
|
@ -202,7 +204,7 @@ public class BaseBlobStoreIntegrationTest {
|
|||
* we will try up to the inconsistency window to see if the assertion completes.
|
||||
*/
|
||||
protected static void assertConsistencyAware(BlobStoreContext context, Runnable assertion)
|
||||
throws InterruptedException {
|
||||
throws InterruptedException {
|
||||
if (context.getConsistencyModel() == ConsistencyModel.STRICT) {
|
||||
assertion.run();
|
||||
return;
|
||||
|
@ -228,7 +230,7 @@ public class BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
|
||||
protected static void createContainerAndEnsureEmpty(BlobStoreContext context, final String containerName)
|
||||
throws InterruptedException {
|
||||
throws InterruptedException {
|
||||
context.getBlobStore().createContainerInLocation(null, containerName);
|
||||
if (context.getConsistencyModel() == ConsistencyModel.EVENTUAL)
|
||||
Thread.sleep(1000);
|
||||
|
@ -250,8 +252,8 @@ public class BaseBlobStoreIntegrationTest {
|
|||
|
||||
protected void add5BlobsUnderPathAnd5UnderRootToContainer(String sourceContainer) {
|
||||
for (Entry<String, String> entry : Iterables.concat(fiveStrings.entrySet(), fiveStringsUnderPath.entrySet())) {
|
||||
Blob sourceObject = context.getBlobStore().blobBuilder(entry.getKey()).payload(entry.getValue())
|
||||
.contentType("text/xml").build();
|
||||
Blob sourceObject = context.getBlobStore().blobBuilder(entry.getKey()).payload(entry.getValue()).contentType(
|
||||
"text/xml").build();
|
||||
addBlobToContainer(sourceContainer, sourceObject);
|
||||
}
|
||||
}
|
||||
|
@ -260,10 +262,18 @@ public class BaseBlobStoreIntegrationTest {
|
|||
return context.getBlobStore().putBlob(sourceContainer, object);
|
||||
}
|
||||
|
||||
protected Blob validateContent(String sourceContainer, String key) throws InterruptedException {
|
||||
assertConsistencyAwareContainerSize(sourceContainer, 1);
|
||||
Blob newObject = context.getBlobStore().getBlob(sourceContainer, key);
|
||||
protected <T extends BlobMetadata> T validateMetadata(T md, String container, String name) {
|
||||
assertEquals(md.getName(), name);
|
||||
assertEquals(md.getContainer(), container);
|
||||
assert md.getUri() != null;
|
||||
return md;
|
||||
}
|
||||
|
||||
protected Blob validateContent(String container, String name) throws InterruptedException {
|
||||
assertConsistencyAwareContainerSize(container, 1);
|
||||
Blob newObject = context.getBlobStore().getBlob(container, name);
|
||||
assert newObject != null;
|
||||
validateMetadata(newObject.getMetadata(), container, name);
|
||||
try {
|
||||
assertEquals(getContentAsStringOrNullAndClose(newObject), TEST_STRING);
|
||||
} catch (IOException e) {
|
||||
|
@ -273,19 +283,19 @@ public class BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
|
||||
protected void assertConsistencyAwareContainerSize(final String containerName, final int count)
|
||||
throws InterruptedException {
|
||||
throws InterruptedException {
|
||||
assertConsistencyAware(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assert context.getBlobStore().countBlobs(containerName) == count : String.format(
|
||||
"expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform(
|
||||
context.getBlobStore().list(containerName), new Function<StorageMetadata, String>() {
|
||||
"expected only %d values in %s: %s", count, containerName, Sets.newHashSet(Iterables.transform(
|
||||
context.getBlobStore().list(containerName), new Function<StorageMetadata, String>() {
|
||||
|
||||
public String apply(StorageMetadata from) {
|
||||
return from.getName();
|
||||
}
|
||||
public String apply(StorageMetadata from) {
|
||||
return from.getName();
|
||||
}
|
||||
|
||||
})));
|
||||
})));
|
||||
} catch (Exception e) {
|
||||
Throwables.propagateIfPossible(e);
|
||||
}
|
||||
|
@ -334,6 +344,19 @@ public class BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
protected void assertNotExists(final String containerName) throws InterruptedException {
|
||||
assertConsistencyAware(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assert !context.getBlobStore().containerExists(containerName) : "container " + containerName
|
||||
+ " still exists";
|
||||
} catch (Exception e) {
|
||||
propagateIfPossible(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* abandon old container name instead of waiting for the container to be created.
|
||||
*
|
||||
|
|
|
@ -295,19 +295,6 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
private void assertNotExists(final String containerName) throws InterruptedException {
|
||||
assertConsistencyAware(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
assert !context.getBlobStore().containerExists(containerName) : "container " + containerName
|
||||
+ " still exists";
|
||||
} catch (Exception e) {
|
||||
propagateIfPossible(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(groups = { "integration", "live" })
|
||||
public void testListContainer() throws InterruptedException, ExecutionException, TimeoutException,
|
||||
UnsupportedEncodingException {
|
||||
|
|
|
@ -19,10 +19,40 @@
|
|||
|
||||
package org.jclouds.blobstore.integration.internal;
|
||||
|
||||
import static org.jclouds.blobstore.options.CreateContainerOptions.Builder.publicRead;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BaseContainerLiveTest extends BaseBlobStoreIntegrationTest {
|
||||
|
||||
@Test(groups = { "live" })
|
||||
public void testPublicAccess() throws InterruptedException, MalformedURLException, IOException {
|
||||
final String containerName = getScratchContainerName();
|
||||
try {
|
||||
context.getBlobStore().createContainerInLocation(null, containerName, publicRead());
|
||||
assertConsistencyAwareContainerSize(containerName, 0);
|
||||
|
||||
context.getBlobStore().putBlob(containerName,
|
||||
context.getBlobStore().blobBuilder("hello").payload(TEST_STRING).build());
|
||||
assertConsistencyAwareContainerSize(containerName, 1);
|
||||
|
||||
BlobMetadata metadata = context.getBlobStore().blobMetadata(containerName, "hello");
|
||||
|
||||
assertEquals(Strings2.toStringAndClose(metadata.getPublicUri().toURL().openStream()), TEST_STRING);
|
||||
|
||||
} finally {
|
||||
// this container is now public, so we can't reuse it directly
|
||||
recycleContainer(containerName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.http.functions;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.http.functions.config.SaxParserModule;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
|
@ -26,6 +28,7 @@ import org.testng.annotations.Test;
|
|||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.sun.jersey.api.uri.UriBuilderImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -39,7 +42,12 @@ public class BaseHandlerTest {
|
|||
|
||||
@BeforeTest
|
||||
protected void setUpInjector() {
|
||||
injector = Guice.createInjector(new SaxParserModule());
|
||||
injector = Guice.createInjector(new SaxParserModule() {
|
||||
public void configure() {
|
||||
super.configure();
|
||||
bind(UriBuilder.class).to(UriBuilderImpl.class);
|
||||
}
|
||||
});
|
||||
factory = injector.getInstance(ParseSax.Factory.class);
|
||||
assert factory != null;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
|
@ -30,7 +31,6 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.aws.s3.AWSS3AsyncClient;
|
||||
import org.jclouds.aws.s3.AWSS3Client;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.AsyncMultipartUploadStrategy;
|
||||
import org.jclouds.aws.s3.blobstore.strategy.MultipartUploadStrategy;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
|
@ -45,9 +45,9 @@ import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
|||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
|
@ -60,16 +60,16 @@ public class AWSS3AsyncBlobStore extends S3AsyncBlobStore {
|
|||
|
||||
@Inject
|
||||
public AWSS3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AWSS3AsyncClient async, AWSS3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
|
||||
Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy) {
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AWSS3AsyncClient async, AWSS3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, Map<String, AccessControlList> bucketAcls,
|
||||
Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy) {
|
||||
super(context, blobUtils, service, defaultLocation, locations, async, sync, bucket2ResourceMd,
|
||||
container2BucketListOptions, bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object,
|
||||
object2BlobMd, fetchBlobMetadataProvider);
|
||||
container2BucketListOptions, bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object,
|
||||
object2BlobMd, fetchBlobMetadataProvider, bucketAcls);
|
||||
this.multipartUploadStrategy = multipartUploadStrategy;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -40,6 +41,7 @@ import org.jclouds.s3.blobstore.functions.BucketToResourceMetadata;
|
|||
import org.jclouds.s3.blobstore.functions.ContainerToBucketListOptions;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlob;
|
||||
import org.jclouds.s3.blobstore.functions.ObjectToBlobMetadata;
|
||||
import org.jclouds.s3.domain.AccessControlList;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
|
@ -54,14 +56,15 @@ public class AWSS3BlobStore extends S3BlobStore {
|
|||
|
||||
@Inject
|
||||
AWSS3BlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AWSS3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, Provider<MultipartUploadStrategy> multipartUploadStrategy) {
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AWSS3Client sync,
|
||||
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, Map<String, AccessControlList> bucketAcls,
|
||||
Provider<MultipartUploadStrategy> multipartUploadStrategy) {
|
||||
super(context, blobUtils, defaultLocation, locations, sync, bucket2ResourceMd, container2BucketListOptions,
|
||||
bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object, object2BlobMd,
|
||||
fetchBlobMetadataProvider);
|
||||
bucket2ResourceList, object2Blob, blob2ObjectGetOptions, blob2Object, object2BlobMd,
|
||||
fetchBlobMetadataProvider, bucketAcls);
|
||||
this.multipartUploadStrategy = multipartUploadStrategy;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,22 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3BlobIntegrationLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3BlobIntegrationLiveTest")
|
||||
public class AWSS3BlobIntegrationLiveTest extends BaseBlobIntegrationTest {
|
||||
|
||||
@Override
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testPutObjectStream() throws InterruptedException, IOException, ExecutionException {
|
||||
super.testPutObjectStream();
|
||||
}
|
||||
@Test(groups = "live", testName = "AWSS3BlobIntegrationLiveTest")
|
||||
public class AWSS3BlobIntegrationLiveTest extends S3BlobIntegrationLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3BlobLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3BlobLiveTest")
|
||||
public class AWSS3BlobLiveTest extends BaseBlobLiveTest {
|
||||
@Test(groups = "live", testName = "AWSS3BlobLiveTest")
|
||||
public class AWSS3BlobLiveTest extends S3BlobLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobMapIntegrationTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3BlobMapIntegrationLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3BlobMapIntegrationLiveTest")
|
||||
public class AWSS3BlobMapIntegrationLiveTest extends BaseBlobMapIntegrationTest {
|
||||
@Test(groups = "live", testName = "AWSS3BlobMapIntegrationLiveTest")
|
||||
public class AWSS3BlobMapIntegrationLiveTest extends S3BlobMapIntegrationLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3BlobSignerLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3BlobSignerLiveTest")
|
||||
public class AWSS3BlobSignerLiveTest extends BaseBlobSignerLiveTest {
|
||||
@Test(groups = "live", testName = "AWSS3BlobSignerLiveTest")
|
||||
public class AWSS3BlobSignerLiveTest extends S3BlobSignerLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3ContainerIntegrationLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3ContainerIntegrationLiveTest")
|
||||
public class AWSS3ContainerIntegrationLiveTest extends BaseContainerIntegrationTest {
|
||||
public class AWSS3ContainerIntegrationLiveTest extends S3ContainerIntegrationLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3ContainerLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3ContainerLiveTest")
|
||||
public class AWSS3ContainerLiveTest extends BaseContainerLiveTest {
|
||||
@Test(groups = "live", testName = "AWSS3ContainerLiveTest")
|
||||
public class AWSS3ContainerLiveTest extends S3ContainerLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.jclouds.aws.s3.blobstore.integration;
|
||||
|
||||
import org.jclouds.blobstore.integration.internal.BaseInputStreamMapIntegrationTest;
|
||||
import org.jclouds.s3.blobstore.integration.S3InputStreamMapIntegrationLiveTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "live", testName = "AWSS3InputStreamMapIntegrationLiveTest")
|
||||
public class AWSS3InputStreamMapIntegrationLiveTest extends BaseInputStreamMapIntegrationTest {
|
||||
public class AWSS3InputStreamMapIntegrationLiveTest extends S3InputStreamMapIntegrationLiveTest {
|
||||
|
||||
}
|
||||
|
|
|
@ -29,24 +29,26 @@ import javax.ws.rs.PUT;
|
|||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
|
||||
import org.jclouds.azureblob.binders.BindAzureBlobMetadataToRequest;
|
||||
import org.jclouds.azureblob.domain.BlobProperties;
|
||||
import org.jclouds.azureblob.domain.ContainerProperties;
|
||||
import org.jclouds.azureblob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.functions.BlobName;
|
||||
import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
|
||||
import org.jclouds.azureblob.functions.ParseBlobPropertiesFromHeaders;
|
||||
import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
|
||||
import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
|
||||
import org.jclouds.azureblob.functions.ReturnFalseIfContainerAlreadyExists;
|
||||
import org.jclouds.azureblob.options.CreateContainerOptions;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.azureblob.predicates.validators.ContainerNameValidator;
|
||||
import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
|
||||
import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
|
||||
import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
|
||||
import org.jclouds.blobstore.functions.ReturnFalseOnContainerNotFound;
|
||||
import org.jclouds.blobstore.functions.ReturnFalseOnKeyNotFound;
|
||||
|
@ -95,8 +97,7 @@ public interface AzureBlobAsyncClient {
|
|||
@GET
|
||||
@XMLResponseParser(AccountNameEnumerationResultsHandler.class)
|
||||
@QueryParams(keys = "comp", values = "list")
|
||||
ListenableFuture<? extends BoundedSet<ContainerProperties>> listContainers(
|
||||
ListOptions... listOptions);
|
||||
ListenableFuture<? extends BoundedSet<ContainerProperties>> listContainers(ListOptions... listOptions);
|
||||
|
||||
/**
|
||||
* @see AzureBlobClient#createContainer
|
||||
|
@ -109,6 +110,17 @@ public interface AzureBlobAsyncClient {
|
|||
@PathParam("container") @ParamValidators( { ContainerNameValidator.class }) String container,
|
||||
CreateContainerOptions... options);
|
||||
|
||||
/**
|
||||
* @see AzureBlobClient#getPublicAccessForContainer
|
||||
*/
|
||||
@HEAD
|
||||
@Path("{container}")
|
||||
@QueryParams(keys = { "restype", "comp" }, values = { "container", "acl" })
|
||||
@ResponseParser(ParsePublicAccessHeader.class)
|
||||
@ExceptionParser(ReturnNullOnContainerNotFound.class)
|
||||
ListenableFuture<PublicAccess> getPublicAccessForContainer(
|
||||
@PathParam("container") @ParamValidators( { ContainerNameValidator.class }) String container);
|
||||
|
||||
/**
|
||||
* @see AzureBlobClient#getContainerProperties
|
||||
*/
|
||||
|
@ -238,8 +250,7 @@ public interface AzureBlobAsyncClient {
|
|||
@QueryParams(keys = { "comp" }, values = { "metadata" })
|
||||
ListenableFuture<Void> setBlobMetadata(
|
||||
@PathParam("container") @ParamValidators( { ContainerNameValidator.class }) String container,
|
||||
@PathParam("name") String name,
|
||||
@BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
|
||||
@PathParam("name") String name, @BinderParam(BindMapToHeadersWithPrefix.class) Map<String, String> metadata);
|
||||
|
||||
/**
|
||||
* @see AzureBlobClient#deleteBlob
|
||||
|
|
|
@ -21,29 +21,28 @@ package org.jclouds.azureblob;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.azureblob.domain.BlobProperties;
|
||||
import org.jclouds.azureblob.domain.ContainerProperties;
|
||||
import org.jclouds.azureblob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.options.CreateContainerOptions;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.blobstore.ContainerNotFoundException;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.http.options.GetOptions;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Provides access to Azure Blob via their REST API.
|
||||
* <p/>
|
||||
* All commands return a Future of the result from Azure Blob. Any exceptions incurred
|
||||
* during processing will be wrapped in an {@link ExecutionException} as documented in
|
||||
* {@link Future#get()}.
|
||||
* All commands return a Future of the result from Azure Blob. Any exceptions incurred during
|
||||
* processing will be wrapped in an {@link ExecutionException} as documented in {@link Future#get()}.
|
||||
*
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
|
||||
* @author Adrian Cole
|
||||
|
@ -131,6 +130,14 @@ public interface AzureBlobClient {
|
|||
*/
|
||||
boolean createRootContainer(CreateContainerOptions... options);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param container
|
||||
* @return whether data in the container may be accessed publicly and the level of access
|
||||
*/
|
||||
PublicAccess getPublicAccessForContainer(String container);
|
||||
|
||||
/**
|
||||
* The Delete Container operation marks the specified container for deletion. The container and
|
||||
* any blobs contained within it are later deleted during garbage collection. <h4>Remarks</h4>
|
||||
|
@ -214,8 +221,7 @@ public interface AzureBlobClient {
|
|||
* properties.
|
||||
*/
|
||||
@Timeout(duration = 10 * 64, timeUnit = TimeUnit.MINUTES)
|
||||
org.jclouds.azureblob.domain.AzureBlob getBlob(String container, String name,
|
||||
GetOptions... options);
|
||||
org.jclouds.azureblob.domain.AzureBlob getBlob(String container, String name, GetOptions... options);
|
||||
|
||||
/**
|
||||
* The Get Blob Properties operation returns all user-defined metadata, standard HTTP properties,
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.jclouds.azureblob.domain.AzureBlob;
|
|||
import org.jclouds.azureblob.domain.BlobProperties;
|
||||
import org.jclouds.azureblob.domain.ContainerProperties;
|
||||
import org.jclouds.azureblob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
|
@ -51,6 +52,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
|
@ -79,18 +81,18 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
|
||||
@Inject
|
||||
AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AzureBlobAsyncClient async,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
||||
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
||||
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions) {
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, AzureBlobAsyncClient async,
|
||||
ContainerToResourceMetadata container2ResourceMd,
|
||||
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
||||
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
||||
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
||||
BlobToHttpGetOptions blob2ObjectGetOptions) {
|
||||
super(context, blobUtils, service, defaultLocation, locations);
|
||||
this.async = checkNotNull(async, "async");
|
||||
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
||||
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
||||
"blobStore2AzureContainerListOptions");
|
||||
"blobStore2AzureContainerListOptions");
|
||||
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, "azure2BlobStoreResourceList");
|
||||
this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
|
||||
this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
|
||||
|
@ -105,15 +107,15 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
@Override
|
||||
public ListenableFuture<org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
|
||||
return Futures
|
||||
.compose(
|
||||
async.listContainers(includeMetadata()),
|
||||
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
||||
BoundedSet<ContainerProperties> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), from
|
||||
.getNextMarker());
|
||||
}
|
||||
}, service);
|
||||
.compose(
|
||||
async.listContainers(includeMetadata()),
|
||||
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
||||
BoundedSet<ContainerProperties> from) {
|
||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd),
|
||||
from.getNextMarker());
|
||||
}
|
||||
}, service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,4 +250,12 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
|||
return putBlob(container, blob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
|
||||
CreateContainerOptions options) {
|
||||
org.jclouds.azureblob.options.CreateContainerOptions createContainerOptions = new org.jclouds.azureblob.options.CreateContainerOptions();
|
||||
if (options.isPublicRead())
|
||||
createContainerOptions.withPublicAccess(PublicAccess.CONTAINER);
|
||||
return async.createContainer(container, createContainerOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azureblob.AzureBlobClient;
|
||||
import org.jclouds.azureblob.blobstore.functions.AzureBlobToBlob;
|
||||
import org.jclouds.azureblob.blobstore.functions.BlobPropertiesToBlobMetadata;
|
||||
|
@ -35,8 +36,8 @@ import org.jclouds.azureblob.blobstore.functions.ContainerToResourceMetadata;
|
|||
import org.jclouds.azureblob.blobstore.functions.ListBlobsResponseToResourceList;
|
||||
import org.jclouds.azureblob.blobstore.functions.ListOptionsToListBlobsOptions;
|
||||
import org.jclouds.azureblob.domain.ContainerProperties;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.domain.Blob;
|
||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||
|
@ -45,6 +46,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
|||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||
import org.jclouds.blobstore.internal.BaseBlobStore;
|
||||
import org.jclouds.blobstore.options.CreateContainerOptions;
|
||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
|
@ -236,4 +238,11 @@ public class AzureBlobStore extends BaseBlobStore {
|
|||
throw new UnsupportedOperationException("please use deleteContainer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) {
|
||||
org.jclouds.azureblob.options.CreateContainerOptions createContainerOptions = new org.jclouds.azureblob.options.CreateContainerOptions();
|
||||
if (options.isPublicRead())
|
||||
createContainerOptions.withPublicAccess(PublicAccess.CONTAINER);
|
||||
return sync.createContainer(container, createContainerOptions);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,18 @@
|
|||
|
||||
package org.jclouds.azureblob.blobstore.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.azureblob.AzureBlobAsyncClient;
|
||||
import org.jclouds.azureblob.AzureBlobClient;
|
||||
import org.jclouds.azureblob.blobstore.AzureAsyncBlobStore;
|
||||
import org.jclouds.azureblob.blobstore.AzureBlobRequestSigner;
|
||||
import org.jclouds.azureblob.blobstore.AzureBlobStore;
|
||||
import org.jclouds.azureblob.blobstore.strategy.FindMD5InBlobProperties;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.blobstore.AsyncBlobStore;
|
||||
import org.jclouds.blobstore.BlobRequestSigner;
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
|
@ -35,7 +41,10 @@ import org.jclouds.blobstore.internal.BlobStoreContextImpl;
|
|||
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||
import org.jclouds.location.config.JustProviderLocationModule;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.TypeLiteral;
|
||||
|
||||
|
@ -59,4 +68,19 @@ public class AzureBlobStoreContextModule extends AbstractModule {
|
|||
bind(BlobRequestSigner.class).to(AzureBlobRequestSigner.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Map<String, PublicAccess> containerAcls(final AzureBlobClient client) {
|
||||
return new MapMaker().expireAfterWrite(30, TimeUnit.SECONDS).makeComputingMap(
|
||||
new Function<String, PublicAccess>() {
|
||||
public PublicAccess apply(String container) {
|
||||
return client.getPublicAccessForContainer(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getPublicAccessForContainer()";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ public class BlobMetadataToBlobProperties implements Function<BlobMetadata, Muta
|
|||
HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata());
|
||||
to.setETag(from.getETag());
|
||||
to.setName(from.getName());
|
||||
to.setUrl(from.getUri());
|
||||
to.setLastModified(from.getLastModified());
|
||||
if (from.getUserMetadata() != null) {
|
||||
for (Entry<String, String> entry : from.getUserMetadata().entrySet())
|
||||
|
|
|
@ -21,10 +21,13 @@ package org.jclouds.azureblob.blobstore.functions;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.azureblob.domain.BlobProperties;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||
import org.jclouds.blobstore.domain.StorageType;
|
||||
import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl;
|
||||
|
@ -39,10 +42,13 @@ import com.google.common.base.Function;
|
|||
@Singleton
|
||||
public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, MutableBlobMetadata> {
|
||||
private final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||
private final Map<String, PublicAccess> containerAcls;
|
||||
|
||||
@Inject
|
||||
public BlobPropertiesToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName) {
|
||||
public BlobPropertiesToBlobMetadata(IfDirectoryReturnNameStrategy ifDirectoryReturnName,
|
||||
Map<String, PublicAccess> containerAcls) {
|
||||
this.ifDirectoryReturnName = checkNotNull(ifDirectoryReturnName, "ifDirectoryReturnName");
|
||||
this.containerAcls = checkNotNull(containerAcls, "containerAcls");
|
||||
}
|
||||
|
||||
public MutableBlobMetadata apply(BlobProperties from) {
|
||||
|
@ -54,6 +60,15 @@ public class BlobPropertiesToBlobMetadata implements Function<BlobProperties, Mu
|
|||
to.setETag(from.getETag());
|
||||
to.setLastModified(from.getLastModified());
|
||||
to.setName(from.getName());
|
||||
to.setContainer(from.getContainer());
|
||||
to.setUri(from.getUrl());
|
||||
try {
|
||||
PublicAccess containerAcl = containerAcls.get(from.getContainer());
|
||||
if (containerAcl != null && containerAcl != PublicAccess.PRIVATE)
|
||||
to.setPublicUri(from.getUrl());
|
||||
} catch (NullPointerException e) {
|
||||
// MapMaker cannot return null, but a call to get acls can
|
||||
}
|
||||
String directoryName = ifDirectoryReturnName.execute(to);
|
||||
if (directoryName != null) {
|
||||
to.setName(directoryName);
|
||||
|
|
|
@ -45,6 +45,8 @@ public interface BlobProperties extends Comparable<BlobProperties> {
|
|||
|
||||
String getName();
|
||||
|
||||
String getContainer();
|
||||
|
||||
Date getLastModified();
|
||||
|
||||
String getETag();
|
||||
|
|
|
@ -44,7 +44,11 @@ public interface MutableBlobProperties extends BlobProperties {
|
|||
* @see ListableContainerProperties#getName
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* @see ListableContainerProperties#getContainer
|
||||
*/
|
||||
void setContainer(String container);
|
||||
|
||||
/**
|
||||
* @see ListableContainerProperties#getLastModified
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed 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.azureblob.domain;
|
||||
|
||||
/**
|
||||
* Indicates whether data in the container may be accessed publicly and the level of access.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd179469.aspx"/>
|
||||
*/
|
||||
public enum PublicAccess {
|
||||
/**
|
||||
* Indicates full public read access for container and blob data. Clients can enumerate blobs
|
||||
* within the container via anonymous request, but cannot enumerate containers within the storage
|
||||
* account.
|
||||
*/
|
||||
CONTAINER,
|
||||
/**
|
||||
* Indicates public read access for blobs. Blob data within this container can be read via
|
||||
* anonymous request, but container data is not available. Clients cannot enumerate blobs within
|
||||
* the container via anonymous request.
|
||||
*/
|
||||
BLOB,
|
||||
/**
|
||||
* the container is private to the account owner.
|
||||
*/
|
||||
PRIVATE;
|
||||
|
||||
}
|
|
@ -47,6 +47,7 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
private static final long serialVersionUID = -4648755473986695062L;
|
||||
private final BlobType type;
|
||||
private final String name;
|
||||
private final String container;
|
||||
private final URI url;
|
||||
private final Date lastModified;
|
||||
private final String eTag;
|
||||
|
@ -54,12 +55,13 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
private final LeaseStatus leaseStatus;
|
||||
private final BaseImmutableContentMetadata contentMetadata;
|
||||
|
||||
public BlobPropertiesImpl(BlobType type, String name, URI url, Date lastModified, String eTag, long size,
|
||||
String contentType, @Nullable byte[] contentMD5, @Nullable String contentMetadata,
|
||||
public BlobPropertiesImpl(BlobType type, String name, String container, URI url, Date lastModified, String eTag,
|
||||
long size, String contentType, @Nullable byte[] contentMD5, @Nullable String contentMetadata,
|
||||
@Nullable String contentLanguage, LeaseStatus leaseStatus, Map<String, String> metadata) {
|
||||
this.type = checkNotNull(type, "type");
|
||||
this.leaseStatus = checkNotNull(leaseStatus, "leaseStatus");
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.container = checkNotNull(container, "container");
|
||||
this.url = checkNotNull(url, "url");
|
||||
this.lastModified = checkNotNull(lastModified, "lastModified");
|
||||
this.eTag = checkNotNull(eTag, "eTag");
|
||||
|
@ -84,6 +86,14 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
|
@ -144,13 +154,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
|
||||
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((leaseStatus == null) ? 0 : leaseStatus.hashCode());
|
||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -164,41 +167,6 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BlobPropertiesImpl other = (BlobPropertiesImpl) obj;
|
||||
if (contentMetadata == null) {
|
||||
if (other.contentMetadata != null)
|
||||
return false;
|
||||
} else if (!contentMetadata.equals(other.contentMetadata))
|
||||
return false;
|
||||
if (eTag == null) {
|
||||
if (other.eTag != null)
|
||||
return false;
|
||||
} else if (!eTag.equals(other.eTag))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (leaseStatus == null) {
|
||||
if (other.leaseStatus != null)
|
||||
return false;
|
||||
} else if (!leaseStatus.equals(other.leaseStatus))
|
||||
return false;
|
||||
if (metadata == null) {
|
||||
if (other.metadata != null)
|
||||
return false;
|
||||
} else if (!metadata.equals(other.metadata))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
} else if (!type.equals(other.type))
|
||||
return false;
|
||||
if (url == null) {
|
||||
if (other.url != null)
|
||||
return false;
|
||||
|
@ -209,8 +177,9 @@ public class BlobPropertiesImpl implements Serializable, BlobProperties {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=" + name + ", type=" + type + ", contentMetadata=" + contentMetadata + ", eTag=" + eTag
|
||||
+ ", lastModified=" + lastModified + "]";
|
||||
return String
|
||||
.format(
|
||||
"[name=%s, container=%s, url=%s, contentMetadata=%s, eTag=%s, lastModified=%s, leaseStatus=%s, metadata=%s, type=%s]",
|
||||
name, container, url, contentMetadata, eTag, lastModified, leaseStatus, metadata, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
private LeaseStatus leaseStatus = LeaseStatus.UNLOCKED;
|
||||
|
||||
private String name;
|
||||
private String container;
|
||||
private URI url;
|
||||
private Date lastModified;
|
||||
private String eTag;
|
||||
|
@ -61,12 +62,19 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
|
||||
public MutableBlobPropertiesImpl(BlobProperties from) {
|
||||
this.contentMetadata = new BaseMutableContentMetadata();
|
||||
this.name = from.getName();
|
||||
this.container = from.getContainer();
|
||||
this.url = from.getUrl();
|
||||
this.lastModified = from.getLastModified();
|
||||
this.eTag = from.getETag();
|
||||
this.metadata.putAll(from.getMetadata());
|
||||
HttpUtils.copy(from.getContentMetadata(), this.contentMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public BlobType getType() {
|
||||
return type;
|
||||
}
|
||||
|
@ -161,12 +169,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode());
|
||||
result = prime * result + ((eTag == null) ? 0 : eTag.hashCode());
|
||||
result = prime * result + ((lastModified == null) ? 0 : lastModified.hashCode());
|
||||
result = prime * result + ((metadata == null) ? 0 : metadata.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
@ -180,36 +182,6 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MutableBlobPropertiesImpl other = (MutableBlobPropertiesImpl) obj;
|
||||
if (contentMetadata == null) {
|
||||
if (other.contentMetadata != null)
|
||||
return false;
|
||||
} else if (!contentMetadata.equals(other.contentMetadata))
|
||||
return false;
|
||||
if (eTag == null) {
|
||||
if (other.eTag != null)
|
||||
return false;
|
||||
} else if (!eTag.equals(other.eTag))
|
||||
return false;
|
||||
if (lastModified == null) {
|
||||
if (other.lastModified != null)
|
||||
return false;
|
||||
} else if (!lastModified.equals(other.lastModified))
|
||||
return false;
|
||||
if (metadata == null) {
|
||||
if (other.metadata != null)
|
||||
return false;
|
||||
} else if (!metadata.equals(other.metadata))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
} else if (!type.equals(other.type))
|
||||
return false;
|
||||
if (url == null) {
|
||||
if (other.url != null)
|
||||
return false;
|
||||
|
@ -220,7 +192,10 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=" + name + ", type=" + type + ", lastModified=" + lastModified + "]";
|
||||
return String
|
||||
.format(
|
||||
"[name=%s, container=%s, url=%s, contentMetadata=%s, eTag=%s, lastModified=%s, leaseStatus=%s, metadata=%s, type=%s]",
|
||||
name, container, url, contentMetadata, eTag, lastModified, leaseStatus, metadata, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,5 +214,20 @@ public class MutableBlobPropertiesImpl implements Serializable, MutableBlobPrope
|
|||
this.contentMetadata = contentMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
*{@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setContainer(String container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.jclouds.azureblob.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.azureblob.blobstore.functions.BlobMetadataToBlobProperties;
|
||||
|
@ -28,6 +30,7 @@ import org.jclouds.blobstore.functions.ParseSystemAndUserMetadataFromHeaders;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.rest.InvocationContext;
|
||||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
|
@ -42,6 +45,7 @@ public class ParseBlobPropertiesFromHeaders implements Function<HttpResponse, Mu
|
|||
InvocationContext<ParseBlobPropertiesFromHeaders> {
|
||||
private final ParseSystemAndUserMetadataFromHeaders blobMetadataParser;
|
||||
private final BlobMetadataToBlobProperties blobToBlobProperties;
|
||||
private String container;
|
||||
|
||||
@Inject
|
||||
public ParseBlobPropertiesFromHeaders(ParseSystemAndUserMetadataFromHeaders blobMetadataParser,
|
||||
|
@ -56,13 +60,20 @@ public class ParseBlobPropertiesFromHeaders implements Function<HttpResponse, Mu
|
|||
public MutableBlobProperties apply(HttpResponse from) {
|
||||
BlobMetadata base = blobMetadataParser.apply(from);
|
||||
MutableBlobProperties to = blobToBlobProperties.apply(base);
|
||||
to.setContainer(container);
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ParseBlobPropertiesFromHeaders setContext(HttpRequest request) {
|
||||
checkArgument(request instanceof GeneratedHttpRequest<?>, "note this handler requires a GeneratedHttpRequest");
|
||||
blobMetadataParser.setContext(request);
|
||||
return this;
|
||||
return setContainer(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
|
||||
}
|
||||
|
||||
private ParseBlobPropertiesFromHeaders setContainer(String container) {
|
||||
this.container = container;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package org.jclouds.azureblob.functions;
|
||||
|
||||
import static org.jclouds.http.HttpUtils.releasePayload;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ParsePublicAccessHeader implements Function<HttpResponse, PublicAccess> {
|
||||
|
||||
public PublicAccess apply(HttpResponse from) {
|
||||
releasePayload(from);
|
||||
String access = from.getFirstHeaderOrNull("x-ms-blob-public-access");
|
||||
if (access == null) {
|
||||
return PublicAccess.PRIVATE;
|
||||
}
|
||||
return PublicAccess.valueOf(access.toUpperCase());
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
package org.jclouds.azureblob.options;
|
||||
|
||||
import org.jclouds.azure.storage.options.CreateOptions;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
|
@ -34,7 +35,7 @@ import com.google.common.collect.Multimap;
|
|||
* import org.jclouds.azureblob.AzureBlobClient;
|
||||
* <p/>
|
||||
* AzureBlobClient connection = // get connection
|
||||
* boolean createdWithPublicAcl = connection.createContainer("containerName", withPublicAcl());
|
||||
* boolean createdWithPublicAccess = connection.createContainer("containerName", withPublicAccess(PublicAccess.BLOB));
|
||||
* <code> *
|
||||
*
|
||||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd179466.aspx" />
|
||||
|
@ -51,19 +52,20 @@ public class CreateContainerOptions extends CreateOptions {
|
|||
/**
|
||||
* Indicates whether a container may be accessed publicly
|
||||
*/
|
||||
public CreateContainerOptions withPublicAcl() {
|
||||
this.headers.put("x-ms-prop-publicaccess", "true");
|
||||
public CreateContainerOptions withPublicAccess(PublicAccess access) {
|
||||
if (access != PublicAccess.PRIVATE)
|
||||
this.headers.put("x-ms-blob-public-access", access.name().toLowerCase());
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
/**
|
||||
* @see CreateContainerOptions#withPublicAcl()
|
||||
* @see CreateContainerOptions#withPublicAccess
|
||||
*/
|
||||
public static CreateContainerOptions withPublicAcl() {
|
||||
public static CreateContainerOptions withPublicAccess(PublicAccess access) {
|
||||
CreateContainerOptions options = new CreateContainerOptions();
|
||||
return options.withPublicAcl();
|
||||
return options.withPublicAccess(access);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,9 +130,10 @@ public class ContainerNameEnumerationResultsHandler extends ParseSax.HandlerWith
|
|||
} else if (qName.equals("LeaseStatus")) {
|
||||
currentLeaseStatus = LeaseStatus.fromValue(currentText.toString().trim());
|
||||
} else if (qName.equals("Blob")) {
|
||||
BlobProperties md = new BlobPropertiesImpl(currentBlobType, currentName, currentUrl, currentLastModified,
|
||||
currentETag, currentSize, currentContentType, currentContentMD5, currentContentEncoding,
|
||||
currentContentLanguage, currentLeaseStatus, currentMetadata);
|
||||
BlobProperties md = new BlobPropertiesImpl(currentBlobType, currentName, containerUrl.getPath().replace("/",
|
||||
""), currentUrl, currentLastModified, currentETag, currentSize, currentContentType,
|
||||
currentContentMD5, currentContentEncoding, currentContentLanguage, currentLeaseStatus,
|
||||
currentMetadata);
|
||||
blobMetadata.add(md);
|
||||
currentBlobType = null;
|
||||
currentName = null;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.jclouds.azureblob;
|
||||
|
||||
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAcl;
|
||||
import static org.jclouds.azure.storage.options.ListOptions.Builder.maxResults;
|
||||
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAccess;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -28,15 +28,17 @@ import java.lang.reflect.Method;
|
|||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.functions.ParseBlobFromHeadersAndHttpContent;
|
||||
import org.jclouds.azureblob.functions.ParseContainerPropertiesFromHeaders;
|
||||
import org.jclouds.azureblob.functions.ParsePublicAccessHeader;
|
||||
import org.jclouds.azureblob.functions.ReturnFalseIfContainerAlreadyExists;
|
||||
import org.jclouds.azureblob.options.CreateContainerOptions;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.azureblob.xml.AccountNameEnumerationResultsHandler;
|
||||
import org.jclouds.azureblob.xml.ContainerNameEnumerationResultsHandler;
|
||||
import org.jclouds.azure.storage.filters.SharedKeyLiteAuthentication;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
|
||||
import org.jclouds.blobstore.functions.ReturnNullOnKeyNotFound;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
|
@ -125,13 +127,13 @@ public class AzureBlobAsyncClientTest extends RestClientTest<AzureBlobAsyncClien
|
|||
public void testCreateContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = AzureBlobAsyncClient.class.getMethod("createContainer", String.class,
|
||||
CreateContainerOptions[].class);
|
||||
HttpRequest request = processor.createRequest(method, "container", withPublicAcl().withMetadata(
|
||||
ImmutableMultimap.of("foo", "bar")));
|
||||
HttpRequest request = processor.createRequest(method, "container", withPublicAccess(PublicAccess.BLOB)
|
||||
.withMetadata(ImmutableMultimap.of("foo", "bar")));
|
||||
|
||||
assertRequestLineEquals(request,
|
||||
"PUT https://identity.blob.core.windows.net/container?restype=container HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request,
|
||||
"x-ms-meta-foo: bar\nx-ms-prop-publicaccess: true\nx-ms-version: 2009-09-19\n");
|
||||
"x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
|
||||
assertPayloadEquals(request, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
|
||||
|
@ -168,12 +170,12 @@ public class AzureBlobAsyncClientTest extends RestClientTest<AzureBlobAsyncClien
|
|||
|
||||
public void testCreateRootContainerOptions() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = AzureBlobAsyncClient.class.getMethod("createRootContainer", CreateContainerOptions[].class);
|
||||
HttpRequest request = processor.createRequest(method, withPublicAcl().withMetadata(
|
||||
HttpRequest request = processor.createRequest(method, withPublicAccess(PublicAccess.BLOB).withMetadata(
|
||||
ImmutableMultimap.of("foo", "bar")));
|
||||
|
||||
assertRequestLineEquals(request, "PUT https://identity.blob.core.windows.net/$root?restype=container HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request,
|
||||
"x-ms-meta-foo: bar\nx-ms-prop-publicaccess: true\nx-ms-version: 2009-09-19\n");
|
||||
"x-ms-blob-public-access: blob\nx-ms-meta-foo: bar\nx-ms-version: 2009-09-19\n");
|
||||
assertPayloadEquals(request, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class);
|
||||
|
@ -223,6 +225,20 @@ public class AzureBlobAsyncClientTest extends RestClientTest<AzureBlobAsyncClien
|
|||
assertExceptionParserClassEquals(method, ReturnNullOnContainerNotFound.class);
|
||||
}
|
||||
|
||||
public void testGetPublicAccessForContainer() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = AzureBlobAsyncClient.class.getMethod("getPublicAccessForContainer", String.class);
|
||||
HttpRequest request = processor.createRequest(method, "container");
|
||||
|
||||
assertRequestLineEquals(request,
|
||||
"HEAD https://identity.blob.core.windows.net/container?restype=container&comp=acl HTTP/1.1");
|
||||
assertNonPayloadHeadersEqual(request, "x-ms-version: 2009-09-19\n");
|
||||
assertPayloadEquals(request, null, null, false);
|
||||
|
||||
assertResponseParserClassEquals(method, request, ParsePublicAccessHeader.class);
|
||||
assertSaxResponseParserClassEquals(method, null);
|
||||
assertExceptionParserClassEquals(method, ReturnNullOnContainerNotFound.class);
|
||||
}
|
||||
|
||||
public void testSetResourceMetadata() throws SecurityException, NoSuchMethodException, IOException {
|
||||
Method method = AzureBlobAsyncClient.class.getMethod("setResourceMetadata", String.class, Map.class);
|
||||
HttpRequest request = processor.createRequest(method,
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.jclouds.azureblob;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withMetadata;
|
||||
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAcl;
|
||||
import static org.jclouds.azureblob.options.CreateContainerOptions.Builder.withPublicAccess;
|
||||
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
@ -39,6 +39,7 @@ import org.jclouds.azureblob.domain.AzureBlob;
|
|||
import org.jclouds.azureblob.domain.BlobProperties;
|
||||
import org.jclouds.azureblob.domain.ContainerProperties;
|
||||
import org.jclouds.azureblob.domain.ListBlobsResponse;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.jclouds.azureblob.options.ListBlobsOptions;
|
||||
import org.jclouds.azure.storage.domain.BoundedSet;
|
||||
import org.jclouds.azure.storage.options.ListOptions;
|
||||
|
@ -151,7 +152,7 @@ public class AzureBlobClientLiveTest {
|
|||
while (!created) {
|
||||
publicContainer = containerPrefix + new SecureRandom().nextInt();
|
||||
try {
|
||||
created = client.createContainer(publicContainer, withPublicAcl());
|
||||
created = client.createContainer(publicContainer, withPublicAccess(PublicAccess.BLOB));
|
||||
} catch (UndeclaredThrowableException e) {
|
||||
HttpResponseException htpe = (HttpResponseException) e.getCause().getCause();
|
||||
if (htpe.getResponse().getStatusCode() == 409)
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.jclouds.azureblob.options;
|
|||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.jclouds.azure.storage.reference.AzureStorageHeaders;
|
||||
import org.jclouds.azureblob.domain.PublicAccess;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -35,16 +36,16 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
@Test(groups = "unit")
|
||||
public class CreateContainerOptionsTest {
|
||||
|
||||
public void testPublicAcl() {
|
||||
CreateContainerOptions options = new CreateContainerOptions().withPublicAcl();
|
||||
assertEquals(ImmutableList.of("true"), options.buildRequestHeaders().get(
|
||||
"x-ms-prop-publicaccess"));
|
||||
public void testPublicAccess() {
|
||||
CreateContainerOptions options = new CreateContainerOptions().withPublicAccess(PublicAccess.BLOB);
|
||||
assertEquals(ImmutableList.of("blob"), options.buildRequestHeaders().get(
|
||||
"x-ms-blob-public-access"));
|
||||
}
|
||||
|
||||
public void testPublicAclStatic() {
|
||||
CreateContainerOptions options = CreateContainerOptions.Builder.withPublicAcl();
|
||||
assertEquals(ImmutableList.of("true"), options.buildRequestHeaders().get(
|
||||
"x-ms-prop-publicaccess"));
|
||||
public void testPublicAccessStatic() {
|
||||
CreateContainerOptions options = CreateContainerOptions.Builder.withPublicAccess(PublicAccess.BLOB);
|
||||
assertEquals(ImmutableList.of("blob"), options.buildRequestHeaders().get(
|
||||
"x-ms-blob-public-access"));
|
||||
}
|
||||
|
||||
public void testMetadata() {
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.testng.annotations.BeforeTest;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
|
@ -59,47 +60,47 @@ public class ContainerNameEnumerationResultsHandlerTest extends BaseHandlerTest
|
|||
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_blobs.xml");
|
||||
Set<BlobProperties> contents = Sets.newTreeSet();
|
||||
contents.add(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob1.txt", URI
|
||||
.create("http://myaccount.blob.core.windows.net/mycontainer/blob1.txt"), dateService
|
||||
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55D050B8B", 8, "text/plain; charset=UTF-8",
|
||||
null, null, null, LeaseStatus.UNLOCKED, ImmutableMap.<String, String> of()));
|
||||
contents.add(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob2.txt", URI
|
||||
.create("http://myaccount.blob.core.windows.net/mycontainer/blob2.txt"), dateService
|
||||
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339", 14, "text/plain; charset=UTF-8",
|
||||
null, null, null, LeaseStatus.UNLOCKED, ImmutableMap.<String, String> of()));
|
||||
contents.add(new BlobPropertiesImpl(BlobType.PAGE_BLOB, "newblob1.txt", URI
|
||||
.create("http://myaccount.blob.core.windows.net/mycontainer/newblob1.txt"), dateService
|
||||
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339", 25, "text/plain; charset=UTF-8",
|
||||
null, null, null, LeaseStatus.UNLOCKED, ImmutableMap.<String, String> of()));
|
||||
Set<BlobProperties> contents = ImmutableSet.<BlobProperties> of(
|
||||
new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob1.txt", "mycontainer", URI
|
||||
.create("http://myaccount.blob.core.windows.net/mycontainer/blob1.txt"), dateService
|
||||
.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55D050B8B", 8,
|
||||
"text/plain; charset=UTF-8", null, null, null, LeaseStatus.UNLOCKED, ImmutableMap
|
||||
.<String, String> of()), new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "blob2.txt",
|
||||
"mycontainer", URI.create("http://myaccount.blob.core.windows.net/mycontainer/blob2.txt"),
|
||||
dateService.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339", 14,
|
||||
"text/plain; charset=UTF-8", null, null, null, LeaseStatus.UNLOCKED, ImmutableMap
|
||||
.<String, String> of()), new BlobPropertiesImpl(BlobType.PAGE_BLOB, "newblob1.txt",
|
||||
"mycontainer", URI.create("http://myaccount.blob.core.windows.net/mycontainer/newblob1.txt"),
|
||||
dateService.rfc822DateParse("Thu, 18 Sep 2008 18:41:57 GMT"), "0x8CAE7D55CF6C339", 25,
|
||||
"text/plain; charset=UTF-8", null, null, null, LeaseStatus.UNLOCKED, ImmutableMap
|
||||
.<String, String> of()));
|
||||
|
||||
ListBlobsResponse list = new HashSetListBlobsResponse(contents,
|
||||
URI.create("http://myaccount.blob.core.windows.net/mycontainer"),
|
||||
ListBlobsResponse list = new HashSetListBlobsResponse(contents, URI
|
||||
.create("http://myaccount.blob.core.windows.net/mycontainer"),
|
||||
|
||||
"myfolder/", null, 4, "newblob2.txt", "/", Sets.<String> newTreeSet());
|
||||
"myfolder/", null, 4, "newblob2.txt", "/", Sets.<String> newTreeSet());
|
||||
|
||||
ListBlobsResponse result = (ListBlobsResponse) factory.create(
|
||||
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
|
||||
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, list);
|
||||
}
|
||||
|
||||
public void testOptions() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_blobs_options.xml");
|
||||
Set<BlobProperties> contents = Sets.newTreeSet();
|
||||
contents.add(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "a", URI
|
||||
.create("https://jclouds.blob.core.windows.net/adriancole-blobstore3/a"), dateService
|
||||
.rfc822DateParse("Sat, 30 Jan 2010 17:46:15 GMT"), "0x8CC6FEB41736428", 8, "application/octet-stream",
|
||||
null, null, null, LeaseStatus.UNLOCKED, ImmutableMap.<String, String> of()));
|
||||
Set<BlobProperties> contents = ImmutableSet.<BlobProperties> of(new BlobPropertiesImpl(BlobType.BLOCK_BLOB, "a",
|
||||
"adriancole-blobstore3", URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore3/a"),
|
||||
dateService.rfc822DateParse("Sat, 30 Jan 2010 17:46:15 GMT"), "0x8CC6FEB41736428", 8,
|
||||
"application/octet-stream", null, null, null, LeaseStatus.UNLOCKED, ImmutableMap.<String, String> of()));
|
||||
|
||||
ListBlobsResponse list = new HashSetListBlobsResponse(contents,
|
||||
URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore3"),
|
||||
ListBlobsResponse list = new HashSetListBlobsResponse(contents, URI
|
||||
.create("https://jclouds.blob.core.windows.net/adriancole-blobstore3"),
|
||||
|
||||
null, null, 1, "2!68!MDAwMDA2IWFwcGxlcyEwMDAwMjghOTk5OS0xMi0zMVQyMzo1OTo1OS45OTk5OTk5WiE-", "/",
|
||||
Sets.<String> newTreeSet());
|
||||
null, null, 1, "2!68!MDAwMDA2IWFwcGxlcyEwMDAwMjghOTk5OS0xMi0zMVQyMzo1OTo1OS45OTk5OTk5WiE-", "/", Sets
|
||||
.<String> newTreeSet());
|
||||
|
||||
ListBlobsResponse result = (ListBlobsResponse) factory.create(
|
||||
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
|
||||
injector.getInstance(ContainerNameEnumerationResultsHandler.class)).parse(is);
|
||||
|
||||
assertEquals(result, list);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue