001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nicolas Chapurlat <nchapurlat@nuxeo.com>
018 */
019
020package org.nuxeo.ecm.webengine.jaxrs.coreiodelegate;
021
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.OutputStream;
025import java.lang.annotation.Annotation;
026import java.lang.reflect.Type;
027
028import javax.servlet.http.HttpServletRequest;
029import javax.ws.rs.WebApplicationException;
030import javax.ws.rs.core.Context;
031import javax.ws.rs.core.HttpHeaders;
032import javax.ws.rs.core.MediaType;
033import javax.ws.rs.core.MultivaluedMap;
034import javax.ws.rs.ext.MessageBodyReader;
035import javax.ws.rs.ext.MessageBodyWriter;
036
037import org.nuxeo.ecm.core.io.registry.MarshallerRegistry;
038import org.nuxeo.ecm.core.io.registry.Reader;
039import org.nuxeo.ecm.core.io.registry.Writer;
040import org.nuxeo.ecm.core.io.registry.context.RenderingContext;
041import org.nuxeo.runtime.api.Framework;
042
043/**
044 * An abstract JAX-RS {@link MessageBodyWriter} that delegate marshalling to all nuxeo-core-io {@link Writer} and
045 * {@link Reader} with conditions.
046 *
047 * @since 7.2
048 */
049public abstract class PartialCoreIODelegate implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
050
051    public static MarshallerRegistry registry;
052
053    public static MarshallerRegistry getRegistry() {
054        if (registry == null) {
055            registry = Framework.getService(MarshallerRegistry.class);
056        }
057        return registry;
058    }
059
060    private Writer<?> writer = null;
061
062    private Reader<?> reader = null;
063
064    @Context
065    private HttpServletRequest request;
066
067    @Context
068    private HttpHeaders headers;
069
070    /**
071     * If it returns true, it delegates marshalling to {@link MarshallerRegistry}.
072     *
073     * @since 7.2
074     */
075    protected abstract boolean accept(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType);
076
077    @Override
078    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
079        if (accept(type, genericType, annotations, mediaType)) {
080            RenderingContext ctx = RenderingContextWebUtils.getContext(request);
081            writer = getRegistry().getWriter(ctx, type, genericType, mediaType);
082            return writer != null;
083        }
084        return false;
085    }
086
087    @Override
088    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
089        if (accept(type, genericType, annotations, mediaType)) {
090            RenderingContext ctx = RenderingContextWebUtils.getContext(request);
091            reader = getRegistry().getReader(ctx, type, genericType, mediaType);
092            if (reader != null) {
093                // backward compatibility for json document model marshalling
094                DocumentModelJsonReaderLegacy.pushInstanceIfNeeded(ctx, request, headers.getRequestHeaders());
095                return true;
096            }
097            return false;
098        }
099        return false;
100    }
101
102    @Override
103    public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
104        return -1;
105    }
106
107    @Override
108    @SuppressWarnings("unchecked")
109    public final void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
110            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
111            WebApplicationException {
112        if (writer != null) {
113            ((Writer<Object>) writer).write(t, type, genericType, mediaType, entityStream);
114        }
115    }
116
117    @Override
118    @SuppressWarnings("unchecked")
119    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
120            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
121            WebApplicationException {
122        if (reader != null) {
123            return ((Reader<Object>) reader).read(type, genericType, mediaType, entityStream);
124        }
125        return null;
126    }
127
128}