<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Kommentare zu: ReloadablePropertiesFactoryBean: Beware of Caching</title>
	<atom:link href="http://www.wuenschenswert.net/wunschdenken/archives/153/feed" rel="self" type="application/rss+xml" />
	<link>http://www.wuenschenswert.net/wunschdenken/archives/153</link>
	<description></description>
	<pubDate>Tue, 07 Feb 2012 16:18:50 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>Von: axel</title>
		<link>http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4304</link>
		<dc:creator>axel</dc:creator>
		<pubDate>Thu, 14 Oct 2010 21:03:06 +0000</pubDate>
		<guid isPermaLink="false">http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4304</guid>
		<description>Thanks for the contribution, again! 

I've finally come around to pushing the code to github, where it should live more easily:  

http://github.com/axeolotl/SpringPropertiesReloaded

A github pull request is a smaller obstacle than fighting wordpress XML filtering, I hope.

In the initial commit I've added a pom. The pom uses maven central dependencies instead of Enterprise Bundle Repository, for the simple reason that I didn't have the repository URL at hand.  What do you think, should it be EBR?</description>
		<content:encoded><![CDATA[<p>Thanks for the contribution, again! </p>
<p>I&#8217;ve finally come around to pushing the code to github, where it should live more easily:  </p>
<p><a href="http://github.com/axeolotl/SpringPropertiesReloaded" rel="nofollow">http://github.com/axeolotl/SpringPropertiesReloaded</a></p>
<p>A github pull request is a smaller obstacle than fighting wordpress XML filtering, I hope.</p>
<p>In the initial commit I&#8217;ve added a pom. The pom uses maven central dependencies instead of Enterprise Bundle Repository, for the simple reason that I didn&#8217;t have the repository URL at hand.  What do you think, should it be EBR?</p>
]]></content:encoded>
	</item>
	<item>
		<title>Von: Lrkwz</title>
		<link>http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4303</link>
		<dc:creator>Lrkwz</dc:creator>
		<pubDate>Tue, 12 Oct 2010 20:52:31 +0000</pubDate>
		<guid isPermaLink="false">http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4303</guid>
		<description>Sorry wordpress removed the &#60; &gr;

&#60;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&#62;
	&#60;modelVersion&#62;4.0.0&#60;/modelVersion&#62;
	&#60;groupId&#62;net.wuenschenswert&#60;/groupId&#62;
	&#60;artifactId&#62;spring-reloaded&#60;/artifactId&#62;
	&#60;version&#62;0.0.1-SNAPSHOT&#60;/version&#62;
	&#60;dependencies&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.springframework&#60;/groupId&#62;
			&#60;artifactId&#62;org.springframework.core&#60;/artifactId&#62;
			&#60;version&#62;${spring.version}&#60;/version&#62;
		&#60;/dependency&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.springframework&#60;/groupId&#62;
			&#60;artifactId&#62;org.springframework.context&#60;/artifactId&#62;
			&#60;version&#62;${spring.version}&#60;/version&#62;
		&#60;/dependency&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.slf4j&#60;/groupId&#62;
			&#60;artifactId&#62;com.springsource.slf4j.log4j&#60;/artifactId&#62;
			&#60;version&#62;${slf4j.version}&#60;/version&#62;
		&#60;/dependency&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.slf4j&#60;/groupId&#62;
			&#60;artifactId&#62;com.springsource.slf4j.api&#60;/artifactId&#62;
			&#60;version&#62;${slf4j.version}&#60;/version&#62;
		&#60;/dependency&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.apache.commons&#60;/groupId&#62;
			&#60;artifactId&#62;com.springsource.org.apache.commons.logging&#60;/artifactId&#62;
			&#60;version&#62;1.1.1&#60;/version&#62;
		&#60;/dependency&#62;
		&#60;dependency&#62;
			&#60;groupId&#62;org.junit&#60;/groupId&#62;
			&#60;artifactId&#62;com.springsource.org.junit&#60;/artifactId&#62;
			&#60;version&#62;4.8.1&#60;/version&#62;
			&#60;scope&#62;test&#60;/scope&#62;
		&#60;/dependency&#62;
	&#60;/dependencies&#62;
	&#60;build&#62;
		&#60;plugins&#62;
			&#60;plugin&#62;
				&#60;groupId&#62;org.apache.maven.plugins&#60;/groupId&#62;
				&#60;artifactId&#62;maven-compiler-plugin&#60;/artifactId&#62;
				&#60;version&#62;2.3.1&#60;/version&#62;
				&#60;configuration&#62;
					&#60;source&#62;${java.source.version}&#60;/source&#62;
					&#60;target&#62;${java.target.version}&#60;/target&#62;
				&#60;/configuration&#62;
			&#60;/plugin&#62;
		&#60;/plugins&#62;
	&#60;/build&#62;
	&#60;properties&#62;
		&#60;java.source.version&#62;1.6&#60;/java.source.version&#62;
		&#60;java.target.version&#62;1.6&#60;/java.target.version&#62;
		&#60;spring.version&#62;3.0.2.RELEASE&#60;/spring.version&#62;
		&#60;slf4j.version&#62;1.5.10&#60;/slf4j.version&#62;
	&#60;/properties&#62;
