diff --git a/edexOsgi/com.raytheon.uf.common.util/.classpath b/edexOsgi/com.raytheon.uf.common.util/.classpath
index c83df31842..1fa3e6803d 100644
--- a/edexOsgi/com.raytheon.uf.common.util/.classpath
+++ b/edexOsgi/com.raytheon.uf.common.util/.classpath
@@ -3,6 +3,5 @@
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 12, 2013 1778 djohnson Initial creation + * + *+ * + * @author djohnson + * @version 1.0 + */ +class FileLastModifiedTimeWatcher implements IFileModifiedWatcher { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(FileLastModifiedTimeWatcher.class); + + private final File file; + + private long configFileLastModified; + + /** + * Constructor. + * + * @param file + * the file to watch + */ + FileLastModifiedTimeWatcher(File file) { + this.file = file; + this.configFileLastModified = file.lastModified(); + } + + @Override + public boolean hasBeenModified() { + final long currentConfigFileLastModified = file.lastModified(); + final boolean fileModified = (currentConfigFileLastModified != configFileLastModified); + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler + .debug(String + .format("last known last modified [%s], current last modified [%s], changed [%s]", + configFileLastModified, + currentConfigFileLastModified, fileModified)); + } + + if (fileModified) { + configFileLastModified = currentConfigFileLastModified; + } + return fileModified; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java index 8ea389f786..1bb04bfdec 100644 --- a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/FileUtil.java @@ -54,12 +54,14 @@ import java.util.zip.GZIPOutputStream; * to create temporary directories and files. * 02/15/2013 #1597 randerso Fixed error when copying empty files * Feb 15, 2013 1638 mschenke Moved EOL field from edex.common Util + * Mar 11, 2013 1645 djohnson Added file modification watcher. * * * * @author njensen */ public class FileUtil { + /** * Displayable string of valid filename characters */ @@ -74,7 +76,7 @@ public class FileUtil { * Easy reference to system-dependent end of line */ public static final String EOL = System.getProperty("line.separator"); - + /** * Joins one or more path components into a single path string. Path * components are separated by the operating system dependent @@ -858,4 +860,15 @@ public class FileUtil { c.close(); } } + + /** + * Retrieve a file modification watcher. + * + * @param file + * the file to watch for modifications + * @return the watcher + */ + public static IFileModifiedWatcher getFileModifiedWatcher(File file) { + return new FileLastModifiedTimeWatcher(file); + } } diff --git a/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/IFileModifiedWatcher.java b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/IFileModifiedWatcher.java new file mode 100644 index 0000000000..a532a9bf6b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.util/src/com/raytheon/uf/common/util/IFileModifiedWatcher.java @@ -0,0 +1,46 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.util; + +/** + * Interface for checking whether a file has been modified. + * + *
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 12, 2013 1778 djohnson Initial creation + * + *+ * + * @author djohnson + * @version 1.0 + */ + +public interface IFileModifiedWatcher { + /** + * Checks whether the file has been modified. + * + * @return true if the file has been modified + */ + boolean hasBeenModified(); +} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index 3315efe49d..53b7bc6011 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -51,6 +51,8 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.util.ITimer; import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.common.util.IFileModifiedWatcher; import com.raytheon.uf.common.util.LogUtil; import com.raytheon.uf.common.util.algorithm.AlgorithmUtil; import com.raytheon.uf.common.util.algorithm.AlgorithmUtil.IBinarySearchResponse; @@ -103,6 +105,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Feb 14, 2013 1596 djohnson Do not reschedule allocations when a subscription is removed. * Feb 20, 2013 1543 djohnson Add try/catch blocks during the shutdown process. * Feb 27, 2013 1644 djohnson Force sub-classes to provide an implementation for how to schedule SBN routed subscriptions. + * Mar 11, 2013 1645 djohnson Watch configuration file for changes. * * * @author dhladky @@ -133,6 +136,20 @@ abstract class BandwidthManager extends @VisibleForTesting final RetrievalManager retrievalManager; + @VisibleForTesting + final Runnable watchForConfigFileChanges = new Runnable() { + + private final IFileModifiedWatcher fileModifiedWatcher = FileUtil.getFileModifiedWatcher(EdexBandwidthContextFactory + .getBandwidthMapConfig()); + + @Override + public void run() { + if (fileModifiedWatcher.hasBeenModified()) { + bandwidthMapConfigurationUpdated(); + } + } + }; + public BandwidthManager(IBandwidthDbInit dbInit, IBandwidthDao bandwidthDao, RetrievalManager retrievalManager, BandwidthDaoUtil bandwidthDaoUtil) { @@ -144,8 +161,10 @@ abstract class BandwidthManager extends EventBus.register(this); BandwidthEventBus.register(this); - // Start a MaintenanceTask + // schedule maintenance tasks scheduler = Executors.newScheduledThreadPool(1); + scheduler.scheduleAtFixedRate(watchForConfigFileChanges, + 1, 1, TimeUnit.MINUTES); scheduler.scheduleAtFixedRate(new MaintanenceTask(), 1, 5, TimeUnit.MINUTES); } @@ -1445,7 +1464,6 @@ abstract class BandwidthManager extends @Override public void run() { - for (RetrievalPlan plan : retrievalManager.getRetrievalPlans() .values()) { plan.resize(); @@ -1672,4 +1690,20 @@ abstract class BandwidthManager extends return true; } } + + /** + * Signals the bandwidth map localization file is updated, perform a + * reinitialize operation. + */ + private void bandwidthMapConfigurationUpdated() { + IBandwidthRequest request = new IBandwidthRequest(); + request.setRequestType(RequestType.REINITIALIZE); + + try { + handleRequest(request); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error while reinitializing the bandwidth manager.", e); + } + } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java index 85f0db5646..61d11cdd6e 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java @@ -128,8 +128,22 @@ class EdexBandwidthContextFactory implements BandwidthContextFactory { /** * Retrieve the actual bandwidth map configuration file. + * + * @return the file reference to the bandwidth map config file, the file may + * or may not exist */ public static File getBandwidthMapConfig() { + LocalizationFile lf = getBandwidthMapLocalizationFile(); + File file = lf.getFile(); + return file; + } + + /** + * Retrieve the actual bandwidth map localization file. + * + * @return the localization file + */ + public static LocalizationFile getBandwidthMapLocalizationFile() { // TODO: Change to be site specific IPathManager pm = PathManagerFactory.getPathManager(); LocalizationContext lc = pm.getContext(LocalizationType.COMMON_STATIC, @@ -137,8 +151,7 @@ class EdexBandwidthContextFactory implements BandwidthContextFactory { LocalizationFile lf = pm.getLocalizationFile(lc, "datadelivery/bandwidthmap.xml"); - File file = lf.getFile(); - return file; + return lf; } /** diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/NcfBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/NcfBandwidthManagerCreator.java index 3d39f7496b..9722a5440a 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/NcfBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/NcfBandwidthManagerCreator.java @@ -43,6 +43,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * ------------ ---------- ----------- -------------------------- * Feb 20, 2013 1543 djohnson Initial creation * Feb 27, 2013 1644 djohnson Schedule SBN subscriptions. + * Mar 11, 2013 1645 djohnson Add missing Spring file. * * * @@ -57,6 +58,7 @@ public class NcfBandwidthManagerCreator implements IEdexBandwidthManagerCreator static class NcfBandwidthManager extends BandwidthManager { private static final String[] NCF_BANDWIDTH_MANAGER_FILES = new String[] { + JarUtil.getResResourcePath("/spring/bandwidth-datadelivery-ncf-edex-impl.xml"), JarUtil.getResResourcePath("/spring/bandwidth-datadelivery-edex-impl.xml"), JarUtil.getResResourcePath("/spring/bandwidth-datadelivery.xml"), JarUtil.getResResourcePath("/spring/thrift-bandwidth.xml"), diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java index 86c906fd2e..996c5fbec6 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java @@ -44,6 +44,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * ------------ ---------- ----------- -------------------------- * Feb 20, 2013 1543 djohnson Initial creation * Feb 27, 2013 1644 djohnson Schedule SBN subscriptions by routing to the NCF bandwidth manager. + * Mar 11, 2013 1645 djohnson Add missing Spring file. * * * @@ -58,6 +59,7 @@ public class WfoBandwidthManagerCreator implements IEdexBandwidthManagerCreator static class WfoBandwidthManager extends BandwidthManager { private static final String[] WFO_BANDWIDTH_MANAGER_FILES = new String[] { + JarUtil.getResResourcePath("/spring/bandwidth-datadelivery-wfo-edex-impl.xml"), JarUtil.getResResourcePath("/spring/bandwidth-datadelivery-edex-impl.xml"), JarUtil.getResResourcePath("/spring/bandwidth-datadelivery.xml"), JarUtil.getResResourcePath("/spring/thrift-bandwidth.xml"), diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManagerIntTest.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManagerIntTest.java index 3d8a5912bf..3b4efe7528 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManagerIntTest.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManagerIntTest.java @@ -24,6 +24,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -100,6 +101,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.RetrievalManagerNotifyEvent; * Jan 30, 2013 1501 djohnson Fix broken calculations for determining required latency. * Feb 14, 2013 1595 djohnson Fix expired subscription updates that weren't scheduling retrievals. * Feb 14, 2013 1596 djohnson Add test duplicating errors deleting multiple subscriptions for the same provider/dataset. + * Mar 11, 2013 1645 djohnson Test configuration file modifications. * * * @@ -956,6 +958,25 @@ public class BandwidthManagerIntTest extends AbstractBandwidthManagerIntTest { subscriptionDaosAfterDelete.size()); } + @Test + public void testModifiedConfigurationFileWillReinitializeBandwidthManager() { + IntegrationTestBandwidthContextFactory + .getIntegrationTestBandwidthMapConfigFile().setLastModified( + Long.MAX_VALUE); + bandwidthManager.watchForConfigFileChanges.run(); + + assertThat(EdexBandwidthContextFactory.getInstance(), + is(not(sameInstance(bandwidthManager)))); + } + + @Test + public void testUnmodifiedConfigurationFileWillNotReinitializeBandwidthManager() { + bandwidthManager.watchForConfigFileChanges.run(); + + assertThat(EdexBandwidthContextFactory.getInstance(), + is(sameInstance(bandwidthManager))); + } + private void testSubscriptionCyclesAreAllocatedOncePerCyclePerPlanDay( List
+ * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Mar 08, 2013 1645 djohnson Initial creation + * + *+ * + * @author djohnson + * @version 1.0 + */ +public class FileLastModifiedTimeWatcherTest { + + private final File testDir = TestUtil + .setupTestClassDir(FileLastModifiedTimeWatcherTest.class); + + private final File file = new File(testDir, "test.txt"); + + private FileLastModifiedTimeWatcher watcher; + + @Before + public void setUp() throws IOException { + file.createNewFile(); + watcher = new FileLastModifiedTimeWatcher(file); + } + + @Test + public void newerLastModifiedWillReturnTrueForModified() throws IOException { + increaseFileLastModifiedTime(); + + assertThat(watcher.hasBeenModified(), is(true)); + } + + private boolean increaseFileLastModifiedTime() { + return file.setLastModified(file.lastModified() + 5000L); + } + + @Test + public void sameLastModifiedWillReturnFalseForModified() throws IOException { + assertThat(watcher.hasBeenModified(), is(false)); + } + + @Test + public void newerLastModifiedTwiceWillReturnTrueForModified() + throws IOException { + increaseFileLastModifiedTime(); + + watcher.hasBeenModified(); + + increaseFileLastModifiedTime(); + + assertThat(watcher.hasBeenModified(), is(true)); + } + + @Test + public void sameLastModifiedAfterNewerWillReturnFalseForModified() + throws IOException { + increaseFileLastModifiedTime(); + + watcher.hasBeenModified(); + + assertThat(watcher.hasBeenModified(), is(false)); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/FileUtilTest.java b/tests/unit/com/raytheon/uf/common/util/FileUtilTest.java similarity index 98% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/FileUtilTest.java rename to tests/unit/com/raytheon/uf/common/util/FileUtilTest.java index 127fccddf4..01ddaf1406 100644 --- a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/FileUtilTest.java +++ b/tests/unit/com/raytheon/uf/common/util/FileUtilTest.java @@ -19,8 +19,8 @@ **/ package com.raytheon.uf.common.util; -import junit.framework.Assert; +import org.junit.Assert; import org.junit.Test; /** diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/PropertiesUtilTest.java b/tests/unit/com/raytheon/uf/common/util/PropertiesUtilTest.java similarity index 81% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/PropertiesUtilTest.java rename to tests/unit/com/raytheon/uf/common/util/PropertiesUtilTest.java index 8397b32dcc..9ab7abca80 100644 --- a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/PropertiesUtilTest.java +++ b/tests/unit/com/raytheon/uf/common/util/PropertiesUtilTest.java @@ -20,7 +20,6 @@ package com.raytheon.uf.common.util; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; @@ -68,22 +67,15 @@ public class PropertiesUtilTest { @Test public void testCanReadPropertiesFile() throws IOException { - File fileToRead = File.createTempFile( - PropertiesUtilTest.class.getSimpleName(), null); + final File testDir = TestUtil.setupTestClassDir(CLASS); + final File fileToRead = new File(testDir, "propertiesFile.properties"); - InputStream is = null; - try { - is = CLASS.getResourceAsStream(CLASS.getSimpleName() - + ".properties"); - - FileUtil.write(is, fileToRead); - - assertTrue("The file to read should exist!", fileToRead.isFile()); - } finally { - PropertiesUtil.close(is); - } + FileUtil.bytes2File( + TestUtil.readResource(CLASS, CLASS.getSimpleName() + + ".properties"), fileToRead); Properties properties = PropertiesUtil.read(fileToRead); + assertFalse("The properties should not be empty after reading a file!", properties.isEmpty()); } diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/PropertiesUtilTest.properties b/tests/unit/com/raytheon/uf/common/util/PropertiesUtilTest.properties similarity index 100% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/PropertiesUtilTest.properties rename to tests/unit/com/raytheon/uf/common/util/PropertiesUtilTest.properties diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/ReflectionUtilTest.java b/tests/unit/com/raytheon/uf/common/util/ReflectionUtilTest.java similarity index 100% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/ReflectionUtilTest.java rename to tests/unit/com/raytheon/uf/common/util/ReflectionUtilTest.java diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/SliceUtilTest.java b/tests/unit/com/raytheon/uf/common/util/SliceUtilTest.java similarity index 97% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/SliceUtilTest.java rename to tests/unit/com/raytheon/uf/common/util/SliceUtilTest.java index d2c15d7db2..ccf27f92c2 100644 --- a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/SliceUtilTest.java +++ b/tests/unit/com/raytheon/uf/common/util/SliceUtilTest.java @@ -22,14 +22,11 @@ package com.raytheon.uf.common.util; import java.awt.Point; import java.util.ArrayList; -import junit.framework.Assert; - import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.raytheon.uf.common.util.GridUtil; - /** * TODO Add Description * diff --git a/edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/StringUtilTest.java b/tests/unit/com/raytheon/uf/common/util/StringUtilTest.java similarity index 100% rename from edexOsgi/com.raytheon.uf.common.util/unit-test/com/raytheon/uf/common/util/StringUtilTest.java rename to tests/unit/com/raytheon/uf/common/util/StringUtilTest.java