mirror of https://github.com/apache/jclouds.git
JCLOUDS-457: Added Glacier vault operations
The Glacier client can create, delete, read, and list vaults.
This commit is contained in:
parent
d4af465ca8
commit
b892afc4d9
|
@ -32,7 +32,7 @@
|
||||||
<packaging>bundle</packaging>
|
<packaging>bundle</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<test.glacier.endpoint>https://glacier.eu-west-1.amazonaws.com</test.glacier.endpoint>
|
<test.glacier.endpoint>https://glacier.us-east-1.amazonaws.com</test.glacier.endpoint>
|
||||||
<test.glacier.api-version>2012-06-01</test.glacier.api-version>
|
<test.glacier.api-version>2012-06-01</test.glacier.api-version>
|
||||||
<test.glacier.build-version />
|
<test.glacier.build-version />
|
||||||
<test.glacier.identity>${test.aws.identity}</test.glacier.identity>
|
<test.glacier.identity>${test.aws.identity}</test.glacier.identity>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.blobstore.BlobStoreContext;
|
import org.jclouds.blobstore.BlobStoreContext;
|
||||||
|
import org.jclouds.glacier.config.GlacierParserModule;
|
||||||
import org.jclouds.glacier.config.GlacierRestClientModule;
|
import org.jclouds.glacier.config.GlacierRestClientModule;
|
||||||
import org.jclouds.glacier.reference.GlacierHeaders;
|
import org.jclouds.glacier.reference.GlacierHeaders;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
||||||
|
@ -82,7 +83,7 @@ public class GlacierApiMetadata extends BaseRestApiMetadata {
|
||||||
.defaultProperties(GlacierApiMetadata.defaultProperties())
|
.defaultProperties(GlacierApiMetadata.defaultProperties())
|
||||||
.context(CONTEXT_TOKEN)
|
.context(CONTEXT_TOKEN)
|
||||||
.view(typeToken(BlobStoreContext.class))
|
.view(typeToken(BlobStoreContext.class))
|
||||||
.defaultModules(ImmutableSet.<Class<? extends Module>> of(GlacierRestClientModule.class));
|
.defaultModules(ImmutableSet.<Class<? extends Module>> of(GlacierRestClientModule.class, GlacierParserModule.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,25 +22,87 @@ import java.io.Closeable;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
import org.jclouds.blobstore.attr.BlobScope;
|
import org.jclouds.blobstore.attr.BlobScope;
|
||||||
|
import org.jclouds.glacier.domain.PaginatedVaultCollection;
|
||||||
|
import org.jclouds.glacier.domain.VaultMetadata;
|
||||||
|
import org.jclouds.glacier.fallbacks.FalseIfVaultNotEmpty;
|
||||||
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
|
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
|
||||||
|
import org.jclouds.glacier.functions.ParseVaultMetadataFromHttpContent;
|
||||||
|
import org.jclouds.glacier.functions.ParseVaultMetadataListFromHttpContent;
|
||||||
|
import org.jclouds.glacier.options.PaginationOptions;
|
||||||
|
import org.jclouds.glacier.predicates.validators.VaultNameValidator;
|
||||||
import org.jclouds.glacier.reference.GlacierHeaders;
|
import org.jclouds.glacier.reference.GlacierHeaders;
|
||||||
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.Headers;
|
import org.jclouds.rest.annotations.Headers;
|
||||||
|
import org.jclouds.rest.annotations.ParamValidators;
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
import org.jclouds.rest.annotations.RequestFilters;
|
||||||
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides asynchronous access to Amazon Glacier resources via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see GlacierClient
|
||||||
|
* @see <a href="http://aws.amazon.com/documentation/glacier/" />
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
@Headers(keys = GlacierHeaders.VERSION, values = "2012-06-01")
|
@Headers(keys = GlacierHeaders.VERSION, values = "2012-06-01")
|
||||||
@RequestFilters(RequestAuthorizeSignature.class)
|
@RequestFilters(RequestAuthorizeSignature.class)
|
||||||
@BlobScope(CONTAINER)
|
@BlobScope(CONTAINER)
|
||||||
public interface GlacierAsyncClient extends Closeable {
|
public interface GlacierAsyncClient extends Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GlacierClient#createVault
|
||||||
|
*/
|
||||||
@Named("CreateVault")
|
@Named("CreateVault")
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/-/vaults/{vault}")
|
@Path("/-/vaults/{vault}")
|
||||||
ListenableFuture<URI> createVault(@PathParam("vault") String vaultName);
|
ListenableFuture<URI> createVault(@PathParam("vault") @ParamValidators(VaultNameValidator.class) String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GlacierClient#deleteVaultIfEmpty
|
||||||
|
*/
|
||||||
|
@Named("DeleteVault")
|
||||||
|
@DELETE
|
||||||
|
@Path("/-/vaults/{vault}")
|
||||||
|
@Fallback(FalseIfVaultNotEmpty.class)
|
||||||
|
ListenableFuture<Boolean> deleteVaultIfEmpty(@PathParam("vault") @ParamValidators(VaultNameValidator.class) String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GlacierClient#describeVault
|
||||||
|
*/
|
||||||
|
@Named("DescribeVault")
|
||||||
|
@GET
|
||||||
|
@Path("/-/vaults/{vault}")
|
||||||
|
@ResponseParser(ParseVaultMetadataFromHttpContent.class)
|
||||||
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<VaultMetadata> describeVault(
|
||||||
|
@PathParam("vault") @ParamValidators(VaultNameValidator.class) String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GlacierClient#listVaults(PaginationOptions)
|
||||||
|
*/
|
||||||
|
@Named("ListVaults")
|
||||||
|
@GET
|
||||||
|
@Path("/-/vaults")
|
||||||
|
@ResponseParser(ParseVaultMetadataListFromHttpContent.class)
|
||||||
|
ListenableFuture<PaginatedVaultCollection> listVaults(PaginationOptions options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GlacierClient#listVaults
|
||||||
|
*/
|
||||||
|
@Named("ListVaults")
|
||||||
|
@GET
|
||||||
|
@Path("/-/vaults")
|
||||||
|
@ResponseParser(ParseVaultMetadataListFromHttpContent.class)
|
||||||
|
ListenableFuture<PaginatedVaultCollection> listVaults();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,64 @@ package org.jclouds.glacier;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.jclouds.glacier.domain.PaginatedVaultCollection;
|
||||||
|
import org.jclouds.glacier.domain.VaultMetadata;
|
||||||
|
import org.jclouds.glacier.options.PaginationOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to Amazon Glacier resources via their REST API.
|
||||||
|
* <p/>
|
||||||
|
*
|
||||||
|
* @see GlacierAsyncClient
|
||||||
|
* @see <a href="http://aws.amazon.com/documentation/glacier/" />
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
public interface GlacierClient extends Closeable {
|
public interface GlacierClient extends Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A PUT request operation with a vault name to create a new vault to store archives.
|
||||||
|
*
|
||||||
|
* @param vaultName
|
||||||
|
* A name for the Vault being created.
|
||||||
|
* @return A reference to an URI pointing to the resource created.
|
||||||
|
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-vault-put.html" />
|
||||||
|
*/
|
||||||
URI createVault(String vaultName);
|
URI createVault(String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DELETE request operation with a vault name to delete an existing vault. The vault must be empty.
|
||||||
|
*
|
||||||
|
* @param vaultName
|
||||||
|
* Name of the Vault being deleted.
|
||||||
|
* @return False if the vault was not empty and therefore not deleted, true otherwise.
|
||||||
|
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-vault-delete.html" />
|
||||||
|
*/
|
||||||
|
boolean deleteVaultIfEmpty(String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GET request operation with a vault name to fetch the vault metadata.
|
||||||
|
*
|
||||||
|
* @param vaultName
|
||||||
|
* Name of the Vault being described.
|
||||||
|
* @return A VaultMetadata object containing all the information relevant to the vault.
|
||||||
|
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-vault-get.html" />
|
||||||
|
*/
|
||||||
|
VaultMetadata describeVault(String vaultName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GET request operation to retrieve a vault listing.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
* Options used for pagination.
|
||||||
|
* @return A PaginatedVaultCollection object containing the list of vaults.
|
||||||
|
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-vaults-get.html" />
|
||||||
|
*/
|
||||||
|
PaginatedVaultCollection listVaults(PaginationOptions options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GET request operation to retrieve a vault listing.
|
||||||
|
*
|
||||||
|
* @see GlacierClient#listVaults(PaginationOptions)
|
||||||
|
*/
|
||||||
|
PaginatedVaultCollection listVaults();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.glacier.domain.GlacierError;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates a GlacierError.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class GlacierResponseException extends HttpResponseException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final GlacierError error;
|
||||||
|
|
||||||
|
public GlacierResponseException(String message, HttpCommand command, HttpResponse response, GlacierError error,
|
||||||
|
Throwable cause) {
|
||||||
|
super(message, command, response, cause);
|
||||||
|
this.error = checkNotNull(error, "error");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlacierResponseException(HttpCommand command, HttpResponse response, GlacierError error, Throwable cause) {
|
||||||
|
super("request " + command.getCurrentRequest().getRequestLine() + " failed with code " + response.getStatusCode()
|
||||||
|
+ ", error: " + error.toString(), command, response, cause);
|
||||||
|
this.error = checkNotNull(error, "error");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlacierResponseException(HttpCommand command, HttpResponse response, GlacierError error) {
|
||||||
|
this(command, response, error, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlacierResponseException(String message, HttpCommand command, HttpResponse response, GlacierError error) {
|
||||||
|
this(message, command, response, error, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlacierError getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.config;
|
||||||
|
|
||||||
|
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||||
|
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the parser mappings.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class GlacierParserModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,11 @@ import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.glacier.GlacierAsyncClient;
|
import org.jclouds.glacier.GlacierAsyncClient;
|
||||||
import org.jclouds.glacier.GlacierClient;
|
import org.jclouds.glacier.GlacierClient;
|
||||||
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
|
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
|
||||||
|
import org.jclouds.glacier.handlers.ParseGlacierErrorFromJsonContent;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
import org.jclouds.http.annotation.ClientError;
|
||||||
|
import org.jclouds.http.annotation.Redirection;
|
||||||
|
import org.jclouds.http.annotation.ServerError;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.RestClientModule;
|
||||||
|
|
||||||
|
@ -34,6 +39,11 @@ import com.google.common.base.Suppliers;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the mappings. Installs the Object and Parser modules.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
@ConfiguresRestClient
|
@ConfiguresRestClient
|
||||||
public class GlacierRestClientModule extends RestClientModule<GlacierClient, GlacierAsyncClient> {
|
public class GlacierRestClientModule extends RestClientModule<GlacierClient, GlacierAsyncClient> {
|
||||||
|
|
||||||
|
@ -61,4 +71,11 @@ public class GlacierRestClientModule extends RestClientModule<GlacierClient, Gla
|
||||||
}
|
}
|
||||||
}, seconds, TimeUnit.SECONDS);
|
}, seconds, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bindErrorHandlers() {
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseGlacierErrorFromJsonContent.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseGlacierErrorFromJsonContent.class);
|
||||||
|
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseGlacierErrorFromJsonContent.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.domain;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines attributes to describe a GlacierError
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class GlacierError {
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String message;
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "code", "message", "type" })
|
||||||
|
public GlacierError(@Nullable String code, @Nullable String message, @Nullable String type) {
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return (this.code != null) && (this.message != null) && (this.type != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(this.code, this.message, this.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
GlacierError other = (GlacierError) obj;
|
||||||
|
|
||||||
|
return Objects.equal(this.code, other.code)
|
||||||
|
&& Objects.equal(this.message, other.message)
|
||||||
|
&& Objects.equal(this.type, other.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "GlacierError [code=" + this.getCode() + ", message=" + this.getMessage() + "type=" + this.getType() + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.domain;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.jclouds.collect.IterableWithMarker;
|
||||||
|
import org.jclouds.glacier.options.PaginationOptions;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paginated collection used to store Vault listing information.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class PaginatedVaultCollection extends IterableWithMarker<VaultMetadata> {
|
||||||
|
|
||||||
|
@SerializedName("VaultList")
|
||||||
|
private final Iterable<VaultMetadata> vaults;
|
||||||
|
@SerializedName("Marker")
|
||||||
|
private final String marker;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "VaultList", "Marker" })
|
||||||
|
public PaginatedVaultCollection(Iterable<VaultMetadata> vaults, String marker) {
|
||||||
|
this.vaults = vaults;
|
||||||
|
this.marker = marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<VaultMetadata> iterator() {
|
||||||
|
return vaults.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Object> nextMarker() {
|
||||||
|
return Optional.<Object>fromNullable(marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaginationOptions nextPaginationOptions() {
|
||||||
|
return PaginationOptions.class.cast(nextMarker().get());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.beans.ConstructorProperties;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the attributes needed to describe a vault.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class VaultMetadata implements Comparable<VaultMetadata> {
|
||||||
|
|
||||||
|
@SerializedName("VaultName")
|
||||||
|
private final String vaultName;
|
||||||
|
@SerializedName("VaultARN")
|
||||||
|
private final String vaultARN;
|
||||||
|
@SerializedName("CreationDate")
|
||||||
|
private final Date creationDate;
|
||||||
|
@SerializedName("LastInventoryDate")
|
||||||
|
private final Date lastInventoryDate;
|
||||||
|
@SerializedName("NumberOfArchives")
|
||||||
|
private final Long numberOfArchives;
|
||||||
|
@SerializedName("SizeInBytes")
|
||||||
|
private final Long sizeInBytes;
|
||||||
|
|
||||||
|
@ConstructorProperties({ "VaultName", "VaultARN", "CreationDate", "LastInventoryDate", "NumberOfArchives",
|
||||||
|
"SizeInBytes" })
|
||||||
|
public VaultMetadata(String vaultName, String vaultARN, Date creationDate, @Nullable Date lastInventoryDate,
|
||||||
|
long numberOfArchives, long sizeInBytes) {
|
||||||
|
this.vaultName = checkNotNull(vaultName);
|
||||||
|
this.vaultARN = checkNotNull(vaultARN);
|
||||||
|
this.creationDate = checkNotNull(creationDate);
|
||||||
|
this.lastInventoryDate = lastInventoryDate;
|
||||||
|
this.numberOfArchives = checkNotNull(numberOfArchives);
|
||||||
|
this.sizeInBytes = checkNotNull(sizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVaultName() {
|
||||||
|
return vaultName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVaultARN() {
|
||||||
|
return vaultARN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getLastInventoryDate() {
|
||||||
|
return lastInventoryDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getNumberOfArchives() {
|
||||||
|
return numberOfArchives;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSizeInBytes() {
|
||||||
|
return sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(this.vaultName, this.vaultARN, this.creationDate, this.lastInventoryDate,
|
||||||
|
this.numberOfArchives, this.sizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
VaultMetadata other = (VaultMetadata) obj;
|
||||||
|
|
||||||
|
return Objects.equal(this.vaultName, other.vaultName) && Objects.equal(this.vaultARN, other.vaultARN)
|
||||||
|
&& Objects.equal(this.creationDate, other.creationDate)
|
||||||
|
&& Objects.equal(this.lastInventoryDate, other.lastInventoryDate)
|
||||||
|
&& Objects.equal(this.numberOfArchives, other.numberOfArchives)
|
||||||
|
&& Objects.equal(this.sizeInBytes, other.sizeInBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "VaultMetadata [vaultName=" + vaultName + ", vaultARN=" + vaultARN + ", creationDate=" + creationDate
|
||||||
|
+ ", lastInventoryDate=" + lastInventoryDate + ", numberOfArchives=" + numberOfArchives + ", sizeInBytes="
|
||||||
|
+ sizeInBytes + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(VaultMetadata o) {
|
||||||
|
return ComparisonChain.start().compare(this.vaultName, o.getVaultName()).result();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.fallbacks;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||||
|
|
||||||
|
import org.jclouds.Fallback;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback used when deleting a vault.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class FalseIfVaultNotEmpty implements Fallback<Boolean> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Boolean> create(Throwable t) throws Exception {
|
||||||
|
return immediateFuture(createOrPropagate(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean createOrPropagate(Throwable t) throws Exception {
|
||||||
|
if (getFirstThrowableOfType(checkNotNull(t, "throwable"), IllegalArgumentException.class) != null)
|
||||||
|
return false;
|
||||||
|
throw propagate(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -39,6 +39,11 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signs the request using the AWSRequestSignerV4.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class RequestAuthorizeSignature implements HttpRequestFilter {
|
public class RequestAuthorizeSignature implements HttpRequestFilter {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.functions;
|
||||||
|
|
||||||
|
import org.jclouds.glacier.domain.VaultMetadata;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the JSON vault information from the HttpResponse.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class ParseVaultMetadataFromHttpContent extends ParseJson<VaultMetadata> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ParseVaultMetadataFromHttpContent(Json json) {
|
||||||
|
super(json, TypeLiteral.get(VaultMetadata.class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.functions;
|
||||||
|
|
||||||
|
import org.jclouds.glacier.domain.PaginatedVaultCollection;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the JSON vault list from the HttpResponse.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class ParseVaultMetadataListFromHttpContent extends ParseJson<PaginatedVaultCollection> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ParseVaultMetadataListFromHttpContent(Json json) {
|
||||||
|
super(json, TypeLiteral.get(PaginatedVaultCollection.class));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.handlers;
|
||||||
|
|
||||||
|
import org.jclouds.glacier.GlacierResponseException;
|
||||||
|
import org.jclouds.glacier.domain.GlacierError;
|
||||||
|
import org.jclouds.http.HttpCommand;
|
||||||
|
import org.jclouds.http.HttpErrorHandler;
|
||||||
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.http.functions.ParseJson;
|
||||||
|
import org.jclouds.json.Json;
|
||||||
|
import org.jclouds.rest.AuthorizationException;
|
||||||
|
import org.jclouds.rest.InsufficientResourcesException;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a GlacierError from a Json response content.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class ParseGlacierErrorFromJsonContent extends ParseJson<GlacierError> implements HttpErrorHandler {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ParseGlacierErrorFromJsonContent(Json json) {
|
||||||
|
super(json, TypeLiteral.get(GlacierError.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Exception refineException(GlacierError error, Exception exception) {
|
||||||
|
if ("AccessDeniedException".equals(error.getCode())) {
|
||||||
|
return new AuthorizationException(error.getMessage(), exception);
|
||||||
|
} else if ("InvalidParameterValueException".equals(error.getCode())) {
|
||||||
|
return new IllegalArgumentException(error.getMessage(), exception);
|
||||||
|
} else if ("LimitExceededException".equals(error.getCode())) {
|
||||||
|
return new InsufficientResourcesException(error.getMessage(), exception);
|
||||||
|
} else if ("ResourceNotFoundException".equals(error.getCode())) {
|
||||||
|
return new ResourceNotFoundException(error.getMessage(), exception);
|
||||||
|
}
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleError(HttpCommand command, HttpResponse response) {
|
||||||
|
GlacierError error = this.apply(response);
|
||||||
|
Exception exception = error.isValid() ? refineException(error, new GlacierResponseException(command, response,
|
||||||
|
error)) : new HttpResponseException(command, response);
|
||||||
|
command.setException(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pagination options used to specify the collection responses.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
public class PaginationOptions extends BaseHttpRequestOptions {
|
||||||
|
|
||||||
|
private static final int MIN_LIMIT = 1;
|
||||||
|
private static final int MAX_LIMIT = 1000;
|
||||||
|
|
||||||
|
public PaginationOptions marker(String marker) {
|
||||||
|
queryParameters.put("marker", checkNotNull(marker, "marker"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaginationOptions limit(int limit) {
|
||||||
|
checkArgument(limit >= MIN_LIMIT, "limit must be >= " + MIN_LIMIT);
|
||||||
|
checkArgument(limit <= MAX_LIMIT, "limit must be <= " + MAX_LIMIT);
|
||||||
|
queryParameters.put("limit", Integer.toString(limit));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
public static PaginationOptions marker(String marker) {
|
||||||
|
PaginationOptions options = new PaginationOptions();
|
||||||
|
return options.marker(marker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PaginationOptions limit(int limit) {
|
||||||
|
PaginationOptions options = new PaginationOptions();
|
||||||
|
return options.limit(limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.predicates.validators;
|
||||||
|
|
||||||
|
import org.jclouds.predicates.Validator;
|
||||||
|
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates Vault names according to Amazon Vault conventions.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class VaultNameValidator extends Validator<String> {
|
||||||
|
|
||||||
|
private static final int MIN_LENGTH = 1;
|
||||||
|
private static final int MAX_LENGTH = 255;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(String vaultName) {
|
||||||
|
if (vaultName == null || vaultName.length() < MIN_LENGTH || vaultName.length() > MAX_LENGTH)
|
||||||
|
throw exception(vaultName, "Can't be null or empty. Length must be " + MIN_LENGTH + " to " + MAX_LENGTH
|
||||||
|
+ " symbols.");
|
||||||
|
CharMatcher range = getAcceptableRange();
|
||||||
|
if (!range.matchesAllOf(vaultName))
|
||||||
|
throw exception(vaultName, "Should have ASCII letters and numbers, underscores, hyphens, or periods.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharMatcher getAcceptableRange() {
|
||||||
|
return CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.inRange('0', '9'))
|
||||||
|
.or(CharMatcher.anyOf("-_."));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IllegalArgumentException exception(String vaultName, String reason) {
|
||||||
|
return new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"Object '%s' doesn't match AWS Vault naming convention. "
|
||||||
|
+ "Reason: %s. For more info, please refer to http://docs.aws.amazon.com/amazonglacier/latest/dev/api-vault-put.html.",
|
||||||
|
vaultName, reason));
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.glacier.reference;
|
package org.jclouds.glacier.reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Headers used by Amazon Glacier.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
public final class GlacierHeaders {
|
public final class GlacierHeaders {
|
||||||
|
|
||||||
public static final String DEFAULT_AMAZON_HEADERTAG = "amz";
|
public static final String DEFAULT_AMAZON_HEADERTAG = "amz";
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.jclouds.apis.BaseApiLiveTest;
|
||||||
|
import org.jclouds.glacier.domain.PaginatedVaultCollection;
|
||||||
|
import org.jclouds.glacier.domain.VaultMetadata;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Live test for Glacier.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
|
@Test(groups = { "integration", "live" })
|
||||||
|
public class GlacierClientLiveTest extends BaseApiLiveTest<GlacierClient>{
|
||||||
|
|
||||||
|
public GlacierClientLiveTest() {
|
||||||
|
this.provider = "glacier";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String VAULT_NAME1 = "testV1";
|
||||||
|
private static final String VAULT_NAME2 = "testV2";
|
||||||
|
private static final String VAULT_NAME3 = "testV3";
|
||||||
|
|
||||||
|
@Test(groups = { "integration", "live" })
|
||||||
|
public void testDeleteVaultIfEmptyOrNotFound() throws Exception {
|
||||||
|
assertTrue(api.deleteVaultIfEmpty(UUID.randomUUID().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(groups = { "integration", "live" })
|
||||||
|
public void testDescribeNonExistentVault() throws Exception {
|
||||||
|
VaultMetadata vault = api.describeVault(UUID.randomUUID().toString());
|
||||||
|
assertEquals(vault, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testDescribeVault() throws Exception {
|
||||||
|
VaultMetadata vault = api.describeVault(VAULT_NAME1);
|
||||||
|
assertEquals(vault.getVaultName(), VAULT_NAME1);
|
||||||
|
assertEquals(vault.getNumberOfArchives(), 0);
|
||||||
|
assertEquals(vault.getSizeInBytes(), 0);
|
||||||
|
assertEquals(vault.getLastInventoryDate(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testListVaults() throws Exception {
|
||||||
|
PaginatedVaultCollection vaults = api.listVaults();
|
||||||
|
Iterator<VaultMetadata> i = vaults.iterator();
|
||||||
|
assertEquals(i.next().getVaultName(), VAULT_NAME1);
|
||||||
|
assertEquals(i.next().getVaultName(), VAULT_NAME2);
|
||||||
|
assertEquals(i.next().getVaultName(), VAULT_NAME3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(groups = { "integration", "live" })
|
||||||
|
public void testCreateDescribeAndListVault() throws Exception {
|
||||||
|
try {
|
||||||
|
String path = api.createVault(VAULT_NAME1).toString();
|
||||||
|
api.createVault(VAULT_NAME2);
|
||||||
|
api.createVault(VAULT_NAME3);
|
||||||
|
assertTrue(path.contains("https://glacier.us-east-1.amazonaws.com/"));
|
||||||
|
assertTrue(path.contains("/vaults/" + VAULT_NAME1));
|
||||||
|
this.testDescribeVault();
|
||||||
|
this.testListVaults();
|
||||||
|
} finally {
|
||||||
|
api.deleteVaultIfEmpty(VAULT_NAME1);
|
||||||
|
api.deleteVaultIfEmpty(VAULT_NAME2);
|
||||||
|
api.deleteVaultIfEmpty(VAULT_NAME3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,15 +20,21 @@ import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor
|
||||||
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
|
import static org.jclouds.Constants.PROPERTY_MAX_RETRIES;
|
||||||
import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
|
import static org.jclouds.Constants.PROPERTY_SO_TIMEOUT;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertFalse;
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
|
import org.jclouds.glacier.domain.PaginatedVaultCollection;
|
||||||
|
import org.jclouds.glacier.domain.VaultMetadata;
|
||||||
|
import org.jclouds.glacier.options.PaginationOptions;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
@ -36,6 +42,11 @@ import com.google.mockwebserver.MockResponse;
|
||||||
import com.google.mockwebserver.MockWebServer;
|
import com.google.mockwebserver.MockWebServer;
|
||||||
import com.google.mockwebserver.RecordedRequest;
|
import com.google.mockwebserver.RecordedRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mock test for Glacier.
|
||||||
|
*
|
||||||
|
* @author Roman Coedo
|
||||||
|
*/
|
||||||
public class GlacierClientMockTest {
|
public class GlacierClientMockTest {
|
||||||
|
|
||||||
private static final String VAULT_NAME = "ConcreteVaultName";
|
private static final String VAULT_NAME = "ConcreteVaultName";
|
||||||
|
@ -74,4 +85,130 @@ public class GlacierClientMockTest {
|
||||||
server.shutdown();
|
server.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDeleteVault() throws IOException, InterruptedException {
|
||||||
|
// Prepare the response
|
||||||
|
MockResponse mr = new MockResponse();
|
||||||
|
mr.setResponseCode(204);
|
||||||
|
mr.addHeader("x-amzn-RequestId", "AAABZpJrTyioDC_HsOmHae8EZp_uBSJr6cnGOLKp_XJCl-Q");
|
||||||
|
mr.addHeader("Date", "Sun, 25 Mar 2012 12:02:00 GMT");
|
||||||
|
MockWebServer server = new MockWebServer();
|
||||||
|
server.enqueue(mr);
|
||||||
|
server.play();
|
||||||
|
|
||||||
|
// Send the request and check the response
|
||||||
|
try {
|
||||||
|
GlacierClient client = getGlacierClient(server.getUrl("/"));
|
||||||
|
assertTrue(client.deleteVaultIfEmpty(VAULT_NAME));
|
||||||
|
RecordedRequest request = server.takeRequest();
|
||||||
|
assertEquals(request.getRequestLine(), "DELETE /-/vaults/" + VAULT_NAME + " HTTP/1.1");
|
||||||
|
} finally {
|
||||||
|
server.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDescribeVault() throws IOException, InterruptedException {
|
||||||
|
// Prepare the response
|
||||||
|
MockResponse mr = new MockResponse();
|
||||||
|
mr.setResponseCode(200);
|
||||||
|
mr.addHeader("x-amzn-RequestId", "AAABZpJrTyioDC_HsOmHae8EZp_uBSJr6cnGOLKp_XJCl-Q");
|
||||||
|
mr.addHeader("Date", "Sun, 25 Mar 2012 12:02:00 GMT");
|
||||||
|
mr.addHeader("Content-Type", "application/json");
|
||||||
|
mr.addHeader("Content-Length", "260");
|
||||||
|
mr.setBody("{\"CreationDate\" : \"2012-02-20T17:01:45.198Z\",\"LastInventoryDate\" : "
|
||||||
|
+ "\"2012-03-20T17:03:43.221Z\",\"NumberOfArchives\" : 192,\"SizeInBytes\" : 78088912,\"VaultARN\" : "
|
||||||
|
+ "\"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault\",\"VaultName\" : \"examplevault\"}");
|
||||||
|
MockWebServer server = new MockWebServer();
|
||||||
|
server.enqueue(mr);
|
||||||
|
server.play();
|
||||||
|
|
||||||
|
// Send the request and check the response
|
||||||
|
try {
|
||||||
|
GlacierClient client = getGlacierClient(server.getUrl("/"));
|
||||||
|
VaultMetadata vm = client.describeVault(VAULT_NAME);
|
||||||
|
RecordedRequest request = server.takeRequest();
|
||||||
|
assertEquals(request.getRequestLine(), "GET /-/vaults/" + VAULT_NAME + " HTTP/1.1");
|
||||||
|
assertEquals(vm.getVaultName(), "examplevault");
|
||||||
|
assertEquals(vm.getVaultARN(), "arn:aws:glacier:us-east-1:012345678901:vaults/examplevault");
|
||||||
|
assertEquals(vm.getSizeInBytes(), 78088912);
|
||||||
|
assertEquals(vm.getNumberOfArchives(), 192);
|
||||||
|
} finally {
|
||||||
|
server.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVaults() throws IOException, InterruptedException {
|
||||||
|
// Prepare the response
|
||||||
|
MockResponse mr = new MockResponse();
|
||||||
|
mr.setResponseCode(200);
|
||||||
|
mr.addHeader("x-amzn-RequestId", "AAABZpJrTyioDC_HsOmHae8EZp_uBSJr6cnGOLKp_XJCl-Q");
|
||||||
|
mr.addHeader("Date", "Sun, 25 Mar 2012 12:02:00 GMT");
|
||||||
|
mr.addHeader("Content-Type", "application/json");
|
||||||
|
mr.addHeader("Content-Length", "497");
|
||||||
|
mr.setBody("{" + "\"Marker\": null,\"VaultList\": [ {\"CreationDate\": \"2012-03-16T22:22:47.214Z\","
|
||||||
|
+ "\"LastInventoryDate\": \"2012-03-21T22:06:51.218Z\",\"NumberOfArchives\": 2,"
|
||||||
|
+ "\"SizeInBytes\": 12334,\"VaultARN\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault1\","
|
||||||
|
+ "\"VaultName\": \"examplevault1\"}, {\"CreationDate\": \"2012-03-19T22:06:51.218Z\","
|
||||||
|
+ "\"LastInventoryDate\": \"2012-03-21T22:06:51.218Z\", \"NumberOfArchives\": 0,\"SizeInBytes\": 0,"
|
||||||
|
+ "\"VaultARN\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault2\","
|
||||||
|
+ "\"VaultName\": \"examplevault2\"},{\"CreationDate\": \"2012-03-19T22:06:51.218Z\","
|
||||||
|
+ "\"LastInventoryDate\": \"2012-03-25T12:14:31.121Z\",\"NumberOfArchives\": 0,\"SizeInBytes\": 0,"
|
||||||
|
+ "\"VaultARN\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault3\","
|
||||||
|
+ "\"VaultName\": \"examplevault3\"}]}");
|
||||||
|
MockWebServer server = new MockWebServer();
|
||||||
|
server.enqueue(mr);
|
||||||
|
server.play();
|
||||||
|
|
||||||
|
// Send the request and check the response
|
||||||
|
try {
|
||||||
|
GlacierClient client = getGlacierClient(server.getUrl("/"));
|
||||||
|
PaginatedVaultCollection vc = client.listVaults();
|
||||||
|
Iterator<VaultMetadata> i = vc.iterator();
|
||||||
|
assertEquals(i.next().getVaultName(), "examplevault1");
|
||||||
|
assertEquals(i.next().getVaultName(), "examplevault2");
|
||||||
|
assertEquals(i.next().getVaultName(), "examplevault3");
|
||||||
|
RecordedRequest request = server.takeRequest();
|
||||||
|
assertEquals(request.getRequestLine(), "GET /-/vaults HTTP/1.1");
|
||||||
|
} finally {
|
||||||
|
server.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListVaultsWithQueryParams() throws IOException, InterruptedException {
|
||||||
|
// Prepare the response
|
||||||
|
MockResponse mr = new MockResponse();
|
||||||
|
mr.setResponseCode(200);
|
||||||
|
mr.addHeader("x-amzn-RequestId", "AAABZpJrTyioDC_HsOmHae8EZp_uBSJr6cnGOLKp_XJCl-Q");
|
||||||
|
mr.addHeader("Date", "Sun, 25 Mar 2012 12:02:00 GMT");
|
||||||
|
mr.addHeader("Content-Type", "application/json");
|
||||||
|
mr.addHeader("Content-Length", "497");
|
||||||
|
mr.setBody("{\"Marker\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault3\","
|
||||||
|
+ "\"VaultList\": [{\"CreationDate\": \"2012-03-16T22:22:47.214Z\",\"LastInventoryDate\":"
|
||||||
|
+ "\"2012-03-21T22:06:51.218Z\",\"NumberOfArchives\": 2,\"SizeInBytes\": 12334,"
|
||||||
|
+ "\"VaultARN\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault1\","
|
||||||
|
+ "\"VaultName\": \"examplevault1\"},{\"CreationDate\": \"2012-03-19T22:06:51.218Z\","
|
||||||
|
+ "\"LastInventoryDate\": \"2012-03-21T22:06:51.218Z\",\"NumberOfArchives\": 0,"
|
||||||
|
+ "\"SizeInBytes\": 0,\"VaultARN\": \"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault2\","
|
||||||
|
+ "\"VaultName\": \"examplevault2\"}]}");
|
||||||
|
MockWebServer server = new MockWebServer();
|
||||||
|
server.enqueue(mr);
|
||||||
|
server.play();
|
||||||
|
|
||||||
|
// Send the request and check the response
|
||||||
|
try {
|
||||||
|
GlacierClient client = getGlacierClient(server.getUrl("/"));
|
||||||
|
PaginatedVaultCollection vc = client.listVaults(PaginationOptions.Builder.limit(2).marker(
|
||||||
|
"arn:aws:glacier:us-east-1:012345678901:vaults/examplevault1"));
|
||||||
|
Iterator<VaultMetadata> i = vc.iterator();
|
||||||
|
assertEquals(i.next().getVaultName(), "examplevault1");
|
||||||
|
assertEquals(i.next().getVaultName(), "examplevault2");
|
||||||
|
assertFalse(i.hasNext());
|
||||||
|
assertEquals(vc.nextMarker().get(), "arn:aws:glacier:us-east-1:012345678901:vaults/examplevault3");
|
||||||
|
RecordedRequest request = server.takeRequest();
|
||||||
|
assertEquals(request.getRequestLine(), "GET /-/vaults?limit=2&"
|
||||||
|
+ "marker=arn%3Aaws%3Aglacier%3Aus-east-1%3A012345678901%3Avaults/examplevault1 HTTP/1.1");
|
||||||
|
} finally {
|
||||||
|
server.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.glacier.predicates.validators;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@Test(groups = "unit", testName = "VaultNameValidatorTest")
|
||||||
|
public class VaultNameValidatorTest {
|
||||||
|
|
||||||
|
private static final VaultNameValidator VALIDATOR = new VaultNameValidator();
|
||||||
|
|
||||||
|
public void testValidate() {
|
||||||
|
VALIDATOR.validate("VALID_NAME");
|
||||||
|
VALIDATOR.validate("VALID-NAME");
|
||||||
|
VALIDATOR.validate("VALID255NAME");
|
||||||
|
VALIDATOR.validate("255VALID-NAME");
|
||||||
|
VALIDATOR.validate("VALID.NAME");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testValidateInvalidName() {
|
||||||
|
VALIDATOR.validate("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testValidateInvalidName2() {
|
||||||
|
VALIDATOR.validate("<InvalidName>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testValidateInvalidName3() {
|
||||||
|
VALIDATOR.validate("INVALID,NAME");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
|
public void testValidateInvalidName4() {
|
||||||
|
VALIDATOR.validate("INVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVAL" +
|
||||||
|
"IDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEI" +
|
||||||
|
"NVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAMEINVALIDNAME");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue