package org.atomnuke.jaxrs.provider.jx; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; 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.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import javax.xml.datatype.DatatypeConfigurationException; import net.jps.jx.JxFactory; import net.jps.jx.JxParsingException; import net.jps.jx.JxWritingException; import net.jps.jx.jackson.JacksonJxFactory; /** * * @author zinic */ @Provider @Produces({"application/json", "text/json"}) @Consumes({"application/json", "text/json"}) public class JxMessageBodyProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> { private final Map<Class, ReaderWriterPair> translatorMap; private final JxFactory jxFactory; public JxMessageBodyProvider() { try { jxFactory = new JacksonJxFactory(); } catch (DatatypeConfigurationException dce) { throw new RuntimeException(dce); } translatorMap = new HashMap<Class, ReaderWriterPair>(); } private synchronized <T> ReaderWriterPair<T> newTranslator(Class<T> type) { final ReaderWriterPair<T> pair = new ReaderWriterPair(jxFactory, type); translatorMap.put(type, pair); return pair; } private synchronized <T> ReaderWriterPair<T> getTranslator(Class<T> type) { final ReaderWriterPair<T> pair = translatorMap.get(type); return pair != null ? pair : newTranslator(type); } @Override public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { try { // attempt to map the type - if no errors then its readable getTranslator(type); return true; } catch (Exception ex) { return false; } } @Override public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException { final ReaderWriterPair pair = getTranslator(type); try { return pair.jsonReader().read(entityStream); } catch (JxParsingException jpe) { throw new IOException(jpe.getMessage(), jpe); } } @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { try { // attempt to map the type - if no errors then its readable getTranslator(type); return true; } catch (Exception ex) { return false; } } @Override public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { final ReaderWriterPair pair = getTranslator(type); try { pair.jsonWriter().write(t, entityStream); } catch (JxWritingException jwe) { throw new IOException(jwe.getMessage(), jwe); } } }