1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.common.cache;
21
22 import java.io.IOException;
23 import java.time.Instant;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map.Entry;
30 import java.util.Set;
31 import java.util.SortedMap;
32 import java.util.TreeMap;
33
34
35
36
37
38 public class MemoryReplayCache implements ReplayCache {
39
40 public static final long DEFAULT_TTL = 60L * 5L;
41 public static final long MAX_TTL = DEFAULT_TTL * 12L;
42 private final SortedMap<Instant, List<String>> cache = new TreeMap<>();
43 private final Set<String> ids = Collections.synchronizedSet(new HashSet<>());
44
45
46
47
48
49 public void add(String identifier) {
50 add(identifier, Instant.now().plusSeconds(DEFAULT_TTL));
51 }
52
53
54
55
56
57
58 public void add(String identifier, Instant expiry) {
59 if (identifier == null || identifier.length() == 0) {
60 return;
61 }
62
63 Instant now = Instant.now();
64 Instant maxTTL = now.plusSeconds(MAX_TTL);
65 if (expiry == null || expiry.isBefore(now) || expiry.isAfter(maxTTL)) {
66 expiry = now.plusSeconds(DEFAULT_TTL);
67 }
68
69 synchronized (cache) {
70 List<String> list = cache.get(expiry);
71 if (list == null) {
72 list = new ArrayList<>(1);
73 cache.put(expiry, list);
74 }
75 list.add(identifier);
76 }
77 ids.add(identifier);
78 }
79
80
81
82
83
84 public boolean contains(String identifier) {
85 processTokenExpiry();
86
87 if (identifier != null && identifier.length() != 0) {
88 return ids.contains(identifier);
89 }
90 return false;
91 }
92
93 protected void processTokenExpiry() {
94 Instant current = Instant.now();
95 synchronized (cache) {
96 Iterator<Entry<Instant, List<String>>> it = cache.entrySet().iterator();
97 while (it.hasNext()) {
98 Entry<Instant, List<String>> entry = it.next();
99 if (entry.getKey().isBefore(current)) {
100 for (String id : entry.getValue()) {
101 ids.remove(id);
102 }
103 it.remove();
104 } else {
105 break;
106 }
107 }
108 }
109 }
110
111 @Override
112 public synchronized void close() throws IOException {
113 cache.clear();
114 ids.clear();
115 }
116 }