001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nicolas Chapurlat <nchapurlat@nuxeo.com>
016 */
017
018package org.nuxeo.ecm.webengine.jaxrs.coreiodelegate;
019
020import java.io.IOException;
021import java.io.InputStream;
022import java.io.OutputStream;
023import java.lang.annotation.Annotation;
024import java.lang.reflect.Type;
025
026import javax.servlet.http.HttpServletRequest;
027import javax.ws.rs.WebApplicationException;
028import javax.ws.rs.core.Context;
029import javax.ws.rs.core.HttpHeaders;
030import javax.ws.rs.core.MediaType;
031import javax.ws.rs.core.MultivaluedMap;
032import javax.ws.rs.ext.MessageBodyReader;
033import javax.ws.rs.ext.MessageBodyWriter;
034
035import org.nuxeo.ecm.core.io.registry.MarshallerRegistry;
036import org.nuxeo.ecm.core.io.registry.Reader;
037import org.nuxeo.ecm.core.io.registry.Writer;
038import org.nuxeo.ecm.core.io.registry.context.RenderingContext;
039import org.nuxeo.runtime.api.Framework;
040
041/**
042 * An abstract JAX-RS {@link MessageBodyWriter} that delegate marshalling to all nuxeo-core-io {@link Writer} and
043 * {@link Reader} with conditions.
044 *
045 * @since 7.2
046 */
047public abstract class PartialCoreIODelegate implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
048
049    public static MarshallerRegistry registry;
050
051    public static MarshallerRegistry getRegistry() {
052        if (registry == null) {
053            registry = Framework.getService(MarshallerRegistry.class);
054        }
055        return registry;
056    }
057
058    private Writer<?> writer = null;
059
060    private Reader<?> reader = null;
061
062    @Context
063    private HttpServletRequest request;
064
065    @Context
066    private HttpHeaders headers;
067
068    /**
069     * If it returns true, it delegates marshalling to {@link MarshallerRegistry}.
070     *
071     * @since 7.2
072     */
073    protected abstract boolean accept(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType);
074
075    @Override
076    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
077        if (accept(type, genericType, annotations, mediaType)) {
078            RenderingContext ctx = RenderingContextWebUtils.getContext(request);
079            writer = getRegistry().getWriter(ctx, type, genericType, mediaType);
080            return writer != null;
081        }
082        return false;
083    }
084
085    @Override
086    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
087        if (accept(type, genericType, annotations, mediaType)) {
088            RenderingContext ctx = RenderingContextWebUtils.getContext(request);
089            reader = getRegistry().getReader(ctx, type, genericType, mediaType);
090            if (reader != null) {
091                // backward compatibility for json document model marshalling
092                DocumentModelJsonReaderLegacy.pushInstanceIfNeeded(ctx, request, headers.getRequestHeaders());
093                return true;
094            }
095            return false;
096        }
097        return false;
098    }
099
100    @Override
101    public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
102        return -1;
103    }
104
105    @Override
106    @SuppressWarnings("unchecked")
107    public final void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
108            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
109            WebApplicationException {
110        if (writer != null) {
111            ((Writer<Object>) writer).write(t, type, genericType, mediaType, entityStream);
112        }
113    }
114
115    @Override
116    @SuppressWarnings("unchecked")
117    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
118            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
119            WebApplicationException {
120        if (reader != null) {
121            return ((Reader<Object>) reader).read(type, genericType, mediaType, entityStream);
122        }
123        return null;
124    }
125
126}