001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.mailrepository.lib;
021
022 import java.util.Hashtable;
023
024 /**
025 * Provides Lock functionality
026 */
027 public class Lock {
028 /**
029 * An internal hash table of keys to locks
030 */
031 private Hashtable locks = new Hashtable();
032
033 /**
034 * Check to see if the object is locked
035 *
036 * @param key
037 * the Object on which to check the lock
038 * @return true if the object is locked, false otherwise
039 */
040 public boolean isLocked(final Object key) {
041 return (locks.get(key) != null);
042 }
043
044 /**
045 * Check to see if we can lock on a given object.
046 *
047 * @param key
048 * the Object on which to lock
049 * @return true if the calling thread can lock, false otherwise
050 */
051 public boolean canI(final Object key) {
052 Object o = locks.get(key);
053
054 if (null == o || o == this.getCallerId()) {
055 return true;
056 }
057
058 return false;
059 }
060
061 /**
062 * Lock on a given object.
063 *
064 * @param key
065 * the Object on which to lock
066 * @return true if the locking was successful, false otherwise
067 */
068 public boolean lock(final Object key) {
069 Object theLock;
070
071 synchronized (this) {
072 theLock = locks.get(key);
073
074 if (null == theLock) {
075 locks.put(key, getCallerId());
076 return true;
077 } else if (getCallerId() == theLock) {
078 return true;
079 } else {
080 return false;
081 }
082 }
083 }
084
085 /**
086 * Release the lock on a given object.
087 *
088 * @param key
089 * the Object on which the lock is held
090 * @return true if the unlocking was successful, false otherwise
091 */
092 public boolean unlock(final Object key) {
093 Object theLock;
094 synchronized (this) {
095 theLock = locks.get(key);
096
097 if (null == theLock) {
098 return true;
099 } else if (getCallerId() == theLock) {
100 locks.remove(key);
101 return true;
102 } else {
103 return false;
104 }
105 }
106 }
107
108 /**
109 * Private helper method to abstract away caller ID.
110 *
111 * @return the id of the caller (i.e. the Thread reference)
112 */
113 private Object getCallerId() {
114 return Thread.currentThread();
115 }
116 }