From 23bfcab73ee9028239998f5ee84aeedb67da28d6 Mon Sep 17 00:00:00 2001 From: adriancole Date: Tue, 9 Apr 2013 18:31:14 -0700 Subject: [PATCH] decoupled code that requires async apis from keystone --- .../keystone/v2_0/AuthenticationApi.java | 57 ++++++++++-- .../keystone/v2_0/AuthenticationAsyncApi.java | 7 +- .../keystone/v2_0/KeystoneApiMetadata.java | 2 + .../v2_0/config/AuthenticationApiModule.java | 39 ++++++++ .../config/KeystoneAuthenticationModule.java | 12 +-- .../config/MappedAuthenticationApiModule.java | 43 +++++++++ .../v2_0/config/ProviderModuleExpectTest.java | 89 ++++++++++++------- 7 files changed, 196 insertions(+), 53 deletions(-) create mode 100644 apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java create mode 100644 apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java index d62bc67788..8fc7aa355f 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java @@ -18,47 +18,88 @@ */ package org.jclouds.openstack.keystone.v2_0; +import java.io.Closeable; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.SelectJson; + +import com.google.inject.name.Named; /** * Provides synchronous access to the KeyStone Service API. *

* - * @see AuthenticationAsyncApi - * @see * @author Adrian Cole */ -public interface AuthenticationApi { +public interface AuthenticationApi extends Closeable { /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials); + @Named("authenticate") + @POST + @SelectJson("access") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens") + @MapBinder(BindAuthToJsonPayload.class) + Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName, + PasswordCredentials passwordCredentials); /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials); + @Named("authenticate") + @POST + @SelectJson("access") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens") + @MapBinder(BindAuthToJsonPayload.class) + Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId, + PasswordCredentials passwordCredentials); /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials); - + @Named("authenticate") + @POST + @SelectJson("access") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens") + @MapBinder(BindAuthToJsonPayload.class) + Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName, + ApiAccessKeyCredentials apiAccessKeyCredentials); + /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials); + @Named("authenticate") + @POST + @SelectJson("access") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens") + @MapBinder(BindAuthToJsonPayload.class) + Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId, + ApiAccessKeyCredentials apiAccessKeyCredentials); } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java index 02dd7c590e..6113aed85c 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java @@ -18,6 +18,8 @@ */ package org.jclouds.openstack.keystone.v2_0; +import java.io.Closeable; + import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; @@ -42,8 +44,11 @@ import com.google.common.util.concurrent.ListenableFuture; * @see * @author Adrian Cole + * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer + * supported. please use {@link AuthenticationApi} */ -public interface AuthenticationAsyncApi { +@Deprecated +public interface AuthenticationAsyncApi extends Closeable { /** * @see AuthenticationApi#authenticateWithTenantNameAndCredentials(String,PasswordCredentials) diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java index 003be876e8..7ddbdab18b 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java @@ -29,6 +29,7 @@ import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule; import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule.KeystoneAdminURLModule; +import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.rest.internal.BaseRestApiMetadata; @@ -90,6 +91,7 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata { .defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/") .defaultProperties(KeystoneApiMetadata.defaultProperties()) .defaultModules(ImmutableSet.>builder() + .add(MappedAuthenticationApiModule.class) .add(KeystoneAuthenticationModule.class) .add(KeystoneAdminURLModule.class) .add(KeystoneParserModule.class) diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java new file mode 100644 index 0000000000..71424604d1 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java @@ -0,0 +1,39 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.keystone.v2_0.config; + +import static org.jclouds.rest.config.BinderUtils.bindHttpApi; + +import org.jclouds.openstack.keystone.v2_0.AuthenticationApi; + +import com.google.inject.AbstractModule; + +/** + * + * @author Adrian Cole + */ +public class AuthenticationApiModule extends AbstractModule { + + @Override + protected void configure() { + // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly + bindHttpApi(binder(), AuthenticationApi.class); + } + +} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java index 52be3baa98..0b2099dc21 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java @@ -19,7 +19,6 @@ package org.jclouds.openstack.keystone.v2_0.config; import static com.google.common.base.Preconditions.checkArgument; -import static org.jclouds.rest.config.BinderUtils.bindMappedHttpApi; import static org.jclouds.util.Suppliers2.getLastValueInMap; import java.net.URI; @@ -47,8 +46,6 @@ import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet; import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet; import org.jclouds.location.suppliers.implicit.FirstRegion; import org.jclouds.location.suppliers.implicit.FirstZone; -import org.jclouds.openstack.keystone.v2_0.AuthenticationApi; -import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials; @@ -60,7 +57,6 @@ import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier; import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersion; import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersion; import org.jclouds.rest.annotations.ApiVersion; -import org.jclouds.rest.config.RestClientModule; import com.google.common.base.Function; import com.google.common.base.Supplier; @@ -89,7 +85,7 @@ public class KeystoneAuthenticationModule extends AbstractModule { * {@link javax.inject.Qualifier} *

  • add the above annotation to any {@link AsyncApi} classes by placing it on the type. ex. * {@code @Endpoint(CloudDNS.class)}
  • - *
  • add the following to your {@link RestClientModule}
  • + *
  • add the following to your {@link org.jclouds.rest.config.RestClientModule}
  • * *
         * bind(new TypeLiteral<Supplier<URI>>() {
    @@ -184,12 +180,6 @@ public class KeystoneAuthenticationModule extends AbstractModule {
        @Override
        protected void configure() {
           bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
    -      bindAuthenticationApi();
    -   }
    -
    -   protected void bindAuthenticationApi() {
    -      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
    -      bindMappedHttpApi(binder(), AuthenticationApi.class, AuthenticationAsyncApi.class);
        }
     
        /**
    diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java
    new file mode 100644
    index 0000000000..96dbb92fb9
    --- /dev/null
    +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java
    @@ -0,0 +1,43 @@
    +/**
    + * Licensed to jclouds, Inc. (jclouds) under one or more
    + * contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  jclouds 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.keystone.v2_0.config;
    +
    +import static org.jclouds.rest.config.BinderUtils.bindMappedHttpApi;
    +
    +import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
    +import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi;
    +
    +import com.google.inject.AbstractModule;
    +
    +/**
    + * 
    + * @author Adrian Cole
    + * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
    + *             supported. please use {@link AuthenticationApiModule}
    + */
    +@Deprecated
    +public class MappedAuthenticationApiModule extends AbstractModule  {
    +
    +   @Override
    +   protected void configure() {
    +      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
    +      bindMappedHttpApi(binder(), AuthenticationApi.class, AuthenticationAsyncApi.class);
    +   }
    +
    +}
    diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
    index 21705c99f9..7cbc64db5b 100644
    --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
    +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
    @@ -1,9 +1,28 @@
    +/**
    + * Licensed to jclouds, Inc. (jclouds) under one or more
    + * contributor license agreements.  See the NOTICE file
    + * distributed with this work for additional information
    + * regarding copyright ownership.  jclouds 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.keystone.v2_0.config;
     
    -import static java.lang.annotation.ElementType.TYPE;
    +import static java.lang.annotation.ElementType.METHOD;
     import static java.lang.annotation.RetentionPolicy.RUNTIME;
     import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
     import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
    +import static org.jclouds.util.Suppliers2.getLastValueInMap;
     import static org.testng.Assert.assertTrue;
     
     import java.io.Closeable;
    @@ -13,6 +32,7 @@ import java.net.URI;
     import java.util.Properties;
     
     import javax.inject.Qualifier;
    +import javax.inject.Singleton;
     import javax.ws.rs.HEAD;
     import javax.ws.rs.Path;
     import javax.ws.rs.PathParam;
    @@ -23,21 +43,23 @@ import org.jclouds.http.HttpRequest;
     import org.jclouds.http.HttpResponse;
     import org.jclouds.json.config.GsonModule.DateAdapter;
     import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
    +import org.jclouds.location.suppliers.RegionIdToURISupplier;
     import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
     import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ProviderModule;
    +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
     import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest;
    -import org.jclouds.rest.ConfiguresRestClient;
    +import org.jclouds.rest.ConfiguresHttpApi;
    +import org.jclouds.rest.annotations.ApiVersion;
     import org.jclouds.rest.annotations.Fallback;
    -import org.jclouds.rest.config.RestClientModule;
    +import org.jclouds.rest.config.HttpApiModule;
    +import org.jclouds.rest.internal.BaseHttpApiMetadata;
     import org.jclouds.rest.internal.BaseRestApiExpectTest;
    -import org.jclouds.rest.internal.BaseRestApiMetadata;
     import org.testng.annotations.Test;
     
     import com.google.common.base.Supplier;
     import com.google.common.collect.ImmutableSet;
    -import com.google.common.util.concurrent.ListenableFuture;
     import com.google.inject.Module;
    -import com.google.inject.TypeLiteral;
    +import com.google.inject.Provides;
     
     /**
      * Tests configuration via {@link ProviderModule}
    @@ -48,31 +70,34 @@ import com.google.inject.TypeLiteral;
     public class ProviderModuleExpectTest extends BaseRestApiExpectTest {
     
        @Retention(RUNTIME)
    -   @Target(TYPE)
    +   @Target(METHOD)
        @Qualifier
        static @interface DNS {
        }
     
    -   @ConfiguresRestClient
    -   public static class DNSRestClientModule extends RestClientModule {
    +   @ConfiguresHttpApi
    +   public static class DNSHttpApiModule extends HttpApiModule {
    +
           @Override
           public void configure() {
    -         bind(new TypeLiteral>() {}).annotatedWith(DNS.class).to(new TypeLiteral>() {});
              bind(DateAdapter.class).to(Iso8601DateAdapter.class);
              super.configure();
           }
    -   }
     
    -   static interface DNSApi extends Closeable {
    -      boolean zoneExists(@PathParam("zoneName") String zoneName);
    +      @Provides
    +      @Singleton
    +      @DNS
    +      protected Supplier provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
    +         return getLastValueInMap(factory.createForApiTypeAndVersion("dns", apiVersion));
    +      }
        }
     
        @org.jclouds.rest.annotations.Endpoint(DNS.class)
    -   static interface DNSAsyncApi extends Closeable {
    +   static interface DNSApi extends Closeable {
           @HEAD
           @Path("/zones/{zoneName}")
           @Fallback(FalseOnNotFoundOr404.class)
    -      public ListenableFuture zoneExists(@PathParam("zoneName") String zoneName);
    +      boolean zoneExists(@PathParam("zoneName") String zoneName);
        }
     
        public void testDNSEndpointApplied() {
    @@ -86,7 +111,7 @@ public class ProviderModuleExpectTest extends BaseRestApiExpectTest {
     
           @Override
           public Builder toBuilder() {
    @@ -102,31 +127,29 @@ public class ProviderModuleExpectTest extends BaseRestApiExpectTest {
    +      public static class Builder extends BaseHttpApiMetadata.Builder {
     
              protected Builder() {
    -            super(DNSApi.class, DNSAsyncApi.class);
                 id("dns")
    -                  .name("DNS API")
    -                  .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
    -                  .credentialName("${password}")
    -                  .endpointName("Keystone base url ending in /v2.0/")
    -                  .documentation(URI.create("http://dns"))
    -                  .version("1.0")
    -                  .defaultEndpoint("http://localhost:5000/v2.0/")
    -                  .defaultProperties(DNSApiMetadata.defaultProperties())
    -                  .defaultModules(
    -                        ImmutableSet.> builder()
    -                           .add(KeystoneAuthenticationModule.class)
    -                           .add(ProviderModule.class)
    -                           .add(DNSRestClientModule.class)
    -                           .build());
    +            .name("DNS API")
    +            .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
    +            .credentialName("${password}")
    +            .endpointName("Keystone base url ending in /v2.0/")
    +            .documentation(URI.create("http://dns"))
    +            .version("1.0")
    +            .defaultEndpoint("http://localhost:5000/v2.0/")
    +            .defaultProperties(DNSApiMetadata.defaultProperties())
    +            .defaultModules(ImmutableSet.>builder()
    +                                        .add(AuthenticationApiModule.class)
    +                                        .add(KeystoneAuthenticationModule.class)
    +                                        .add(RegionModule.class)
    +                                        .add(DNSHttpApiModule.class).build());
              }
     
              @Override