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