001/*
002 * (C) Copyright 2006-2016 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
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.platform.ui.web.restAPI;
021
022import java.text.DateFormat;
023import java.util.Date;
024import java.util.List;
025
026import org.dom4j.dom.DOMDocument;
027import org.dom4j.dom.DOMDocumentFactory;
028import org.joda.time.DateTime;
029import org.joda.time.format.ISODateTimeFormat;
030import org.nuxeo.ecm.core.api.Lock;
031import org.nuxeo.ecm.core.api.NuxeoException;
032import org.restlet.Request;
033import org.restlet.Response;
034import org.restlet.data.CharacterSet;
035import org.restlet.data.MediaType;
036import org.restlet.data.Method;
037import org.w3c.dom.Element;
038
039/**
040 * Restlet returning the locking information on a document.
041 */
042public class LockingRestlet extends BaseStatelessNuxeoRestlet {
043
044    public static final String LOCK = "lock";
045
046    public static final String UNLOCK = "unlock";
047
048    public static final String STATUS = "status";
049
050    public static final String STATE = "state";
051
052    public static final String SC_LOCKINFO_LOCKED = "LOCKED";
053
054    public static final String SC_LOCKINFO_NOT_LOCKED = "NOTLOCKED";
055
056    public static final String SC_LOCKED_OK = "OK";
057
058    public static final String SC_ALREADY_LOCKED_KO = "ALREADYLOCKED";
059
060    public static final String SC_ALREADY_LOCKED_OK = "ALREADYLOCKEDBYYOU";
061
062    public static final String SC_UNLOCKED_OK = "OK";
063
064    public static final String SC_ALREADY_UNLOCKED_OK = "NOT LOCKED";
065
066    @Override
067    protected void doHandleStatelessRequest(Request req, Response res) {
068        logDeprecation();
069
070        String repoId = (String) req.getAttributes().get("repo");
071        String docid = (String) req.getAttributes().get("docid");
072
073        DOMDocumentFactory domFactory = new DOMDocumentFactory();
074        DOMDocument result = (DOMDocument) domFactory.createDocument();
075
076        // init repo and document
077        boolean initOk = initRepositoryAndTargetDocument(res, repoId, docid);
078        if (!initOk) {
079            return;
080        }
081
082        String cUserName = session.getPrincipal().getName();
083
084        // get Action
085        String action = STATUS;
086        List<String> segments = req.getResourceRef().getSegments();
087        int pos = segments.indexOf("restAPI") + 4;
088        if (segments.size() > pos) {
089            action = segments.get(pos).toLowerCase();
090        }
091        if (req.getMethod().equals(Method.LOCK)) {
092            action = LOCK;
093        }
094        if (req.getMethod().equals(Method.UNLOCK)) {
095            action = UNLOCK;
096        }
097
098        String response;
099        String code;
100        if (action.equals(LOCK)) {
101            try {
102                Lock lock = session.getLockInfo(targetDocRef);
103                if (lock == null) {
104                    session.setLock(targetDocRef);
105                    session.save();
106                    response = "lock acquired on document " + docid;
107                    code = SC_LOCKED_OK;
108                } else if (lock.getOwner().equals(cUserName)) {
109                    response = "document " + docid + " is already locked by you";
110                    code = SC_ALREADY_LOCKED_OK;
111                } else {
112                    response = "document " + docid + " is already locked by " + lock.getOwner();
113                    code = SC_ALREADY_LOCKED_KO;
114                }
115            } catch (NuxeoException e) {
116                handleError(result, res, e);
117                return;
118            }
119        } else if (action.equals(UNLOCK)) {
120
121            try {
122                Lock lock = session.getLockInfo(targetDocRef);
123                if (lock == null) {
124                    response = "document " + docid + " is not locked";
125                    code = SC_ALREADY_UNLOCKED_OK;
126                } else if (lock.getOwner().equals(cUserName)) {
127                    session.removeLock(targetDocRef);
128                    session.save();
129                    response = "document " + docid + " unlocked";
130                    code = SC_UNLOCKED_OK;
131                } else {
132                    response = "document " + docid + " is locked by " + lock.getOwner();
133                    code = SC_ALREADY_LOCKED_KO;
134                }
135            } catch (NuxeoException e) {
136                handleError(result, res, e);
137                return;
138            }
139
140        } else if (action.equals(STATUS)) {
141            try {
142                Lock lock = session.getLockInfo(targetDocRef);
143                response = oldLockKey(session.getLockInfo(targetDocRef));
144                if (lock == null) {
145                    code = SC_LOCKINFO_NOT_LOCKED;
146                } else {
147                    code = SC_LOCKINFO_LOCKED;
148                }
149            } catch (NuxeoException e) {
150                handleError(result, res, e);
151                return;
152            }
153
154        } else if (action.equals(STATE)) {
155            try {
156                Lock lock = session.getLockInfo(targetDocRef);
157                if (lock == null) {
158                    code = SC_LOCKINFO_NOT_LOCKED;
159                    response = "";
160                } else {
161                    code = SC_LOCKINFO_LOCKED;
162                    response = lock.getOwner() + '/'
163                            + ISODateTimeFormat.dateTime().print(new DateTime(lock.getCreated()));
164                }
165            } catch (NuxeoException e) {
166                handleError(result, res, e);
167                return;
168            }
169
170        } else {
171            handleError(result, res, "Unsupported operation");
172            return;
173        }
174
175        Element current = result.createElement("document");
176        current.setAttribute("code", code);
177        current.setAttribute("message", response);
178        result.setRootElement((org.dom4j.Element) current);
179        res.setEntity(result.asXML(), MediaType.APPLICATION_XML);
180        res.getEntity().setCharacterSet(CharacterSet.UTF_8);
181    }
182
183    protected String oldLockKey(Lock lock) {
184        if (lock == null) {
185            return null;
186        }
187        // return deprecated format, like "someuser:Nov 29, 2010"
188        String lockCreationDate = (lock.getCreated() == null) ? null : DateFormat.getDateInstance(DateFormat.MEDIUM)
189                                                                                 .format(new Date(
190                                                                                         lock.getCreated()
191                                                                                             .getTimeInMillis()));
192        return lock.getOwner() + ':' + lockCreationDate;
193    }
194
195}