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            String filenamePropertyName = getQueryParamValue(req, FILENAME_PROPERTY_NAME, null);
105
106            if (blobPropertyName == null || filenamePropertyName == null) {
107                // find the names of the fields from the optional request
108                // parameters with fallback to defaults if none is provided
109                String schemaName = getQueryParamValue(req, SCHEMA, DEFAULT_SCHEMA);
110                String blobFieldName = getQueryParamValue(req, BLOB_FIELD, DEFAULT_BLOB_FIELD);
111                String filenameFieldName = getQueryParamValue(req, FILENAME_FIELD, DEFAULT_FILENAME_FIELD);
112                blobPropertyName = schemaName + ":" + blobFieldName;
113                filenamePropertyName = schemaName + ":" + filenameFieldName;
114            }
115
116            InputStream is = req.getEntity().getStream();
117
118            saveFileToDocument(filename, dm, blobPropertyName, filenamePropertyName, is);
119        } catch (NuxeoException | IOException e) {
120            handleError(res, e);
121        }
122    }
123
124    protected CoreSession getDocumentManager() {
125        return documentManager;
126    }
127
128    /**
129     * Save the file into the document.
130     */
131    protected void saveFileToDocument(String filename, DocumentModel dm, String blobPropertyName,
132            String filenamePropertyName, InputStream is) throws IOException, PropertyException {
133        // persisting the blob makes it possible to read the binary content
134        // of the request stream several times (mimetype sniffing, digest
135        // computation, core binary storage)
136        Blob blob = Blobs.createBlob(is);
137        blob.setFilename(filename);
138
139        dm.setPropertyValue(blobPropertyName, (Serializable) blob);
140        dm.setPropertyValue(filenamePropertyName, filename);
141
142        getDocumentManager().saveDocument(dm);
143        // autoversioning see https://jira.nuxeo.org/browse/NXP-5849 for more
144        // details
145        String versioningPolicy = Framework.getProperty(LIVED_AUTOVERSIONING_PROP);
146        if (doAutoMinorIncrement(versioningPolicy, dm)) {
147            if (dm.isCheckedOut()) {
148                dm.checkIn(VersioningOption.MINOR, "Live edit (UploadFileRestlet) autoversioning");
149            }
150        }
151
152        getDocumentManager().save();
153    }
154
155    /**
156     * According to the policy, decide to auto minor increment or not
157     *
158     * @param policy
159     * @return return true if the the version should be minor increment
160     */
161    protected boolean doAutoMinorIncrement(String policy, DocumentModel doc) {
162        if (POLICY_MINOR_INCR.equals(policy)) {
163            return true;
164        }
165        return false;
166
167    }
168}