Issue 797: converted many adapters to the new gson streaming method

This commit is contained in:
Adrian Cole 2012-01-01 19:24:42 -08:00
parent 8b492a63e3
commit 7146572620
10 changed files with 106 additions and 166 deletions

View File

@ -18,17 +18,15 @@
*/
package org.jclouds.cloudstack.config;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import org.jclouds.date.DateService;
import org.jclouds.json.config.GsonModule;
import java.io.IOException;
import java.util.Date;
import javax.inject.Inject;
import java.lang.reflect.Type;
import java.util.Date;
import org.jclouds.date.DateService;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import com.google.gson.stream.JsonReader;
/**
* Data adapter for the date formats used by CloudStack.
@ -39,27 +37,15 @@ import java.util.Date;
*
* @author Richard Downer
*/
public class CloudStackDateAdapter implements GsonModule.DateAdapter {
private final DateService dateService;
public class CloudStackDateAdapter extends Iso8601DateAdapter {
@Inject
private CloudStackDateAdapter(DateService dateService) {
this.dateService = dateService;
super(dateService);
}
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateService.iso8601DateFormat(src));
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
toParse = toParse.replaceAll("'T'", "T");
try {
return dateService.iso8601DateParse(toParse);
} catch (RuntimeException e) {
return dateService.iso8601SecondsDateParse(toParse);
}
public Date read(JsonReader reader) throws IOException {
return parseDate(reader.nextString().replaceAll("'T'", "T"));
}
}

View File

