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 org.jclouds.date.DateService;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.JsonBall;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.json.Json;
import org.jclouds.json.SerializedNames;
import org.jclouds.json.internal.DeserializationConstructorAndReflectiveTypeAdapterFactory;
@ -94,8 +96,9 @@ public class GsonModule extends AbstractModule {
@Singleton
Gson provideGson(TypeAdapter<JsonBall> jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings,
OptionalTypeAdapterFactory optional, SetTypeAdapterFactory set, ImmutableSetTypeAdapterFactory immutableSet,
MapTypeAdapterFactory map, MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
CredentialsAdapterFactory credentialsAdapterFactory, OptionalTypeAdapterFactory optional,
SetTypeAdapterFactory set, ImmutableSetTypeAdapterFactory immutableSet, MapTypeAdapterFactory map,
MultimapTypeAdapterFactory multimap, IterableTypeAdapterFactory iterable,
CollectionTypeAdapterFactory collection, ListTypeAdapterFactory list,
ImmutableListTypeAdapterFactory immutableList, FluentIterableTypeAdapterFactory fluentIterable,
ImmutableMapTypeAdapterFactory immutableMap, DefaultExclusionStrategy exclusionStrategy,
@ -112,6 +115,7 @@ public class GsonModule extends AbstractModule {
builder.registerTypeAdapter(Date.class, adapter.nullSafe());
builder.registerTypeAdapter(byte[].class, byteArrayAdapter.nullSafe());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter.nullSafe());
builder.registerTypeAdapterFactory(credentialsAdapterFactory);
builder.registerTypeAdapterFactory(optional);
builder.registerTypeAdapterFactory(iterable);
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
public static class JsonAdapterBindings {
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.domain.Credentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.json.Json;
import org.jclouds.logging.Logger;
import org.jclouds.rest.ConfiguresCredentialStore;
@ -69,62 +68,33 @@ public class CredentialStoreModule extends AbstractModule {
}
}
@Singleton
public static class CredentialsToJsonByteSource implements Function<Credentials, ByteSource> {
private final Json json;
@Inject
CredentialsToJsonByteSource(Json json) {
@Inject CredentialsToJsonByteSource(Json json) {
this.json = json;
}
@Override
public ByteSource apply(Credentials from) {
@Override public ByteSource apply(Credentials from) {
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));
}
}
static class JsonLoginCredentials {
private String user;
private String password;
private String privateKey;
private Boolean authenticateSudo;
}
@Singleton
public static class CredentialsFromJsonByteSource implements Function<ByteSource, Credentials> {
@Resource
protected Logger logger = Logger.NULL;
private final Json json;
@Inject
CredentialsFromJsonByteSource(Json json) {
@Inject CredentialsFromJsonByteSource(Json json) {
this.json = json;
}
@Override
public Credentials apply(ByteSource from) {
@Override public Credentials apply(ByteSource from) {
try {
String creds = (checkNotNull(from)).asCharSource(Charsets.UTF_8).read();
if (creds.indexOf("\"user\":") == -1) {
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) {
logger.warn(e, "ignoring problem retrieving credentials");
return null;