KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > slide > webdav > method > UnlockMethod


1 /*
2  * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UnlockMethod.java,v 1.39.2.3 2004/11/30 07:05:53 masonjm Exp $
3  * $Revision: 1.39.2.3 $
4  * $Date: 2004/11/30 07:05:53 $
5  *
6  * ====================================================================
7  *
8  * Copyright 1999-2002 The Apache Software Foundation
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */

23
24 package org.apache.slide.webdav.method;
25
26 import java.io.IOException JavaDoc;
27 import java.util.Enumeration JavaDoc;
28
29 import javax.transaction.Transaction JavaDoc;
30
31 import org.apache.slide.common.NamespaceAccessToken;
32 import org.apache.slide.common.ServiceAccessException;
33 import org.apache.slide.common.SlideException;
34 import org.apache.slide.content.NodeProperty;
35 import org.apache.slide.content.NodeRevisionDescriptor;
36 import org.apache.slide.content.NodeRevisionDescriptors;
37 import org.apache.slide.content.RevisionDescriptorNotFoundException;
38 import org.apache.slide.content.NodeProperty.NamespaceCache;
39 import org.apache.slide.event.EventDispatcher;
40 import org.apache.slide.lock.LockTokenNotFoundException;
41 import org.apache.slide.lock.NodeLock;
42 import org.apache.slide.structure.LinkedObjectNotFoundException;
43 import org.apache.slide.structure.ObjectNode;
44 import org.apache.slide.structure.ObjectNotFoundException;
45 import org.apache.slide.transaction.ExternalTransactionContext;
46 import org.apache.slide.util.Configuration;
47 import org.apache.slide.webdav.WebdavException;
48 import org.apache.slide.webdav.WebdavServletConfig;
49 import org.apache.slide.webdav.event.WebdavEvent;
50 import org.apache.slide.webdav.util.DeltavConstants;
51 import org.apache.slide.webdav.util.PreconditionViolationException;
52 import org.apache.slide.webdav.util.VersioningHelper;
53 import org.apache.slide.webdav.util.ViolatedPrecondition;
54 import org.apache.slide.webdav.util.WebdavConstants;
55 import org.apache.slide.webdav.util.WebdavStatus;
56 import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
57 import org.apache.slide.webdav.util.resourcekind.CheckedOutVersionControlled;
58 import org.apache.slide.webdav.util.resourcekind.ResourceKind;
59 import org.jdom.Document;
60 import org.jdom.Element;
61 import org.jdom.Namespace;
62
63 /**
64  * UNLOCK method.
65  *
66  */