@ -18,14 +18,13 @@
*/
package org.jclouds.json.config;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -48,10 +47,13 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.JsonReaderInternalAccess;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.google.inject.AbstractModule;
import com.google.inject.ImplementedBy;
import com.google.inject.Provides;
@ -68,20 +70,25 @@ public class GsonModule extends AbstractModule {
@Provides
@Singleton
Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter,
JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings)
throws ClassNotFoundException, Exception {
GsonBuilder builder = new GsonBuilder();
Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap").setLevel(Level.OFF);
// simple (type adapters)
builder.registerTypeAdapter(Properties.class, propertiesAdapter.nullSafe());
builder.registerTypeAdapter(Date.class, adapter.nullSafe());
builder.registerTypeAdapter(new TypeToken<List<Byte>>() {
}.getType(), byteListAdapter.nullSafe());
builder.registerTypeAdapter(byte[].class, byteArrayAdapter.nullSafe());
// complicated (serializers/deserializers as they need context to operate)
builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
builder.registerTypeAdapter(Date.class, adapter);
builder.registerTypeAdapter(Properties.class, propertiesAdapter);
builder.registerTypeAdapter(new TypeToken<List<Byte>>() {
}.getType(), byteListAdapter);
builder.registerTypeAdapter(byte[].class, byteArrayAdapter);
for (Map.Entry<Type, Object> binding : bindings.getBindings().entrySet()) {
builder.registerTypeAdapter(binding.getKey(), binding.getValue());
}
return builder.create();
}
@ -99,74 +106,74 @@ public class GsonModule extends AbstractModule {
}
public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
throws JsonParseException {
return new JsonBall(json.toString());
}
}
@ImplementedBy(CDateAdapter.class)
public static interface DateAdapter extends JsonSerializer<Date>, JsonDeserializer<Date> {
public static abstract class DateAdapter extends TypeAdapter<Date> {
}
@ImplementedBy(HexByteListAdapter.class)
public static interface ByteListAdapter extends JsonSerializer<List<Byte>>, JsonDeserializer<List<Byte>> {
public static abstract class ByteListAdapter extends TypeAdapter<List<Byte>> {
}
@ImplementedBy(HexByteArrayAdapter.class)
public static interface ByteArrayAdapter extends JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
public static abstract class ByteArrayAdapter extends TypeAdapter<byte[]> {
}
@Singleton
public static class HexByteListAdapter implements ByteListAdapter {
public static class HexByteListAdapter extends ByteListAdapter {
@Override
public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return Bytes.asList(CryptoStreams.hex(json.getAsString()));
public void write(JsonWriter writer, List<Byte> value) throws IOException {
writer.value(CryptoStreams.hex(Bytes.toArray(value)));
}
@Override
public JsonElement serialize(List<Byte> src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(CryptoStreams.hex(Bytes.toArray(src)));
public List<Byte> read(JsonReader reader) throws IOException {
return Bytes.asList(CryptoStreams.hex(reader.nextString()));
}
}
@Singleton
public static class HexByteArrayAdapter implements ByteArrayAdapter {
public static class HexByteArrayAdapter extends ByteArrayAdapter {
@Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return CryptoStreams.hex(json.getAsString());
public void write(JsonWriter writer, byte[] value) throws IOException {
writer.value(CryptoStreams.hex(value));
}
@Override
public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(CryptoStreams.hex(src));
public byte[] read(JsonReader reader) throws IOException {
return CryptoStreams.hex(reader.nextString());
}
}
@Singleton
public static class Iso8601DateAdapter implements DateAdapter {
public static class Iso8601DateAdapter extends DateAdapter {
private final DateService dateService;
@Inject
private Iso8601DateAdapter(DateService dateService) {
public Iso8601DateAdapter(DateService dateService) {
this.dateService = dateService;
}
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateService.iso8601DateFormat(src));
public void write(JsonWriter writer, Date value) throws IOException {
writer.value(dateService.iso8601DateFormat(value));
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
public Date read(JsonReader reader) throws IOException {
return parseDate(reader.nextString());
}
protected Date parseDate(String toParse) {
try {
return dateService.iso8601DateParse(toParse);
} catch (RuntimeException e) {
@ -177,63 +184,71 @@ public class GsonModule extends AbstractModule {
}
@Singleton
public static class SerializePropertiesDefaults implements JsonSerializer<Properties> {
public static class PropertiesAdapter extends TypeAdapter<Properties> {
private final Json json;
private final Type mapType = new TypeLiteral<Map<String, String>>() {
}.getRawType();
@Inject
public SerializePropertiesDefaults(Json json) {
public PropertiesAdapter(Json json) {
this.json = json;
}
public JsonElement serialize(Properties src, Type typeOfSrc, JsonSerializationContext context) {
@Override
public void write(JsonWriter out, Properties value) throws IOException {
Builder<String, String> srcMap = ImmutableMap.<String, String> builder();
for (Enumeration<?> propNames = src.propertyNames(); propNames.hasMoreElements();) {
for (Enumeration<?> propNames = value.propertyNames(); propNames.hasMoreElements();) {
String propName = (String) propNames.nextElement();
srcMap.put(propName, src.getProperty(propName));
srcMap.put(propName, value.getProperty(propName));
}
return new JsonLiteral(json.toJson(srcMap.build(), mapType));
out.value(new JsonLiteral(json.toJson(srcMap.build(), mapType)));
}
@Override
public Properties read(JsonReader in) throws IOException {
Properties props = new Properties();
in.beginObject();
while (in.hasNext()) {
JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
props.setProperty(in.nextString(), in.nextString());
}
in.endObject();
return props;
}
}
@Singleton
public static class CDateAdapter implements DateAdapter {
public static class CDateAdapter extends DateAdapter {
private final DateService dateService;
@Inject
private CDateAdapter(DateService dateService) {
public CDateAdapter(DateService dateService) {
this.dateService = dateService;
}
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(dateService.cDateFormat(src));
public void write(JsonWriter writer, Date value) throws IOException {
writer.value(dateService.cDateFormat(value));
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
Date toReturn = dateService.cDateParse(toParse);
return toReturn;
public Date read(JsonReader reader) throws IOException {
return dateService.cDateParse(reader.nextString());
}
}
@Singleton
public static class LongDateAdapter implements DateAdapter {
public static class LongDateAdapter extends DateAdapter {
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getTime());
public void write(JsonWriter writer, Date value) throws IOException {
writer.value(value.getTime());
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
long toParse = json.getAsJsonPrimitive().getAsLong();
public Date read(JsonReader reader) throws IOException {
long toParse = reader.nextLong();
if (toParse == -1)
return null;
Date toReturn = new Date(toParse);
return toReturn;
return new Date(toParse);
}
}

View File

@ -1,52 +0,0 @@
/**
* 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.gogrid.config;
import java.lang.reflect.Type;
import java.util.Date;
import javax.inject.Singleton;
import org.jclouds.json.config.GsonModule.DateAdapter;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
/**
* Configures the GoGrid connection, including logging and http transport.
*
* @author Adrian Cole
* @author Oleksiy Yarmula
*/
@Singleton
public class DateSecondsAdapter implements DateAdapter {
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.getTime());
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String toParse = json.getAsJsonPrimitive().getAsString();
return new Date(Long.valueOf(toParse));
}
}

View File

@ -35,6 +35,7 @@ import org.jclouds.gogrid.domain.ServerImageType;
import org.jclouds.gogrid.domain.ServerState;
import org.jclouds.gogrid.functions.internal.CustomDeserializers;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.LongDateAdapter;
import com.google.common.collect.Maps;
import com.google.inject.AbstractModule;
@ -68,7 +69,7 @@ public class GoGridParserModule extends AbstractModule {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
}
}

View File

@ -28,7 +28,6 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.config.DateSecondsAdapter;
import org.jclouds.gogrid.domain.IpState;
import org.jclouds.gogrid.domain.ServerImageState;
import org.jclouds.gogrid.domain.ServerImageType;
@ -77,7 +76,7 @@ public class ParseCredentialsFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}

View File

@ -21,7 +21,6 @@ package org.jclouds.gogrid.functions;
import java.io.InputStream;
import java.net.UnknownHostException;
import org.jclouds.gogrid.config.DateSecondsAdapter;
import org.jclouds.gogrid.domain.internal.ErrorResponse;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads;
@ -42,7 +41,7 @@ public class ParseErrorFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}
});

View File

@ -29,7 +29,6 @@ import java.util.SortedSet;
import javax.inject.Singleton;
import org.jclouds.gogrid.config.DateSecondsAdapter;
import org.jclouds.gogrid.domain.Job;
import org.jclouds.gogrid.domain.JobProperties;
import org.jclouds.gogrid.domain.JobState;
@ -80,7 +79,7 @@ public class ParseJobsFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}

View File

@ -28,7 +28,6 @@ import java.util.SortedSet;
import javax.inject.Singleton;
import org.jclouds.gogrid.config.DateSecondsAdapter;
import org.jclouds.gogrid.domain.Ip;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.gogrid.domain.IpState;
@ -79,7 +78,7 @@ public class ParseLoadBalancersFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}

View File

@ -28,7 +28,6 @@ import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.gogrid.config.DateSecondsAdapter;
import org.jclouds.gogrid.domain.IpState;
import org.jclouds.gogrid.domain.ServerImageState;
import org.jclouds.gogrid.domain.ServerImageType;
@ -65,7 +64,7 @@ public class ParseServerNameToCredentialsMapFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(DateSecondsAdapter.class);
bind(DateAdapter.class).to(LongDateAdapter.class);
super.configure();
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.rimuhosting.miro.config;
import java.lang.reflect.Type;
import java.io.IOException;
import java.util.Date;
import javax.inject.Inject;
@ -26,17 +26,16 @@ import javax.inject.Singleton;
import org.jclouds.date.DateService;
import org.jclouds.http.RequiresHttp;
import org.jclouds.json.Json;
import org.jclouds.json.config.GsonModule;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.PropertiesAdapter;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
import org.jclouds.rimuhosting.miro.RimuHostingClient;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
/**
*
@ -57,29 +56,25 @@ public class RimuHostingRestClientModule extends RestClientModule<RimuHostingCli
}
@Singleton
public static class RimuIso8601DateAdapter implements DateAdapter {
public static class RimuIso8601DateAdapter extends GsonModule.DateAdapter {
private final DateService dateService;
private final Json json;
private static class DateHolder {
String iso_format;
}
private final PropertiesAdapter propertiesAdapter;
@Inject
private RimuIso8601DateAdapter(DateService dateService, Json json) {
private RimuIso8601DateAdapter(DateService dateService, PropertiesAdapter propertiesAdapter) {
this.dateService = dateService;
this.json = json;
this.propertiesAdapter = propertiesAdapter;
}
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
public void write(JsonWriter writer, Date value) throws IOException {
throw new UnsupportedOperationException();
}
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String toParse = json.toString();
DateHolder dateHolder = this.json.fromJson(toParse, DateHolder.class);
return (dateHolder.iso_format != null) ? dateService.iso8601SecondsDateParse(dateHolder.iso_format) : null;
public Date read(JsonReader in) throws IOException {
String isoFormat = propertiesAdapter.read(in).getProperty("iso_format");
if (isoFormat != null)
return dateService.iso8601SecondsDateParse(isoFormat);
return null;
}
}