package org.dynjs.debugger.agent;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import org.dynjs.debugger.Debugger;
import org.dynjs.debugger.agent.serializers.*;
import org.dynjs.debugger.events.ConnectEvent;
import org.dynjs.debugger.events.Event;
import org.dynjs.debugger.requests.Response;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author Bob McWhirter
*/
public class JSONEncoder extends ChannelDuplexHandler {
private static final Charset UTF8 = Charset.forName("UTF8");
private final ObjectMapper mapper;
private Debugger debugger;
public JSONEncoder(Debugger debugger) {
this.debugger = debugger;
HandleSerializer handleSerializer = new HandleSerializer(this.debugger);
SimpleModule module = new SimpleModule();
AtomicInteger seqCounter = new AtomicInteger(0);
module.addSerializer(new EventSerializer(seqCounter));
module.addSerializer(new DefaultResponseSerializer(handleSerializer, seqCounter));
module.addSerializer(new EvaluateResponseSerializer(handleSerializer, seqCounter));
module.addSerializer(new LookupResponseSerializer(handleSerializer, seqCounter));
module.addSerializer(new FrameSerializer(handleSerializer));
module.addSerializer(new ScriptSerializer());
this.mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (msg instanceof ConnectEvent) {
String headers = "Type: connect\r\nContent-Length: 0\r\n\r\n";
ByteBuf buffer = ctx.alloc().buffer();
buffer.writeBytes(headers.getBytes(UTF8));
super.write(ctx, buffer, promise);
} else if (msg instanceof Response || msg instanceof Event) {
String json = toJSON(msg);
byte[] jsonBytes = json.getBytes(UTF8);
String headers = "Content-Length: " + jsonBytes.length + "\r\n\r\n";
ByteBuf buffer = ctx.alloc().buffer();
buffer.writeBytes(headers.getBytes(UTF8));
buffer.writeBytes(jsonBytes);
super.write(ctx, buffer, promise);
} else {
super.write(ctx, msg, promise);
}
}
protected String toJSON(Object msg) throws JsonProcessingException {
try {
String json = this.mapper.writeValueAsString(msg);
json += "\r\n";
return json;
} catch (Throwable t) {
t.printStackTrace();
}
return "";
}
}