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