1111import org .apache .commons .configuration .CompositeConfiguration ;
1212import org .apache .commons .configuration .Configuration ;
1313import org .apache .commons .configuration .MapConfiguration ;
14+ import org .apache .commons .lang .StringUtils ;
1415
1516/**
1617 * The Config class is the central access point to the configuration mechanism, and is used to read or modify the
3435 * <li><code>bordertech-local.properties</code> - local developer properties</li>
3536 * </ul>
3637 *
38+ * <p>
39+ * A touchfile can be set via the parameter <code>bordertech.config.touchfile</code>. The touchfile is checked when
40+ * {@link #getInstance()} is called. To avoid excessive IO an interval (in milli seconds) between checks can be set via
41+ * <code>bordertech.config.touchfile.interval</code> and defaults to <code>10000</code>.
42+ * </p>
43+ *
3744 * @author Joshua Barclay
3845 * @author Jonathan Austin
3946 * @since 1.0.0
47+ *
48+ * @see DefaultConfiguration
49+ * @see InitHelper
50+ * @see ConfigurationLoader
4051 */
4152public final class Config {
4253
4354 /**
44- * The current configuration .
55+ * Used to lock the config .
4556 */
46- private static Configuration configuration = loadConfiguration ();
57+ private static final Object LOCK = new Object ();
4758
4859 /**
4960 * Contains the complete set of property change listeners that have registered with this class.
5061 */
5162 private static final Set <PropertyChangeListener > PROPERTY_CHANGE_LISTENERS = new HashSet <>();
5263
64+ /**
65+ * The current configuration.
66+ */
67+ private static Configuration configuration ;
68+
69+ /**
70+ * Touchfile (if configured).
71+ */
72+ private static Touchfile touchfile ;
73+
74+ static {
75+ loadConfiguration ();
76+ }
77+
5378 /**
5479 * Prevent instantiation of this utility class.
5580 */
@@ -60,16 +85,41 @@ private Config() {
6085 * @return the current configuration.
6186 */
6287 public static Configuration getInstance () {
88+ // If a touchfile has been set, check if it has changed and reload if necessary
89+ if (touchfile != null ) {
90+ synchronized (LOCK ) {
91+ if (touchfile .hasChanged ()) {
92+ loadConfiguration ();
93+ }
94+ }
95+ }
6396 return configuration ;
6497 }
6598
6699 /**
67100 * Resets the configuration back to the default internal configuration. All configuration changes which have been
68101 * made will be lost. This method is primarily intended for unit testing.
69102 */
70- public static synchronized void reset () {
71- configuration = loadConfiguration ();
72- notifyListeners ();
103+ public static void reset () {
104+ synchronized (LOCK ) {
105+ loadConfiguration ();
106+ }
107+ }
108+
109+ /**
110+ * <p>
111+ * Sets the current configuration.</p>
112+ * <p>
113+ * <b>Warning: </b> this will ignore any defined ConfigurationLoaders</p>
114+ *
115+ * @param configuration the configuration to set.
116+ */
117+ public static void setConfiguration (final Configuration configuration ) {
118+ synchronized (LOCK ) {
119+ Config .configuration = configuration ;
120+ configTouchfile ();
121+ notifyListeners ();
122+ }
73123 }
74124
75125 /**
@@ -79,7 +129,7 @@ public static synchronized void reset() {
79129 * @return a copy of the given configuration.
80130 */
81131 public static Configuration copyConfiguration (final Configuration original ) {
82- Configuration copy = new MapConfiguration (new HashMap <String , Object >());
132+ Configuration copy = new MapConfiguration (new HashMap <>());
83133
84134 for (Iterator <?> i = original .getKeys (); i .hasNext ();) {
85135 String key = (String ) i .next ();
@@ -91,23 +141,9 @@ public static Configuration copyConfiguration(final Configuration original) {
91141
92142 copy .setProperty (key , value );
93143 }
94-
95144 return copy ;
96145 }
97146
98- /**
99- * <p>
100- * Sets the current configuration.</p>
101- * <p>
102- * <b>Warning: </b> this will ignore any defined ConfigurationLoaders</p>
103- *
104- * @param configuration the configuration to set.
105- */
106- public static synchronized void setConfiguration (final Configuration configuration ) {
107- Config .configuration = configuration ;
108- notifyListeners ();
109- }
110-
111147 /**
112148 * This method notifies all the {@link PropertyChangeListener}s that have registered with this object that a change
113149 * has occurred.
@@ -147,11 +183,42 @@ public static void addPropertyChangeListener(final PropertyChangeListener listen
147183 }
148184
149185 /**
150- * @return the configuration to use .
186+ * Load the configuration.
151187 */
152- private static synchronized Configuration loadConfiguration () {
188+ private static void loadConfiguration () {
153189 Configuration config = checkSLIConfiguration ();
154- return config == null ? getDefaultConfiguration () : config ;
190+ if (config == null ) {
191+ config = getDefaultConfiguration ();
192+ }
193+ Config .configuration = config ;
194+ configTouchfile ();
195+ notifyListeners ();
196+ }
197+
198+ /**
199+ * Configure the touchfile (if provided).
200+ */
201+ private static void configTouchfile () {
202+ String file = getTouchFileName ();
203+ if (StringUtils .isEmpty (file )) {
204+ touchfile = null ;
205+ } else {
206+ touchfile = new Touchfile (file , getTouchFileInterval ());
207+ }
208+ }
209+
210+ /**
211+ * @return the touch file name
212+ */
213+ private static String getTouchFileName () {
214+ return configuration .getString ("bordertech.config.touchfile" );
215+ }
216+
217+ /**
218+ * @return the touch file interval (in milli seconds)
219+ */
220+ private static long getTouchFileInterval () {
221+ return configuration .getLong ("bordertech.config.touchfile.interval" , 10000 );
155222 }
156223
157224 /**
@@ -170,7 +237,7 @@ private static Configuration checkSLIConfiguration() {
170237
171238 // Use a CompositeConfiguration if there are custom ConfigurationLoader implementations.
172239 if (iterator .hasNext ()) {
173- CompositeConfiguration compositeConfig = new CompositeConfiguration (new MapConfiguration (new HashMap <String , Object >()));
240+ CompositeConfiguration compositeConfig = new CompositeConfiguration (new MapConfiguration (new HashMap <>()));
174241 while (iterator .hasNext ()) {
175242 compositeConfig .addConfiguration (iterator .next ().getConfiguration ());
176243 }
0 commit comments