-
Notifications
You must be signed in to change notification settings - Fork 126
Description
PutHandler contains the following code:
Resource r = parent.child(path.getName());
if (r == null) {
log.info("Could not find child: " + path.getName() + " in parent: " + parent.getName() + " - " + parent.getClass());
if (parent instanceof MakeCollectionableResource) {
MakeCollectionableResource mkcol = (MakeCollectionableResource) parent;
if (!handlerHelper.checkAuthorisation(manager, mkcol, request)) {
throw new NotAuthorizedException(mkcol);
}
log.info("autocreating new folder: " + path.getName());
CollectionResource newCol = mkcol.createCollection(path.getName());
manager.getEventManager().fireEvent(new NewFolderEvent(newCol));
return newCol;
} else {
log.info("parent folder isnt a MakeCollectionableResource: " + parent.getName() + " - " + parent.getClass());
return null;
}
} else if (r instanceof CollectionResource) {
The problem is that, if there are many concurrent requests targeting the same non-existing path then it is possible for a collection that does not exist for parent.child(path.getName()) to be created by the time mkcol.createCollection(path.getName()) is called.
RFC 4918 is a little vague on how MKCOL should react if the entity already exists: it says the request must fail, but does not indicate with which status code. I believe 400 Bad Request (i.e., BadRequestException) is the expected response, despite not being listed in RFC 4918 § 9.3.1. The MakeCollectionableResource interface supports BadRequestException but the JavaDoc doesn't describe the expectation (i.e., when this exception is to be thrown).
Assuming BadRequestException is the expected reaction, one way of fixing this would be to catch this exception and retry the parent.child(path.getName()) request.