From 613290ea8d16f3744cd25384a464b63594565495 Mon Sep 17 00:00:00 2001 From: Ignasi Barrera Date: Sat, 21 May 2016 00:25:31 +0200 Subject: [PATCH] Allow to link contexts and views together Some providers need other APIs or portable services to perform certain operations. This change allows to pass existing Context and View instances when creating a context, so they are added to the injector of the context being built. This allows to inject external apis and providers into an existing provider to leverage the external functionality. --- .../org/jclouds/config/ContextLinking.java | 78 +++++++++++++++++++ .../jclouds/config/ContextLinkingTest.java | 69 ++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 core/src/main/java/org/jclouds/config/ContextLinking.java create mode 100644 core/src/test/java/org/jclouds/config/ContextLinkingTest.java diff --git a/core/src/main/java/org/jclouds/config/ContextLinking.java b/core/src/main/java/org/jclouds/config/ContextLinking.java new file mode 100644 index 0000000000..51f9a2f444 --- /dev/null +++ b/core/src/main/java/org/jclouds/config/ContextLinking.java @@ -0,0 +1,78 @@ +/* + * 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.config; + +import org.jclouds.Context; +import org.jclouds.View; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.inject.AbstractModule; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; +import com.google.inject.name.Names; + +/** + * Utility methods to allow {@link Context} and {@link View} linking between + * contexts. + *

+ * By using this module users can configure a context to be able to inject other + * contexts or views by their provider id. + */ +public class ContextLinking { + + static final TypeLiteral> CONTEXT_SUPPLIER = new TypeLiteral>() { + }; + + static final TypeLiteral> VIEW_SUPPLIER = new TypeLiteral>() { + }; + + public static Module linkView(final String id, final Supplier view) { + return new AbstractModule() { + @Override + protected void configure() { + bind(VIEW_SUPPLIER).annotatedWith(Names.named(id)).toInstance(view); + bind(CONTEXT_SUPPLIER).annotatedWith(Names.named(id)).toInstance(Suppliers.compose(ViewToContext, view)); + } + }; + } + + public static Module linkContext(final String id, final Supplier context) { + return new AbstractModule() { + @Override + protected void configure() { + bind(CONTEXT_SUPPLIER).annotatedWith(Names.named(id)).toInstance(context); + } + }; + } + + public static Module linkView(View view) { + return linkView(view.unwrap().getId(), Suppliers.ofInstance(view)); + } + + public static Module linkContext(Context context) { + return linkContext(context.getId(), Suppliers.ofInstance(context)); + } + + private static final Function ViewToContext = new Function() { + @Override + public Context apply(View input) { + return input.unwrap(); + } + }; +} diff --git a/core/src/test/java/org/jclouds/config/ContextLinkingTest.java b/core/src/test/java/org/jclouds/config/ContextLinkingTest.java new file mode 100644 index 0000000000..7d2f2a21f7 --- /dev/null +++ b/core/src/test/java/org/jclouds/config/ContextLinkingTest.java @@ -0,0 +1,69 @@ +/* + * 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.config; + +import static org.jclouds.config.ContextLinking.CONTEXT_SUPPLIER; +import static org.jclouds.config.ContextLinking.VIEW_SUPPLIER; +import static org.jclouds.config.ContextLinking.linkContext; +import static org.jclouds.config.ContextLinking.linkView; +import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint; +import static org.testng.Assert.assertNotNull; + +import java.io.Closeable; + +import org.jclouds.Context; +import org.jclouds.ContextBuilder; +import org.jclouds.http.IntegrationTestClient; +import org.jclouds.internal.BaseView; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; + +@Test(groups = "unit", testName = "ContextLinkingTest") +public class ContextLinkingTest { + + @Test + public void testLinkedViewBindsViewAndContextSuppliers() { + Injector injector = Guice.createInjector(linkView(new DummyView(contextFor(IntegrationTestClient.class)))); + + assertNotNull(injector.getExistingBinding(Key.get(CONTEXT_SUPPLIER, Names.named("IntegrationTestClient")))); + assertNotNull(injector.getExistingBinding(Key.get(VIEW_SUPPLIER, Names.named("IntegrationTestClient")))); + } + + @Test + public void testLinkedContextBindsContextSupplier() { + Injector injector = Guice.createInjector(linkContext(contextFor(IntegrationTestClient.class))); + + assertNotNull(injector.getExistingBinding(Key.get(CONTEXT_SUPPLIER, Names.named("IntegrationTestClient")))); + } + + private static class DummyView extends BaseView { + protected DummyView(Context context) { + super(context, new TypeToken() { + private static final long serialVersionUID = 1L; + }); + } + } + + private static Context contextFor(Class apiClass) { + return ContextBuilder.newBuilder(forApiOnEndpoint(apiClass, "http://localhost")).build(); + } +}