Author: tchemit Date: 2013-01-04 14:51:09 +0100 (Fri, 04 Jan 2013) New Revision: 2452 Url: http://nuiton.org/projects/nuiton-utils/repository/revisions/2452 Log: fixes #2500: [ApplicationConfig] Add a method to reset all options with *blank* values Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/ApplicationConfig.java trunk/nuiton-utils/src/test/java/org/nuiton/util/ApplicationConfigTest.java Modified: trunk/nuiton-utils/src/main/java/org/nuiton/util/ApplicationConfig.java =================================================================== --- trunk/nuiton-utils/src/main/java/org/nuiton/util/ApplicationConfig.java 2012-12-29 11:29:25 UTC (rev 2451) +++ trunk/nuiton-utils/src/main/java/org/nuiton/util/ApplicationConfig.java 2013-01-04 13:51:09 UTC (rev 2452) @@ -69,6 +69,7 @@ import org.apache.commons.beanutils.ConstructorUtils; import org.apache.commons.collections.EnumerationUtils; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.util.converter.ConverterUtil; @@ -708,6 +709,50 @@ } /** + * Clean the user configuration file (The one in user home) and save it + * in user config file. + * + * All options with an empty value will be removed from this file. + * + * Moreover, like {@link #saveForUser(String...)} the given + * {@code excludeKeys} will never be saved. + * + * This method can be useful when migrating some configuration from a + * version to another one with deprecated options (otherwise they will stay + * for ever in the configuration file with an empty value which is not + * acceptable). + * + * <strong>Important note:</strong> Using this method can have some strange + * side effects, since it could then allow to reuse default configurations + * from other level (default, env, jvm,...). Use with care only! + * + * @param excludeKeys optional list of key to not treat in cleaning process, + * nor save in user user config file. + * @since 2.6.6 + */ + public void cleanUserConfig(String... excludeKeys) { + + Set<String> keys = new HashSet<String>(homefile.stringPropertyNames()); + + List<String> toExclude = Arrays.asList(excludeKeys); + + for (String key : keys) { + if (!toExclude.contains(key)) { + String property = homefile.getProperty(key); + if (StringUtils.isBlank(property)) { + if (log.isInfoEnabled()) { + log.info("Remove blank property: " + key); + } + homefile.remove(key); + } + } + } + + // can now save cleaned user config + saveForUser(excludeKeys); + } + + /** * Obtain the system config file location. * * @return the system config file location Modified: trunk/nuiton-utils/src/test/java/org/nuiton/util/ApplicationConfigTest.java =================================================================== --- trunk/nuiton-utils/src/test/java/org/nuiton/util/ApplicationConfigTest.java 2012-12-29 11:29:25 UTC (rev 2451) +++ trunk/nuiton-utils/src/test/java/org/nuiton/util/ApplicationConfigTest.java 2013-01-04 13:51:09 UTC (rev 2452) @@ -25,15 +25,23 @@ package org.nuiton.util; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.SystemUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.nuiton.util.ApplicationConfig.Action; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; @@ -44,86 +52,205 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; +import java.util.Properties; -/** - * - * @author poussin - */ +/** @author poussin */ public class ApplicationConfigTest { private static final Log log = LogFactory.getLog(ApplicationConfigTest.class); - /** main folder for tests data **/ + /** main folder for tests data * */ protected static File DIR_TESTS_DATA; - protected static final String SYSTEM_PROPERTY_USER_HOME = "user.home"; - protected static int DUMMY_ACTION_CALL; public static class DummyAction { @Action.Step(1) public void dummyAction(String s, int step) { DUMMY_ACTION_CALL++; - log.info(s + ":" + step); + log.info(s + ':' + step); } } + protected static String oldHome; + @BeforeClass public static void setUpClass() { // Initialize DIR_TESTS_DATA to target/surefire-data - DIR_TESTS_DATA = TestHelper.createDefaultTestsDataDirectory(); + DIR_TESTS_DATA = FileUtil.getFileFromFQN(TestHelper.createDefaultTestsDataDirectory(), ApplicationConfigTest.class.getName() + "." + System.nanoTime()); + + oldHome = SystemUtils.getUserHome().getAbsolutePath(); } + protected File testDirectory; + + @Rule + public final TestName testName = new TestName(); + + @Before + public void before() { + testDirectory = new File(DIR_TESTS_DATA, testName.getMethodName()); + } + @Test - public void testSaveForUser() { - log.info("testSaveForUser"); + public void testSaveForUser() throws IOException { - /** PREPARE DATA **/ + // Initiliaze path and filename + String path = testDirectory.getAbsolutePath(); + try { + System.setProperty(SystemUtils.USER_HOME, path); + + ApplicationConfig config = + new ApplicationConfig(testName.getMethodName()); + + File userFile = config.getUserConfigFile(); + + userFile.delete(); + + config.setOption("key1", "toto"); + config.setOption("key2", "tata"); + config.setOption("key3", "tutu"); + + // Parent directory will be created + config.saveForUser(); + + // I like to test that file.create works :( + Assert.assertTrue(userFile.exists()); + + Properties p = loadPropertyFile(userFile); + + Assert.assertEquals(3, p.size()); + + String property; + + property = p.getProperty("key1"); + Assert.assertEquals("toto", property); + + property = p.getProperty("key2"); + Assert.assertEquals("tata", property); + + property = p.getProperty("key3"); + Assert.assertEquals("tutu", property); + + } finally { + + if (oldHome != null) { + System.setProperty("user.home", oldHome); + } + } + + } + + @Test + public void cleanUserConfig() throws IOException, ArgumentsParserException { + // Initiliaze path and filename - String path = new File(DIR_TESTS_DATA, "user").getAbsolutePath(); - String filename = "test-saveForUser.properties"; + String path = testDirectory.getAbsolutePath(); - // Set path to USER_HOME (keep old value) - String oldHome = System.getProperty(SYSTEM_PROPERTY_USER_HOME); - System.setProperty(SYSTEM_PROPERTY_USER_HOME, path); + try { + System.setProperty("user.home", path); - /** EXEC METHOD **/ + ApplicationConfig config = + new ApplicationConfig(testName.getMethodName()); - ApplicationConfig config = new ApplicationConfig(); - config.setOption(ApplicationConfig.CONFIG_FILE_NAME, filename); - File userFile = config.getUserConfigFile(); + config.setOption("key1", "toto"); + config.setOption("key2", ""); + config.setOption("key3", "tutu"); - // If file exists, delete the file and his parent directory - if (userFile.exists()) { + File userFile = config.getUserConfigFile(); + + Assert.assertTrue(userFile.getAbsolutePath().startsWith(path)); + userFile.delete(); - userFile.getParentFile().delete(); - } - Assert.assertFalse(userFile.exists()); - //FIXME-tchemit-2012-07-23 : why this should be false ? False test - //Assert.assertFalse(userFile.getParentFile().exists()); + config.saveForUser(); - log.info("execute saveForUser : path = " + path + " _ filename = " + filename); - // Parent directory will be created - config.saveForUser(); - Assert.assertTrue(userFile.exists()); + Assert.assertTrue(userFile.exists()); - /** CLEAN **/ + Properties p = loadPropertyFile(userFile); - // Reset initial values - System.setProperty(SYSTEM_PROPERTY_USER_HOME, oldHome); + Assert.assertEquals(3, p.size()); + + String property; + + property = p.getProperty("key1"); + Assert.assertEquals("toto", property); + + property = p.getProperty("key2"); + Assert.assertEquals("", property); + + property = p.getProperty("key3"); + Assert.assertEquals("tutu", property); + + // reload config + config = new ApplicationConfig(testName.getMethodName()); + config.parse(); + + config.cleanUserConfig(); + + Properties p2 = loadPropertyFile(userFile); + + // key2 was removed + Assert.assertEquals(2, p2.size()); + + property = p2.getProperty("key1"); + Assert.assertEquals("toto", property); + + property = p2.getProperty("key2"); + Assert.assertNull(property); + + property = p2.getProperty("key3"); + Assert.assertEquals("tutu", property); + + // now key3 will be removed (even if not blank) + config.cleanUserConfig("key3"); + + // reload config + config = new ApplicationConfig(testName.getMethodName()); + config.parse(); + + Properties p3 = loadPropertyFile(userFile); + + // key3 was removed + Assert.assertEquals(1, p3.size()); + + property = p3.getProperty("key1"); + Assert.assertEquals("toto", property); + + + } finally { + + if (oldHome != null) { + System.setProperty("user.home", oldHome); + } + } + } + protected Properties loadPropertyFile(File file) throws IOException { + FileInputStream inStream; + + inStream = FileUtils.openInputStream(file); + try { + Properties p = new Properties(); + p.load(inStream); + inStream.close(); + return p; + } finally { + IOUtils.closeQuietly(inStream); + } + } + /** * Test of getUnparsed method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testGetUnparsed() throws Exception { - log.info("getUnparsed"); ApplicationConfig instance = new ApplicationConfig(); List<String> expResult = new ArrayList<String>(); List<String> result = instance.getUnparsed(); @@ -140,11 +267,11 @@ /** * Test of addAction method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testAddAction() throws Exception { - log.info("addAction"); Action action = null; ApplicationConfig instance = new ApplicationConfig(); @@ -157,11 +284,11 @@ /** * Test of doAction method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testDoAction() throws Exception { - log.info("doAction"); ApplicationConfig instance = new ApplicationConfig(); Action action = new Action(1, new DummyAction(), DummyAction.class.getMethod("dummyAction", String.class, Integer.TYPE), "coucou", "12"); @@ -177,12 +304,9 @@ Assert.assertEquals(1, DUMMY_ACTION_CALL); } - /** - * Test of setUseOnlyAliases method, of class ApplicationConfig. - */ + /** Test of setUseOnlyAliases method, of class ApplicationConfig. */ @Test public void testSetUseOnlyAliases() { - log.info("setUseOnlyAliases"); ApplicationConfig instance = new ApplicationConfig(); Assert.assertEquals(false, instance.isUseOnlyAliases()); instance.setUseOnlyAliases(false); @@ -193,11 +317,11 @@ /** * Test of addAlias method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testAddAlias() throws Exception { - log.info("addAlias"); ApplicationConfig instance = new ApplicationConfig(); instance.addAlias("toto", "totochange"); instance.addAlias("titi", "titichange"); @@ -215,23 +339,17 @@ Assert.assertEquals(expResult, result); } - /** - * Test of setConfigFileName method, of class ApplicationConfig. - */ + /** Test of setConfigFileName method, of class ApplicationConfig. */ @Test public void testSetConfigFileName() { - log.info("setConfigFileName"); ApplicationConfig instance = new ApplicationConfig(); instance.setConfigFileName("bidulle"); Assert.assertEquals("bidulle", instance.getConfigFileName()); } - /** - * Test of setOption method, of class ApplicationConfig. - */ + /** Test of setOption method, of class ApplicationConfig. */ @Test public void testSetOption() { - log.info("setOption"); ApplicationConfig instance = new ApplicationConfig(); Assert.assertEquals(null, instance.getOption("truc")); instance.setOption("truc", "bidulle"); @@ -260,9 +378,7 @@ // TODO ajouter d'autres tests pour des sub-(sub-(sub)) config } - /** - * Test convertion to list - */ + /** Test convertion to list */ @Test public void testGetAsList() { List<String> asString = new ArrayList<String>(); @@ -278,18 +394,15 @@ Assert.assertEquals(Collections.EMPTY_LIST, instance.getOptionAsList("truc").getOption()); instance.setOption("truc", ApplicationConfig.class.getName() - + "," + ApplicationConfigTest.class.getName()); + + "," + ApplicationConfigTest.class.getName()); Assert.assertEquals(asString, instance.getOptionAsList("truc").getOption()); Assert.assertEquals(asClass, instance.getOptionAsList("truc").getOptionAsClass()); } - /** - * Test of getMethods method, of class ApplicationConfig. - */ + /** Test of getMethods method, of class ApplicationConfig. */ @Test public void testGetMethods() { - log.info("getMethods"); ApplicationConfig instance = new ApplicationConfig(); Map<String, Method> result = instance.getMethods(); Assert.assertTrue(result.containsKey("option")); @@ -297,11 +410,11 @@ /** * Test of getParams method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testGetParams() throws Exception { - log.info("getParams"); Method m = DummyAction.class.getMethod("dummyAction", String.class, Integer.TYPE); List<String> list = new ArrayList<String>(Arrays.asList("toto", "10", "/tmp", "9")); ListIterator<String> args = list.listIterator(); @@ -315,11 +428,11 @@ /** * Test of createAction method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testCreateAction() throws Exception { - log.info("createAction"); List<String> list = new ArrayList<String>(Arrays.asList("dummy", "toto", "10", "/tmp", "9")); ListIterator<String> args = list.listIterator(); args.next(); @@ -335,11 +448,11 @@ /** * Test of parse method, of class ApplicationConfig. + * * @throws Exception */ @Test public void testParse() throws Exception { - log.info("parse"); String[] args = "-f file -v -d -o /tmp/file -m coucou 10 others args".split(" "); ApplicationConfig instance = new ApplicationConfig(); instance.addAlias("-f", "--option", "file"); @@ -363,6 +476,7 @@ /** * Test that system properties such as ${user.home}, ${user.name} are * replaced. + * * @throws ArgumentsParserException */ @Test @@ -378,7 +492,7 @@ instance.setOption("tempdir", "${java.io.tmpdir}" + File.separator + "blah"); File tempDir = instance.getOptionAsFile("tempdir"); - Assert.assertEquals(new File(System.getProperty("java.io.tmpdir") , "blah").getAbsolutePath(), tempDir.getAbsolutePath()); + Assert.assertEquals(new File(System.getProperty("java.io.tmpdir"), "blah").getAbsolutePath(), tempDir.getAbsolutePath()); instance.setOption("system", "${os.name}"); instance.setOption("os", "${system}"); @@ -392,6 +506,7 @@ /** * Test unparsed options + * * @throws Exception */ @Test @@ -410,6 +525,7 @@ /** * Test get flat options method. + * * @throws Exception */ @Test @@ -427,17 +543,18 @@ // test replacement and non replacement Assert.assertEquals("tutu toto", - instance.getFlatOptions().getProperty("user.fullname")); + instance.getFlatOptions().getProperty("user.fullname")); Assert.assertEquals("tutu toto", - instance.getFlatOptions(true).getProperty("user.fullname")); + instance.getFlatOptions(true).getProperty("user.fullname")); Assert.assertEquals("${user.lastname} ${user.firstname}", - instance.getFlatOptions(false).getProperty("user.fullname")); + instance.getFlatOptions(false).getProperty("user.fullname")); } /** * Test null options. + * <p/> + * TODO EC20100503 this test throw a huge exception * - * TODO EC20100503 this test throw a huge exception * @throws Exception */ @Test