package kademlia.util.serializer;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import kademlia.routing.JKademliaRoutingTable;
import java.lang.reflect.Type;
import java.util.List;
import kademlia.KadConfiguration;
import kademlia.routing.Contact;
import kademlia.routing.KademliaRoutingTable;
/**
* A KadSerializer that serializes routing tables to JSON format
The generic serializer is not working for routing tables
Why a JKademliaRoutingTable specific serializer?
The routing table structure:
- JKademliaRoutingTable
-- Buckets[]
--- Map<NodeId, Node>
* ---- NodeId:KeyBytes
* ---- Node: NodeId, InetAddress, Port
*
* The above structure seems to be causing some problem for Gson,
* especially at the Map part.
*
* Solution
- Make the Buckets[] transient
- Simply store all Nodes in the serialized object
- When reloading, re-add all nodes to the JKademliaRoutingTable
*
* @author Joshua Kissoon
*
* @since 20140310
*/
public class JsonRoutingTableSerializer implements KadSerializer<KademliaRoutingTable>
{
private final Gson gson;
Type contactCollectionType = new TypeToken<List<Contact>>()
{
}.getType();
private final KadConfiguration config;
{
gson = new Gson();
}
/**
* Initialize the class
*
* @param config
*/
public JsonRoutingTableSerializer(KadConfiguration config)
{
this.config = config;
}
@Override
public void write(KademliaRoutingTable data, DataOutputStream out) throws IOException
{
try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(out)))
{
writer.beginArray();
/* Write the basic JKademliaRoutingTable */
gson.toJson(data, JKademliaRoutingTable.class, writer);
/* Now Store the Contacts */
gson.toJson(data.getAllContacts(), contactCollectionType, writer);
writer.endArray();
}
}
@Override
public KademliaRoutingTable read(DataInputStream in) throws IOException, ClassNotFoundException
{
try (DataInputStream din = new DataInputStream(in);
JsonReader reader = new JsonReader(new InputStreamReader(in)))
{
reader.beginArray();
/* Read the basic JKademliaRoutingTable */
KademliaRoutingTable tbl = gson.fromJson(reader, KademliaRoutingTable.class);
tbl.setConfiguration(config);
/* Now get the Contacts and add them back to the JKademliaRoutingTable */
List<Contact> contacts = gson.fromJson(reader, contactCollectionType);
tbl.initialize();
for (Contact c : contacts)
{
tbl.insert(c);
}
reader.endArray();
/* Read and return the Content*/
return tbl;
}
}
}