/* * Copyright 2005-2006 webdav-servlet group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ejie.x38.webdav.locking; import org.springframework.stereotype.Component; import org.springframework.web.context.support.SpringBeanAutowiringSupport; import com.ejie.x38.webdav.ITransaction; import com.ejie.x38.webdav.exceptions.LockFailedException; /** * * @author UDA */ @Component(value="dataBaseResourceLocks") public class DataBaseResourceLocks extends SpringBeanAutowiringSupport implements IResourceLocks { private static org.slf4j.Logger LOG = org.slf4j.LoggerFactory .getLogger(DataBaseResourceLocks.class); private boolean _temporary = true; protected DataBaseLockService dataBaseLockService; public synchronized boolean lock(ITransaction transaction, String path, String owner, boolean exclusive, int depth, int timeout, boolean temporary) throws LockFailedException { LOG.debug("DataBaseResourceLocks.lock()"); DataBaseLockedObject lo = null; if (temporary) { lo = generateTempLockedObjects(transaction, path); lo._type = "read"; } else { lo = generateLockedObjects(transaction, path); lo._type = "write"; } if (lo.checkLocks(exclusive, depth)) { lo._exclusive = exclusive; lo._lockDepth = depth; lo._expiresAt = System.currentTimeMillis() + (timeout * 1000); if (lo._parent != null) { lo._parent._expiresAt = lo._expiresAt; // if (lo._parent.equals(_root)) { // if (lo._parent.getPath().equals("/")) { // DataBaseLockedObject rootLo = getLockedObjectByPath(transaction, // "/"); // rootLo._expiresAt = lo._expiresAt; // } else if (lo._parent.equals(_tempRoot)) { // } else if (lo._parent.getPath().equals("/")) { // DataBaseLockedObject tempRootLo = getTempLockedObjectByPath( // transaction, "/"); // tempRootLo._expiresAt = lo._expiresAt; // } } if (lo.addLockedObjectOwner(owner)) { dataBaseLockService.addLockedObject(lo); return true; } else { LOG.trace("Couldn't set owner \"" + owner + "\" to resource at '" + path + "'"); return false; } } else { LOG.trace("Lock resource at " + path + " failed because" + "\na parent or child resource is currently locked"); return false; } } public synchronized boolean unlock(ITransaction transaction, String id, String owner) { LOG.debug("DataBaseResourceLocks.unlock()"); if (dataBaseLockService.isLockedById(id, Boolean.FALSE)){ dataBaseLockService.unlockObjectById(id, Boolean.FALSE); } this.checkTimeouts(transaction, Boolean.FALSE); return true; } public synchronized void unlockTemporaryLockedObjects( ITransaction transaction, String path, String owner) { LOG.debug("DataBaseResourceLocks.unlockTemporaryLockedObjects()"); if (dataBaseLockService.isLockedByPath(path, Boolean.TRUE)){ dataBaseLockService.unlockObjectByPath(path, Boolean.TRUE); } this.checkTimeouts(transaction, Boolean.TRUE); } public void checkTimeouts(ITransaction transaction, boolean temporary) { LOG.debug("DataBaseResourceLocks.checkTimeouts()"); dataBaseLockService.removeTimeoutLocks(temporary); } public boolean checkLocks(boolean exclusive, int depth) { LOG.debug("DataBaseResourceLocks.checkLocks()"); return false; } public boolean exclusiveLock(ITransaction transaction, String path, String owner, int depth, int timeout) throws LockFailedException { LOG.debug("DataBaseResourceLocks.exclusiveLock()"); return lock(transaction, path, owner, true, depth, timeout, false); } public boolean sharedLock(ITransaction transaction, String path, String owner, int depth, int timeout) throws LockFailedException { LOG.debug("DataBaseResourceLocks.sharedLock()"); return lock(transaction, path, owner, false, depth, timeout, false); } public DataBaseLockedObject getLockedObjectByID(ITransaction transaction, String id) { LOG.debug("DataBaseResourceLocks.getLockedObjectByID()"); DataBaseLockedObject lockedObject = dataBaseLockService.getLockedObjectById(id, Boolean.FALSE); if (lockedObject!=null) { return lockedObject; } else { return null; } } public DataBaseLockedObject getLockedObjectByPath(ITransaction transaction, String path) { LOG.debug("DataBaseResourceLocks.getLockedObjectByPath()"); DataBaseLockedObject lockedObject = dataBaseLockService.getLockedObjectByPath(path, Boolean.FALSE); if (lockedObject!=null) { return lockedObject; } else { return null; } } public DataBaseLockedObject getTempLockedObjectByID(ITransaction transaction, String id) { LOG.debug("DataBaseResourceLocks.getTempLockedObjectById()"); DataBaseLockedObject lockedObject = dataBaseLockService.getLockedObjectById(id, Boolean.TRUE); if (lockedObject!=null) { return lockedObject; } else { return null; } } public DataBaseLockedObject getTempLockedObjectByPath(ITransaction transaction, String path) { LOG.debug("DataBaseResourceLocks.getTempLockedObjectByPath()"); DataBaseLockedObject lockedObject = dataBaseLockService.getLockedObjectByPath(path, Boolean.TRUE); if (lockedObject!=null) { return lockedObject; } else { return null; } } /** * generates real LockedObjects for the resource at path and its parent * folders. does not create new LockedObjects if they already exist * * @param transaction * @param path * path to the (new) LockedObject * @return the LockedObject for path. */ private DataBaseLockedObject generateLockedObjects(ITransaction transaction, String path) { LOG.debug("DataBaseResourceLocks.generateLockedObjects()"); if (!dataBaseLockService.isLockedByPath(path, Boolean.FALSE) ){ DataBaseLockedObject returnObject = new DataBaseLockedObject(this, path, !_temporary); String parentPath = getParentPath(path); if (parentPath != null && !"/".equals(path)) { DataBaseLockedObject parentLockedObject = generateLockedObjects( transaction, parentPath); parentLockedObject.addChild(returnObject); returnObject._parent = parentLockedObject; } return returnObject; } else { // there is already a LockedObject on the specified path return dataBaseLockService.getLockedObjectByPath(path, Boolean.FALSE); } } /** * generates temporary LockedObjects for the resource at path and its parent * folders. does not create new LockedObjects if they already exist * * @param transaction * @param path * path to the (new) LockedObject * @return the LockedObject for path. */ private DataBaseLockedObject generateTempLockedObjects(ITransaction transaction, String path) { LOG.debug("DataBaseResourceLocks.generateTempLockedObjects()"); if (!dataBaseLockService.isLockedByPath(path, Boolean.TRUE) ){ DataBaseLockedObject returnObject = new DataBaseLockedObject(this, path, _temporary); String parentPath = getParentPath(path); if (parentPath != null && !"/".equals(path)) { DataBaseLockedObject parentLockedObject = generateTempLockedObjects( transaction, parentPath); parentLockedObject.addChild(returnObject); returnObject._parent = parentLockedObject; } return returnObject; } else { // there is already a LockedObject on the specified path return dataBaseLockService.getLockedObjectByPath(path, _temporary); } } /** * creates the parent path from the given path by removing the last '/' and * everything after that * * @param path * the path * @return parent path */ private String getParentPath(String path) { LOG.debug("DataBaseResourceLocks.getParentPath()"); int slash = path.lastIndexOf('/'); if (slash == -1) { return null; } else { if (slash == 0) { // return "root" if parent path is empty string return "/"; } else { return path.substring(0, slash); } } } public void setDataBaseLockService(DataBaseLockService dataBaseLockService) { this.dataBaseLockService = dataBaseLockService; } }