JCLOUDS-82: Added method to get the underlying Api from a View

This commit is contained in:
Ignasi Barrera 2013-05-24 09:23:53 +02:00
parent b3a320e015
commit 334bd36730
3 changed files with 77 additions and 1 deletions

View File

@ -16,6 +16,8 @@
*/
package org.jclouds;
import java.io.Closeable;
import com.google.common.annotations.Beta;
import com.google.common.reflect.TypeToken;
@ -68,4 +70,14 @@ public interface View {
*/
<C extends Context> C unwrap() throws ClassCastException;
/**
* Unwraps the underlying api from this view.
*
* @param apiClass The class of the api to unwrap.
* @return The unwrapped api.
*
* @since 1.7
*/
<A extends Closeable> A unwrapApi(Class<A> apiClass);
}

View File

@ -19,15 +19,19 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Closeable;
import javax.inject.Singleton;
import org.jclouds.Context;
import org.jclouds.View;
import org.jclouds.location.Provider;
import org.jclouds.rest.ApiContext;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ForwardingObject;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
/**
@ -62,6 +66,17 @@ public abstract class BaseView extends ForwardingObject implements View {
return (C) unwrap(getBackendType());
}
@Override
public <A extends Closeable> A unwrapApi(Class<A> apiClass) {
checkArgument(ApiContext.class.isAssignableFrom(backendType.getRawType()),
"backend type: %s should be an ApiContext", backendType);
TypeToken<ApiContext<A>> contextToken = new TypeToken<ApiContext<A>>(delegate().getClass()) {
private static final long serialVersionUID = 1L;
}.where(new TypeParameter<A>() {
}, TypeToken.of(apiClass));
return unwrap(contextToken).getApi();
}
@Override
protected Context delegate() {
return backend;

View File

@ -17,19 +17,27 @@
package org.jclouds.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.reflect.Reflection2.typeToken;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.fail;
import java.io.Closeable;
import java.io.IOException;
import org.jclouds.domain.Credentials;
import org.jclouds.lifecycle.Closer;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.ApiContext;
import org.jclouds.rest.Utils;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken;
/**
* @author Adrian Cole
@ -66,6 +74,23 @@ public class BaseViewTest {
}
}
private static class DummyApi implements Closeable {
@Override
public void close() throws IOException {
}
}
public class DummyView extends BaseView {
protected DummyView(ApiContext<DummyApi> context) {
super(context, new TypeToken<ApiContext<DummyApi>>() {
private static final long serialVersionUID = 1L;
});
}
}
public void testWaterTurnedIntoWine() {
Wine wine = new Wine();
assertEquals(wine.getBackendType(), typeToken(Water.class));
@ -84,4 +109,28 @@ public class BaseViewTest {
}
}
public void testCannotUnwrapIfNotApiContext() {
Wine wine = new Wine();
try {
wine.unwrapApi(DummyApi.class);
fail();
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "backend type: org.jclouds.internal.BaseViewTest$Water should be an ApiContext");
}
}
@SuppressWarnings("unchecked")
public void testUnwrapApi() {
DummyApi beer = new DummyApi();
ApiContext<DummyApi> beerContext = createMock(ApiContext.class);
expect(beerContext.getApi()).andReturn(beer);
replay(beerContext);
DummyView bar = new DummyView(beerContext);
DummyApi result = bar.unwrapApi(DummyApi.class);
assertEquals(result, beer);
verify(beerContext);
}
}