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