package voldemort.serialization.protobuf;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import voldemort.serialization.SerializationUtils;
import voldemort.serialization.Serializer;
import com.google.protobuf.Message;
/**
* A serializer that relies on Protocol Buffers for serialization and
* deserialization. Only Java clients are supported currently, but there are
* plans to support clients in other languages.
*
* An example configuration of a value-serializer follows.
*
* <pre>
* <value-serializer>
* <type>protobuf</type>
* <schema-info>java=com.linkedin.foobar.FooMessage</schema-info>
* </value-serializer>
* </pre>
*
* Once support for clients in other languages is available, a comma-separated
* list will be accepted for the schema-info element (one for each language).
*/
public class ProtoBufSerializer<T extends Message> implements Serializer<T> {
private final Method parseFromMethod;
private final Class<T> messageClass;
@SuppressWarnings("unchecked")
public ProtoBufSerializer(String currentSchemaInfo) {
try {
this.messageClass = (Class<T>) Class.forName(SerializationUtils.getJavaClassFromSchemaInfo(currentSchemaInfo),
false,
Thread.currentThread()
.getContextClassLoader());
if(!Message.class.isAssignableFrom(messageClass))
throw new IllegalArgumentException("Class provided should be a subtype of Message");
parseFromMethod = messageClass.getMethod("parseFrom", byte[].class);
} catch(NoSuchMethodException e) {
throw new IllegalArgumentException("No parseFrom static method found, the provided class is not a Message.",
e);
} catch(ClassNotFoundException e) {
throw new IllegalArgumentException(e);
}
}
public byte[] toBytes(T object) {
return object.toByteArray();
}
public T toObject(byte[] bytes) {
try {
return messageClass.cast(parseFromMethod.invoke(null, bytes));
} catch(InvocationTargetException e) {
throw new IllegalArgumentException(e);
} catch(IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
}
}