&#60;/project&#62;</description>
		<content:encoded><![CDATA[<p>Sorry wordpress removed the &lt; &gr;</p>
<p>&lt;project xmlns=&#8221;http://maven.apache.org/POM/4.0.0&#8243; xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221; xsi:schemaLocation=&#8221;http://maven.apache.org/POM/4.0.0 <a href="http://maven.apache.org/maven-v4_0_0.xsd" rel="nofollow">http://maven.apache.org/maven-v4_0_0.xsd</a>&#8220;&gt;<br />
	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;<br />
	&lt;groupId&gt;net.wuenschenswert&lt;/groupId&gt;<br />
	&lt;artifactId&gt;spring-reloaded&lt;/artifactId&gt;<br />
	&lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;<br />
	&lt;dependencies&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.springframework&lt;/groupId&gt;<br />
			&lt;artifactId&gt;org.springframework.core&lt;/artifactId&gt;<br />
			&lt;version&gt;${spring.version}&lt;/version&gt;<br />
		&lt;/dependency&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.springframework&lt;/groupId&gt;<br />
			&lt;artifactId&gt;org.springframework.context&lt;/artifactId&gt;<br />
			&lt;version&gt;${spring.version}&lt;/version&gt;<br />
		&lt;/dependency&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.slf4j&lt;/groupId&gt;<br />
			&lt;artifactId&gt;com.springsource.slf4j.log4j&lt;/artifactId&gt;<br />
			&lt;version&gt;${slf4j.version}&lt;/version&gt;<br />
		&lt;/dependency&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.slf4j&lt;/groupId&gt;<br />
			&lt;artifactId&gt;com.springsource.slf4j.api&lt;/artifactId&gt;<br />
			&lt;version&gt;${slf4j.version}&lt;/version&gt;<br />
		&lt;/dependency&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.apache.commons&lt;/groupId&gt;<br />
			&lt;artifactId&gt;com.springsource.org.apache.commons.logging&lt;/artifactId&gt;<br />
			&lt;version&gt;1.1.1&lt;/version&gt;<br />
		&lt;/dependency&gt;<br />
		&lt;dependency&gt;<br />
			&lt;groupId&gt;org.junit&lt;/groupId&gt;<br />
			&lt;artifactId&gt;com.springsource.org.junit&lt;/artifactId&gt;<br />
			&lt;version&gt;4.8.1&lt;/version&gt;<br />
			&lt;scope&gt;test&lt;/scope&gt;<br />
		&lt;/dependency&gt;<br />
	&lt;/dependencies&gt;<br />
	&lt;build&gt;<br />
		&lt;plugins&gt;<br />
			&lt;plugin&gt;<br />
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
				&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;<br />
				&lt;version&gt;2.3.1&lt;/version&gt;<br />
				&lt;configuration&gt;<br />
					&lt;source&gt;${java.source.version}&lt;/source&gt;<br />
					&lt;target&gt;${java.target.version}&lt;/target&gt;<br />
				&lt;/configuration&gt;<br />
			&lt;/plugin&gt;<br />
		&lt;/plugins&gt;<br />
	&lt;/build&gt;<br />
	&lt;properties&gt;<br />
		&lt;java.source.version&gt;1.6&lt;/java.source.version&gt;<br />
		&lt;java.target.version&gt;1.6&lt;/java.target.version&gt;<br />
		&lt;spring.version&gt;3.0.2.RELEASE&lt;/spring.version&gt;<br />
		&lt;slf4j.version&gt;1.5.10&lt;/slf4j.version&gt;<br />
	&lt;/properties&gt;<br />
&lt;/project&gt;</p>
]]></content:encoded>
	</item>
	<item>
		<title>Von: Lrkwz</title>
		<link>http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4302</link>
		<dc:creator>Lrkwz</dc:creator>
		<pubDate>Tue, 12 Oct 2010 20:50:44 +0000</pubDate>
		<guid isPermaLink="false">http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4302</guid>
		<description>I've assembled a minimal mavenized version for your jar just move code in the standard maven file system structure (src/main/java, src/test/java and be sure to move config.properties and dynamic.xml into src/test/resources/net/wu.../spring/example, test1.xml into src/test/resources/net/wu.../spring/).

