1 23 24 package org.apache.slide.webdav.method; 25 26 import java.io.IOException ; 27 import java.util.Enumeration ; 28 29 import javax.transaction.Transaction ; 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 67 public class UnlockMethod extends AbstractWebdavMethod implements 68 WebdavConstants, WriteMethod { 69 70 public static final String LOCK_TOKEN_HEADER_MISSING = "Lock-Token header missing"; 71 72 public static final String INVALID_LOCK_TOKEN = "Lock-Token is invalid"; 73 74 public static final String UNLOCK_NOT_ALLOWED = "Principal is neither the lock-owner nor has DAV:unlock privilege"; 75 76 public static final String 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 86 89 private String resourcePath; 90 91 94 private String lockId; 95 96 private int command = NO_TRANSACTION; 97 98 100 108 public UnlockMethod(NamespaceAccessToken token, WebdavServletConfig config) { 109 super(token, config); 110 } 111 112 114 119 public int getCommand() 120 { 121 return command; 122 } 123 124 130 protected void parseRequest() throws WebdavException { 131 132 resourcePath = requestUri; 134 if (resourcePath == null) { 135 resourcePath = "/"; 136 } 137 138 lockId = requestHeaders.getLockToken().trim(); 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 exception) { 178 sendError(WebdavStatus.SC_BAD_REQUEST, exception); 179 throw new WebdavException(WebdavStatus.SC_BAD_REQUEST); 180 } 181 } 182 183 188 protected void executeRequest() throws WebdavException { 189 190 slideToken.setForceStoreEnlistment(true); 192 if (command == COMMIT_TRANSACTION || command == ABORT_TRANSACTION) { 193 194 String fullTxId = "<" + S_LOCK_TOKEN + lockId + ">"; 195 196 ExternalTransactionContext externalTransaction = ExternalTransactionContext.lookupContext(fullTxId); 197 if (externalTransaction != null) { 198 Transaction tx = externalTransaction.getTransaction(); 199 try { 200 token.getTransactionManager().resume(tx); 201 } catch (Exception 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 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 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 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 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 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 x) { 283 } 284 throw new WebdavException(e.getStatusCode()); 285 } catch (Exception e) { 286 int statusCode = getErrorCode(e); 287 sendError(statusCode, e); 288 throw new WebdavException(statusCode); 289 } 290 } 291 } 292 293 296 protected int getErrorCode(Exception 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 e) { 304 return super.getErrorCode(e); 305 } 306 } 307 308 private void checkPreconditions() throws SlideException { 309 Enumeration 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 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 |