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: 606798 $, $Date: 2007-12-25 20:05:58 +0100 (Di, 25 Dez 2007) $ 042 * @since 1.1 043 */ 044 public class FileChangedReloadingStrategy implements ReloadingStrategy 045 { 046 /** Constant for the jar URL protocol.*/ 047 private static final String JAR_PROTOCOL = "jar"; 048 049 /** Constant for the default refresh delay.*/ 050 private static final int DEFAULT_REFRESH_DELAY = 5000; 051 052 /** Stores a reference to the configuration to be monitored.*/ 053 protected FileConfiguration configuration; 054 055 /** The last time the configuration file was modified. */ 056 protected long lastModified; 057 058 /** The last time the file was checked for changes. */ 059 protected long lastChecked; 060 061 /** The minimum delay in milliseconds between checks. */ 062 protected long refreshDelay = DEFAULT_REFRESH_DELAY; 063 064 /** A flag whether a reload is required.*/ 065 private boolean reloading; 066 067 public void setConfiguration(FileConfiguration configuration) 068 { 069 this.configuration = configuration; 070 } 071 072 public void init() 073 { 074 updateLastModified(); 075 } 076 077 public boolean reloadingRequired() 078 { 079 if (!reloading) 080 { 081 long now = System.currentTimeMillis(); 082 083 if (now > lastChecked + refreshDelay) 084 { 085 lastChecked = now; 086 if (hasChanged()) 087 { 088 reloading = true; 089 } 090 } 091 } 092 093 return reloading; 094 } 095 096 public void reloadingPerformed() 097 { 098 updateLastModified(); 099 } 100 101 /** 102 * Return the minimal time in milliseconds between two reloadings. 103 * 104 * @return the refresh delay (in milliseconds) 105 */ 106 public long getRefreshDelay() 107 { 108 return refreshDelay; 109 } 110 111 /** 112 * Set the minimal time between two reloadings. 113 * 114 * @param refreshDelay refresh delay in milliseconds 115 */ 116 public void setRefreshDelay(long refreshDelay) 117 { 118 this.refreshDelay = refreshDelay; 119 } 120 121 /** 122 * Update the last modified time. 123 */ 124 protected void updateLastModified() 125 { 126 File file = getFile(); 127 if (file != null) 128 { 129 lastModified = file.lastModified(); 130 } 131 reloading = false; 132 } 133 134 /** 135 * Check if the configuration has changed since the last time it was loaded. 136 * 137 * @return a flag whether the configuration has changed 138 */ 139 protected boolean hasChanged() 140 { 141 File file = getFile(); 142 if (file == null || !file.exists()) 143 { 144 return false; 145 } 146 147 return file.lastModified() > lastModified; 148 } 149 150 /** 151 * Returns the file that is monitored by this strategy. Note that the return 152 * value can be <b>null </b> under some circumstances. 153 * 154 * @return the monitored file 155 */ 156 protected File getFile() 157 { 158 return (configuration.getURL() != null) ? fileFromURL(configuration 159 .getURL()) : configuration.getFile(); 160 } 161 162 /** 163 * Helper method for transforming a URL into a file object. This method 164 * handles file: and jar: URLs. 165 * 166 * @param url the URL to be converted 167 * @return the resulting file or <b>null </b> 168 */ 169 private File fileFromURL(URL url) 170 { 171 if (JAR_PROTOCOL.equals(url.getProtocol())) 172 { 173 String path = url.getPath(); 174 try 175 { 176 return ConfigurationUtils.fileFromURL(new URL(path.substring(0, 177 path.indexOf('!')))); 178 } 179 catch (MalformedURLException mex) 180 { 181 return null; 182 } 183 } 184 else 185 { 186 return ConfigurationUtils.fileFromURL(url); 187 } 188 } 189 }