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: ****************************************************************/package org.apache.james.util;
019:
020: import java.util.Hashtable;
021:
022: /**
023: * Provides Lock functionality
024: *
025: */
026: public class Lock {
027: /**
028: * An internal hash table of keys to locks
029: */
030: private Hashtable locks = new Hashtable();
031:
032: /**
033: * Check to see if the object is locked
034: *
035: * @param key the Object on which to check the lock
036: * @return true if the object is locked, false otherwise
037: */
038: public boolean isLocked(final Object key) {
039: return (locks.get(key) != null);
040: }
041:
042: /**
043: * Check to see if we can lock on a given object.
044: *
045: * @param key the Object on which to lock
046: * @return true if the calling thread can lock, false otherwise
047: */
048: public boolean canI(final Object key) {
049: Object o = locks.get(key);
050:
051: if (null == o || o == this .getCallerId()) {
052: return true;
053: }
054:
055: return false;
056: }
057:
058: /**
059: * Lock on a given object.
060: *
061: * @param key the Object on which to lock
062: * @return true if the locking was successful, false otherwise
063: */
064: public boolean lock(final Object key) {
065: Object theLock;
066:
067: synchronized (this ) {
068: theLock = locks.get(key);
069:
070: if (null == theLock) {
071: locks.put(key, getCallerId());
072: return true;
073: } else if (getCallerId() == theLock) {
074: return true;
075: } else {
076: return false;
077: }
078: }
079: }
080:
081: /**
082: * Release the lock on a given object.
083: *
084: * @param key the Object on which the lock is held
085: * @return true if the unlocking was successful, false otherwise
086: */
087: public boolean unlock(final Object key) {
088: Object theLock;
089: synchronized (this ) {
090: theLock = locks.get(key);
091:
092: if (null == theLock) {
093: return true;
094: } else if (getCallerId() == theLock) {
095: locks.remove(key);
096: return true;
097: } else {
098: return false;
099: }
100: }
101: }
102:
103: /**
104: * Private helper method to abstract away caller ID.
105: *
106: * @return the id of the caller (i.e. the Thread reference)
107: */
108: private Object getCallerId() {
109: return Thread.currentThread();
110: }
111: }
|