src/org/sonews/util/TimeoutMap.java
author František Kučera <franta-hg@frantovo.cz>
Tue Oct 25 10:39:57 2011 +0200 (2011-10-25)
changeset 108 fdc075324ef3
parent 35 ed84c8bdd87b
permissions -rwxr-xr-x
SMTP: correct escaping of messages containing lines with single dot.
chris@1
     1
/*
chris@1
     2
 *   SONEWS News Server
chris@1
     3
 *   see AUTHORS for the list of contributors
chris@1
     4
 *
chris@1
     5
 *   This program is free software: you can redistribute it and/or modify
chris@1
     6
 *   it under the terms of the GNU General Public License as published by
chris@1
     7
 *   the Free Software Foundation, either version 3 of the License, or
chris@1
     8
 *   (at your option) any later version.
chris@1
     9
 *
chris@1
    10
 *   This program is distributed in the hope that it will be useful,
chris@1
    11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@1
    12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
chris@1
    13
 *   GNU General Public License for more details.
chris@1
    14
 *
chris@1
    15
 *   You should have received a copy of the GNU General Public License
chris@1
    16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
chris@1
    17
 */
chris@1
    18
chris@1
    19
package org.sonews.util;
chris@1
    20
chris@1
    21
import java.util.HashMap;
chris@1
    22
import java.util.HashSet;
chris@1
    23
import java.util.Map;
chris@1
    24
import java.util.Set;
chris@1
    25
import java.util.concurrent.ConcurrentHashMap;
chris@1
    26
chris@1
    27
/**
chris@1
    28
 * Implementation of a Map that will loose its stored values after a 
chris@1
    29
 * configurable amount of time.
chris@1
    30
 * This class may be used to cache config values for example.
chris@1
    31
 * @author Christian Lins
chris@1
    32
 * @since sonews/0.5.0
chris@1
    33
 */
cli@37
    34
public class TimeoutMap<K, V> extends ConcurrentHashMap<K, V>
chris@1
    35
{
chris@1
    36
cli@37
    37
	private static final long serialVersionUID = 453453467700345L;
cli@37
    38
	private int timeout = 60000; // 60 sec
cli@37
    39
	private transient Map<K, Long> timeoutMap = new HashMap<K, Long>();
chris@1
    40
cli@37
    41
	/**
cli@37
    42
	 * Constructor.
cli@37
    43
	 * @param timeout Timeout in milliseconds
cli@37
    44
	 */
cli@37
    45
	public TimeoutMap(final int timeout)
cli@37
    46
	{
cli@37
    47
		this.timeout = timeout;
cli@37
    48
	}
chris@1
    49
cli@37
    50
	/**
cli@37
    51
	 * Uses default timeout (60 sec).
cli@37
    52
	 */
cli@37
    53
	public TimeoutMap()
cli@37
    54
	{
cli@37
    55
	}
chris@1
    56
cli@37
    57
	/**
cli@37
    58
	 *
cli@37
    59
	 * @param key
cli@37
    60
	 * @return true if key is still valid.
cli@37
    61
	 */
cli@37
    62
	protected boolean checkTimeOut(Object key)
cli@37
    63
	{
cli@37
    64
		synchronized (this.timeoutMap) {
cli@37
    65
			if (this.timeoutMap.containsKey(key)) {
cli@37
    66
				long keytime = this.timeoutMap.get(key);
cli@37
    67
				if ((System.currentTimeMillis() - keytime) < this.timeout) {
cli@37
    68
					return true;
cli@37
    69
				} else {
cli@37
    70
					remove(key);
cli@37
    71
					return false;
cli@37
    72
				}
cli@37
    73
			} else {
cli@37
    74
				return false;
cli@37
    75
			}
cli@37
    76
		}
cli@37
    77
	}
chris@1
    78
cli@37
    79
	@Override
cli@37
    80
	public boolean containsKey(Object key)
cli@37
    81
	{
cli@37
    82
		return checkTimeOut(key);
cli@37
    83
	}
cli@37
    84
cli@37
    85
	@Override
cli@37
    86
	public synchronized V get(Object key)
cli@37
    87
	{
cli@37
    88
		if (checkTimeOut(key)) {
cli@37
    89
			return super.get(key);
cli@37
    90
		} else {
cli@37
    91
			return null;
cli@37
    92
		}
cli@37
    93
	}
cli@37
    94
cli@37
    95
	@Override
cli@37
    96
	public V put(K key, V value)
cli@37
    97
	{
cli@37
    98
		synchronized (this.timeoutMap) {
cli@37
    99
			removeStaleKeys();
cli@37
   100
			this.timeoutMap.put(key, System.currentTimeMillis());
cli@37
   101
			return super.put(key, value);
cli@37
   102
		}
cli@37
   103
	}
cli@37
   104
cli@37
   105
	/**
cli@37
   106
	 * @param arg0
cli@37
   107
	 * @return
cli@37
   108
	 */
cli@37
   109
	@Override
cli@37
   110
	public V remove(Object arg0)
cli@37
   111
	{
cli@37
   112
		synchronized (this.timeoutMap) {
cli@37
   113
			this.timeoutMap.remove(arg0);
cli@37
   114
			V val = super.remove(arg0);
cli@37
   115
			return val;
cli@37
   116
		}
cli@37
   117
	}
cli@37
   118
cli@37
   119
	protected void removeStaleKeys()
cli@37
   120
	{
cli@37
   121
		synchronized (this.timeoutMap) {
cli@37
   122
			Set<Object> keySet = new HashSet<Object>(this.timeoutMap.keySet());
cli@37
   123
			for (Object key : keySet) {
cli@37
   124
				// The key/value is removed by the checkTimeOut() method if true
cli@37
   125
				checkTimeOut(key);
cli@37
   126
			}
cli@37
   127
		}
cli@37
   128
	}
chris@1
   129
}