diff --git a/opennms-base-assembly/src/main/filtered/etc/opennms.properties b/opennms-base-assembly/src/main/filtered/etc/opennms.properties index 5031f73..be41c26 100644 --- a/opennms-base-assembly/src/main/filtered/etc/opennms.properties +++ b/opennms-base-assembly/src/main/filtered/etc/opennms.properties @@ -116,6 +116,13 @@ rrd.binary=${install.rrdtool.bin} # Collectd Instrumentation class # org.opennms.collectd.instrumentationClass=org.opennms.netmgt.collectd.DefaultCollectInstrumentation +# Enable an aggresive validation against the last modification time of the strings.properties files. +# This is useful only if the OpenNMS WebUI is running on a different server. +# Check NMS-5806 for more details. +# +# Default: false +#org.opennms.utils.propertiesCache.enableCheckFileModified=false + ###### REMOTE METHOD INVOCATION ###### # Though this is not strictly an OpenNMS property this is a setting that you # may need to set if you are using the distributed monitor either via webstart diff --git a/opennms-dao/src/test/java/org/opennms/netmgt/dao/support/ResourceTypeUtilsTest.java b/opennms-dao/src/test/java/org/opennms/netmgt/dao/support/ResourceTypeUtilsTest.java index e344357..690c844 100644 --- a/opennms-dao/src/test/java/org/opennms/netmgt/dao/support/ResourceTypeUtilsTest.java +++ b/opennms-dao/src/test/java/org/opennms/netmgt/dao/support/ResourceTypeUtilsTest.java @@ -28,14 +28,23 @@ package org.opennms.netmgt.dao.support; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; import java.io.IOException; import java.util.HashSet; import java.util.Properties; import java.util.Set; -import junit.framework.TestCase; - +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.opennms.core.utils.PropertiesCache; import org.opennms.netmgt.model.OnmsAttribute; import org.opennms.netmgt.model.OnmsResource; import org.opennms.netmgt.model.RrdGraphAttribute; @@ -45,27 +54,26 @@ import org.opennms.test.ThrowableAnticipator; /** * @author DJ Gregor */ -public class ResourceTypeUtilsTest extends TestCase { +public class ResourceTypeUtilsTest { private FileAnticipator m_fileAnticipator; private File m_snmp; private File m_node; private File m_intf; - @Override - protected void setUp() throws Exception { - super.setUp(); - + @Before + public void setUp() throws Exception { m_fileAnticipator = new FileAnticipator(); RrdTestUtils.initializeNullStrategy(); } - @Override - protected void tearDown() { + @After + public void tearDown() throws Exception { m_fileAnticipator.tearDown(); } + @Test public void testLoadPropertiesNullRrdDirectory() { ThrowableAnticipator ta = new ThrowableAnticipator(); ta.anticipate(new IllegalArgumentException("rrdDirectory argument must not be null")); @@ -78,6 +86,7 @@ public class ResourceTypeUtilsTest extends TestCase { ta.verifyAnticipated(); } + @Test public void testLoadPropertiesNullRelativePath() { ThrowableAnticipator ta = new ThrowableAnticipator(); ta.anticipate(new IllegalArgumentException("relativePath argument must not be null")); @@ -90,6 +99,7 @@ public class ResourceTypeUtilsTest extends TestCase { ta.verifyAnticipated(); } + @Test public void testLoadPropertiesEmpty() throws Exception { OnmsResource childResource = createResource(); createPropertiesFile(childResource, "", false); @@ -100,6 +110,7 @@ public class ResourceTypeUtilsTest extends TestCase { assertEquals("properties size", 0, p.size()); } + @Test public void testLoadPropertiesNonEmpty() throws Exception { OnmsResource childResource = createResource(); createPropertiesFile(childResource, "foo=bar", false); @@ -112,6 +123,7 @@ public class ResourceTypeUtilsTest extends TestCase { assertEquals("property 'foo' value", "bar", p.get("foo")); } + @Test public void testLoadPropertiesDoesNotExist() throws Exception { OnmsResource childResource = createResource(); createPropertiesFile(childResource, "", true); @@ -120,12 +132,41 @@ public class ResourceTypeUtilsTest extends TestCase { assertNull("no properties file was created, so the properties object should be null", p); } + @Test public void testGetAttributesAtRelativePathWithBogusDirectory() { File bogusRrdDirectory = new File("/foo/bogus/blam/cheese/this/really/should/never/exist"); assertFalse("bogus RRD directory " + bogusRrdDirectory + " should not exist", bogusRrdDirectory.exists()); ResourceTypeUtils.getAttributesAtRelativePath(bogusRrdDirectory, "also-should-never-exist"); } + /* + * This test is associated with issue NMS-5806: + * http://issues.opennms.org/browse/NMS-5806 + */ + @Test + public void testUpdateFileOutsideResourceTypeUtils() throws Exception { + System.setProperty(PropertiesCache.CHECK_LAST_MODIFY_STRING, "true"); + + // Be sure that the file doesn't exist. + File resourceDir = new File("target/"); + File propertiesFile = new File(resourceDir, "strings.properties"); + propertiesFile.delete(); + + // Creating a new strings.properties file and adding one value to it + ResourceTypeUtils.updateStringProperty(resourceDir, "2012", "year"); + assertEquals("2012", ResourceTypeUtils.getStringProperty(resourceDir, "year")); + Thread.sleep(1000l); // Simulate a delay, to be sure that we are going to have a different lastModifyTime + + // Externally updating the strings.proeprties file + Properties properties = new Properties(); + properties.load(new FileInputStream(propertiesFile)); + properties.setProperty("year", "2013"); + properties.store(new FileWriter(propertiesFile), "Updated!"); + + // Verify that after the external update, we can get the updated value + assertEquals("2013", ResourceTypeUtils.getStringProperty(resourceDir, "year")); + } + private OnmsResource createResource() { OnmsResource topResource = new OnmsResource("1", "Node One", new MockResourceType(), new HashSet(0)); diff --git a/opennms-util/src/main/java/org/opennms/core/utils/PropertiesCache.java b/opennms-util/src/main/java/org/opennms/core/utils/PropertiesCache.java index 976e967..68c5883 100644 --- a/opennms-util/src/main/java/org/opennms/core/utils/PropertiesCache.java +++ b/opennms-util/src/main/java/org/opennms/core/utils/PropertiesCache.java @@ -48,12 +48,16 @@ import java.util.concurrent.locks.ReentrantLock; * @version $Id: $ */ public class PropertiesCache { - + + public static final String CHECK_LAST_MODIFY_STRING = "org.opennms.utils.propertiesCache.enableCheckFileModified"; + private static class PropertiesHolder { private Properties m_properties; private final File m_file; private final Lock lock = new ReentrantLock(); - + private long m_lastModify = 0; + private boolean m_checkLastModify = Boolean.getBoolean(CHECK_LAST_MODIFY_STRING); + PropertiesHolder(File file) { m_file = file; m_properties = null; @@ -69,6 +73,9 @@ public class PropertiesCache { in = new FileInputStream(m_file); Properties prop = new Properties(); prop.load(in); + if (m_checkLastModify) { + m_lastModify = m_file.lastModified(); + } return prop; } finally { if (in != null) { @@ -95,6 +102,10 @@ public class PropertiesCache { try { if (m_properties == null) { readWithDefault(new Properties()); + } else { + if (m_checkLastModify && m_file.canRead() && m_lastModify != m_file.lastModified()) { + m_properties = read(); + } } return m_properties; } finally {