1
22
23 package com.liferay.lock.util;
24
25 import com.liferay.lock.DuplicateLockException;
26 import com.liferay.lock.ExpiredLockException;
27 import com.liferay.lock.NoSuchLockException;
28 import com.liferay.lock.model.Lock;
29 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
30
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33
34
41 public class LockPool {
42
43 public static void clear() {
44 _instance._clear();
45 }
46
47 public static Lock getLock(String className, Comparable<?> pk)
48 throws ExpiredLockException, NoSuchLockException {
49
50 return _instance._getLock(className, pk);
51 }
52
53 public static boolean hasLock(
54 String className, Comparable<?> pk, long userId) {
55
56 return _instance._hasLock(className, pk, userId);
57 }
58
59 public static boolean isLocked(String className, Comparable<?> pk) {
60 return _instance._isLocked(className, pk);
61 }
62
63 public static Lock lock(
64 String className, Comparable<?> pk, long userId, String owner,
65 boolean inheritable, long expirationTime)
66 throws DuplicateLockException {
67
68 return _instance._lock(
69 className, pk, userId, owner, inheritable, expirationTime);
70 }
71
72 public static Lock refresh(String uuid, long expirationTime)
73 throws NoSuchLockException {
74
75 return _instance._refresh(uuid, expirationTime);
76 }
77
78 public static void unlock(String className, Comparable<?> pk) {
79 _instance._unlock(className, pk);
80 }
81
82 private LockPool() {
83 _locksByClassName =
84 new ConcurrentHashMap<String, Map<Comparable<?>, Lock>>();
85 _lockByUuid = new ConcurrentHashMap<String, Lock>();
86 }
87
88 private void _clear() {
89 _locksByClassName.clear();
90 _lockByUuid.clear();
91 }
92
93 private Lock _getLock(String className, Comparable<?> pk)
94 throws ExpiredLockException, NoSuchLockException {
95
96 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
97
98 Lock lock = locksByPK.get(pk);
99
100 if (lock == null) {
101 throw new NoSuchLockException();
102 }
103 else if (lock.isExpired()) {
104 _unlock(className, pk);
105
106 throw new ExpiredLockException();
107 }
108
109 return lock;
110 }
111
112 private Map<Comparable<?>, Lock> _getLocks(String className) {
113 Map<Comparable<?>, Lock> locksByPK = _locksByClassName.get(className);
114
115 if (locksByPK == null) {
116 locksByPK = new ConcurrentHashMap<Comparable<?>, Lock>();
117
118 _locksByClassName.put(className, locksByPK);
119 }
120
121 return locksByPK;
122 }
123
124 private boolean _hasLock(String className, Comparable<?> pk, long userId) {
125 try {
126 Lock lock = _getLock(className, pk);
127
128 if (lock.getUserId() == userId) {
129 return true;
130 }
131 }
132 catch (ExpiredLockException ele) {
133 }
134 catch (NoSuchLockException nsle) {
135 }
136
137 return false;
138 }
139
140 private boolean _isLocked(String className, Comparable<?> pk) {
141 try {
142 _getLock(className, pk);
143
144 return true;
145 }
146 catch (ExpiredLockException ele) {
147 }
148 catch (NoSuchLockException nsle) {
149 }
150
151 return false;
152 }
153
154 private Lock _lock(
155 String className, Comparable<?> pk, long userId, String owner,
156 boolean inheritable, long expirationTime)
157 throws DuplicateLockException {
158
159 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
160
161 Lock lock = locksByPK.get(pk);
162
163 if (lock != null) {
164 if (lock.isExpired()) {
165 _unlock(className, pk);
166
167 lock = null;
168 }
169 else if (!lock.getOwner().equals(owner)) {
170 throw new DuplicateLockException(lock);
171 }
172 }
173
174 if (lock == null) {
175 String uuid = PortalUUIDUtil.generate();
176
177 lock = new Lock(
178 uuid, className, pk, userId, owner, inheritable,
179 expirationTime);
180
181 locksByPK.put(pk, lock);
182
183 _lockByUuid.put(uuid, lock);
184 }
185 else {
186 lock.setExpirationTime(expirationTime);
187 }
188
189 return lock;
190 }
191
192 private Lock _refresh(String uuid, long expirationTime)
193 throws NoSuchLockException {
194
195 Lock lock = _lockByUuid.get(uuid);
196
197 if (lock != null) {
198 lock.setExpirationTime(expirationTime);
199
200 return lock;
201 }
202
203 throw new NoSuchLockException();
204 }
205
206 private void _unlock(String className, Comparable<?> pk) {
207 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
208
209 Lock lock = locksByPK.remove(pk);
210
211 if (lock != null) {
212 _lockByUuid.remove(lock.getUuid());
213 }
214 }
215
216 private static LockPool _instance = new LockPool();
217
218 private Map<String, Map<Comparable<?>, Lock>> _locksByClassName;
219 private Map<String, Lock> _lockByUuid;
220
221 }