package org.zstack.core.rest; import com.google.gson.*; import org.zstack.header.message.Message; import org.zstack.header.rest.APINoSee; import org.zstack.utils.Utils; import org.zstack.utils.gson.GsonTypeCoder; import org.zstack.utils.gson.GsonUtil; import org.zstack.utils.logging.CLogger; import java.lang.reflect.Type; import java.util.Map; public class RESTApiDecoder { private static CLogger logger = Utils.getLogger(RESTApiDecoder.class); private final Gson gsonEncoder; private final Gson gsonDecoder; private static final RESTApiDecoder self; private class Encoder implements GsonTypeCoder<Message>, ExclusionStrategy { private Gson gson; void setGson(Gson gson) { this.gson = gson; } @Override public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jObj = json.getAsJsonObject(); Map.Entry<String, JsonElement> entry = jObj.entrySet().iterator().next(); String className = entry.getKey(); Class<?> clazz; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new JsonParseException("Unable to deserialize class " + className, e); } return (Message) this.gson.fromJson(entry.getValue(), clazz); } @Override public JsonElement serialize(Message msg, Type typeOfSrc, JsonSerializationContext context) { JsonObject jObj = new JsonObject(); jObj.add(msg.getClass().getName(), this.gson.toJsonTree(msg)); return jObj; } @Override public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(APINoSee.class) != null; } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } } private class Decoder implements GsonTypeCoder<Message> { private Gson gson; void setGson(Gson gson) { this.gson = gson; } @Override public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jObj = json.getAsJsonObject(); Map.Entry<String, JsonElement> entry = jObj.entrySet().iterator().next(); String className = entry.getKey(); Class<?> clazz; try { clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new JsonParseException("Unable to deserialize class " + className, e); } Message msg = (Message) this.gson.fromJson(entry.getValue(), clazz); return msg; } @Override public JsonElement serialize(Message msg, Type typeOfSrc, JsonSerializationContext context) { JsonObject jObj = new JsonObject(); jObj.add(msg.getClass().getName(), this.gson.toJsonTree(msg)); return jObj; } } static { self = new RESTApiDecoder(); } private RESTApiDecoder() { Encoder encoder = new Encoder(); gsonEncoder = new GsonUtil().setCoder(Message.class, encoder).setExclusionStrategies(new ExclusionStrategy[]{encoder}).create(); encoder.setGson(gsonEncoder); Decoder decoder = new Decoder(); gsonDecoder = new GsonUtil().setCoder(Message.class, decoder).create(); decoder.setGson(gsonDecoder); } public static Message loads(String jsonStr) { Message msg = self.gsonDecoder.fromJson(jsonStr, Message.class); return msg; } public static String dump(Message msg) { return self.gsonEncoder.toJson(msg, Message.class); } }