001/*
002 * (C) Copyright 2014 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 *     <a href="mailto:grenard@nuxeo.com">Guillaume Renard</a>
016 *
017 */
018
019package org.nuxeo.ecm.restapi.server.jaxrs.routing.io.util;
020
021import java.io.IOException;
022import java.io.Serializable;
023import java.util.HashMap;
024import java.util.Iterator;
025import java.util.Map;
026import java.util.Map.Entry;
027
028import javax.servlet.ServletRequest;
029import javax.servlet.http.HttpServletRequest;
030
031import org.apache.commons.lang.StringUtils;
032import org.codehaus.jackson.JsonGenerationException;
033import org.codehaus.jackson.JsonGenerator;
034import org.codehaus.jackson.JsonNode;
035import org.codehaus.jackson.node.ObjectNode;
036import org.nuxeo.ecm.core.api.Blob;
037import org.nuxeo.ecm.core.api.CoreSession;
038import org.nuxeo.ecm.core.api.DocumentModel;
039import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
040import org.nuxeo.ecm.core.io.download.DownloadService;
041import org.nuxeo.ecm.core.schema.SchemaManager;
042import org.nuxeo.ecm.core.schema.types.CompositeType;
043import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper;
044import org.nuxeo.runtime.api.Framework;
045
046/**
047 * @since 7.2
048 */
049public class JsonEncodeDecodeUtils {
050
051    public static void encodeBlob(DocumentModel doc, String propVariableFacet, String variableName, Blob blob,
052            JsonGenerator jg, ServletRequest request) throws JsonGenerationException, IOException {
053        if (blob == null) {
054            jg.writeNull();
055            return;
056        }
057        jg.writeStartObject();
058        String filename = blob.getFilename();
059        if (filename == null) {
060            jg.writeNullField("name");
061        } else {
062            jg.writeStringField("name", filename);
063        }
064        String v = blob.getMimeType();
065        if (v == null) {
066            jg.writeNullField("mime-type");
067        } else {
068            jg.writeStringField("mime-type", v);
069        }
070        v = blob.getEncoding();
071        if (v == null) {
072            jg.writeNullField("encoding");
073        } else {
074            jg.writeStringField("encoding", v);
075        }
076        v = blob.getDigest();
077        if (v == null) {
078            jg.writeNullField("digest");
079        } else {
080            jg.writeStringField("digest", v);
081        }
082        jg.writeStringField("length", Long.toString(blob.getLength()));
083
084        String facet = null;
085        try {
086            facet = (String) doc.getPropertyValue(propVariableFacet);
087        } catch (PropertyNotFoundException e) {
088            facet = propVariableFacet;
089        }
090        if (StringUtils.isBlank(facet)) {
091            return;
092        }
093        CompositeType type = Framework.getLocalService(SchemaManager.class).getFacet(facet);
094
095        DownloadService downloadService = Framework.getService(DownloadService.class);
096        String xpath = type.getField(variableName).getName().getPrefixedName();
097        String blobUrl = VirtualHostHelper.getBaseURL(request) + downloadService.getDownloadUrl(doc, xpath, filename);
098        jg.writeStringField("url", blobUrl);
099
100        jg.writeEndObject();
101    }
102
103    public static Map<String, Serializable> decodeVariables(JsonNode jsnode,
104            Map<String, Serializable> originalVariables, CoreSession session) throws ClassNotFoundException,
105            IOException {
106        Map<String, Serializable> variables = new HashMap<String, Serializable>();
107        Iterator<Entry<String, JsonNode>> it = jsnode.getFields();
108        while (it.hasNext()) {
109            Entry<String, JsonNode> variable = it.next();
110            String key = variable.getKey();
111            JsonNode value = variable.getValue();
112            if (value.isNumber()) {
113                // We are working with String which will be correctly decoded by
114                // org.nuxeo.ecm.platform.routing.core.impl.GraphVariablesUtil.setJSONVariables(DocumentModel, String,
115                // Map<String, String>, boolean)
116                // But we'll definitely need to convert submitted json variable to proper typed objects
117                variables.put(key, value.getNumberValue().toString());
118            } else if (value.isObject()) {
119                if (value.has("upload-batch")) {
120                    // Decoding of the blob will be handled in ComplexTypeJSONDecoder.decode
121                    ObjectNode upload = (ObjectNode) value;
122                    upload.put("type", "blob");
123                    variables.put(key, upload.toString());
124                }
125            } else {
126                variables.put(key, value.getTextValue());
127            }
128
129        }
130        return variables;
131    }
132
133    public static void encodeVariableEntry(DocumentModel doc, String propVariableFacet, Entry<String, Serializable> e, JsonGenerator jg,
134            HttpServletRequest request) throws JsonGenerationException, IOException {
135        if (e.getValue() instanceof Blob) {
136            jg.writeFieldName(e.getKey());
137            JsonEncodeDecodeUtils.encodeBlob(doc, propVariableFacet, e.getKey(), (Blob) e.getValue(), jg,
138                    request);
139        } else {
140            jg.writeObjectField(e.getKey(), e.getValue());
141        }
142    }
143}