001/*
002 * (C) Copyright 2006-2007 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 *     Nuxeo - initial API and implementation
018 *
019 * $Id: JOOoConvertPluginImpl.java 18651 2007-05-13 20:28:53Z sfermigier $
020 */
021
022package org.nuxeo.ecm.platform.ui.web.restAPI;
023
024import static org.jboss.seam.ScopeType.EVENT;
025
026import java.io.IOException;
027import java.io.InputStream;
028import java.io.Serializable;
029import java.io.UnsupportedEncodingException;
030import java.net.URLDecoder;
031
032import org.jboss.seam.annotations.In;
033import org.jboss.seam.annotations.Name;
034import org.jboss.seam.annotations.Scope;
035import org.nuxeo.ecm.core.api.Blob;
036import org.nuxeo.ecm.core.api.Blobs;
037import org.nuxeo.ecm.core.api.CoreSession;
038import org.nuxeo.ecm.core.api.DocumentModel;
039import org.nuxeo.ecm.core.api.IdRef;
040import org.nuxeo.ecm.core.api.NuxeoException;
041import org.nuxeo.ecm.core.api.PropertyException;
042import org.nuxeo.ecm.core.api.VersioningOption;
043import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
044import org.nuxeo.ecm.platform.ui.web.tag.fn.LiveEditConstants;
045import org.nuxeo.ecm.platform.util.RepositoryLocation;
046import org.nuxeo.runtime.api.Framework;
047import org.restlet.data.Request;
048import org.restlet.data.Response;
049
050/**
051 * Restlet to help LiveEdit clients update the blob content of a document
052 *
053 * @author Sun Tan <stan@nuxeo.com>
054 * @author Olivier Grisel <ogrisel@nuxeo.com>
055 */
056@Name("uploadFileRestlet")
057@Scope(EVENT)
058public class UploadFileRestlet extends BaseNuxeoRestlet implements LiveEditConstants, Serializable {
059
060    public static final String LIVED_AUTOVERSIONING_PROP = "org.nuxeo.ecm.platform.liveedit.autoversioning";
061
062    public static final String POLICY_MINOR_INCR = "minor";
063
064    private static final long serialVersionUID = -6167207806181917456L;
065
066    @In(create = true)
067    protected transient NavigationContext navigationContext;
068
069    protected CoreSession documentManager;
070
071    @SuppressWarnings("deprecation")
072    @Override
073    public void handle(Request req, Response res) {
074        String repo = (String) req.getAttributes().get("repo");
075        String docid = (String) req.getAttributes().get("docid");
076        String filename = (String) req.getAttributes().get("filename");
077        try {
078            filename = URLDecoder.decode(filename, URL_ENCODE_CHARSET);
079        } catch (UnsupportedEncodingException e) {
080            handleError(res, e);
081            return;
082        }
083
084        if (repo == null || repo.equals("*")) {
085            handleError(res, "you must specify a repository");
086            return;
087        }
088
089        DocumentModel dm = null;
090        try {
091            navigationContext.setCurrentServerLocation(new RepositoryLocation(repo));
092            documentManager = navigationContext.getOrCreateDocumentManager();
093            if (docid != null) {
094                dm = documentManager.getDocument(new IdRef(docid));
095            }
096        } catch (NuxeoException e) {
097            handleError(res, e);
098            return;
099        }
100
101        try {
102
103            String blobPropertyName = getQueryParamValue(req, BLOB_PROPERTY_NAME, null);
104
105            if (blobPropertyName == null) {
106                // find the names of the fields from the optional request
107                // parameters with fallback to defaults if none is provided
108                String schemaName = getQueryParamValue(req, SCHEMA, DEFAULT_SCHEMA);
109                String blobFieldName = getQueryParamValue(req, BLOB_FIELD, DEFAULT_BLOB_FIELD);
110                blobPropertyName = schemaName + ":" + blobFieldName;
111            }
112
113            InputStream is = req.getEntity().getStream();
114
115            saveFileToDocument(filename, dm, blobPropertyName, is);
116        } catch (NuxeoException | IOException e) {
117            handleError(res, e);
118        }
119    }
120
121    protected CoreSession getDocumentManager() {
122        return documentManager;
123    }
124
125    /**
126     * Save the file into the document.
127     *
128     * @deprecated since 9.1 filename is now stored in blob
129     */
130    @Deprecated
131    protected void saveFileToDocument(String filename, DocumentModel dm, String blobPropertyName,
132            String filenamePropertyName, InputStream is) throws IOException, PropertyException {
133        saveFileToDocument(filename, dm, blobPropertyName, is);
134    }
135
136    /**
137     * Save the file into the document.
138     */
139    protected void saveFileToDocument(String filename, DocumentModel dm, String blobPropertyName,
140            InputStream is) throws IOException, PropertyException {
141        // persisting the blob makes it possible to read the binary content
142        // of the request stream several times (mimetype sniffing, digest
143        // computation, core binary storage)
144        Blob blob = Blobs.createBlob(is);
145        blob.setFilename(filename);
146
147        dm.setPropertyValue(blobPropertyName, (Serializable) blob);
148
149        getDocumentManager().saveDocument(dm);
150        // autoversioning see https://jira.nuxeo.org/browse/NXP-5849 for more
151        // details
152        String versioningPolicy = Framework.getProperty(LIVED_AUTOVERSIONING_PROP);
153        if (doAutoMinorIncrement(versioningPolicy, dm)) {
154            if (dm.isCheckedOut()) {
155                dm.checkIn(VersioningOption.MINOR, "Live edit (UploadFileRestlet) autoversioning");
156            }
157        }
158
159        getDocumentManager().save();
160    }
161
162    /**
163     * According to the policy, decide to auto minor increment or not
164     *
165     * @param policy
166     * @return return true if the the version should be minor increment
167     */
168    protected boolean doAutoMinorIncrement(String policy, DocumentModel doc) {
169        if (POLICY_MINOR_INCR.equals(policy)) {
170            return true;
171        }
172        return false;
173
174    }
175}