This is the pom.xml file


	4.0.0
	net.wuenschenswert
	spring-reloaded
	0.0.1-SNAPSHOT
	
		
			org.springframework
			org.springframework.core
			${spring.version}
		
		
			org.springframework
			org.springframework.context
			${spring.version}
		
		
			org.slf4j
			com.springsource.slf4j.log4j
			${slf4j.version}
		
		
			org.slf4j
			com.springsource.slf4j.api
			${slf4j.version}
		
		
			org.apache.commons
			com.springsource.org.apache.commons.logging
			1.1.1
		
		
			org.junit
			com.springsource.org.junit
			4.8.1
			test
		
	
	
		
			
				org.apache.maven.plugins
				maven-compiler-plugin
				2.3.1
				
					${java.source.version}
					${java.target.version}
				
			
		
	
	
		1.6
		1.6
		3.0.2.RELEASE
		1.5.10
	
</description>
		<content:encoded><![CDATA[<p>I&#8217;ve assembled a minimal mavenized version for your jar just move code in the standard maven file system structure (src/main/java, src/test/java and be sure to move config.properties and dynamic.xml into src/test/resources/net/wu&#8230;/spring/example, test1.xml into src/test/resources/net/wu&#8230;/spring/).</p>
<p>This is the pom.xml file</p>
<p>	4.0.0<br />
	net.wuenschenswert<br />
	spring-reloaded<br />
	0.0.1-SNAPSHOT</p>
<p>			org.springframework<br />
			org.springframework.core<br />
			${spring.version}</p>
<p>			org.springframework<br />
			org.springframework.context<br />
			${spring.version}</p>
<p>			org.slf4j<br />
			com.springsource.slf4j.log4j<br />
			${slf4j.version}</p>
<p>			org.slf4j<br />
			com.springsource.slf4j.api<br />
			${slf4j.version}</p>
<p>			org.apache.commons<br />
			com.springsource.org.apache.commons.logging<br />
			1.1.1</p>
<p>			org.junit<br />
			com.springsource.org.junit<br />
			4.8.1<br />
			test</p>
<p>				org.apache.maven.plugins<br />
				maven-compiler-plugin<br />
				2.3.1</p>
<p>					${java.source.version}<br />
					${java.target.version}</p>
<p>		1.6<br />
		1.6<br />
		3.0.2.RELEASE<br />
		1.5.10</p>
]]></content:encoded>
	</item>
	<item>
		<title>Von: axel</title>
		<link>http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4289</link>
		<dc:creator>axel</dc:creator>
		<pubDate>Mon, 22 Mar 2010 20:44:06 +0000</pubDate>
		<guid isPermaLink="false">http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4289</guid>
		<description>Thanks alot for the contribution! I'm currently annoyingly busy with work not even related to programming, but it's becoming obvious to me that this piece of code merits revived attention.

