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