001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.DuplicateLockException;
018    import com.liferay.portal.ExpiredLockException;
019    import com.liferay.portal.NoSuchLockException;
020    import com.liferay.portal.kernel.dao.jdbc.aop.MasterDataSource;
021    import com.liferay.portal.kernel.dao.orm.LockMode;
022    import com.liferay.portal.kernel.exception.PortalException;
023    import com.liferay.portal.kernel.exception.SystemException;
024    import com.liferay.portal.kernel.lock.LockListener;
025    import com.liferay.portal.kernel.lock.LockListenerRegistryUtil;
026    import com.liferay.portal.kernel.transaction.Propagation;
027    import com.liferay.portal.kernel.transaction.Transactional;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.model.Lock;
031    import com.liferay.portal.model.User;
032    import com.liferay.portal.service.base.LockLocalServiceBaseImpl;
033    
034    import java.util.Date;
035    import java.util.List;
036    
037    /**
038     * @author Brian Wing Shun Chan
039     * @author Shuyang Zhou
040     */
041    public class LockLocalServiceImpl extends LockLocalServiceBaseImpl {
042    
043            @Override
044            public void clear() throws SystemException {
045                    lockPersistence.removeByLtExpirationDate(new Date());
046            }
047    
048            @Override
049            public Lock getLock(String className, long key)
050                    throws PortalException, SystemException {
051    
052                    return getLock(className, String.valueOf(key));
053            }
054    
055            @Override
056            public Lock getLock(String className, String key)
057                    throws PortalException, SystemException {
058    
059                    Lock lock = lockPersistence.findByC_K(className, key);
060    
061                    if (lock.isExpired()) {
062                            expireLock(lock);
063    
064                            throw new ExpiredLockException();
065                    }
066    
067                    return lock;
068            }
069    
070            @Override
071            public Lock getLockByUuidAndCompanyId(String uuid, long companyId)
072                    throws PortalException, SystemException {
073    
074                    List<Lock> locks = lockPersistence.findByUuid_C(uuid, companyId);
075    
076                    if (locks.isEmpty()) {
077                            StringBundler sb = new StringBundler(5);
078    
079                            sb.append("{uuid=");
080                            sb.append(uuid);
081                            sb.append(", companyId=");
082                            sb.append(companyId);
083                            sb.append("}");
084    
085                            throw new NoSuchLockException(sb.toString());
086                    }
087    
088                    return locks.get(0);
089            }
090    
091            @Override
092            public boolean hasLock(long userId, String className, long key)
093                    throws SystemException {
094    
095                    return hasLock(userId, className, String.valueOf(key));
096            }
097    
098            @Override
099            public boolean hasLock(long userId, String className, String key)
100                    throws SystemException {
101    
102                    Lock lock = fetchLock(className, key);
103    
104                    if ((lock != null) && (lock.getUserId() == userId)) {
105                            return true;
106                    }
107                    else {
108                            return false;
109                    }
110            }
111    
112            @Override
113            public boolean isLocked(String className, long key) throws SystemException {
114                    return isLocked(className, String.valueOf(key));
115            }
116    
117            @Override
118            public boolean isLocked(String className, String key)
119                    throws SystemException {
120    
121                    Lock lock = fetchLock(className, key);
122    
123                    if (lock == null) {
124                            return false;
125                    }
126                    else {
127                            return true;
128                    }
129            }
130    
131            @Override
132            public Lock lock(
133                            long userId, String className, long key, String owner,
134                            boolean inheritable, long expirationTime)
135                    throws PortalException, SystemException {
136    
137                    return lock(
138                            userId, className, String.valueOf(key), owner, inheritable,
139                            expirationTime);
140            }
141    
142            @Override
143            public Lock lock(
144                            long userId, String className, String key, String owner,
145                            boolean inheritable, long expirationTime)
146                    throws PortalException, SystemException {
147    
148                    Date now = new Date();
149    
150                    Lock lock = lockPersistence.fetchByC_K(className, key);
151    
152                    if (lock != null) {
153                            if (lock.isExpired()) {
154                                    expireLock(lock);
155    
156                                    lockPersistence.flush();
157    
158                                    lock = null;
159                            }
160                            else if (lock.getUserId() != userId) {
161                                    throw new DuplicateLockException(lock);
162                            }
163                    }
164    
165                    if (lock == null) {
166                            User user = userPersistence.findByPrimaryKey(userId);
167    
168                            long lockId = counterLocalService.increment();
169    
170                            lock = lockPersistence.create(lockId);
171    
172                            lock.setCompanyId(user.getCompanyId());
173                            lock.setUserId(user.getUserId());
174                            lock.setUserName(user.getFullName());
175                            lock.setClassName(className);
176                            lock.setKey(key);
177                            lock.setOwner(owner);
178                            lock.setInheritable(inheritable);
179                    }
180    
181                    lock.setCreateDate(now);
182    
183                    if (expirationTime == 0) {
184                            lock.setExpirationDate(null);
185                    }
186                    else {
187                            lock.setExpirationDate(new Date(now.getTime() + expirationTime));
188                    }
189    
190                    lockPersistence.update(lock);
191    
192                    return lock;
193            }
194    
195            @MasterDataSource
196            @Override
197            @Transactional(propagation = Propagation.REQUIRES_NEW)
198            public Lock lock(String className, String key, String owner)
199                    throws SystemException {
200    
201                    return lock(className, key, null, owner);
202            }
203    
204            /**
205             * @deprecated As of 6.2.0, replaced by {@link #lock(String, String,
206             *             String)}
207             */
208            @MasterDataSource
209            @Override
210            @Transactional(propagation = Propagation.REQUIRES_NEW)
211            public Lock lock(
212                            String className, String key, String owner,
213                            boolean retrieveFromCache)
214                    throws SystemException {
215    
216                    return lock(className, key, null, owner);
217            }
218    
219            @MasterDataSource
220            @Override
221            @Transactional(propagation = Propagation.REQUIRES_NEW)
222            public Lock lock(
223                            String className, String key, String expectedOwner,
224                            String updatedOwner)
225                    throws SystemException {
226    
227                    Lock lock = lockFinder.fetchByC_K(className, key, LockMode.UPGRADE);
228    
229                    if (lock == null) {
230                            long lockId = counterLocalService.increment();
231    
232                            lock = lockPersistence.create(lockId);
233    
234                            lock.setCreateDate(new Date());
235                            lock.setClassName(className);
236                            lock.setKey(key);
237                            lock.setOwner(updatedOwner);
238    
239                            lockPersistence.update(lock);
240    
241                            lock.setNew(true);
242    
243                            lockPersistence.flush();
244                    }
245                    else if (Validator.equals(lock.getOwner(), expectedOwner)) {
246                            lock.setCreateDate(new Date());
247                            lock.setClassName(className);
248                            lock.setKey(key);
249                            lock.setOwner(updatedOwner);
250    
251                            lockPersistence.update(lock);
252    
253                            lock.setNew(true);
254    
255                            lockPersistence.flush();
256                    }
257    
258                    return lock;
259            }
260    
261            /**
262             * @deprecated As of 6.2.0, replaced by {@link #lock(String, String, String,
263             *             String)}
264             */
265            @MasterDataSource
266            @Override
267            @Transactional(propagation = Propagation.REQUIRES_NEW)
268            public Lock lock(
269                            String className, String key, String expectedOwner,
270                            String updatedOwner, boolean retrieveFromCache)
271                    throws SystemException {
272    
273                    return lock(className, key, expectedOwner, updatedOwner);
274            }
275    
276            @Override
277            public Lock refresh(String uuid, long companyId, long expirationTime)
278                    throws PortalException, SystemException {
279    
280                    Date now = new Date();
281    
282                    List<Lock> locks = lockPersistence.findByUuid_C(uuid, companyId);
283    
284                    if (locks.isEmpty()) {
285                            StringBundler sb = new StringBundler(5);
286    
287                            sb.append("{uuid=");
288                            sb.append(uuid);
289                            sb.append(", companyId=");
290                            sb.append(companyId);
291                            sb.append("}");
292    
293                            throw new NoSuchLockException(sb.toString());
294                    }
295    
296                    Lock lock = locks.get(0);
297    
298                    LockListener lockListener = LockListenerRegistryUtil.getLockListener(
299                            lock.getClassName());
300    
301                    String key = lock.getKey();
302    
303                    if (lockListener != null) {
304                            lockListener.onBeforeRefresh(key);
305                    }
306    
307                    try {
308                            lock.setCreateDate(now);
309    
310                            if (expirationTime == 0) {
311                                    lock.setExpirationDate(null);
312                            }
313                            else {
314                                    lock.setExpirationDate(
315                                            new Date(now.getTime() + expirationTime));
316                            }
317    
318                            lockPersistence.update(lock);
319    
320                            return lock;
321                    }
322                    finally {
323                            if (lockListener != null) {
324                                    lockListener.onAfterRefresh(key);
325                            }
326                    }
327            }
328    
329            @Override
330            public void unlock(String className, long key) throws SystemException {
331                    unlock(className, String.valueOf(key));
332            }
333    
334            @Override
335            public void unlock(String className, String key) throws SystemException {
336                    try {
337                            lockPersistence.removeByC_K(className, key);
338                    }
339                    catch (NoSuchLockException nsle) {
340                    }
341            }
342    
343            @MasterDataSource
344            @Override
345            @Transactional(propagation = Propagation.REQUIRES_NEW)
346            public void unlock(String className, String key, String owner)
347                    throws SystemException {
348    
349                    Lock lock = lockFinder.fetchByC_K(className, key, LockMode.UPGRADE);
350    
351                    if (lock == null) {
352                            return;
353                    }
354    
355                    if (Validator.equals(lock.getOwner(), owner)) {
356                            lockPersistence.remove(lock);
357                            lockPersistence.flush();
358                    }
359            }
360    
361            /**
362             * @deprecated As of 6.2.0, replaced by {@link #unlock(String, String,
363             *             String)}
364             */
365            @MasterDataSource
366            @Override
367            @Transactional(propagation = Propagation.REQUIRES_NEW)
368            public void unlock(
369                            String className, String key, String owner,
370                            boolean retrieveFromCache)
371                    throws SystemException {
372    
373                    unlock(className, key, owner);
374            }
375    
376            protected void expireLock(Lock lock) throws SystemException {
377                    LockListener lockListener = LockListenerRegistryUtil.getLockListener(
378                            lock.getClassName());
379    
380                    String key = lock.getKey();
381    
382                    if (lockListener != null) {
383                            lockListener.onBeforeExpire(key);
384                    }
385    
386                    try {
387                            lockPersistence.remove(lock);
388                    }
389                    finally {
390                            if (lockListener != null) {
391                                    lockListener.onAfterExpire(key);
392                            }
393                    }
394            }
395    
396            protected Lock fetchLock(String className, String key)
397                    throws SystemException {
398    
399                    Lock lock = lockPersistence.fetchByC_K(className, key);
400    
401                    if (lock != null) {
402                            if (lock.isExpired()) {
403                                    expireLock(lock);
404    
405                                    lock = null;
406                            }
407                    }
408    
409                    return lock;
410            }
411    
412    }