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.notifications;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    
020    import java.util.ArrayList;
021    import java.util.List;
022    import java.util.concurrent.locks.Lock;
023    import java.util.concurrent.locks.ReentrantLock;
024    
025    /**
026     * @author Edward Han
027     */
028    public abstract class BaseChannelImpl implements Channel {
029    
030            @Override
031            public void cleanUp() throws ChannelException {
032                    lock.lock();
033    
034                    try {
035                            long currentTime = System.currentTimeMillis();
036    
037                            if (currentTime > _nextCleanUpTime) {
038                                    _nextCleanUpTime = currentTime + _cleanUpInterval;
039    
040                                    try {
041                                            doCleanUp();
042                                    }
043                                    catch (ChannelException ce) {
044                                            throw ce;
045                                    }
046                                    catch (Exception e) {
047                                            throw new ChannelException(e);
048                                    }
049                            }
050                    }
051                    finally {
052                            lock.unlock();
053                    }
054            }
055    
056            @Override
057            public void close() throws ChannelException {
058                    flush();
059            }
060    
061            public long getCompanyId() {
062                    return _companyId;
063            }
064    
065            @Override
066            public List<NotificationEvent> getNotificationEvents()
067                    throws ChannelException {
068    
069                    return getNotificationEvents(true);
070            }
071    
072            @Override
073            public long getUserId() {
074                    return _userId;
075            }
076    
077            public boolean hasNotificationEvents() {
078                    try {
079                            List<NotificationEvent> notificationEvents = getNotificationEvents(
080                                    false);
081    
082                            if (!notificationEvents.isEmpty()) {
083                                    return true;
084                            }
085                    }
086                    catch (ChannelException ce) {
087                            if (_log.isErrorEnabled()) {
088                                    _log.error("Unable to fetch notifications", ce);
089                            }
090                    }
091    
092                    return false;
093            }
094    
095            @Override
096            public void registerChannelListener(ChannelListener channelListener) {
097                    lock.lock();
098    
099                    try {
100                            List<ChannelListener> channelListeners = _getChannelListeners();
101    
102                            channelListeners.add(channelListener);
103    
104                            if (hasNotificationEvents()) {
105                                    notifyChannelListeners();
106                            }
107                    }
108                    finally {
109                            lock.unlock();
110                    }
111            }
112    
113            public void setCleanUpInterval(long cleanUpInterval) {
114                    _cleanUpInterval = cleanUpInterval;
115            }
116    
117            @Override
118            public void unregisterChannelListener(ChannelListener channelListener) {
119                    lock.lock();
120    
121                    try {
122                            List<ChannelListener> channelListeners = _getChannelListeners();
123    
124                            channelListeners.remove(channelListener);
125                    }
126                    finally {
127                            lock.unlock();
128                    }
129    
130                    channelListener.channelListenerRemoved(_userId);
131            }
132    
133            protected BaseChannelImpl(long companyId, long usedId) {
134                    _companyId = companyId;
135                    _userId = usedId;
136            }
137    
138            protected abstract void doCleanUp() throws Exception;
139    
140            protected void notifyChannelListeners() {
141                    for (ChannelListener channelListener : _getChannelListeners()) {
142                            channelListener.notificationEventsAvailable(_userId);
143                    }
144            }
145    
146            protected final Lock lock = new ReentrantLock();
147    
148            private List<ChannelListener> _getChannelListeners() {
149                    if (_channelListeners == null) {
150                            _channelListeners = new ArrayList<>();
151                    }
152    
153                    return _channelListeners;
154            }
155    
156            private static final Log _log = LogFactoryUtil.getLog(
157                    BaseChannelImpl.class);
158    
159            private List<ChannelListener> _channelListeners;
160            private long _cleanUpInterval;
161            private final long _companyId;
162            private long _nextCleanUpTime;
163            private final long _userId;
164    
165    }