And I'll definitely have to get my head around a proper place to host a piece of code - wordpress clearly isn't.  Will keep you posted.</description>
		<content:encoded><![CDATA[<p>Thanks alot for the contribution! I&#8217;m currently annoyingly busy with work not even related to programming, but it&#8217;s becoming obvious to me that this piece of code merits revived attention.</p>
<p>And I&#8217;ll definitely have to get my head around a proper place to host a piece of code - wordpress clearly isn&#8217;t.  Will keep you posted.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Von: Dag Framstad</title>
		<link>http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4286</link>
		<dc:creator>Dag Framstad</dc:creator>
		<pubDate>Mon, 22 Mar 2010 19:20:19 +0000</pubDate>
		<guid isPermaLink="false">http://www.wuenschenswert.net/wunschdenken/archives/153#comment-4286</guid>
		<description>Chris Gilbert proposed a fix for Spring 3.0 in http://www.wuenschenswert.net/wunschdenken/archives/138#comments.
I could not get his fix to work, so here are my changes to the code from 31.08.2007 (+ some other changes) that passes my unit tests. I have not yet converted to Spring 3.0, so there could be errors that my unit tests don't detect.
I have modified this code several times including formatting in Eclipse, so I post the complete class, not a diff.

ReloadablePropertiesFactoryBean.java:
&lt;pre&gt;
package net.wuenschenswert.spring;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderSupport;
import org.springframework.util.DefaultPropertiesPersister;
import org.springframework.util.PropertiesPersister;

/**
 * A properties factory bean that creates a reconfigurable Properties object.
 * When the Properties' reloadConfiguration method is called, and the file has
 * changed, the properties are read again from the file.
 */
public class ReloadablePropertiesFactoryBean extends PropertiesLoaderSupport
		implements DisposableBean, FactoryBean&#60;ReconfigurableBean&gt;, InitializingBean {

	private Logger log = Logger.getLogger(getClass());

	// add missing getter for locations

	private Resource[] locations;

	private long[] lastModified;
	
	private boolean ignoreResourceNotFound = false;
	
	private String fileEncoding;
	
	private boolean singleton;
		
	private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();

	private List&#60;ReloadablePropertiesListener&gt; preListeners;
	
	public ReloadablePropertiesFactoryBean() {
		singleton = true;
	}
	
	@Override
	public void setLocation(Resource location) {
		setLocations(new Resource[] { location });
	}

	@Override
	public void setLocations(Resource[] locations) {
		if(locations != null) {
			this.locations = locations.clone();
			lastModified = new long[locations.length];
			super.setLocations(locations);
		}
	}

	protected Resource[] getLocations() {
		return locations;
	}

	public void setListeners(List listeners) {
		// early type check, and avoid aliassing
		this.preListeners = new ArrayList&#60;ReloadablePropertiesListener&gt;();
		for (Object o : listeners) {
			preListeners.add((ReloadablePropertiesListener) o);
		}
	}
	
	  @Override
	public void setFileEncoding(String encoding) {
		this.fileEncoding = encoding;
		super.setFileEncoding(encoding);
	}

	@Override
	public void setPropertiesPersister(PropertiesPersister propertiesPersister) {
		this.propertiesPersister = (propertiesPersister != null ? propertiesPersister
				: new DefaultPropertiesPersister());
		super.setPropertiesPersister(this.propertiesPersister);
	}

	@Override
	public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) {
		this.ignoreResourceNotFound = ignoreResourceNotFound;
		super.setIgnoreResourceNotFound(ignoreResourceNotFound);
	}

	private ReloadablePropertiesImpl reloadableProperties;

	private ReloadablePropertiesImpl createInstance() throws IOException {
		// would like to uninherit from AbstractFactoryBean (but it's final!)
		
		if (!isSingleton()) {
			throw new RuntimeException(
					"ReloadablePropertiesFactoryBean only works as singleton");
		}
		ReloadablePropertiesImpl reloadableProperties = new ReloadablePropertiesImpl();
		if (preListeners != null) {
			reloadableProperties.setListeners(preListeners);
		}
		return reloadableProperties;
	}

	public void destroy(){
		reloadableProperties = null;
	}

	protected void reload(boolean forceReload) throws IOException {
		boolean reload = forceReload;
		for (int i = 0; i &#60; locations.length; i++) {
			Resource location = locations[i];
			File file;
			try {
				file = location.getFile();
			} catch (IOException e) {
				// not a file resource
				continue;
			}
			try {
				long l = file.lastModified();
				if (l &gt; lastModified[i]) {
					lastModified[i] = l;
					reload = true;
				}
			} catch (Exception e) {
				// cannot access file. assume unchanged.
				if (log.isDebugEnabled()) {
					log.debug("can't determine modification time of " + file
							+ " for " + location, e);
				}
			}
		}
		if (reload) {
			doReload();			
		}
	}

	private void doReload() throws IOException {
		reloadableProperties.setProperties(mergeProperties());
	}

	  /**
		 * Load properties into the given instance. Overridden to use
		 * {@link Resource#getFile} instead of {@link Resource#getInputStream},
		 * as the latter may be have undesirable caching effects on a
		 * ServletContextResource.
		 * 
		 * @param props
		 *            the Properties instance to load into
		 * @throws java.io.IOException
		 *             in case of I/O errors
		 * @see #setLocations
		 */
	@Override
	protected void loadProperties(Properties props) throws IOException {
		if (this.locations != null) {
			for (int i = 0; i &#60; this.locations.length; i++) {
				Resource location = this.locations[i];
				if (logger.isInfoEnabled()) {
					logger.info("Loading properties file from " + location);
				}
				InputStream is = null;
				try {
					File file = null;
					try {
						file = location.getFile();
					} catch (IOException e) {
						logger.warn(
								"Not a file resource, may not be able to reload: "
										+ location, e);
					}
					if (file != null){
						is = new FileInputStream(file);
					}
						
					else {
						is = location.getInputStream();
					}
						
					if (location.getFilename().endsWith(XML_FILE_EXTENSION)) {
						this.propertiesPersister.loadFromXml(props, is);
					} else {
						if (this.fileEncoding != null) {
							this.propertiesPersister
									.load(props, new InputStreamReader(is,
											this.fileEncoding));
						} else {
							this.propertiesPersister.load(props, is);
						}
					}
				} catch (IOException ex) {
					if (this.ignoreResourceNotFound) {
						if (logger.isWarnEnabled()) {
							logger.warn("Could not load properties from "
									+ location + ": " + ex.getMessage());
						}
					} else {
						throw ex;
					}
				} finally {
					IOUtils.closeQuietly(is);
				}
			}
		}
	}

	class ReloadablePropertiesImpl extends ReloadablePropertiesBase implements
			ReconfigurableBean {

		private static final long serialVersionUID = 8997200726392650775L;

		public void reloadConfiguration() throws IOException {
			ReloadablePropertiesFactoryBean.this.reload(false);
		}
	}

	public ReconfigurableBean getObject() throws Exception {
		ReconfigurableBean object = singleton ? reloadableProperties : createInstance();
		reload(true);
		return object;

	}

	public Class&#60;? extends ReconfigurableBean&gt; getObjectType() {
		return ReconfigurableBean.class;
	}

	public boolean isSingleton() {
		return singleton;
	}

	public void setSingleton(boolean singleton) {
		this.singleton = singleton;
	}

	public void afterPropertiesSet() throws Exception {
		if(singleton)
            reloadableProperties = createInstance();
	}

}
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>Chris Gilbert proposed a fix for Spring 3.0 in <a href="http://www.wuenschenswert.net/wunschdenken/archives/138#comments" rel="nofollow">http://www.wuenschenswert.net/wunschdenken/archives/138#comments</a>.<br />
I could not get his fix to work, so here are my changes to the code from 31.08.2007 (+ some other changes) that passes my unit tests. I have not yet converted to Spring 3.0, so there could be errors that my unit tests don&#8217;t detect.<br />
I have modified this code several times including formatting in Eclipse, so I post the complete class, not a diff.</p>
<p>ReloadablePropertiesFactoryBean.java:</p>
<pre>
package net.wuenschenswert.spring;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderSupport;
import org.springframework.util.DefaultPropertiesPersister;
import org.springframework.util.PropertiesPersister;

