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.kernel.lock;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.model.Lock;
021    import com.liferay.portal.service.LockLocalServiceUtil;
022    
023    import java.util.Date;
024    
025    /**
026     * @author Zsolt Berentey
027     */
028    public class LockProtectedAction<T> {
029    
030            public LockProtectedAction(
031                    Class<?> clazz, String lockKey, long timeout, long retryDelay) {
032    
033                    _className = clazz.getName();
034                    _lockKey = lockKey;
035                    _timeout = timeout;
036                    _retryDelay = retryDelay;
037            }
038    
039            public T getReturnValue() {
040                    return _returnValue;
041            }
042    
043            public void performAction() throws PortalException {
044                    Lock lock = null;
045    
046                    while (true) {
047                            try {
048                                    lock = LockLocalServiceUtil.lock(
049                                            _className, _lockKey, _lockKey);
050                            }
051                            catch (Exception e) {
052                                    if (_log.isWarnEnabled()) {
053                                            _log.warn("Unable to acquire lock. Retrying.");
054                                    }
055    
056                                    continue;
057                            }
058    
059                            if (lock.isNew()) {
060                                    try {
061                                            _returnValue = performProtectedAction();
062                                    }
063                                    finally {
064                                            LockLocalServiceUtil.unlock(_className, _lockKey, _lockKey);
065                                    }
066    
067                                    break;
068                            }
069    
070                            Date createDate = lock.getCreateDate();
071    
072                            if ((System.currentTimeMillis() - createDate.getTime()) >=
073                                            _timeout) {
074    
075                                    LockLocalServiceUtil.unlock(
076                                            _className, _lockKey, lock.getOwner());
077    
078                                    if (_log.isWarnEnabled()) {
079                                            _log.warn("Removed lock " + lock + " due to timeout");
080                                    }
081                            }
082                            else {
083                                    try {
084                                            Thread.sleep(_retryDelay);
085                                    }
086                                    catch (InterruptedException ie) {
087                                            if (_log.isWarnEnabled()) {
088                                                    _log.warn(
089                                                            "Interrupted while waiting to reacquire lock", ie);
090                                            }
091                                    }
092                            }
093                    }
094            }
095    
096            @SuppressWarnings("unused")
097            protected T performProtectedAction() throws PortalException {
098                    return null;
099            }
100    
101            private static final Log _log = LogFactoryUtil.getLog(
102                    LockProtectedAction.class);
103    
104            private final String _className;
105            private final String _lockKey;
106            private final long _retryDelay;
107            private T _returnValue;
108            private final long _timeout;
109    
110    }