org.agnitas.util.TimeoutLRUMap.java Source code

Java tutorial

Introduction

Here is the source code for org.agnitas.util.TimeoutLRUMap.java

Source

/*********************************************************************************
 * The contents of this file are subject to the Common Public Attribution
 * License Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.openemm.org/cpal1.html. The License is based on the Mozilla
 * Public License Version 1.1 but Sections 14 and 15 have been added to cover
 * use of software over a computer network and provide for limited attribution
 * for the Original Developer. In addition, Exhibit A has been modified to be
 * consistent with Exhibit B.
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 * 
 * The Original Code is OpenEMM.
 * The Original Developer is the Initial Developer.
 * The Initial Developer of the Original Code is AGNITAS AG. All portions of
 * the code written by AGNITAS AG are Copyright (c) 2007 AGNITAS AG. All Rights
 * Reserved.
 * 
 * Contributor(s): AGNITAS AG. 
 ********************************************************************************/

package org.agnitas.util;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.map.LRUMap;

/**
 * 
 * @author mhe
 */
public class TimeoutLRUMap<K, V> implements java.io.Serializable {
    private static final long serialVersionUID = -1755144418309829988L;

    /**
     * Holds value of property timeout.
     */
    private long timeoutInMillis;

    private LRUMap internalMap;

    /**
     * Creates a new instance of TimeoutLRUMap
     */
    public TimeoutLRUMap() {
        timeoutInMillis = 5000; // Milliseconds
        internalMap = new LRUMap(1000);
    }

    /**
     * Creates a new instance of TimeoutLRUMap
     * 
     * @param capacity
     * @param to
     */
    public TimeoutLRUMap(int capacity, long timeoutInMillis) {
        setTimeout(timeoutInMillis);
        internalMap = new LRUMap(capacity);
    }

    /**
     * Saves a key with value and default timeout period
     */
    public synchronized K put(K key, V value) {
        return put(key, value, timeoutInMillis);
    }

    /**
     * Saves a key with value and explicit timeout period
     */
    public synchronized K put(K key, V value, long validityPeriod) {
        if (!internalMap.containsKey(key)) {
            TimeoutObject aObject = new TimeoutObject();
            aObject.object = value;
            aObject.validUtil = System.currentTimeMillis() + validityPeriod;
            internalMap.put(key, aObject);
        }
        return key;
    }

    /**
     * Gets the value from a key
     */
    public synchronized V get(Object key) {
        @SuppressWarnings("unchecked")
        TimeoutObject timeoutObject = (TimeoutObject) internalMap.get(key);
        if (timeoutObject != null) {
            if (System.currentTimeMillis() < timeoutObject.validUtil) {
                return timeoutObject.object;
            } else {
                internalMap.remove(key);
            }
        }
        return null;
    }

    /**
     * Removes unused objects.
     */
    public synchronized int cleanupGarbage() {
        int removedCount = 0;
        long time = System.currentTimeMillis();

        // Watch out, because every get() may change the internalMap.
        // Therefore we store the keys in a separate list and iterate that, instead of iterating over the keyset.
        @SuppressWarnings("unchecked")
        List<String> keyList = new ArrayList<String>(internalMap.keySet());

        for (String key : keyList) {
            @SuppressWarnings("unchecked")
            TimeoutObject aObject = (TimeoutObject) internalMap.get(key);
            if (time >= aObject.validUtil) {
                internalMap.remove(key);
                removedCount++;
            }
        }

        return removedCount;
    }

    /**
     * Getter for property timeout.
     * 
     * @return Value of property timeout.
     * 
     */
    public long getTimeout() {
        return timeoutInMillis;
    }

    /**
     * Setter for property timeout.
     * 
     * @param timeout
     *            New value of property timeout.
     */
    public void setTimeout(long timeoutInMillis) {
        this.timeoutInMillis = timeoutInMillis;
    }

    public synchronized int size() {
        return internalMap.size();
    }

    private class TimeoutObject {
        public V object;
        public long validUtil;
    }
}