/**
 * A properties factory bean that creates a reconfigurable Properties object.
 * When the Properties' reloadConfiguration method is called, and the file has
 * changed, the properties are read again from the file.
 */
public class ReloadablePropertiesFactoryBean extends PropertiesLoaderSupport
		implements DisposableBean, FactoryBean&lt;ReconfigurableBean>, InitializingBean {

	private Logger log = Logger.getLogger(getClass());

	// add missing getter for locations

	private Resource[] locations;

	private long[] lastModified;

	private boolean ignoreResourceNotFound = false;

	private String fileEncoding;

	private boolean singleton;

	private PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();

	private List&lt;ReloadablePropertiesListener> preListeners;

	public ReloadablePropertiesFactoryBean() {
		singleton = true;
	}

	@Override
	public void setLocation(Resource location) {
		setLocations(new Resource[] { location });
	}

	@Override
	public void setLocations(Resource[] locations) {
		if(locations != null) {
			this.locations = locations.clone();
			lastModified = new long[locations.length];
			super.setLocations(locations);
		}
	}

	protected Resource[] getLocations() {
		return locations;
	}

	public void setListeners(List listeners) {
		// early type check, and avoid aliassing
		this.preListeners = new ArrayList&lt;ReloadablePropertiesListener>();
		for (Object o : listeners) {
			preListeners.add((ReloadablePropertiesListener) o);
		}
	}

	  @Override
	public void setFileEncoding(String encoding) {
		this.fileEncoding = encoding;
		super.setFileEncoding(encoding);
	}

	@Override
	public void setPropertiesPersister(PropertiesPersister propertiesPersister) {
		this.propertiesPersister = (propertiesPersister != null ? propertiesPersister
				: new DefaultPropertiesPersister());
		super.setPropertiesPersister(this.propertiesPersister);
	}

	@Override
	public void setIgnoreResourceNotFound(boolean ignoreResourceNotFound) {
		this.ignoreResourceNotFound = ignoreResourceNotFound;
		super.setIgnoreResourceNotFound(ignoreResourceNotFound);
	}

	private ReloadablePropertiesImpl reloadableProperties;

	private ReloadablePropertiesImpl createInstance() throws IOException {
		// would like to uninherit from AbstractFactoryBean (but it&#8217;s final!)

		if (!isSingleton()) {
			throw new RuntimeException(
					&#8220;ReloadablePropertiesFactoryBean only works as singleton&#8221;);
		}
		ReloadablePropertiesImpl reloadableProperties = new ReloadablePropertiesImpl();
		if (preListeners != null) {
			reloadableProperties.setListeners(preListeners);
		}
		return reloadableProperties;
	}

	public void destroy(){
		reloadableProperties = null;
	}

	protected void reload(boolean forceReload) throws IOException {
		boolean reload = forceReload;
		for (int i = 0; i &lt; locations.length; i++) {
			Resource location = locations[i];
			File file;
			try {
				file = location.getFile();
			} catch (IOException e) {
				// not a file resource
				continue;
			}
			try {
				long l = file.lastModified();
				if (l > lastModified[i]) {
					lastModified[i] = l;
					reload = true;
				}
			} catch (Exception e) {
				// cannot access file. assume unchanged.
				if (log.isDebugEnabled()) {
					log.debug(&#8221;can&#8217;t determine modification time of &#8221; + file
							+ &#8221; for &#8221; + location, e);
				}
			}
		}
		if (reload) {
			doReload();
		}
	}

	private void doReload() throws IOException {
		reloadableProperties.setProperties(mergeProperties());
	}

	  /**
		 * Load properties into the given instance. Overridden to use
		 * {@link Resource#getFile} instead of {@link Resource#getInputStream},
		 * as the latter may be have undesirable caching effects on a
		 * ServletContextResource.
		 *
		 * @param props
		 *            the Properties instance to load into
		 * @throws java.io.IOException
		 *             in case of I/O errors
		 * @see #setLocations
		 */
	@Override
	protected void loadProperties(Properties props) throws IOException {
		if (this.locations != null) {
			for (int i = 0; i &lt; this.locations.length; i++) {
				Resource location = this.locations[i];
				if (logger.isInfoEnabled()) {
					logger.info(&#8221;Loading properties file from &#8221; + location);
				}
				InputStream is = null;
				try {
					File file = null;
					try {
						file = location.getFile();
					} catch (IOException e) {
						logger.warn(
								&#8220;Not a file resource, may not be able to reload: &#8221;
										+ location, e);
					}
					if (file != null){
						is = new FileInputStream(file);
					}

					else {
						is = location.getInputStream();
					}

					if (location.getFilename().endsWith(XML_FILE_EXTENSION)) {
						this.propertiesPersister.loadFromXml(props, is);
					} else {
						if (this.fileEncoding != null) {
							this.propertiesPersister
									.load(props, new InputStreamReader(is,
											this.fileEncoding));
						} else {
							this.propertiesPersister.load(props, is);
						}
					}
				} catch (IOException ex) {
					if (this.ignoreResourceNotFound) {
						if (logger.isWarnEnabled()) {
							logger.warn(&#8221;Could not load properties from &#8221;
									+ location + &#8220;: &#8221; + ex.getMessage());
						}
					} else {
						throw ex;
					}
				} finally {
					IOUtils.closeQuietly(is);
				}
			}
		}
	}

	class ReloadablePropertiesImpl extends ReloadablePropertiesBase implements
			ReconfigurableBean {

		private static final long serialVersionUID = 8997200726392650775L;

		public void reloadConfiguration() throws IOException {
			ReloadablePropertiesFactoryBean.this.reload(false);
		}
	}

	public ReconfigurableBean getObject() throws Exception {
		ReconfigurableBean object = singleton ? reloadableProperties : createInstance();
		reload(true);
		return object;

	}

	public Class&lt;? extends ReconfigurableBean> getObjectType() {
		return ReconfigurableBean.class;
	}

	public boolean isSingleton() {
		return singleton;
	}

	public void setSingleton(boolean singleton) {
		this.singleton = singleton;
	}

	public void afterPropertiesSet() throws Exception {
		if(singleton)
            reloadableProperties = createInstance();
	}

}
</pre>
]]></content:encoded>
	</item>
</channel>
</rss>

