/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.common;
/**
* This class is usefull, if the stored object of derived classes has to be cached. After reaching expireTime during a request, the method
* refresh will be called.
* @author Kai Reinhard (k.reinhard@micromata.de)
*/
public abstract class AbstractCache
{
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(AbstractCache.class);
public static final long TICKS_PER_SECOND = 1000;
public static final long TICKS_PER_MINUTE = TICKS_PER_SECOND * 60;
public static final long TICKS_PER_HOUR = TICKS_PER_MINUTE * 60;
protected long expireTime = 60 * TICKS_PER_MINUTE;
private transient long timeOfLastRefresh = -1;
private transient boolean isExpired = true;
private transient boolean refreshInProgress = false;
protected AbstractCache()
{
}
protected AbstractCache(final long expireTime)
{
this.expireTime = expireTime;
}
public void setExpireTimeInMinutes(final long expireTime)
{
this.expireTime = expireTime * TICKS_PER_MINUTE;
}
public void setExpireTimeInSeconds(final long expireTime)
{
this.expireTime = expireTime * TICKS_PER_SECOND;
}
public void setExpireTimeInHours(final long expireTime)
{
this.expireTime = expireTime * TICKS_PER_HOUR;
}
/**
* Cache will be refreshed before next use.
*/
public void setExpired()
{
this.isExpired = true;
}
/**
* Sets the cache to expired and calls checkRefresh, which forces refresh.
*/
public void forceReload()
{
setExpired();
checkRefresh();
}
/**
* Checks the expire time and calls refresh, if cache is expired.
*/
protected synchronized void checkRefresh()
{
if (refreshInProgress == true) {
// Do nothing because refreshing is already in progress.
return;
}
if (this.isExpired == true || System.currentTimeMillis() - this.timeOfLastRefresh > this.expireTime) {
try {
refreshInProgress = true;
this.timeOfLastRefresh = System.currentTimeMillis();
try {
this.refresh();
} catch (final Throwable ex) {
log.error(ex.getMessage(), ex);
}
this.isExpired = false;
} finally {
refreshInProgress = false;
}
}
}
/**
* @return true if currently a cache refresh is running, otherwise false.
*/
public boolean isRefreshInProgress()
{
return refreshInProgress;
}
/**
* Please implement this method refreshing the stored object _data. Do not forget to call checkRefresh in your cache methods.
* @see #checkRefresh()
*/
protected abstract void refresh();
}