1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
18 package org.apache.james.util;
19
20 import java.util.Hashtable;
21
22 /***
23 * Provides Lock functionality
24 *
25 */
26 public class Lock {
27 /***
28 * An internal hash table of keys to locks
29 */
30 private Hashtable locks = new Hashtable();
31
32 /***
33 * Check to see if the object is locked
34 *
35 * @param key the Object on which to check the lock
36 * @return true if the object is locked, false otherwise
37 */
38 public boolean isLocked(final Object key) {
39 return (locks.get(key) != null);
40 }
41
42 /***
43 * Check to see if we can lock on a given object.
44 *
45 * @param key the Object on which to lock
46 * @return true if the calling thread can lock, false otherwise
47 */
48 public boolean canI(final Object key) {
49 Object o = locks.get( key );
50
51 if (null == o || o == this.getCallerId()) {
52 return true;
53 }
54
55 return false;
56 }
57
58 /***
59 * Lock on a given object.
60 *
61 * @param key the Object on which to lock
62 * @return true if the locking was successful, false otherwise
63 */
64 public boolean lock(final Object key) {
65 Object theLock;
66
67 synchronized(this) {
68 theLock = locks.get(key);
69
70 if (null == theLock) {
71 locks.put(key, getCallerId());
72 return true;
73 } else if (getCallerId() == theLock) {
74 return true;
75 } else {
76 return false;
77 }
78 }
79 }
80
81 /***
82 * Release the lock on a given object.
83 *
84 * @param key the Object on which the lock is held
85 * @return true if the unlocking was successful, false otherwise
86 */
87 public boolean unlock(final Object key) {
88 Object theLock;
89 synchronized (this) {
90 theLock = locks.get(key);
91
92 if (null == theLock) {
93 return true;
94 } else if (getCallerId() == theLock) {
95 locks.remove(key);
96 return true;
97 } else {
98 return false;
99 }
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 }