rsanchez
2015-01-28 da889d489da5d7fa8c71d9f21f24b1dc2e29d8e1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package net.curisit.securis.utils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
 * Cache implementation with TTL (time To Live) The objects are removed from
 * cache when TTL is reached.
 * 
 * @author roberto <roberto.sanchez@curisit.net>
 */
@ApplicationScoped
public class CacheTTL {
    private static final Logger LOG = LogManager.getLogger(CacheTTL.class);
    /**
     * Period before token expires, set in seconds.
     */
    private static int DEFAULT_CACHE_DURATION = 24 * 60 * 60;
    private Map<String, CachedObject> data = new HashMap<>();
    private Thread cleaningThread = null;
    @Inject
    public CacheTTL() {
        cleaningThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (CacheTTL.this.data != null) {
                    try {
                        // We check for expired object every 60 seconds
                        Thread.sleep(60 * 1000);
                    } catch (InterruptedException e) {
                        LOG.error("Exiting from Cache Thread");
                        data.clear();
                        return;
                    }
                    Date now = new Date();
                    List<String> keysToRemove = new ArrayList<>();
                    for (String key : CacheTTL.this.data.keySet()) {
                        CachedObject co = CacheTTL.this.data.get(key);
                        if (now.after(co.getExpireAt())) {
                            keysToRemove.add(key);
                        }
                    }
                    for (String key : keysToRemove) {
                        // If we try to remove directly in the previous loop an
                        // exception is thrown
                        // java.util.ConcurrentModificationException
                        CacheTTL.this.data.remove(key);
                    }
                }
            }
        });
        cleaningThread.start();
    }
    /**
     * 
     * @param key
     * @param obj
     * @param ttl
     *            Time To Live in seconds
     */
    public void set(String key, Object obj, int ttl) {
        Date expirationDate = new Date(new Date().getTime() + ttl * 1000);
        data.put(key, new CachedObject(expirationDate, obj));
    }
    public void set(String key, Object obj) {
        set(key, obj, DEFAULT_CACHE_DURATION);
    }
    public Object get(String key) {
        CachedObject co = data.get(key);
        return co == null ? null : co.getObject();
    }
    public <T> T get(String key, Class<T> type) {
        CachedObject co = data.get(key);
        return co == null ? null : co.getObject(type);
    }
    public <T> T remove(String key, Class<T> type) {
        CachedObject co = data.remove(key);
        return co == null ? null : co.getObject(type);
    }
    public Object remove(String key) {
        CachedObject co = data.remove(key);
        return co == null ? null : co.getObject();
    }
    public void clear() {
        data.clear();
    }
    private class CachedObject {
        Date expireAt;
        Object object;
        public CachedObject(Date date, Object obj) {
            expireAt = date;
            object = obj;
        }
        public Date getExpireAt() {
            return expireAt;
        }
        public Object getObject() {
            return object;
        }
        @SuppressWarnings("unchecked")
        public <T> T getObject(Class<T> type) {
            return (T) object;
        }
    }
}