package io.fathom.cloud.protobuf;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import com.google.common.base.Charsets;
import com.google.gson.stream.JsonReader;
import com.google.protobuf.Message;
import com.google.protobuf.MessageOrBuilder;
@Provider
@Singleton
@Consumes(MediaType.APPLICATION_JSON)
public final class ProtobufMessageBodyReader implements MessageBodyReader<Object> {
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
if (MessageOrBuilder.class.isAssignableFrom(type)) {
return true;
}
return false;
}
@Override
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
WebApplicationException {
try (InputStreamReader streamReader = new InputStreamReader(entityStream, Charsets.UTF_8)) {
try (JsonReader jsonReader = new JsonReader(streamReader)) {
Message.Builder builder;
boolean returnBuilder;
if (Message.Builder.class.isAssignableFrom(type)) {
builder = ProtobufUtils.newBuilder(type);
returnBuilder = true;
} else if (Message.class.isAssignableFrom(type)) {
builder = ProtobufUtils.newBuilder(type);
returnBuilder = false;
} else {
throw new UnsupportedOperationException();
}
ProtobufJsonReader.deserialize(builder, jsonReader);
if (returnBuilder) {
return builder;
} else {
return builder.build();
}
}
}
}
}