1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.tomgibara.pronto.config.source;
19
20 import java.util.Map;
21
22 import com.tomgibara.pronto.config.ConfigSource;
23 import com.tomgibara.pronto.util.Arguments;
24
25 /**
26 * Instances of this class wrap other ConfigSource instances and cache the
27 * values they return.
28 *
29 * Instances of this class are not safe for concurrent use, even if the
30 * underlying ConfigSource is. Wrap instances in a SynchronousConfigSource if
31 * thread safety is required.
32 *
33 * @author Tom Gibara
34 */
35
36 public class CachingConfigSource implements ConfigSource {
37
38
39
40 /** The length of time for which properties will be cached. */
41 private long ttl;
42
43 /** The underlying config source which provides the cached properties. */
44 private final ConfigSource source;
45
46 /** The time in milliseconds at which the properties were last refreshed. */
47 private long lastRead = -1L;
48
49 /** The cached modification time. */
50 private long lastModified;
51
52 /** The cached properties. */
53 private Map<String, String> properties;
54
55
56
57 /**
58 * Creates new a source which caches responses from another ConfigSource.
59 *
60 * @param source
61 * the configuration source to be cached, not null
62 * @param ttl
63 * the length time for which values may be cached without being
64 * refresed, not negative
65 */
66
67 public CachingConfigSource(final ConfigSource source, final long ttl) {
68 Arguments.notNull(source, "source");
69 Arguments.notNegative(ttl, "ttl");
70 this.source = source;
71 this.ttl = ttl;
72 }
73
74
75
76 /**
77 * Changes the length time for which values may be cached without being
78 * refreshed.
79 *
80 * @param ttl
81 * changes the time-to-live value, not negative
82 */
83
84 public void setTTL(final long ttl) {
85 Arguments.notNegative(ttl, "ttl");
86 this.ttl = ttl;
87 }
88
89 /**
90 * The length time for which values may be cached without being refreshed.
91 *
92 * @return the time-to-live value, not negative
93 */
94
95 public long getTTL() {
96 return ttl;
97 }
98
99 /**
100 * Returns the ConfigSource which is being cached by this object.
101 *
102 * @return the cached config source, never null
103 */
104
105 public ConfigSource getSource() {
106 return source;
107 }
108
109
110
111 /**
112 * Return the cached lastModified field from the underlying ConfigSource.
113 *
114 * @throws RuntimeException
115 * if the field could not be read
116 *
117 * @return the cached lastModified time
118 */
119
120 public long lastModified() throws RuntimeException {
121 update();
122 return lastModified;
123 }
124
125 /**
126 * Return the cached properties field from the underlying ConfigSource.
127 *
128 * @throws RuntimeException
129 * if the field could not be read
130 *
131 * @return the cached properties
132 */
133
134 public Map<String, String> getProperties() throws RuntimeException {
135 update();
136 return properties;
137 }
138
139
140
141 private void update() {
142 long now = System.currentTimeMillis();
143 if (lastRead < 0L || now - lastRead > ttl) {
144 lastRead = now;
145 lastModified = source.lastModified();
146 properties = source.getProperties();
147 }
148 }
149
150 }