001/*
002 * (C) Copyright 2013 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 *     dmetzler
018 */
019package org.nuxeo.ecm.automation.jaxrs.io.documents;
020
021import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
022
023import java.io.IOException;
024import java.io.InputStream;
025import java.lang.annotation.Annotation;
026import java.lang.reflect.Type;
027
028import javax.servlet.http.HttpServletRequest;
029import javax.ws.rs.Consumes;
030import javax.ws.rs.WebApplicationException;
031import javax.ws.rs.core.Context;
032import javax.ws.rs.core.MediaType;
033import javax.ws.rs.core.MultivaluedMap;
034import javax.ws.rs.core.Response;
035import javax.ws.rs.ext.MessageBodyReader;
036import javax.ws.rs.ext.Provider;
037
038import org.apache.commons.io.IOUtils;
039import org.nuxeo.ecm.automation.core.operations.business.adapter.BusinessAdapter;
040import org.nuxeo.ecm.automation.io.services.codec.ObjectCodecService;
041import org.nuxeo.ecm.core.api.CoreSession;
042import org.nuxeo.ecm.webengine.jaxrs.session.SessionFactory;
043import org.nuxeo.runtime.api.Framework;
044
045import com.fasterxml.jackson.core.JsonFactory;
046import com.fasterxml.jackson.core.JsonParser;
047import com.fasterxml.jackson.core.JsonProcessingException;
048import com.fasterxml.jackson.databind.JsonNode;
049
050/**
051 * JAX-RS Message body reeader to decode BusinessAdapter
052 *
053 * @since 5.7.2
054 */
055@Provider
056@Consumes(MediaType.APPLICATION_JSON)
057public class BusinessAdapterReader implements MessageBodyReader<BusinessAdapter> {
058
059    @Context
060    protected HttpServletRequest request;
061
062    @Context
063    JsonFactory factory;
064
065    private CoreSession getCoreSession() {
066        return SessionFactory.getSession(request);
067    }
068
069    @Override
070    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
071        return BusinessAdapter.class.isAssignableFrom(type);
072    }
073
074    @Override
075    public BusinessAdapter readFrom(Class<BusinessAdapter> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
076            MultivaluedMap<String, String> headers, InputStream in) throws IOException, WebApplicationException {
077        return readRequest(in, headers);
078    }
079
080    public BusinessAdapter readRequest(InputStream in, MultivaluedMap<String, String> headers) throws IOException,
081            WebApplicationException {
082        // As stated in http://tools.ietf.org/html/rfc4627.html UTF-8 is the
083        // default encoding for JSON content
084        // TODO: add introspection on the first bytes to detect other admissible
085        // json encodings, namely: UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE)
086        String content = IOUtils.toString(in, "UTF-8");
087        if (content.isEmpty()) {
088            throw new WebApplicationException(Response.Status.BAD_REQUEST);
089        }
090        return readRequest(content, headers);
091    }
092
093    public BusinessAdapter readRequest(String content, MultivaluedMap<String, String> headers)
094            throws WebApplicationException {
095        try {
096            return readRequest0(content, headers);
097        } catch (WebApplicationException e) {
098            throw e;
099        } catch (IOException e) {
100            throw new WebApplicationException(e);
101        }
102    }
103
104    public BusinessAdapter readRequest0(String content, MultivaluedMap<String, String> headers) throws IOException {
105        ObjectCodecService codecService = Framework.getService(ObjectCodecService.class);
106        try (JsonParser jp = factory.createParser(content)) {
107            JsonNode inputNode = jp.readValueAsTree();
108            return (BusinessAdapter) codecService.readNode(inputNode, getCoreSession());
109        } catch (JsonProcessingException e) {
110            throw new WebApplicationException(e, SC_BAD_REQUEST);
111        }
112
113    }
114
115}