View Javadoc

1   /*
2    * Copyright (C) 2006  Tom Gibara
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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      // fields
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      // constructors
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      // accessors
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     // config methods
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     // private utility methods
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 }