001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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                                    lock = null;
157                            }
158                            else if (lock.getUserId() != userId) {
159                                    throw new DuplicateLockException(lock);
160                            }
161                    }
162    
163                    if (lock == null) {
164                            User user = userPersistence.findByPrimaryKey(userId);
165    
166                            long lockId = counterLocalService.increment();
167    
168                            lock = lockPersistence.create(lockId);
169    
170                            lock.setCompanyId(user.getCompanyId());
171                            lock.setUserId(user.getUserId());
172                            lock.setUserName(user.getFullName());
173                            lock.setClassName(className);
174                            lock.setKey(key);
175                            lock.setOwner(owner);
176                            lock.setInheritable(inheritable);
177                    }
178    
179                    lock.setCreateDate(now);
180    
181                    if (expirationTime == 0) {
182                            lock.setExpirationDate(null);
183                    }
184                    else {
185                            lock.setExpirationDate(new Date(now.getTime() + expirationTime));
186                    }
187    
188                    lockPersistence.update(lock);
189    
190                    return lock;
191            }
192    
193            @MasterDataSource
194            @Override
195            @Transactional(propagation = Propagation.REQUIRES_NEW)
196            public Lock lock(String className, String key, String owner)
197                    throws SystemException {
198    
199                    return lock(className, key, null, owner);
200            }
201    
202            /**
203             * @deprecated As of 6.2.0, replaced by {@link #lock(String, String,
204             *             String)}
205             */
206            @MasterDataSource
207            @Override
208            @Transactional(propagation = Propagation.REQUIRES_NEW)
209            public Lock lock(
210                            String className, String key, String owner,
211                            boolean retrieveFromCache)
212                    throws SystemException {
213    
214                    return lock(className, key, null, owner);
215            }
216    
217            @MasterDataSource
218            @Override
219            @Transactional(propagation = Propagation.REQUIRES_NEW)
220            public Lock lock(
221                            String className, String key, String expectedOwner,
222                            String updatedOwner)
223                    throws SystemException {
224    
225                    Lock lock = lockFinder.fetchByC_K(className, key, LockMode.UPGRADE);
226    
227                    if (lock == null) {
228                            long lockId = counterLocalService.increment();
229    
230                            lock = lockPersistence.create(lockId);
231    
232                            lock.setCreateDate(new Date());
233                            lock.setClassName(className);
234                            lock.setKey(key);
235                            lock.setOwner(updatedOwner);
236    
237                            lockPersistence.update(lock);
238    
239                            lock.setNew(true);
240    
241                            lockPersistence.flush();
242                    }
243                    else if (Validator.equals(lock.getOwner(), expectedOwner)) {
244                            lock.setCreateDate(new Date());
245                            lock.setClassName(className);
246                            lock.setKey(key);
247                            lock.setOwner(updatedOwner);
248    
249                            lockPersistence.update(lock);
250    
251                            lock.setNew(true);
252    
253                            lockPersistence.flush();
254                    }
255    
256                    return lock;
257            }
258    
259            /**
260             * @deprecated As of 6.2.0, replaced by {@link #lock(String, String, String,
261             *             String)}
262             */
263            @MasterDataSource
264            @Override
265            @Transactional(propagation = Propagation.REQUIRES_NEW)
266            public Lock lock(
267                            String className, String key, String expectedOwner,
268                            String updatedOwner, boolean retrieveFromCache)
269                    throws SystemException {
270    
271                    return lock(className, key, expectedOwner, updatedOwner);
272            }
273    
274            @Override
275            public Lock refresh(String uuid, long companyId, long expirationTime)
276                    throws PortalException, SystemException {
277    
278                    Date now = new Date();
279    
280                    List<Lock> locks = lockPersistence.findByUuid_C(uuid, companyId);
281    
282                    if (locks.isEmpty()) {
283                            StringBundler sb = new StringBundler(5);
284    
285                            sb.append("{uuid=");
286                            sb.append(uuid);
287                            sb.append(", companyId=");
288                            sb.append(companyId);
289                            sb.append("}");
290    
291                            throw new NoSuchLockException(sb.toString());
292                    }
293    
294                    Lock lock = locks.get(0);
295    
296                    LockListener lockListener = LockListenerRegistryUtil.getLockListener(
297                            lock.getClassName());
298    
299                    String key = lock.getKey();
300    
301                    if (lockListener != null) {
302                            lockListener.onBeforeRefresh(key);
303                    }
304    
305                    try {
306                            lock.setCreateDate(now);
307    
308                            if (expirationTime == 0) {
309                                    lock.setExpirationDate(null);
310                            }
311                            else {
312                                    lock.setExpirationDate(
313                                            new Date(now.getTime() + expirationTime));
314                            }
315    
316                            lockPersistence.update(lock);
317    
318                            return lock;
319                    }
320                    finally {
321                            if (lockListener != null) {
322                                    lockListener.onAfterRefresh(key);
323                            }
324                    }
325            }
326    
327            @Override
328            public void unlock(String className, long key) throws SystemException {
329                    unlock(className, String.valueOf(key));
330            }
331    
332            @Override
333            public void unlock(String className, String key) throws SystemException {
334                    try {
335                            lockPersistence.removeByC_K(className, key);
336                    }
337                    catch (NoSuchLockException nsle) {
338                    }
339            }
340    
341            @MasterDataSource
342            @Override
343            @Transactional(propagation = Propagation.REQUIRES_NEW)
344            public void unlock(String className, String key, String owner)
345                    throws SystemException {
346    
347                    Lock lock = lockFinder.fetchByC_K(className, key, LockMode.UPGRADE);
348    
349                    if (lock == null) {
350                            return;
351                    }
352    
353                    if (Validator.equals(lock.getOwner(), owner)) {
354                            lockPersistence.remove(lock);
355                            lockPersistence.flush();
356                    }
357            }
358    
359            /**
360             * @deprecated As of 6.2.0, replaced by {@link #unlock(String, String,
361             *             String)}
362             */
363            @MasterDataSource
364            @Override
365            @Transactional(propagation = Propagation.REQUIRES_NEW)
366            public void unlock(
367                            String className, String key, String owner,
368                            boolean retrieveFromCache)
369                    throws SystemException {
370    
371                    unlock(className, key, owner);
372            }
373    
374            protected void expireLock(Lock lock) throws SystemException {
375                    LockListener lockListener = LockListenerRegistryUtil.getLockListener(
376                            lock.getClassName());
377    
378                    String key = lock.getKey();
379    
380                    if (lockListener != null) {
381                            lockListener.onBeforeExpire(key);
382                    }
383    
384                    try {
385                            lockPersistence.remove(lock);
386                    }
387                    finally {
388                            if (lockListener != null) {
389                                    lockListener.onAfterExpire(key);
390                            }
391                    }
392            }
393    
394            protected Lock fetchLock(String className, String key)
395                    throws SystemException {
396    
397                    Lock lock = lockPersistence.fetchByC_K(className, key);
398    
399                    if (lock != null) {
400                            if (lock.isExpired()) {
401                                    expireLock(lock);
402    
403                                    lock = null;
404                            }
405                    }
406    
407                    return lock;
408            }
409    
410    }