CcmNG: Implementation of the lock method for WebDAV access to theme files
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5450 8810af33-2d31-482b-a856-94f89814c4df
Former-commit-id: 4b1ce34f51
pull/2/head
parent
abaa9b8be3
commit
ccb31ce189
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2018 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.libreccm.theming.webdav;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class AlreadyLockedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>AlreadyLockedException</code> without detail message.
|
||||
*/
|
||||
public AlreadyLockedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>AlreadyLockedException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg The detail message.
|
||||
*/
|
||||
public AlreadyLockedException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>AlreadyLockedException</code> which wraps the
|
||||
* specified exception.
|
||||
*
|
||||
* @param exception The exception to wrap.
|
||||
*/
|
||||
public AlreadyLockedException(final Exception exception) {
|
||||
super(exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>AlreadyLockedException</code> with the specified message which also wraps the
|
||||
* specified exception.
|
||||
*
|
||||
* @param msg The detail message.
|
||||
* @param exception The exception to wrap.
|
||||
*/
|
||||
public AlreadyLockedException(final String msg, final Exception exception) {
|
||||
super(msg, exception);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,16 +41,24 @@ import org.libreccm.theming.ThemeInfo;
|
|||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.Themes;
|
||||
import org.libreccm.webdav.ResponseStatus;
|
||||
import org.libreccm.webdav.methods.LOCK;
|
||||
import org.libreccm.webdav.xml.elements.ActiveLock;
|
||||
import org.libreccm.webdav.xml.elements.Collection;
|
||||
import org.libreccm.webdav.xml.elements.Depth;
|
||||
import org.libreccm.webdav.xml.elements.HRef;
|
||||
import org.libreccm.webdav.xml.elements.LockInfo;
|
||||
import org.libreccm.webdav.xml.elements.LockRoot;
|
||||
import org.libreccm.webdav.xml.elements.LockToken;
|
||||
import org.libreccm.webdav.xml.elements.MultiStatus;
|
||||
import org.libreccm.webdav.xml.elements.Prop;
|
||||
import org.libreccm.webdav.xml.elements.PropStat;
|
||||
import org.libreccm.webdav.xml.elements.Status;
|
||||
import org.libreccm.webdav.xml.elements.TimeOut;
|
||||
import org.libreccm.webdav.xml.elements.WebDavResponse;
|
||||
import org.libreccm.webdav.xml.properties.DisplayName;
|
||||
import org.libreccm.webdav.xml.properties.GetContentLength;
|
||||
import org.libreccm.webdav.xml.properties.GetContentType;
|
||||
import org.libreccm.webdav.xml.properties.LockDiscovery;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
|
@ -72,13 +80,16 @@ import javax.ws.rs.ext.Providers;
|
|||
public class ThemeFiles {
|
||||
|
||||
@Inject
|
||||
private Themes themes;
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Inject
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Inject
|
||||
private HttpServletRequest request;
|
||||
private Themes themes;
|
||||
|
||||
@Inject
|
||||
private ThemeFilesLockManager lockManager;
|
||||
|
||||
@GET
|
||||
@Path("/{path}")
|
||||
|
|
@ -117,6 +128,38 @@ public class ThemeFiles {
|
|||
|
||||
}
|
||||
|
||||
@LOCK
|
||||
@Path("/{path}")
|
||||
public Prop lock(@PathParam("theme")
|
||||
final String theme,
|
||||
@PathParam("path")
|
||||
final String path,
|
||||
final LockInfo lockInfo) {
|
||||
|
||||
final String lockedPath = String.format("%s/path",
|
||||
theme,
|
||||
path);
|
||||
|
||||
try {
|
||||
final String lockToken = lockManager.lockFile(lockedPath);
|
||||
|
||||
return new Prop(new LockDiscovery(
|
||||
new ActiveLock(lockInfo.getLockScope(),
|
||||
lockInfo.getLockType(),
|
||||
Depth.ZERO,
|
||||
lockInfo.getOwner(),
|
||||
new TimeOut(3600),
|
||||
new LockToken(new HRef(String
|
||||
.format("opaquelocktoken:%s",
|
||||
lockToken))),
|
||||
new LockRoot(new HRef(lockedPath)))));
|
||||
|
||||
} catch (AlreadyLockedException ex) {
|
||||
throw new WebApplicationException(
|
||||
ResponseStatus.LOCKED.getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
@OPTIONS
|
||||
public Response options() {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (C) 2018 LibreCCM Foundation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package org.libreccm.theming.webdav;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
|
||||
/**
|
||||
* Manages the locks on files for WebDAV.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
class ThemeFilesLockManager {
|
||||
|
||||
/**
|
||||
* Mapping between file path and lock token
|
||||
*/
|
||||
private final Map<String, String> lockedFiles = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Mapping between lock token and file.
|
||||
*/
|
||||
private final Map<String, String> locks = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Lock a file
|
||||
*
|
||||
* @param file Path of the file to lock.
|
||||
*
|
||||
* @return The lock token.
|
||||
*
|
||||
* @throws AlreadyLockedException If the file is already locked.
|
||||
*/
|
||||
protected String lockFile(final String file) throws AlreadyLockedException {
|
||||
|
||||
if (lockedFiles.containsKey(file)) {
|
||||
throw new AlreadyLockedException(String.format(
|
||||
"File %s is already locked.", file));
|
||||
} else {
|
||||
|
||||
final String lockToken = UUID.randomUUID().toString();
|
||||
lockedFiles.put(file, lockToken);
|
||||
locks.put(lockToken, file);
|
||||
|
||||
return lockToken;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is locked.
|
||||
*
|
||||
* @param file The file to check for a lock.
|
||||
*
|
||||
* @return An {@link Optional} with the lock token of the file if the file
|
||||
* is locked, an empty {@code Optional} otherwise.
|
||||
*/
|
||||
protected Optional<String> isLocked(final String file) {
|
||||
if (lockedFiles.containsKey(file)) {
|
||||
return Optional.of(lockedFiles.get(file));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the lock from a file.
|
||||
*
|
||||
* @param lockToken The token of the lock to remove.
|
||||
*/
|
||||
protected void unlock(final String lockToken) {
|
||||
|
||||
final String file = locks.get(lockToken);
|
||||
locks.remove(lockToken);
|
||||
lockedFiles.remove(file);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue