001/*
002 * (C) Copyright 2014-2018 Nuxeo (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.platform.routing.core.io;
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.lang3.StringUtils;
034import org.nuxeo.ecm.core.api.Blob;
035import org.nuxeo.ecm.core.api.CoreSession;
036import org.nuxeo.ecm.core.api.DocumentModel;
037import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
038import org.nuxeo.ecm.core.io.download.DownloadService;
039import org.nuxeo.ecm.core.schema.SchemaManager;
040import org.nuxeo.ecm.core.schema.types.CompositeType;
041import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper;
042import org.nuxeo.runtime.api.Framework;
043
044import com.fasterxml.jackson.core.JsonGenerationException;
045import com.fasterxml.jackson.core.JsonGenerator;
046import com.fasterxml.jackson.databind.JsonNode;
047import com.fasterxml.jackson.databind.node.ObjectNode;
048
049/**
050 * @since 7.2
051 * @deprecated since 8.3, use
052 *             {@link org.nuxeo.ecm.core.io.registry.Writer#write(Object, Class, java.lang.reflect.Type, javax.ws.rs.core.MediaType, java.io.OutputStream)}
053 *             instead. See how
054 *             {@link org.nuxeo.ecm.platform.routing.core.io.DocumentRouteWriter#writeVariables(org.nuxeo.ecm.platform.routing.api.DocumentRoute, JsonGenerator, org.nuxeo.ecm.core.io.registry.MarshallerRegistry, org.nuxeo.ecm.core.io.registry.context.RenderingContext, SchemaManager)}
055 *             uses it.
056 */
057@Deprecated
058public class JsonEncodeDecodeUtils {
059
060    public static void encodeBlob(DocumentModel doc, String propVariableFacet, String variableName, Blob blob,
061            JsonGenerator jg, ServletRequest request) throws JsonGenerationException, IOException {
062        if (blob == null) {
063            jg.writeNull();
064            return;
065        }
066        jg.writeStartObject();
067        String filename = blob.getFilename();
068        if (filename == null) {
069            jg.writeNullField("name");
070        } else {
071            jg.writeStringField("name", filename);
072        }
073        String v = blob.getMimeType();
074        if (v == null) {
075            jg.writeNullField("mime-type");
076        } else {
077            jg.writeStringField("mime-type", v);
078        }
079        v = blob.getEncoding();
080        if (v == null) {
081            jg.writeNullField("encoding");
082        } else {
083            jg.writeStringField("encoding", v);
084        }
085        v = blob.getDigest();
086        if (v == null) {
087            jg.writeNullField("digest");
088        } else {
089            jg.writeStringField("digest", v);
090        }
091        jg.writeStringField("length", Long.toString(blob.getLength()));
092
093        String facet = null;
094        try {
095            facet = (String) doc.getPropertyValue(propVariableFacet);
096        } catch (PropertyNotFoundException e) {
097            facet = propVariableFacet;
098        }
099        if (StringUtils.isBlank(facet)) {
100            return;
101        }
102        CompositeType type = Framework.getService(SchemaManager.class).getFacet(facet);
103
104        DownloadService downloadService = Framework.getService(DownloadService.class);
105        String xpath = type.getField(variableName).getName().getPrefixedName();
106        String blobUrl = VirtualHostHelper.getBaseURL(request) + downloadService.getDownloadUrl(doc, xpath, filename);
107        jg.writeStringField("url", blobUrl);
108
109        jg.writeEndObject();
110    }
111
112    public static Map<String, Serializable> decodeVariables(JsonNode jsnode,
113            Map<String, Serializable> originalVariables, CoreSession session) throws ClassNotFoundException,
114            IOException {
115        Map<String, Serializable> variables = new HashMap<>();
116        Iterator<Entry<String, JsonNode>> it = jsnode.fields();
117        while (it.hasNext()) {
118            Entry<String, JsonNode> variable = it.next();
119            String key = variable.getKey();
120            JsonNode value = variable.getValue();
121            if (value.isNumber()) {
122                // We are working with String which will be correctly decoded by
123                // org.nuxeo.ecm.platform.routing.core.impl.GraphVariablesUtil.setJSONVariables(DocumentModel, String,
124                // Map<String, String>, boolean)
125                // But we'll definitely need to convert submitted json variable to proper typed objects
126                variables.put(key, value.numberValue().toString());
127            } else if (value.isObject()) {
128                if (value.has("upload-batch")) {
129                    // Decoding of the blob will be handled in ComplexTypeJSONDecoder.decode
130                    ObjectNode upload = (ObjectNode) value;
131                    upload.put("type", "blob");
132                    variables.put(key, upload.toString());
133                }
134            } else {
135                variables.put(key, value.textValue());
136            }
137
138        }
139        return variables;
140    }
141
142    public static void encodeVariableEntry(DocumentModel doc, String propVariableFacet, Entry<String, Serializable> e, JsonGenerator jg,
143            HttpServletRequest request) throws JsonGenerationException, IOException {
144        if (e.getValue() instanceof Blob) {
145            jg.writeFieldName(e.getKey());
146            JsonEncodeDecodeUtils.encodeBlob(doc, propVariableFacet, e.getKey(), (Blob) e.getValue(), jg,
147                    request);
148        } else {
149            jg.writeObjectField(e.getKey(), e.getValue());
150        }
151    }
152}