package com.ctriposs.baiji; import com.ctriposs.baiji.generic.DatumReader; import com.ctriposs.baiji.generic.DatumWriter; import com.ctriposs.baiji.io.BinaryDecoder; import com.ctriposs.baiji.io.BinaryEncoder; import com.ctriposs.baiji.specific.SpecificDatumReader; import com.ctriposs.baiji.specific.SpecificDatumWriter; import com.ctriposs.baiji.specific.SpecificRecord; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class BinarySerializer implements Serializer { private static final ConcurrentMap<Class<?>, DatumReader> _readerCache = new ConcurrentHashMap<Class<?>, DatumReader>(); private static final ConcurrentMap<Class<?>, DatumWriter> _writerCache = new ConcurrentHashMap<Class<?>, DatumWriter>(); @Override public <T extends SpecificRecord> void serialize(T obj, OutputStream stream) throws IOException { DatumWriter<T> writer = getWriter(obj); writer.write(obj, new BinaryEncoder(stream)); } @Override public <T extends SpecificRecord> T deserialize(Class<T> objClass, InputStream stream) throws IOException { DatumReader<T> reader = getReader(objClass); return reader.read(null, new BinaryDecoder(stream)); } private static <T> DatumWriter<T> getWriter(T obj) { Class clazz = obj.getClass(); DatumWriter<T> writer = _writerCache.get(clazz); if (writer == null) { writer = new SpecificDatumWriter<T>(((SpecificRecord) obj).getSchema()); DatumWriter<T> existedWriter = _writerCache.putIfAbsent(clazz, writer); if (existedWriter != null) { writer = existedWriter; } } return writer; } private static <T extends SpecificRecord> DatumReader<T> getReader(Class<T> clazz) { DatumReader<T> reader = _readerCache.get(clazz); if (reader == null) { SpecificRecord record; try { Constructor<T> ctor = clazz.getDeclaredConstructor(); ctor.setAccessible(true); record = ctor.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } reader = new SpecificDatumReader<T>(record.getSchema()); DatumReader<T> existedReader = _readerCache.putIfAbsent(clazz, reader); if (existedReader != null) { reader = existedReader; } } return reader; } public void clearCache() { _readerCache.clear(); _writerCache.clear(); } }