JCLOUDS-306. refactored AccountApi to be usable from container
Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/commit/f867518d Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/tree/f867518d Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/diff/f867518d Branch: refs/heads/master Commit: f867518d6d43f2fd61df23cec6bb21fdd9e8b4e7 Parents: 4902919 Author: Adrian Cole <[email protected]> Authored: Fri Sep 27 21:36:43 2013 -0700 Committer: Adrian Cole <[email protected]> Committed: Sat Sep 28 07:12:01 2013 -0700 ---------------------------------------------------------------------- .../binders/BindAccountMetadataToHeaders.java | 92 -------------- .../swift/v1/binders/BindMetadataToHeaders.java | 124 +++++++++++++++++++ .../openstack/swift/v1/features/AccountApi.java | 20 +-- .../swift/v1/features/AccountApiLiveTest.java | 6 +- .../swift/v1/features/AccountApiMockTest.java | 12 +- 5 files changed, 145 insertions(+), 109 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/f867518d/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindAccountMetadataToHeaders.java ---------------------------------------------------------------------- diff --git a/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindAccountMetadataToHeaders.java b/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindAccountMetadataToHeaders.java deleted file mode 100644 index 96e58bc..0000000 --- a/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindAccountMetadataToHeaders.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.openstack.swift.v1.binders; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.Map; -import java.util.Map.Entry; - -import org.jclouds.http.HttpRequest; -import org.jclouds.rest.Binder; - -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableMultimap.Builder; - -/** - * Will lower-case header keys due to a swift implementation to return headers - * in a different case than sent. ex. - * - * <pre> - * >> X-Account-Meta-MyDelete1: foo - * >> X-Account-Meta-MyDelete2: bar - * </pre> - * - * results in: - * - * <pre> - * << X-Account-Meta-Mydelete1: foo - * << X-Account-Meta-Mydelete2: bar - * </pre> - * - * <h4>Note</h4> <br/> - * HTTP response headers keys are known to be case-insensitive, but this - * practice of mixing up case will prevent metadata keys such as those in - * Turkish from working. - * - * @see <a - * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/create-update-account-metadata.html">documentation</a> - */ -public class BindAccountMetadataToHeaders implements Binder { - - private static final String ACCOUNT_METADATA_PREFIX = "x-account-meta-"; - - @SuppressWarnings("unchecked") - @Override - public <R extends HttpRequest> R bindToRequest(R request, Object input) { - checkNotNull(request, "request"); - checkArgument(input instanceof Map<?, ?>, "input must be a non-null java.util.Map!"); - Map<String, String> metadata = Map.class.cast(input); - Builder<String, String> headers = ImmutableMultimap.<String, String> builder(); - for (Entry<String, String> keyVal : metadata.entrySet()) { - String keyInLowercase = keyVal.getKey().toLowerCase(); - if (keyVal.getKey().startsWith(ACCOUNT_METADATA_PREFIX)) { - putAccountMetadata(headers, keyInLowercase, keyVal.getValue()); - } else { - putAccountMetadata(headers, String.format("%s%s", ACCOUNT_METADATA_PREFIX, keyInLowercase), - keyVal.getValue()); - } - } - return (R) request.toBuilder().replaceHeaders(headers.build()).build(); - } - - protected void putAccountMetadata(Builder<String, String> headers, String key, String value) { - headers.put(key, value); - } - - /** - * @see <a - * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/delete-account-metadata.html">documentation</a> - */ - public static class InRemoval extends BindAccountMetadataToHeaders { - @Override - protected void putAccountMetadata(Builder<String, String> headers, String key, String value) { - headers.put(String.format("x-remove%s", key.substring(1)), "ignored"); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/f867518d/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java ---------------------------------------------------------------------- diff --git a/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java b/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java new file mode 100644 index 0000000..dd3f803 --- /dev/null +++ b/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/binders/BindMetadataToHeaders.java @@ -0,0 +1,124 @@ +/* + * 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.openstack.swift.v1.binders; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Map.Entry; + +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableMultimap.Builder; + +/** + * Will lower-case header keys due to a swift implementation to return headers + * in a different case than sent. ex. + * + * <pre> + * >> X-Account-Meta-MyDelete1: foo + * >> X-Account-Meta-MyDelete2: bar + * </pre> + * + * results in: + * + * <pre> + * << X-Account-Meta-Mydelete1: foo + * << X-Account-Meta-Mydelete2: bar + * </pre> + * + * <h4>Note</h4> <br/> + * HTTP response headers keys are known to be case-insensitive, but this + * practice of mixing up case will prevent metadata keys such as those in + * Turkish from working. + * + * @see <a + * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/create-update-account-metadata.html">documentation</a> + */ +public abstract class BindMetadataToHeaders implements Binder { + + public static class BindAccountMetadataToHeaders extends BindMetadataToHeaders { + BindAccountMetadataToHeaders() { + super("x-account-meta-"); + } + } + + public static class BindRemoveAccountMetadataToHeaders extends BindMetadataToHeaders.ForRemoval { + BindRemoveAccountMetadataToHeaders() { + super("x-account-meta-"); + } + } + + public static class BindContainerMetadataToHeaders extends BindMetadataToHeaders { + BindContainerMetadataToHeaders() { + super("x-container-meta-"); + } + } + + public static class BindRemoveContainerMetadataToHeaders extends BindMetadataToHeaders.ForRemoval { + BindRemoveContainerMetadataToHeaders() { + super("x-container-meta-"); + } + } + + /** + * @see <a + * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/delete-account-metadata.html">documentation</a> + */ + public static abstract class ForRemoval extends BindMetadataToHeaders { + ForRemoval(String metadataPrefix) { + super(metadataPrefix); + } + + @Override + protected void putMetadata(Builder<String, String> headers, String key, String value) { + headers.put(String.format("x-remove%s", key.substring(1)), "ignored"); + } + } + + private final String metadataPrefix; + + BindMetadataToHeaders(String metadataPrefix) { + this.metadataPrefix = metadataPrefix; + } + + @SuppressWarnings("unchecked") + @Override + public <R extends HttpRequest> R bindToRequest(R request, Object input) { + checkNotNull(request, "request"); + checkArgument(input instanceof Map<?, ?>, "input must be a non-null java.util.Map!"); + Map<String, String> metadata = Map.class.cast(input); + Builder<String, String> headers = ImmutableMultimap.<String, String> builder(); + for (Entry<String, String> keyVal : metadata.entrySet()) { + String keyInLowercase = keyVal.getKey().toLowerCase(); + if (keyVal.getKey().startsWith(metadataPrefix)) { + putMetadata(headers, keyInLowercase, keyVal.getValue()); + } else { + putMetadata(headers, String.format("%s%s", metadataPrefix, keyInLowercase), keyVal.getValue()); + } + } + return (R) request.toBuilder().replaceHeaders(headers.build()).build(); + } + + protected void putMetadata(Builder<String, String> headers, String key, String value) { + headers.put(key, value); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/f867518d/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java ---------------------------------------------------------------------- diff --git a/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java b/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java index fe49b4e..0b0c65c 100644 --- a/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java +++ b/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/features/AccountApi.java @@ -16,6 +16,8 @@ */ package org.jclouds.openstack.swift.v1.features; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + import java.util.Map; import javax.inject.Named; @@ -23,11 +25,11 @@ import javax.ws.rs.Consumes; import javax.ws.rs.HEAD; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.core.MediaType; import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; -import org.jclouds.openstack.swift.v1.binders.BindAccountMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindAccountMetadataToHeaders; +import org.jclouds.openstack.swift.v1.binders.BindMetadataToHeaders.BindRemoveAccountMetadataToHeaders; import org.jclouds.openstack.swift.v1.domain.Account; import org.jclouds.openstack.swift.v1.functions.ParseAccountFromHeaders; import org.jclouds.rest.annotations.BinderParam; @@ -49,6 +51,7 @@ import org.jclouds.rest.annotations.ResponseParser; * Storage Account Services API</a> */ @RequestFilters(AuthenticateRequest.class) +@Consumes(APPLICATION_JSON) public interface AccountApi { /** @@ -60,8 +63,7 @@ public interface AccountApi { * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/retrieve-account-metadata.html"> * Get Account Metadata API</a> */ - @Named("account:get") - @Consumes(MediaType.APPLICATION_JSON) + @Named("GetAccount") @HEAD @ResponseParser(ParseAccountFromHeaders.class) @Path("/") @@ -80,12 +82,11 @@ public interface AccountApi { * @return <code>true</code> if the Account Metadata was successfully created * or updated, false if not. */ - @Named("account:createOrUpdateMetadata") - @Consumes + @Named("UpdateAccountMetadata") @POST @Fallback(FalseOnNotFoundOr404.class) @Path("/") - boolean createOrUpdateMetadata(@BinderParam(BindAccountMetadataToHeaders.class) Map<String, String> metadata); + boolean updateMetadata(@BinderParam(BindAccountMetadataToHeaders.class) Map<String, String> metadata); /** * Deletes Account metadata. @@ -100,10 +101,9 @@ public interface AccountApi { * href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/delete-account-metadata.html"> * Delete Account Metadata API</a> */ - @Named("account:deleteMetadata") - @Consumes + @Named("DeleteAccountMetadata") @POST @Fallback(FalseOnNotFoundOr404.class) @Path("/") - boolean deleteMetadata(@BinderParam(BindAccountMetadataToHeaders.InRemoval.class) Map<String, String> metadata); + boolean deleteMetadata(@BinderParam(BindRemoveAccountMetadataToHeaders.class) Map<String, String> metadata); } http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/f867518d/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiLiveTest.java ---------------------------------------------------------------------- diff --git a/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiLiveTest.java b/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiLiveTest.java index af9f879..a1b388e 100644 --- a/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiLiveTest.java +++ b/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiLiveTest.java @@ -45,13 +45,13 @@ public class AccountApiLiveTest extends BaseSwiftApiLiveTest { } } - public void createOrUpdateMetadata() throws Exception { + public void updateMetadata() throws Exception { for (String regionId : api.configuredRegions()) { AccountApi accountApi = api.accountApiInRegion(regionId); Map<String, String> meta = ImmutableMap.of("MyAdd1", "foo", "MyAdd2", "bar"); - assertTrue(accountApi.createOrUpdateMetadata(meta)); + assertTrue(accountApi.updateMetadata(meta)); accountHasMetadata(accountApi, meta); } @@ -63,7 +63,7 @@ public class AccountApiLiveTest extends BaseSwiftApiLiveTest { Map<String, String> meta = ImmutableMap.of("MyDelete1", "foo", "MyDelete2", "bar"); - assertTrue(accountApi.createOrUpdateMetadata(meta)); + assertTrue(accountApi.updateMetadata(meta)); accountHasMetadata(accountApi, meta); assertTrue(accountApi.deleteMetadata(meta)); http://git-wip-us.apache.org/repos/asf/incubator-jclouds-labs-openstack/blob/f867518d/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiMockTest.java ---------------------------------------------------------------------- diff --git a/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiMockTest.java b/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiMockTest.java index b561ca2..c2a37c3 100644 --- a/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiMockTest.java +++ b/openstack-swift/src/test/java/org/jclouds/openstack/swift/v1/features/AccountApiMockTest.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Map.Entry; import org.jclouds.openstack.swift.v1.SwiftApi; +import org.jclouds.openstack.swift.v1.domain.Account; import org.jclouds.openstack.swift.v1.internal.BaseSwiftMockTest; import org.testng.annotations.Test; @@ -48,9 +49,12 @@ public class AccountApiMockTest extends BaseSwiftMockTest { try { SwiftApi api = swiftApi(server.getUrl("/").toString()); - Map<String, String> metadata = api.accountApiInRegion("DFW").get().metadata(); + Account account = api.accountApiInRegion("DFW").get(); + assertEquals(account.containerCount(), 3l); + assertEquals(account.objectCount(), 42l); + assertEquals(account.bytesUsed(), 323479l); for (Entry<String, String> entry : metadata.entrySet()) { - assertEquals(metadata.get(entry.getKey().toLowerCase()), entry.getValue()); + assertEquals(account.metadata().get(entry.getKey().toLowerCase()), entry.getValue()); } assertEquals(server.getRequestCount(), 2); @@ -62,7 +66,7 @@ public class AccountApiMockTest extends BaseSwiftMockTest { } } - public void createOrUpdateMetadata() throws Exception { + public void updateMetadata() throws Exception { MockWebServer server = mockSwiftServer(); server.enqueue(new MockResponse().setBody(access)); server.enqueue(accountResponse() // @@ -71,7 +75,7 @@ public class AccountApiMockTest extends BaseSwiftMockTest { try { SwiftApi api = swiftApi(server.getUrl("/").toString()); - assertTrue(api.accountApiInRegion("DFW").createOrUpdateMetadata(metadata)); + assertTrue(api.accountApiInRegion("DFW").updateMetadata(metadata)); assertEquals(server.getRequestCount(), 2); assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
