001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.configuration.reloading;
019:
020: import java.io.File;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023:
024: import org.apache.commons.configuration.ConfigurationUtils;
025: import org.apache.commons.configuration.FileConfiguration;
026:
027: /**
028: * <p>A reloading strategy that will reload the configuration every time its
029: * underlying file is changed.</p>
030: * <p>This reloading strategy does not actively monitor a configuration file,
031: * but is triggered by its associated configuration whenever properties are
032: * accessed. It then checks the configuration file's last modification date
033: * and causes a reload if this has changed.</p>
034: * <p>To avoid permanent disc access on successive property lookups a refresh
035: * delay can be specified. This has the effect that the configuration file's
036: * last modification date is only checked once in this delay period. The default
037: * value for this refresh delay is 5 seconds.</p>
038: * <p>This strategy only works with FileConfiguration instances.</p>
039: *
040: * @author Emmanuel Bourg
041: * @version $Revision: 439648 $, $Date: 2006-09-02 22:42:10 +0200 (Sa, 02 Sep 2006) $
042: * @since 1.1
043: */
044: public class FileChangedReloadingStrategy implements ReloadingStrategy {
045: /** Constant for the jar URL protocol.*/
046: private static final String JAR_PROTOCOL = "jar";
047:
048: /** Constant for the default refresh delay.*/
049: private static final int DEFAULT_REFRESH_DELAY = 5000;
050:
051: /** Stores a reference to the configuration to be monitored.*/
052: protected FileConfiguration configuration;
053:
054: /** The last time the configuration file was modified. */
055: protected long lastModified;
056:
057: /** The last time the file was checked for changes. */
058: protected long lastChecked;
059:
060: /** The minimum delay in milliseconds between checks. */
061: protected long refreshDelay = DEFAULT_REFRESH_DELAY;
062:
063: public void setConfiguration(FileConfiguration configuration) {
064: this .configuration = configuration;
065: }
066:
067: public void init() {
068: updateLastModified();
069: }
070:
071: public boolean reloadingRequired() {
072: boolean reloading = false;
073:
074: long now = System.currentTimeMillis();
075:
076: if (now > lastChecked + refreshDelay) {
077: lastChecked = now;
078: if (hasChanged()) {
079: reloading = true;
080: }
081: }
082:
083: return reloading;
084: }
085:
086: public void reloadingPerformed() {
087: updateLastModified();
088: }
089:
090: /**
091: * Return the minimal time in milliseconds between two reloadings.
092: *
093: * @return the refresh delay (in milliseconds)
094: */
095: public long getRefreshDelay() {
096: return refreshDelay;
097: }
098:
099: /**
100: * Set the minimal time between two reloadings.
101: *
102: * @param refreshDelay refresh delay in milliseconds
103: */
104: public void setRefreshDelay(long refreshDelay) {
105: this .refreshDelay = refreshDelay;
106: }
107:
108: /**
109: * Update the last modified time.
110: */
111: protected void updateLastModified() {
112: File file = getFile();
113: if (file != null) {
114: lastModified = file.lastModified();
115: }
116: }
117:
118: /**
119: * Check if the configuration has changed since the last time it was loaded.
120: *
121: * @return a flag whether the configuration has changed
122: */
123: protected boolean hasChanged() {
124: File file = getFile();
125: if (file == null || !file.exists()) {
126: return false;
127: }
128:
129: return file.lastModified() > lastModified;
130: }
131:
132: /**
133: * Returns the file that is monitored by this strategy. Note that the return
134: * value can be <b>null </b> under some circumstances.
135: *
136: * @return the monitored file
137: */
138: protected File getFile() {
139: return (configuration.getURL() != null) ? fileFromURL(configuration
140: .getURL())
141: : configuration.getFile();
142: }
143:
144: /**
145: * Helper method for transforming a URL into a file object. This method
146: * handles file: and jar: URLs.
147: *
148: * @param url the URL to be converted
149: * @return the resulting file or <b>null </b>
150: */
151: private File fileFromURL(URL url) {
152: if (JAR_PROTOCOL.equals(url.getProtocol())) {
153: String path = url.getPath();
154: try {
155: return ConfigurationUtils.fileFromURL(new URL(path
156: .substring(0, path.indexOf('!'))));
157: } catch (MalformedURLException mex) {
158: return null;
159: }
160: } else {
161: return ConfigurationUtils.fileFromURL(url);
162: }
163: }
164: }
|