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