Use type adapter factory to hard-set serialization of Credentials.

This commit is contained in:
Adrian Cole 2014-10-30 09:22:28 -07:00 committed by Adrian Cole
parent e21cbd09cb
commit 1e35c0fe19
2 changed files with 73 additions and 37 deletions

View File

@ -32,7 +32,9 @@ import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.JsonBall; import org.jclouds.domain.JsonBall;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory; import org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory;
@ -94,8 +96,9 @@ public class GsonModule extends AbstractModule {
@Singleton @Singleton
Gson provideGson(TypeAdapter<JsonBall> jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter, Gson provideGson(TypeAdapter<JsonBall> jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings, ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings,
OptionalTypeAdapterFactory optional, SetTypeAdapterFactory set, ImmutableSetTypeAdapterFactory immutableSet, CredentialsAdapterFactory credentialsAdapterFactory, OptionalTypeAdapterFactory optional,
MapTypeAdapterFactory map, MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable, SetTypeAdapterFactory set, ImmutableSetTypeAdapterFactory immutableSet, MapTypeAdapterFactory map,
MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
CollectionTypeAdapterFactory collection, ListTypeAdapterFactory list, CollectionTypeAdapterFactory collection, ListTypeAdapterFactory list,
ImmutableListTypeAdapterFactory immutableList, FluentIterableTypeAdapterFactory fluentIterable, ImmutableListTypeAdapterFactory immutableList, FluentIterableTypeAdapterFactory fluentIterable,
ImmutableMapTypeAdapterFactory immutableMap, DefaultExclusionStrategy exclusionStrategy, ImmutableMapTypeAdapterFactory immutableMap, DefaultExclusionStrategy exclusionStrategy,
@ -112,6 +115,7 @@ public class GsonModule extends AbstractModule {
builder.registerTypeAdapter(Date.class, adapter.nullSafe()); builder.registerTypeAdapter(Date.class, adapter.nullSafe());
builder.registerTypeAdapter(byte[].class, byteArrayAdapter.nullSafe()); builder.registerTypeAdapter(byte[].class, byteArrayAdapter.nullSafe());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter.nullSafe()); builder.registerTypeAdapter(JsonBall.class, jsonAdapter.nullSafe());
builder.registerTypeAdapterFactory(credentialsAdapterFactory);
builder.registerTypeAdapterFactory(optional); builder.registerTypeAdapterFactory(optional);
builder.registerTypeAdapterFactory(iterable); builder.registerTypeAdapterFactory(iterable);
builder.registerTypeAdapterFactory(collection); builder.registerTypeAdapterFactory(collection);
@ -316,6 +320,68 @@ public class GsonModule extends AbstractModule {
} }
} }
/** Special cases serialization for {@linkplain LoginCredentials} and normalizes all others. */
public static class CredentialsAdapterFactory extends TypeAdapter<Credentials> implements TypeAdapterFactory {
@Override public void write(JsonWriter out, Credentials credentials) throws IOException {
out.beginObject();
if (credentials instanceof LoginCredentials) {
LoginCredentials login = (LoginCredentials) credentials;
out.name("user");
out.value(login.getUser());
out.name("password");
out.value(login.getOptionalPassword().orNull());
out.name("privateKey");
out.value(login.getOptionalPrivateKey().orNull());
if (login.shouldAuthenticateSudo()) {
out.name("authenticateSudo");
out.value(login.shouldAuthenticateSudo());
}
} else {
out.name("identity");
out.value(credentials.identity);
out.name("credential");
out.value(credentials.credential);
}
out.endObject();
}
@Override public Credentials read(JsonReader in) throws IOException {
LoginCredentials.Builder builder = LoginCredentials.builder();
String identity = null;
String credential = null;
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.equals("identity")) {
identity = in.nextString();
} else if (name.equals("credential")) {
credential = in.nextString();
} else if (name.equals("user")) {
builder.user(in.nextString());
} else if (name.equals("password")) {
builder.password(in.nextString());
} else if (name.equals("privateKey")) {
builder.privateKey(in.nextString());
} else if (name.equals("authenticateSudo")) {
builder.authenticateSudo(in.nextBoolean());
} else {
in.skipValue();
}
}
in.endObject();
LoginCredentials result = builder.build();
return result != null ? result : new Credentials(identity, credential);
}
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (!(Credentials.class.isAssignableFrom(typeToken.getRawType()))) {
return null;
}
return (TypeAdapter<T>) this;
}
}
@Singleton @Singleton
public static class JsonAdapterBindings { public static class JsonAdapterBindings {
private final Map<Type, Object> bindings = Maps.newHashMap(); private final Map<Type, Object> bindings = Maps.newHashMap();

View File

@ -27,7 +27,6 @@ import javax.inject.Singleton;
import org.jclouds.collect.TransformingMap; import org.jclouds.collect.TransformingMap;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.ConfiguresCredentialStore; import org.jclouds.rest.ConfiguresCredentialStore;
@ -69,62 +68,33 @@ public class CredentialStoreModule extends AbstractModule {
} }
} }
@Singleton
public static class CredentialsToJsonByteSource implements Function<Credentials, ByteSource> { public static class CredentialsToJsonByteSource implements Function<Credentials, ByteSource> {
private final Json json; private final Json json;
@Inject @Inject CredentialsToJsonByteSource(Json json) {
CredentialsToJsonByteSource(Json json) {
this.json = json; this.json = json;
} }
@Override @Override public ByteSource apply(Credentials from) {
public ByteSource apply(Credentials from) {
checkNotNull(from, "inputCredentials"); checkNotNull(from, "inputCredentials");
if (from instanceof LoginCredentials) {
LoginCredentials login = LoginCredentials.class.cast(from);
JsonLoginCredentials val = new JsonLoginCredentials();
val.user = login.getUser();
val.password = login.getOptionalPassword().orNull();
val.privateKey = login.getOptionalPrivateKey().orNull();
if (login.shouldAuthenticateSudo())
val.authenticateSudo = login.shouldAuthenticateSudo();
return ByteSource.wrap(json.toJson(val).getBytes(Charsets.UTF_8));
}
return ByteSource.wrap(json.toJson(from).getBytes(Charsets.UTF_8)); return ByteSource.wrap(json.toJson(from).getBytes(Charsets.UTF_8));
} }
} }
static class JsonLoginCredentials {
private String user;
private String password;
private String privateKey;
private Boolean authenticateSudo;
}
@Singleton
public static class CredentialsFromJsonByteSource implements Function<ByteSource, Credentials> { public static class CredentialsFromJsonByteSource implements Function<ByteSource, Credentials> {
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Json json; private final Json json;
@Inject @Inject CredentialsFromJsonByteSource(Json json) {
CredentialsFromJsonByteSource(Json json) {
this.json = json; this.json = json;
} }
@Override @Override public Credentials apply(ByteSource from) {
public Credentials apply(ByteSource from) {
try { try {
String creds = (checkNotNull(from)).asCharSource(Charsets.UTF_8).read(); String creds = (checkNotNull(from)).asCharSource(Charsets.UTF_8).read();
if (creds.indexOf("\"user\":") == -1) {
return json.fromJson(creds, Credentials.class); return json.fromJson(creds, Credentials.class);
} else {
JsonLoginCredentials val = json.fromJson(creds, JsonLoginCredentials.class);
return LoginCredentials.builder().user(val.user).password(val.password).privateKey(val.privateKey)
.authenticateSudo(Boolean.TRUE.equals(val.authenticateSudo)).build();
}
} catch (Exception e) { } catch (Exception e) {
logger.warn(e, "ignoring problem retrieving credentials"); logger.warn(e, "ignoring problem retrieving credentials");
return null; return null;