org/sonews/util/TimeoutMap.java
author cli
Sat, 01 May 2010 18:51:57 +0200
changeset 29 60c237bb677a
parent 1 6fceb66e1ad7
permissions -rw-r--r--
Refactor logging to fix NullPointerException.
     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 
    39   private int                    timeout     = 60000; // 60 sec
    40   private transient Map<K, Long> timeoutMap  = new HashMap<K, Long>();
    41   
    42   /**
    43    * Constructor.
    44    * @param timeout Timeout in milliseconds
    45    */
    46   public TimeoutMap(final int timeout)
    47   {
    48     this.timeout = timeout;
    49   }
    50   
    51   /**
    52    * Uses default timeout (60 sec).
    53    */
    54   public TimeoutMap()
    55   {
    56   }
    57   
    58   /**
    59    * 
    60    * @param key
    61    * @return true if key is still valid.
    62    */
    63   protected boolean checkTimeOut(Object key)
    64   {
    65     synchronized(this.timeoutMap)
    66     {
    67       if(this.timeoutMap.containsKey(key))
    68       {
    69         long keytime = this.timeoutMap.get(key);
    70         if((System.currentTimeMillis() - keytime) < this.timeout)
    71         {
    72           return true;
    73         }
    74         else
    75         {
    76           remove(key);
    77           return false;
    78         }
    79       }
    80       else
    81       {
    82         return false;
    83       }
    84     }
    85   }
    86   
    87   @Override
    88   public boolean containsKey(Object key)
    89   {
    90     return checkTimeOut(key);
    91   }
    92 
    93   @Override
    94   public synchronized V get(Object key)
    95   {
    96     if(checkTimeOut(key))
    97     {
    98       return super.get(key);
    99     }
   100     else
   101     {
   102       return null;
   103     }
   104   }
   105 
   106   @Override
   107   public V put(K key, V value)
   108   {
   109     synchronized(this.timeoutMap)
   110     {
   111       removeStaleKeys();
   112       this.timeoutMap.put(key, System.currentTimeMillis());
   113       return super.put(key, value);
   114     }
   115   }
   116 
   117   /**
   118    * @param arg0
   119    * @return
   120    */
   121   @Override
   122   public V remove(Object arg0)
   123   {
   124     synchronized(this.timeoutMap)
   125     {
   126       this.timeoutMap.remove(arg0);
   127       V val = super.remove(arg0);
   128       return val;
   129     }
   130   }
   131 
   132   protected void removeStaleKeys()
   133   {
   134     synchronized(this.timeoutMap)
   135     {
   136       Set<Object> keySet = new HashSet<Object>(this.timeoutMap.keySet());
   137       for(Object key : keySet)
   138       {
   139         // The key/value is removed by the checkTimeOut() method if true
   140         checkTimeOut(key);
   141       }
   142     }
   143   }
   144   
   145 }