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