Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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 net.sf.webdav;
 
some very simple locking management for concurrent data access, NOT the webdav locking. ( could that be used instead? )

Author(s):
re
 
 public class ResourceLocks {

    
after creating this much LockObjects, a cleanup delets unused LockObjects
 
     private final int fCleanupLimit = 100000;
 
     private int fCleanupCounter = 0;

    
keys: path value: LockObject from that path
 
     private Hashtable fLocks = null;
 
     // REMEMBER TO REMOVE UNUSED LOCKS FROM THE HASHTABLE AS WELL
 
     private LockObject fRoot = null;
 
     public ResourceLocks() {
 	this. = new Hashtable();
 	 = new LockObject("/");
     }

    
trys to lock the resource at "path".

Parameters:
path what resource to lock
owner the owner of the lock
exclusive if the lock should be exclusive (or shared)
depth depth
Returns:
true if the resource at path was successfully locked, false if an existing lock prevented this
 
     public synchronized boolean lock(String pathString owner,
 	    boolean exclusiveint depth) {
 
 	if (lo.checkLocks(exclusivedepth)) {
 	    if (lo.addLockObjectOwner(owner)) {
 		lo.fExclusive = exclusive;
 		return true;
 	    } else {
 		return false;
 	    }
 	} else {
 	    // can not lock
 	    return false;
 	}
     }

    
unlocks all resources at "path" (and all subfolders if existing)

that have the same owner

Parameters:
path what resource to unlock
owner who wants to unlock
 
     public synchronized void unlock(String pathString owner) {
 
 	if (this..containsKey(path)) {
 	    LockObject lo = (LockObjectthis..get(path);
 	    lo.removeLockObjectOwner(owner);
 	    // System.out.println("number of LockObjects in the hashtable: "
 	    // + fLocks.size());
 
 	} else {
	    // there is no lock at that path. someone tried to unlock it
	    // anyway. could point to a problem
	    .
		    .println("net.sf.webdav.ResourceLocks.unlock(): no lock for path "
			    + path);
	}
	     = 0;
	}
    }

    
generates LockObjects for the resource at path and its parent folders. does not create new LockObjects if they already exist

Parameters:
path path to the (new) LockObject
Returns:
the LockObject for path.
    private LockObject generateLockObjects(String path) {
	if (!this..containsKey(path)) {
	    LockObject returnObject = new LockObject(path);
	    String parentPath = getParentPath(path);
	    if (parentPath != null) {
		LockObject parentLockObject = generateLockObjects(parentPath);
		parentLockObject.addChild(returnObject);
		returnObject.fParent = parentLockObject;
	    }
	    return returnObject;
else {
	    return (LockObjectthis..get(path);
	}
    }

    
deletes unused LockObjects and resets the counter. works recursively starting at the given LockObject

Parameters:
lo lock object
Returns:
if cleaned
    private boolean cleanLockObjects(LockObject lo) {
	if (lo.fChildren == null) {
	    if (lo.fOwner == null) {
		return true;
	    } else {
		return false;
	    }
else {
	    boolean canDelete = true;
	    int limit = lo.fChildren.length;
	    for (int i = 0; i < limiti++) {
		if (!cleanLockObjects(lo.fChildren[i])) {
		    canDelete = false;
else {
		    // because the deleting shifts the array
		    i--;
		    limit--;
		}
	    }
	    if (canDelete) {
		if (lo.fOwner == null) {
		    lo.removeLockObject();
		    return true;
else {
		    return false;
		}
	    } else {
		return false;
	    }
	}
    }

    
creates the parent path from the given path by removing the last '/' and everything after that

Parameters:
path the path
Returns:
parent path
    private String getParentPath(String path) {
	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);
	    }
	}
    }
    // ----------------------------------------------------------------------------

    
a helper class for ResourceLocks, represents the Locks

Author(s):
re
    private class LockObject {
owner of the lock. shared locks can have multiple owners. is null if no owner is present
	String[] fOwner = null;

children of that lock
	LockObject[] fChildren = null;
	LockObject fParent = null;

weather the lock is exclusive or not. if owner=null the exclusive value doesn't matter
	boolean fExclusive = false;

Parameters:
path the path to the locked object
	    this. = path;
	    .put(paththis);
	    ++;
	}

adds a new owner to a lock

Parameters:
owner string that represents the owner
Returns:
true if the owner was added, false otherwise
	boolean addLockObjectOwner(String owner) {
	    if (this. == null) {
		this. = new String[1];
	    } else {
		int size = this..length;
		String[] newLockObjectOwner = new String[size + 1];
		// check if the owner is already here (that should actually not
		// happen)
		for (int i = 0; i < sizei++) {
		    if (this.[i].equals(owner)) {
			return false;
		    }
		}
		System.arraycopy(this., 0, newLockObjectOwner, 0, size);
		this. = newLockObjectOwner;
	    }
	    this.[this..length - 1] = owner;
	    return true;
	}

tries to remove the owner from the lock

Parameters:
owner string that represents the owner
	    if (this. != null) {
		int size = this..length;
		for (int i = 0; i < sizei++) {
		    // check every owner if it is the requested one
		    if (this.[i].equals(owner)) {
			// remove the owner
			String[] newLockObjectOwner = new String[size - 1];
			for (int i2 = 0; i2 < (size - 1); i2++) {
			    if (i2 < i) {
				newLockObjectOwner[i2] = this.[i2];
			    } else {
				newLockObjectOwner[i2] = this.[i2 + 1];
			    }
			}
			this. = newLockObjectOwner;
		    }
		}
		if (this..length == 0) {
		    this. = null;
		}
	    }
	}

adds a new child lock to this lock

Parameters:
newChild new child
	void addChild(LockObject newChild) {
	    if (this. == null) {
		this. = new LockObject[0];
	    }
	    int size = this..length;
	    LockObject[] newChildren = new LockObject[size + 1];
	    System.arraycopy(this., 0, newChildren, 0, size);
	    newChildren[size] = newChild;
	    this. = newChildren;
	}

deletes this Lock object. assumes that it has no children and no owners (does not check this itself)
	    if (this != ) {
		// removing from tree
		int size = this...length;
		for (int i = 0; i < sizei++) {
		    if (this..[i].equals(this)) {
			LockObject[] newChildren = new LockObject[size - 1];
			for (int i2 = 0; i2 < (size - 1); i2++) {
			    if (i2 < i) {
				newChildren[i2] = this..[i2];
			    } else {
				newChildren[i2] = this..[i2 + 1];
			    }
			}
			if (newChildren.length != 0) {
			    this.. = newChildren;
else {
			    this.. = null;
			}
			break;
		    }
		}
		// removing from hashtable
		// now the garbage collector has some work to do
	    }
	}

checks if a lock of the given exclusivity can be placed, only considering cildren up to "depth"

Parameters:
exclusive wheather the new lock should be exclusive
depth the depth to which should be checked
Returns:
true if the lock can be placed
	boolean checkLocks(boolean exclusiveint depth) {
	    return (checkParents(exclusive) && checkChildren(exclusivedepth));
	}

helper of checkLocks(). looks if the parents are locked

Parameters:
exclusive wheather the new lock should be exclusive
Returns:
true if no locks at the parent path are forbidding a new lock
	private boolean checkParents(boolean exclusive) {
	    if (this..equals("/")) {
		return true;
	    } else {
		if (this. == null) {
		    // no owner, checking parents
		    return this. != null
			    && this..checkParents(exclusive);
else {
		    // there already is a owner
		    return !(this. || exclusive)
			    && this..checkParents(exclusive);
		}
	    }
	}

helper of checkLocks(). looks if the children are locked

Parameters:
exclusive wheather the new lock should be exclusive
depth depth
Returns:
true if no locks at the children paths are forbidding a new lock
	private boolean checkChildren(boolean exclusiveint depth) {
	    if (this. == null) {
		// a file
		return this. == null || !(this. || exclusive);
	    } else {
		// a folder
		if (this. == null) {
		    // no owner, checking children
		    if (depth != 0) {
			boolean canLock = true;
			int limit = this..length;
			for (int i = 0; i < limiti++) {
			    if (!this.[i].checkChildren(exclusive,
				    depth - 1)) {
				canLock = false;
			    }
			}
			return canLock;
		    } else {
			// depth == 0 -> we don't care for children
			return true;
		    }
else {
		    // there already is a owner
		    return !(this. || exclusive);
		}
	    }
	}
    }
New to GrepCode? Check out our FAQ X