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 long expirationTime)
66 throws DuplicateLockException {
67
68 return _instance._lock(className, pk, userId, owner, expirationTime);
69 }
70
71 public static Lock refresh(String uuid, long expirationTime)
72 throws NoSuchLockException {
73
74 return _instance._refresh(uuid, expirationTime);
75 }
76
77 public static void unlock(String className, Comparable<?> pk) {
78 _instance._unlock(className, pk);
79 }
80
81 private LockPool() {
82 _locksByClassName =
83 new ConcurrentHashMap<String, Map<Comparable<?>, Lock>>();
84 _lockByUuid = new ConcurrentHashMap<String, Lock>();
85 }
86
87 private void _clear() {
88 _locksByClassName.clear();
89 _lockByUuid.clear();
90 }
91
92 private Lock _getLock(String className, Comparable<?> pk)
93 throws ExpiredLockException, NoSuchLockException {
94
95 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
96
97 Lock lock = locksByPK.get(pk);
98
99 if (lock == null) {
100 throw new NoSuchLockException();
101 }
102 else if (lock.isExpired()) {
103 _unlock(className, pk);
104
105 throw new ExpiredLockException();
106 }
107
108 return lock;
109 }
110
111 private Map<Comparable<?>, Lock> _getLocks(String className) {
112 Map<Comparable<?>, Lock> locksByPK = _locksByClassName.get(className);
113
114 if (locksByPK == null) {
115 locksByPK = new ConcurrentHashMap<Comparable<?>, Lock>();
116
117 _locksByClassName.put(className, locksByPK);
118 }
119
120 return locksByPK;
121 }
122
123 private boolean _hasLock(String className, Comparable<?> pk, long userId) {
124 try {
125 Lock lock = _getLock(className, pk);
126
127 if (lock.getUserId() == userId) {
128 return true;
129 }
130 }
131 catch (ExpiredLockException ele) {
132 }
133 catch (NoSuchLockException nsle) {
134 }
135
136 return false;
137 }
138
139 private boolean _isLocked(String className, Comparable<?> pk) {
140 try {
141 _getLock(className, pk);
142
143 return true;
144 }
145 catch (ExpiredLockException ele) {
146 }
147 catch (NoSuchLockException nsle) {
148 }
149
150 return false;
151 }
152
153 private Lock _lock(
154 String className, Comparable<?> pk, long userId, String owner,
155 long expirationTime)
156 throws DuplicateLockException {
157
158 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
159
160 Lock lock = locksByPK.get(pk);
161
162 if (lock != null) {
163 if (lock.isExpired()) {
164 _unlock(className, pk);
165
166 lock = null;
167 }
168 else if (!lock.getOwner().equals(owner)) {
169 throw new DuplicateLockException(lock);
170 }
171 }
172
173 if (lock == null) {
174 String uuid = PortalUUIDUtil.generate();
175
176 lock = new Lock(uuid, className, pk, userId, owner, expirationTime);
177
178 locksByPK.put(pk, lock);
179
180 _lockByUuid.put(uuid, lock);
181 }
182 else {
183 lock.setExpirationTime(expirationTime);
184 }
185
186 return lock;
187 }
188
189 private Lock _refresh(String uuid, long expirationTime)
190 throws NoSuchLockException {
191
192 Lock lock = _lockByUuid.get(uuid);
193
194 if (lock != null) {
195 lock.setExpirationTime(expirationTime);
196
197 return lock;
198 }
199
200 throw new NoSuchLockException();
201 }
202
203 private void _unlock(String className, Comparable<?> pk) {
204 Map<Comparable<?>, Lock> locksByPK = _getLocks(className);
205
206 Lock lock = locksByPK.remove(pk);
207
208 if (lock != null) {
209 _lockByUuid.remove(lock.getUuid());
210 }
211 }
212
213 private static LockPool _instance = new LockPool();
214
215 private Map<String, Map<Comparable<?>, Lock>> _locksByClassName;
216 private Map<String, Lock> _lockByUuid;
217
218 }