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.lock.model.impl.LockImpl;
30 import com.liferay.util.ConcurrentHashSet;
31
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.concurrent.ConcurrentHashMap;
36
37
43 public class LockPool {
44
45 public static void clear() {
46 _instance._clear();
47 }
48
49 public static Lock getLock(String className, Comparable<?> pk)
50 throws ExpiredLockException, NoSuchLockException {
51
52 return _instance._getLock(className, pk);
53 }
54
55 public static Set<Lock> getLocksByCompanyId(long companyId) {
56 Set<Lock> locksByCompanyId = _instance._getLocksByCompanyId(companyId);
57
58 Iterator<Lock> itr = locksByCompanyId.iterator();
59
60 while (itr.hasNext()) {
61 Lock lock = itr.next();
62
63 if (lock.isExpired()) {
64 itr.remove();
65
66 _instance._getLocks(
67 lock.getClassName(), lock.getPrimaryKey()).remove(lock);
68 _instance._getLocksByUserId(lock.getUserId()).remove(lock);
69 }
70 }
71
72 return locksByCompanyId;
73 }
74
75 public static Set<Lock> getLocksByUserId(long userId) {
76 Set<Lock> locksByUserId = _instance._getLocksByUserId(userId);
77
78 Iterator<Lock> itr = locksByUserId.iterator();
79
80 while (itr.hasNext()) {
81 Lock lock = itr.next();
82
83 if (lock.isExpired()) {
84 itr.remove();
85
86 _instance._getLocks(
87 lock.getClassName(), lock.getPrimaryKey()).remove(lock);
88 _instance._getLocksByCompanyId(
89 lock.getCompanyId()).remove(lock);
90 }
91 }
92
93 return locksByUserId;
94 }
95
96 public static boolean hasLock(
97 String className, Comparable<?> pk, long userId) {
98
99 return _instance._hasLock(className, pk, userId);
100 }
101
102 public static boolean isLocked(String className, Comparable<?> pk) {
103 return _instance._isLocked(className, pk);
104 }
105
106 public static void lock(
107 String className, Comparable<?> pk, long companyId, long userId,
108 long expirationTime)
109 throws DuplicateLockException {
110
111 _instance._lock(className, pk, companyId, userId, expirationTime);
112 }
113
114 public static void unlock(String className, Comparable<?> pk) {
115 _instance._unlock(className, pk);
116 }
117
118 private LockPool() {
119 _locksByClassName =
120 new ConcurrentHashMap<String, Map<Comparable<?>, Lock>>();
121 _locksByCompanyId = new ConcurrentHashMap<Long, Set<Lock>>();
122 _locksByUserId = new ConcurrentHashMap<Long, Set<Lock>>();
123 }
124
125 private void _clear() {
126 _locksByClassName.clear();
127 _locksByCompanyId.clear();
128 _locksByUserId.clear();
129 }
130
131 private Lock _getLock(String className, Comparable<?> pk)
132 throws ExpiredLockException, NoSuchLockException {
133
134 Map<Comparable<?>, Lock> locksByPK = _getLocks(className, pk);
135
136 Lock lock = locksByPK.get(pk);
137
138 if (lock == null) {
139 throw new NoSuchLockException();
140 }
141 else if (lock.isExpired()) {
142 _unlock(className, pk);
143
144 throw new ExpiredLockException();
145 }
146
147 return lock;
148 }
149
150 private Map<Comparable<?>, Lock> _getLocks(
151 String className, Comparable<?> pk) {
152
153 Map<Comparable<?>, Lock> locksByPK = _locksByClassName.get(className);
154
155 if (locksByPK == null) {
156 locksByPK = new ConcurrentHashMap<Comparable<?>, Lock>();
157
158 _locksByClassName.put(className, locksByPK);
159 }
160
161 return locksByPK;
162 }
163
164 private Set<Lock> _getLocksByCompanyId(long companyId) {
165 Set<Lock> set = _locksByCompanyId.get(companyId);
166
167 if (set == null) {
168 set = new ConcurrentHashSet<Lock>();
169
170 _locksByCompanyId.put(companyId, set);
171 }
172
173 return set;
174 }
175
176 private Set<Lock> _getLocksByUserId(long userId) {
177 Set<Lock> set = _locksByUserId.get(userId);
178
179 if (set == null) {
180 set = new ConcurrentHashSet<Lock>();
181
182 _locksByUserId.put(userId, set);
183 }
184
185 return set;
186 }
187
188 private boolean _hasLock(String className, Comparable<?> pk, long userId) {
189 try {
190 Lock lock = _getLock(className, pk);
191
192 if (lock.getUserId() == userId) {
193 return true;
194 }
195 }
196 catch (ExpiredLockException ele) {
197 }
198 catch (NoSuchLockException nsle) {
199 }
200
201 return false;
202 }
203
204 private boolean _isLocked(String className, Comparable<?> pk) {
205 try {
206 _getLock(className, pk);
207
208 return true;
209 }
210 catch (ExpiredLockException ele) {
211 }
212 catch (NoSuchLockException nsle) {
213 }
214
215 return false;
216 }
217
218 private void _lock(
219 String className, Comparable<?> pk, long companyId, long userId,
220 long expirationTime)
221 throws DuplicateLockException {
222
223 Map<Comparable<?>, Lock> locksByPK = _getLocks(className, pk);
224
225 Lock lock = locksByPK.get(pk);
226
227 if (lock != null && lock.isExpired()) {
228 _unlock(className, pk);
229
230 lock = null;
231 }
232 else if ((lock != null) && (lock.getUserId() != userId)) {
233 throw new DuplicateLockException(lock);
234 }
235
236 if (lock == null) {
237 lock = new LockImpl(
238 className, pk, companyId, userId, expirationTime);
239
240 locksByPK.put(pk, lock);
241
242 _getLocksByCompanyId(companyId).add(lock);
243 _getLocksByUserId(userId).add(lock);
244 }
245 else {
246 lock.setExpirationTime(expirationTime);
247 }
248 }
249
250 private void _unlock(String className, Comparable<?> pk) {
251 Map<Comparable<?>, Lock> locksByPK = _getLocks(className, pk);
252
253 Lock lock = locksByPK.remove(pk);
254
255 if (lock != null) {
256 _getLocksByCompanyId(lock.getCompanyId()).remove(lock);
257 _getLocksByUserId(lock.getUserId()).remove(lock);
258 }
259 }
260
261 private static LockPool _instance = new LockPool();
262
263 private Map<String, Map<Comparable<?>, Lock>> _locksByClassName;
264 private Map<Long, Set<Lock>> _locksByCompanyId;
265 private Map<Long, Set<Lock>> _locksByUserId;
266
267 }