diff --git a/.gitignore b/.gitignore
index 69cb3e6..3079950 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,7 @@ build/
### VS Code ###
.vscode/
**script**
-*config.json
\ No newline at end of file
+*config.json
+
+### Logs ###
+*.log
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 853f4c4..8e4cb8c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.smart.home
file.is.my.command
- 1.1-SNAPSHOT
+ 1.2-SNAPSHOT
pc.daemon
jar
Daemon that will be installed on computers and will handle simple daily tasks
@@ -82,5 +82,20 @@
3.4.2
+
+
+
+ org.mockito
+ mockito-core
+ 2.23.0
+ test
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
diff --git a/src/main/java/com/smart/home/pc/daemon/Application.java b/src/main/java/com/smart/home/pc/daemon/Application.java
index afe8399..d9a385b 100644
--- a/src/main/java/com/smart/home/pc/daemon/Application.java
+++ b/src/main/java/com/smart/home/pc/daemon/Application.java
@@ -2,21 +2,19 @@
import java.io.File;
import java.io.IOException;
-import java.io.Reader;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import com.google.gson.Gson;
import com.smart.home.pc.daemon.dto.Config;
import com.smart.home.pc.daemon.dto.FullConfiguration;
import com.smart.home.pc.daemon.impl.Daemon;
+import com.smart.home.pc.daemon.service.impl.ConfigurationLoaderServiceImpl;
public class Application {
@@ -30,57 +28,24 @@ public static void main(String[] args) throws RuntimeException, IOException, Int
// Determine local jar path
Path jarAbsolutePath = FileSystems.getDefault().getPath("").toAbsolutePath();
- // Check and create configuration file if not found
- String configPath = jarAbsolutePath.toString() + File.separator + CONFIGURATION_FILE_NAME;
- Path configFilePath = Paths.get(configPath);
- File configFile = new File(configPath);
-
- // Create configuration file
- if (!configFile.isFile()) {
- try {
- configFile.createNewFile();
- } catch (IOException e) {
- LOGGER.error("Could not create the configuration file: " + configFilePath.toString());
- e.printStackTrace();
- System.exit(1);
- }
- }
-
- if (configFile.isFile()) {
- LOGGER.info("Configuration location: " + configPath);
- }
-
- // create Gson instance
- Gson gson = new Gson();
- Config daemonConfig = new Config();
-
- // create a reader
- Reader reader;
- try {
- reader = Files.newBufferedReader(configFilePath);
-
- // convert JSON file to map
- daemonConfig = gson.fromJson(reader, Config.class);
- reader.close();
-
- } catch (IOException e) {
- e.printStackTrace();
- System.exit(1);
- }
+ // Load configuration file
+ String initialUserConfigurationPath = jarAbsolutePath.toString() + File.separator + CONFIGURATION_FILE_NAME;
+ ConfigurationLoaderServiceImpl configurationLoaderService = new ConfigurationLoaderServiceImpl(initialUserConfigurationPath);
+ Config initialUserConfiguration = configurationLoaderService.getCurrentUserConfiguration();
// Configuration not found we exit the app for now
- if (daemonConfig == null) {
+ if (initialUserConfiguration == null) {
LOGGER.error("Configuration file is either empty or malformed, exiting...");
System.exit(1);
}
-
+
// Create script directory
- if (StringUtils.isBlank(daemonConfig.getScriptDir())) {
+ if (StringUtils.isBlank(initialUserConfiguration.getScriptDir())) {
LOGGER.warn("Missing scriptDir property in configuration file. Will be using 'script' dir");
- daemonConfig.setScriptDir("script");
+ initialUserConfiguration.setScriptDir("script");
}
-
- Path batchPath = Paths.get(jarAbsolutePath + File.separator + daemonConfig.getScriptDir() + File.separator);
+
+ Path batchPath = Paths.get(jarAbsolutePath + File.separator + initialUserConfiguration.getScriptDir() + File.separator);
LOGGER.info("Script location:" + batchPath);
try {
@@ -93,11 +58,28 @@ public static void main(String[] args) throws RuntimeException, IOException, Int
// Initialise and run Daemon
FullConfiguration configuration = new FullConfiguration();
- configuration.setUserConfiguration(daemonConfig);
+ configuration.setUserConfiguration(initialUserConfiguration);
configuration.setAbsPathHomeFolder(jarAbsolutePath.toString());
- configuration.setAbsPathScriptFolder(configuration.getAbsPathHomeFolder() + File.separator + daemonConfig.getScriptDir() + File.separator);
+ configuration.setAbsPathScriptFolder(configuration.getAbsPathHomeFolder() + File.separator + initialUserConfiguration.getScriptDir() + File.separator);
+
Daemon deamon = new Daemon();
while (true) {
+
+ // New configuration detected
+ if (configurationLoaderService.isConfigurationUpdated(initialUserConfigurationPath)) {
+
+ if (configuration.getUserConfiguration().isLogEverything()) {
+ LOGGER.info("New configuration detected !");
+ }
+ // Load configuration
+ Config newUserConfiguration = configurationLoaderService.loadConfiguration(initialUserConfigurationPath);
+ if (newUserConfiguration != null) {
+ configuration.setUserConfiguration(newUserConfiguration);
+ } else {
+ LOGGER.warn("Cound not load new configuration, will keep using the old one !");
+ }
+ }
+
deamon.run(configuration);
Thread.sleep(10000);
}
diff --git a/src/main/java/com/smart/home/pc/daemon/service/ConfigurationLoaderService.java b/src/main/java/com/smart/home/pc/daemon/service/ConfigurationLoaderService.java
new file mode 100644
index 0000000..e4eab11
--- /dev/null
+++ b/src/main/java/com/smart/home/pc/daemon/service/ConfigurationLoaderService.java
@@ -0,0 +1,11 @@
+package com.smart.home.pc.daemon.service;
+
+import com.smart.home.pc.daemon.dto.Config;
+
+public interface ConfigurationLoaderService {
+
+ public Config loadConfiguration(String configurationPath);
+
+ public boolean isConfigurationUpdated(String configurationPath);
+
+}
diff --git a/src/main/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceImpl.java b/src/main/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceImpl.java
new file mode 100644
index 0000000..83002b6
--- /dev/null
+++ b/src/main/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceImpl.java
@@ -0,0 +1,77 @@
+package com.smart.home.pc.daemon.service.impl;
+
+import java.util.Date;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.smart.home.pc.daemon.dto.Config;
+import com.smart.home.pc.daemon.service.ConfigurationLoaderService;
+import com.smart.home.pc.daemon.util.FileHelper;
+
+public class ConfigurationLoaderServiceImpl implements ConfigurationLoaderService {
+
+ private static final Logger LOGGER = LogManager.getLogger(ConfigurationLoaderServiceImpl.class);
+
+ private Date configurationFileLastModifiedDate;
+
+ private Config currentUserConfiguration;
+
+ private FileHelper fileHelper = new FileHelper();
+
+ public ConfigurationLoaderServiceImpl() {
+
+ }
+
+ public ConfigurationLoaderServiceImpl(String configurationPath) {
+ loadConfiguration(configurationPath);
+ }
+
+ @Override
+ public Config loadConfiguration(String configurationPath) {
+ Date configurationPathLastModificationDate = fileHelper.getFileLastModificationDate(configurationPath);
+ // Configuration is found and is a file.
+ if (configurationPathLastModificationDate != null) {
+ Config loadedConfiguration = fileHelper.getConfigurationFromPath(configurationPath);
+ if (loadedConfiguration != null) {
+ configurationFileLastModifiedDate = configurationPathLastModificationDate;
+ currentUserConfiguration = loadedConfiguration;
+ return currentUserConfiguration;
+ } else {
+ LOGGER.error("Issue loading configuration file: " + configurationPath);
+ }
+ } else {
+ // Configuration file not found or null
+ LOGGER.error("The provided configuration path was not found: " + configurationPath);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isConfigurationUpdated(String configurationPath) {
+ if (configurationPath != null) {
+ Date currentConfigDate = fileHelper.getFileLastModificationDate(configurationPath);
+ if (currentConfigDate == null || currentConfigDate.equals(configurationFileLastModifiedDate)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public Date getConfigurationLoadDate() {
+ return configurationFileLastModifiedDate;
+ }
+
+ public void setConfigurationLoadDate(Date configurationLoadDate) {
+ this.configurationFileLastModifiedDate = configurationLoadDate;
+ }
+
+ public Config getCurrentUserConfiguration() {
+ return currentUserConfiguration;
+ }
+
+ public void setCurrentUserConfiguration(Config currentUserConfiguration) {
+ this.currentUserConfiguration = currentUserConfiguration;
+ }
+
+}
diff --git a/src/main/java/com/smart/home/pc/daemon/util/FileHelper.java b/src/main/java/com/smart/home/pc/daemon/util/FileHelper.java
new file mode 100644
index 0000000..1c0601c
--- /dev/null
+++ b/src/main/java/com/smart/home/pc/daemon/util/FileHelper.java
@@ -0,0 +1,79 @@
+package com.smart.home.pc.daemon.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Date;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.google.gson.Gson;
+import com.smart.home.pc.daemon.dto.Config;
+
+/**
+ * Helper class to manage file actions
+ *
+ * @author Ramzi
+ *
+ */
+public class FileHelper {
+
+ private static final Logger LOGGER = LogManager.getLogger(FileHelper.class);
+
+ private Gson gson = new Gson();
+
+ /**
+ * Get last modification date for the given file path
+ *
+ * @param filePath, String containing the absolute path of the file
+ * @return last modification date or null
+ */
+ public Date getFileLastModificationDate(String fileAbsPath) {
+ if (StringUtils.isEmpty(fileAbsPath)) {
+ return null;
+ }
+
+ File configFile = new File(fileAbsPath);
+ if (configFile.exists()) {
+ return new Date(configFile.lastModified());
+ }
+
+ return null;
+ }
+
+ /**
+ * Reads the configuration file as a Json and returns the corresponding object
+ *
+ * @param configFilePath
+ * @return
+ */
+ public Config getConfigurationFromPath(String configurationPath) {
+ Path configFilePath = Paths.get(configurationPath);
+ Config userConfiguration = null;
+
+ Reader reader;
+ try {
+ reader = Files.newBufferedReader(configFilePath);
+
+ // convert JSON file to map
+ userConfiguration = gson.fromJson(reader, Config.class);
+ reader.close();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ LOGGER.error("Exception while reading configuration file please check file format: " + configFilePath);
+ }
+
+ if (userConfiguration == null) {
+ LOGGER.error("Configuration file is either empty or malformed");
+ }
+
+ return userConfiguration;
+ }
+
+}
diff --git a/src/test/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceTest.java b/src/test/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceTest.java
new file mode 100644
index 0000000..7ee7863
--- /dev/null
+++ b/src/test/java/com/smart/home/pc/daemon/service/impl/ConfigurationLoaderServiceTest.java
@@ -0,0 +1,126 @@
+package com.smart.home.pc.daemon.service.impl;
+
+import java.util.Date;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import com.smart.home.pc.daemon.dto.Config;
+import com.smart.home.pc.daemon.util.FileHelper;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ConfigurationLoaderServiceTest {
+
+ @InjectMocks
+ ConfigurationLoaderServiceImpl configurationLoaderServiceImpl = new ConfigurationLoaderServiceImpl();
+
+ @Mock
+ FileHelper fileHelper;
+
+ @Test
+ public void isConfigurationUpdatedInitialLoadTest() {
+ /*
+ * Initial configuration, new configuration has a last modification date (file
+ * FOUND)
+ *
+ */
+
+ configurationLoaderServiceImpl.setConfigurationLoadDate(null);
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(new Date());
+ Assert.assertTrue(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+
+ /*
+ * Initial configuration, new configuration has a last modification date (file
+ * NOT FOUND)
+ *
+ */
+ configurationLoaderServiceImpl.setConfigurationLoadDate(null);
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(null);
+ Assert.assertFalse(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+ }
+
+ @Test
+ public void isConfigurationUpdatedAfterInitialLoadTest() {
+ /*
+ * Initial configuration is SET we will play with the new configuration last
+ * modification test
+ */
+ Date lastModificationDate = new Date();
+ Date before = new Date(lastModificationDate.getTime() - 10);
+ Date after = new Date(lastModificationDate.getTime());
+
+ // New configuration file modification date is same as initial configuration
+ configurationLoaderServiceImpl.setConfigurationLoadDate(lastModificationDate);
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(lastModificationDate);
+ Assert.assertFalse(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+
+ // New configuration file modification date is null
+ configurationLoaderServiceImpl.setConfigurationLoadDate(new Date());
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(null);
+ Assert.assertFalse(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+
+ // New configuration last modification is in the future
+ configurationLoaderServiceImpl.setConfigurationLoadDate(after); // Set last modification
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(before);
+ Assert.assertTrue(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+
+ // New configuration last modification is in the past
+ configurationLoaderServiceImpl.setConfigurationLoadDate(before); // Set last modification
+ Mockito.when(fileHelper.getFileLastModificationDate("")).thenReturn(after);
+ Assert.assertTrue(configurationLoaderServiceImpl.isConfigurationUpdated(""));
+
+ }
+
+ @Test
+ public void loadConfigurationTestEmpty() {
+ Assert.assertNull(configurationLoaderServiceImpl.loadConfiguration(null));
+ Assert.assertNull(configurationLoaderServiceImpl.loadConfiguration(""));
+ Assert.assertNull(configurationLoaderServiceImpl.loadConfiguration(" "));
+ }
+
+ @Test
+ public void loadConfigurationTest() {
+
+ String dummyConfigFilePath = "dummyConfigFilePath";
+ String dummyCommandPath = "dummyCommandPath";
+ Date lastModificationDate = new Date();
+ Date lastModificationDatePast = new Date(lastModificationDate.getTime() - 10);
+ Config expectedConfiguration = new Config();
+ expectedConfiguration.setCommandPath(dummyCommandPath);
+
+ // Configuration file not found
+ Mockito.when(fileHelper.getFileLastModificationDate(dummyConfigFilePath)).thenReturn(null);
+ // Execute loading
+ Assert.assertNull(configurationLoaderServiceImpl.loadConfiguration(dummyConfigFilePath));
+
+ // Configuration file found but issue in the loading
+ configurationLoaderServiceImpl.setConfigurationLoadDate(lastModificationDatePast); // Set last configuration modification date in the past
+ configurationLoaderServiceImpl.setCurrentUserConfiguration(null);
+ Mockito.when(fileHelper.getFileLastModificationDate(dummyConfigFilePath)).thenReturn(lastModificationDate);
+ Mockito.when(fileHelper.getConfigurationFromPath(dummyConfigFilePath)).thenReturn(null); // Issue in loading the configuration object
+ // Execute loading
+ Assert.assertNull(configurationLoaderServiceImpl.loadConfiguration(dummyConfigFilePath));
+ // Modification date should not be altered
+ Assert.assertFalse(configurationLoaderServiceImpl.getConfigurationLoadDate().equals(lastModificationDate));
+ Assert.assertTrue(configurationLoaderServiceImpl.getConfigurationLoadDate().equals(lastModificationDatePast));
+
+ // Configuration file found and loaded
+ configurationLoaderServiceImpl.setConfigurationLoadDate(lastModificationDatePast); // Set last configuration modification date in the past
+ configurationLoaderServiceImpl.setCurrentUserConfiguration(null);
+ Mockito.when(fileHelper.getFileLastModificationDate(dummyConfigFilePath)).thenReturn(lastModificationDate);
+ Mockito.when(fileHelper.getConfigurationFromPath(dummyConfigFilePath)).thenReturn(expectedConfiguration);
+ // Execute loading
+ Assert.assertNotNull(configurationLoaderServiceImpl.loadConfiguration(dummyConfigFilePath));
+ // Modification date should be updated
+ Assert.assertTrue(configurationLoaderServiceImpl.getConfigurationLoadDate().equals(lastModificationDate));
+ // Current configuration should be updated
+ Assert.assertTrue(configurationLoaderServiceImpl.getCurrentUserConfiguration().getCommandPath().equals(dummyCommandPath));
+
+ }
+
+}