package org.fenixedu.bennu.core.rest;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.stream.JsonWriter;
/***
*
* Reads/writes {@link JsonElement} objects from/to messages when using {@link Consumes} {@link Produces} on JAX-RS methods.
*
* @author Sérgio Silva (sergio.silva@tecnico.ulisboa.pt)
* @see Gson
* @param <T> subclass of {@link JsonElement}
*/
@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class JsonBodyReaderWriter<T extends JsonElement> implements MessageBodyReader<T>, MessageBodyWriter<T> {
private final Gson gson;
public JsonBodyReaderWriter() {
GsonBuilder builder = new GsonBuilder();
if (CoreConfiguration.getConfiguration().developmentMode()) {
builder = builder.setPrettyPrinting();
}
gson = builder.create();
}
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// ignore media type parameters
return MediaType.APPLICATION_JSON_TYPE.equals(new MediaType(mediaType.getType(), mediaType.getSubtype()));
}
@Override
public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
try (InputStreamReader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) {
return gson.fromJson(reader, genericType);
} catch (Throwable e) {
throw new WebApplicationException(e.getMessage(), Status.BAD_REQUEST);
}
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return isReadable(type, genericType, annotations, mediaType);
}
@Override
public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(entityStream, StandardCharsets.UTF_8))) {
gson.toJson(t, writer);
} catch (Throwable e) {
throw new WebApplicationException(e.getMessage(), Status.BAD_REQUEST);
}
}
}