67 public class UnlockMethod extends AbstractWebdavMethod implements
68         WebdavConstants, WriteMethod {
69
70     public static final String JavaDoc LOCK_TOKEN_HEADER_MISSING = "Lock-Token header missing";
71
72     public static final String JavaDoc INVALID_LOCK_TOKEN = "Lock-Token is invalid";
73
74     public static final String JavaDoc UNLOCK_NOT_ALLOWED = "Principal is neither the lock-owner nor has DAV:unlock privilege";
75
76     public static final String JavaDoc IS_NOT_LOCK_ROOT = "Please try to unlock the root of the lock: ";
77
78     public final static int NO_TRANSACTION = 0;
79
80     public final static int ABORT_TRANSACTION = 1;
81
82     public final static int COMMIT_TRANSACTION = 2;
83
84     // ----------------------------------------------------- Instance Variables
85

86     /**
87      * Resource to unlock.
88      */

89     private String JavaDoc resourcePath;
90
91     /**
92      * Id.
93      */

94     private String JavaDoc lockId;
95
96     private int command = NO_TRANSACTION;
97
98     // ----------------------------------------------------------- Constructors
99

100     /**
101      * Constructor.
102      *
103      * @param token
104      * the token for accessing the namespace
105      * @param config
106      * configuration of the WebDAV servlet
107      */

108     public UnlockMethod(NamespaceAccessToken token, WebdavServletConfig config) {
109         super(token, config);
110     }
111
112     // ------------------------------------------------------ Protected Methods
113

114     /**
115      * get the command for this unlock operation.
116      *
117      * @return int command. One of NO_TRANSACTION, COMMIT_TRANSACTION, ABORT_TRANSACTION
118      */

119     public int getCommand()
120     {
121         return command;
122     }
123     
124     /**
125      * Parse the request.
126      *
127      * @exception WebdavException
128      * Bad request
129      */

130     protected void parseRequest() throws WebdavException {
131
132         // Loads the associated object from the store.
133
resourcePath = requestUri;
134         if (resourcePath == null) {
135             resourcePath = "/";
136         }
137
138         lockId = requestHeaders.getLockToken().trim(); // XXX trim is needed for Netdrive which sends trailing spaces
139
if (lockId == null) {
140             sendError(WebdavStatus.SC_PRECONDITION_FAILED,
141                     LOCK_TOKEN_HEADER_MISSING);
142             throw new WebdavException(WebdavStatus.SC_PRECONDITION_FAILED);
143         }
144         try {
145             Document requestContent = parseRequestContent();
146             if (requestContent != null) {
147                 Element transactioninfo = requestContent.getRootElement();
148                 if (E_TRANSACTIONINFO.equals(transactioninfo.getName())) {
149                     slideToken.setExternalTx();
150                     Element transactionstatus = transactioninfo
151                             .getChild(E_TRANSACTIONSTATUS, Namespace.getNamespace(S_DAV));
152                     if (transactionstatus != null) {
153                         Element action = (Element) transactionstatus
154                                 .getChildren().get(0);
155                         if (action != null) {
156                             if (E_COMMIT.equals(action.getName())) {
157                                 command = COMMIT_TRANSACTION;
158                             } else if (E_ABORT.equals(action.getName())) {
159                                 command = ABORT_TRANSACTION;
160                             } else {
161                         sendError(WebdavStatus.SC_BAD_REQUEST,
162                                 "transactionstatus must be one of commit or abort");
163                         throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
164                      }
165                         } else {
166                             sendError(WebdavStatus.SC_BAD_REQUEST,
167                           "transactionstatus must contain one of commit or abort");
168                       throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
169                   }
170                     }
171                 }
172             }
173         }
174       catch (WebdavException e) {
175           throw e;
176       }
177       catch (Exception JavaDoc exception) {
178            sendError(WebdavStatus.SC_BAD_REQUEST, exception);
179             throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
180         }
181     }
182
183     /**
184      * Execute the request.
185      *
186      * @exception WebdavException
187      */

188     protected void executeRequest() throws WebdavException {
189
190         // Prevent dirty reads
191
slideToken.setForceStoreEnlistment(true);
192         if (command == COMMIT_TRANSACTION || command == ABORT_TRANSACTION) {
193
194             String JavaDoc fullTxId = "<" + S_LOCK_TOKEN + lockId + ">";
195
196             ExternalTransactionContext externalTransaction = ExternalTransactionContext.lookupContext(fullTxId);
197             if (externalTransaction != null) {
198                 Transaction JavaDoc tx = externalTransaction.getTransaction();
199                 try {
200                     token.getTransactionManager().resume(tx);
201                 } catch (Exception JavaDoc exception) {
202                     sendError(WebdavStatus.SC_METHOD_FAILURE, "No such transaction");
203                 }
204             } else {
205                 sendError(WebdavStatus.SC_METHOD_FAILURE, "No such transaction");
206             }
207
208             if (command == COMMIT_TRANSACTION) {
209                 try {
210                     token.commit();
211                 } catch (Exception JavaDoc exception) {
212                     sendError(WebdavStatus.SC_METHOD_FAILURE, "Could not commit transaction");
213                 }
214             } else if (command == ABORT_TRANSACTION) {
215                 try {
216                     token.rollback();
217                 } catch (Exception JavaDoc exception) {
218                     sendError(WebdavStatus.SC_METHOD_FAILURE, "Could not roll back transaction");
219                 }
220             }
221             ExternalTransactionContext.deregisterContext(lockId);
222             
223             resp.setStatus(WebdavStatus.SC_NO_CONTENT);
224         } else {
225             try {
226                 if (WebdavEvent.UNLOCK.isEnabled())
227                     EventDispatcher.getInstance().fireVetoableEvent(
228                             WebdavEvent.UNLOCK, new WebdavEvent(this));
229
230                 checkPreconditions();
231                 lock.unlock(slideToken, requestUri, lockId);
232
233                 NodeRevisionDescriptors revisionDescriptors = content.retrieve(
234                         slideToken, requestUri);
235                 NodeRevisionDescriptor revisionDescriptor = content.retrieve(
236                         slideToken, revisionDescriptors);
237
238                 // Check if resource must be checked in due to auto-versioning
239
// semantics.
240
ResourceKind resourceKind = AbstractResourceKind
241                         .determineResourceKind(token, requestUri,
242                                 revisionDescriptor);
243                 if (Configuration.useVersionControl()
244                         && (resourceKind instanceof CheckedOutVersionControlled)) {
245                     NodeProperty checkinLocktokenProperty = revisionDescriptor
246                             .getProperty(DeltavConstants.I_CHECKIN_LOCKTOKEN,
247                                     NamespaceCache.SLIDE_URI);
248                     if (checkinLocktokenProperty == null) {
249                         // retry with default (DAV:) namespace which was the
250
// former namespace of this property
251
checkinLocktokenProperty = revisionDescriptor
252                                 .getProperty(DeltavConstants.I_CHECKIN_LOCKTOKEN);
253                     }
254                     if ((checkinLocktokenProperty != null)
255                             && (checkinLocktokenProperty.getValue() != null)
256                             && lockId.equals(checkinLocktokenProperty
257                                     .getValue().toString())) {
258                         VersioningHelper versionHelper = VersioningHelper
259                                 .getVersioningHelper(slideToken, token, req,
260                                         resp, config);
261                         versionHelper.checkin(revisionDescriptors,
262                                 revisionDescriptor, false, false, true);
263                     }
264                 }
265
266                 // Checking if the resource at the URI isn't a lock-null
267
// resource, in which case we must attempt to delete it
268
ObjectNode node = structure.retrieve(slideToken, requestUri);
269
270                 if (isLockNull(revisionDescriptor)) {
271                     content.remove(slideToken, requestUri, revisionDescriptor);
272                     content.remove(slideToken, revisionDescriptors);
273                     structure.remove(slideToken, node);
274                 }
275
276                 resp.setStatus(WebdavStatus.SC_NO_CONTENT);
277
278             } catch (PreconditionViolationException e) {
279                 try {
280                     sendPreconditionViolation(e);
281                     throw e;
282                 } catch (IOException JavaDoc x) {
283                 }
284                 throw new WebdavException(e.getStatusCode());
285             } catch (Exception JavaDoc e) {
286                 int statusCode = getErrorCode(e);
287                 sendError(statusCode, e);
288                 throw new WebdavException(statusCode);
289             }
290         }
291     }
292
293     /**
294      * Get return status based on exception type.
295      */

296     protected int getErrorCode(Exception JavaDoc ex) {
297         try {
298             throw ex;
299         } catch (RevisionDescriptorNotFoundException e) {
300             return WebdavStatus.SC_OK;
301         } catch (LinkedObjectNotFoundException e) {
302             return WebdavStatus.SC_NOT_FOUND;
303         } catch (Exception JavaDoc e) {
304             return super.getErrorCode(e);
305         }
306     }
307
308     private void checkPreconditions() throws SlideException {
309         Enumeration JavaDoc locksAll = lock.enumerateLocks(slideToken, resourcePath,
310                 true);
311         if (!locksAll.hasMoreElements()) {
312             return;
313         }
314
315         NodeLock nodeLock = findMatchingNodeLock(false);
316
317         if (nodeLock != null) {
318             if (!lock.checkLockOwner(slideToken, nodeLock)) {
319                 throw new PreconditionViolationException(
320                         new ViolatedPrecondition(
321                                 "lock-owner-or-unlock-privilege",
322                                 WebdavStatus.SC_FORBIDDEN, UNLOCK_NOT_ALLOWED),
323                         resourcePath);
324             }
325         } else {
326             nodeLock = findMatchingNodeLock(true);
327             if (nodeLock != null) {
328                 throw new PreconditionViolationException(
329                         new ViolatedPrecondition("lock-root",
330                                 WebdavStatus.SC_CONFLICT, IS_NOT_LOCK_ROOT
331                                         + getFullPath(nodeLock.getObjectUri())),
332                         resourcePath);
333             } else {
334                 throw new PreconditionViolationException(
335                         new ViolatedPrecondition("valid-lock-token",
336                                 WebdavStatus.SC_CONFLICT, INVALID_LOCK_TOKEN),
337                         resourcePath);
338             }
339         }
340     }
341
342     private NodeLock findMatchingNodeLock(boolean inherited)
343             throws ObjectNotFoundException, LockTokenNotFoundException,
344             ServiceAccessException {
345         NodeLock nodeLock = null;
346         Enumeration JavaDoc locks = lock.enumerateLocks(slideToken, resourcePath,
347                 inherited);
348         while (nodeLock == null && locks.hasMoreElements()) {
349             NodeLock nl = (NodeLock) locks.nextElement();
350             if (nl.getLockId().equals(lockId)) {
351                 nodeLock = nl;
352             }
353         }
354         return nodeLock;
355     }
356 }
Popular Tags