String path = getRelativePath(req);
lock.path = path;
WebResource resource = resources.getResource(path);
Enumeration<LockInfo> locksList = null;
if (lockRequestType == LOCK_CREATION) {
// Generating lock id
String lockTokenStr = req.getServletPath() + "-" + lock.type + "-"
+ lock.scope + "-" + req.getUserPrincipal() + "-"
+ lock.depth + "-" + lock.owner + "-" + lock.tokens + "-"
+ lock.expiresAt + "-" + System.currentTimeMillis() + "-"
+ secret;
String lockToken = MD5Encoder.encode(md5Helper.digest(
lockTokenStr.getBytes(StandardCharsets.ISO_8859_1)));
if (resource.isDirectory() && lock.depth == maxDepth) {
// Locking a collection (and all its member resources)
// Checking if a child resource of this collection is
// already locked
Vector<String> lockPaths = new Vector<>();
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child collection of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
locksList = resourceLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.hasExpired()) {
resourceLocks.remove(currentLock.path);
continue;
}
if ( (currentLock.path.startsWith(lock.path)) &&
((currentLock.isExclusive()) ||
(lock.isExclusive())) ) {
// A child resource of this collection is locked
lockPaths.addElement(currentLock.path);
}
}
if (!lockPaths.isEmpty()) {
// One of the child paths was locked
// We generate a multistatus error report
Enumeration<String> lockPathsList = lockPaths.elements();
resp.setStatus(WebdavStatus.SC_CONFLICT);
XMLWriter generatedXML = new XMLWriter();
generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE,
"multistatus", XMLWriter.OPENING);
while (lockPathsList.hasMoreElements()) {
generatedXML.writeElement("D", "response",
XMLWriter.OPENING);
generatedXML.writeElement("D", "href",
XMLWriter.OPENING);
generatedXML.writeText(lockPathsList.nextElement());
generatedXML.writeElement("D", "href",
XMLWriter.CLOSING);
generatedXML.writeElement("D", "status",
XMLWriter.OPENING);
generatedXML
.writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED
+ " " + WebdavStatus
.getStatusText(WebdavStatus.SC_LOCKED));
generatedXML.writeElement("D", "status",
XMLWriter.CLOSING);
generatedXML.writeElement("D", "response",
XMLWriter.CLOSING);
}
generatedXML.writeElement("D", "multistatus",
XMLWriter.CLOSING);
Writer writer = resp.getWriter();
writer.write(generatedXML.toString());
writer.close();
return;
}
boolean addLock = true;
// Checking if there is already a shared lock on this path
locksList = collectionLocks.elements();
while (locksList.hasMoreElements()) {
LockInfo currentLock = locksList.nextElement();
if (currentLock.path.equals(lock.path)) {
if (currentLock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
} else {
if (lock.isExclusive()) {
resp.sendError(WebdavStatus.SC_LOCKED);
return;
}
}
currentLock.tokens.addElement(lockToken);
lock = currentLock;
addLock = false;
}
}
if (addLock) {
lock.tokens.addElement(lockToken);
collectionLocks.addElement(lock);
}
} else {
// Locking a single resource
// Retrieving an already existing lock on that resource
LockInfo presentLock = resourceLocks.get(lock.path);
if (presentLock != null) {
if ((presentLock.isExclusive()) || (lock.isExclusive())) {
// If either lock is exclusive, the lock can't be
// granted
resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
return;
} else {
presentLock.tokens.addElement(lockToken);
lock = presentLock;
}
} else {
lock.tokens.addElement(lockToken);
resourceLocks.put(lock.path, lock);
// Checking if a resource exists at this path
if (!resource.exists()) {
// "Creating" a lock-null resource
int slash = lock.path.lastIndexOf('/');
String parentPath = lock.path.substring(0, slash);