Introduce ConfigFileBuilder class.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/26155757
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/26155757
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/26155757

Branch: refs/heads/master
Commit: 2615575787b2b8e302068e6170e64e19f05b7e38
Parents: b37a47d
Author: JamesBognar <[email protected]>
Authored: Wed Mar 29 20:39:56 2017 -0400
Committer: JamesBognar <[email protected]>
Committed: Wed Mar 29 20:39:56 2017 -0400

----------------------------------------------------------------------
 .../juneau/ini/ConfigFileBuilderTest.java       | 196 ++++++++++++
 .../org/apache/juneau/ini/ConfigFileTest.java   | 138 ++++----
 .../org/apache/juneau/ini/ConfigMgrTest.java    | 204 ------------
 .../java/org/apache/juneau/ini/ConfigFile.java  |   1 -
 .../apache/juneau/ini/ConfigFileBuilder.java    | 311 ++++++++++++++++++
 .../java/org/apache/juneau/ini/ConfigMgr.java   | 314 -------------------
 .../java/org/apache/juneau/ini/package.html     |  33 +-
 .../apache/juneau/svl/vars/ConfigFileVar.java   |   2 +-
 juneau-core/src/main/javadoc/overview.html      |  21 +-
 .../juneau/microservice/Microservice.java       |   7 +-
 .../microservice/resources/ConfigResource.java  |   2 +-
 .../org/apache/juneau/rest/client/package.html  |   2 +-
 .../java/org/apache/juneau/rest/RestConfig.java |   6 +-
 .../java/org/apache/juneau/rest/package.html    |   2 +-
 14 files changed, 611 insertions(+), 628 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileBuilderTest.java
 
b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileBuilderTest.java
new file mode 100755
index 0000000..7a3501e
--- /dev/null
+++ 
b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileBuilderTest.java
@@ -0,0 +1,196 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.ini;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.svl.*;
+import org.junit.*;
+
+@SuppressWarnings("javadoc")
+public class ConfigFileBuilderTest {
+
+       private static File tempDir;
+       private static String[] TEMP_DIR;
+
+       @BeforeClass
+       public static void setup() {
+               tempDir = new File(System.getProperty("java.io.tmpdir"), 
StringUtils.generateUUID(12));
+               FileUtils.mkdirs(tempDir, true);
+               TEMP_DIR = new String[]{tempDir.getAbsolutePath()};
+       }
+
+       @AfterClass
+       public static void teardown() {
+               FileUtils.delete(tempDir);
+       }
+
+       /**
+        * 
+        * @throws Exception
+        */
+       @Test
+       public void testGet() throws Exception {
+               File f;
+               ConfigFileBuilder b1 = new 
ConfigFileBuilder().paths(TEMP_DIR).createIfNotExists();
+
+               ConfigFile cf = b1.build("TestGet.cfg");
+               cf.put("Test/A", "a");
+
+               f = new File(tempDir, "TestGet.cfg");
+               assertTrue(f.exists());
+
+               cf.save();
+               assertTextEquals("[Test]|A = a|", IOUtils.read(f));
+
+               cf = b1.build("TestGet.cfg");
+               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
+
+               String NL = System.getProperty("line.separator");
+               cf = b1.build(new StringReader(("[Test]"+NL+"A = a"+NL)));
+               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
+
+               b1.charset(IOUtils.UTF8);
+               cf = b1.build("TestGet.cfg");
+               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
+       }
+       
+       /**
+        * Retrieving config file should fail if the file doesn't exist and 
createIfNotExist == false.
+        */
+       @Test
+       public void testFailOnNonExistentFiles() throws Exception {
+               ConfigFileBuilder b = new ConfigFileBuilder().paths(new 
String[]{tempDir.getAbsolutePath()});
+               try { b.build("TestGet2.cfg"); fail(); } catch 
(FileNotFoundException e) {}
+               try { b.build(tempDir.getAbsolutePath() + "TestGet2.cfg"); 
fail(); } catch (FileNotFoundException e) {}
+
+               b = new ConfigFileBuilder().paths().createIfNotExists();
+               try { b.build("TestGet.cfg"); fail(); } catch 
(FileNotFoundException e) {}
+       }       
+
+       
+       
//====================================================================================================
+       // loadIfModified()
+       
//====================================================================================================
+       @Test
+       public void testLoadIfModified() throws Exception {
+               ConfigFileBuilder b = new 
ConfigFileBuilder().paths(TEMP_DIR).createIfNotExists();
+               File f;
+               ConfigFile cf = b.build("TestGet.cfg");
+               cf.put("Test/A", "a");
+
+               f = new File(tempDir, "TestGet.cfg");
+               String NL = System.getProperty("line.separator");
+               IOUtils.write(f, new StringReader("[Test]"+NL+"A = b"+NL));
+               FileUtils.modifyTimestamp(f);
+
+               cf.loadIfModified();
+               assertEquals("b", cf.getString("Test/A"));
+               cf.loadIfModified();
+               assertEquals("b", cf.getString("Test/A"));
+
+               // Config file with no backing file.
+               cf = b.build();
+               cf.put("Test/B", "b");
+               cf.loadIfModified();
+               cf.loadIfModified();
+               assertEquals("b", cf.getString("Test/B"));
+       }
+
+       
//====================================================================================================
+       // read only
+       
//====================================================================================================
+       @Test
+       public void testReadOnly() throws Exception {
+               ConfigFileBuilder cm = new 
ConfigFileBuilder().paths(TEMP_DIR).createIfNotExists().readOnly();
+               ConfigFile cf = cm.build("TestGet.cfg");
+
+               // All these should fail.
+               try { cf.loadIfModified(); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.load(); fail(); } catch (UnsupportedOperationException 
e) {}
+               try { cf.load(new StringReader("")); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.put("A","b"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.put("A","b",true); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.put("A","b"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.put("A","b",true); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.removeString("A"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.addLines("A","b=c"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.addHeaderComments("A", "b=c"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.clearHeaderComments("A"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.addSection("A"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.setSection("A",null); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.removeSection("A"); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.save(); fail(); } catch (UnsupportedOperationException 
e) {}
+               try { cf.merge(cf); fail(); } catch 
(UnsupportedOperationException e) {}
+               try { cf.addListener(new ConfigFileListener(){}); fail(); } 
catch (UnsupportedOperationException e) {}
+
+               // All these should succeed.
+               cf.getObject(String.class, "A");
+               cf.getObject(String.class, "A", "a");
+               cf.getString("A");
+               cf.getString("A","a");
+               cf.getObject(String.class, "A");
+               cf.getObject(String.class, "A", "a");
+               cf.getObject(String[].class, "A");
+               cf.getStringArray("A");
+               cf.getStringArray("A", null);
+               cf.getInt("A");
+               cf.getInt("A", 0);
+               cf.getBoolean("A");
+               cf.getBoolean("A", true);
+               cf.containsNonEmptyValue("A");
+               cf.getSectionMap("A");
+               cf.serializeTo(new StringWriter());
+               cf.serializeTo(new StringWriter(), ConfigFileFormat.INI);
+               cf.getResolving(VarResolver.DEFAULT);
+               cf.toWritable();
+       }
+
+       
//====================================================================================================
+       // main(String[] args)
+       
//====================================================================================================
+       @Test
+       public void testMain() throws Exception {
+               System.setProperty("exit.2", "0");
+               ConfigFileBuilder cm = new 
ConfigFileBuilder().paths(TEMP_DIR).createIfNotExists();
+
+               ConfigFile cf = cm.build("Test.cfg")
+                       .addLines(null, "# c1", "\t# c2", " c3 ", "  ", "x1=1", 
"x2=true", "x3=null")
+                       .addLines("s1", "#c4", "k1=1", "#c5 foo=bar", "k2 = 
true", "k3  = \tnull");
+               cf.save();
+
+               File configFile = new File(tempDir, "Test.cfg");
+               File envFile = new File(tempDir, "Test.bat");
+
+               ConfigFileBuilder.main(new String[]{"createBatchEnvFile", 
"-configFile", configFile.getAbsolutePath(), "-envFile", 
envFile.getAbsolutePath()});
+               String expected = "rem c1|rem c2|rem c3||set x1 = 1|set x2 = 
true|set x3 = null|rem c4|set s1_k1 = 1|rem c5 foo=bar|set s1_k2 = true|set 
s1_k3 = null|";
+               String actual = IOUtils.read(envFile);
+               assertTextEquals(expected, actual);
+
+               ConfigFileBuilder.main(new String[]{"createShellEnvFile", 
"-configFile", configFile.getAbsolutePath(), "-envFile", 
envFile.getAbsolutePath()});
+               expected = "# c1|# c2|# c3||export x1=\"1\"|export 
x2=\"true\"|export x3=\"null\"|# c4|export s1_k1=\"1\"|# c5 foo=bar|export 
s1_k2=\"true\"|export s1_k3=\"null\"|";
+               actual = IOUtils.read(envFile);
+               assertTextEquals(expected, actual);
+
+               ConfigFileBuilder.main(new String[]{"setVals", "-configFile", 
configFile.getAbsolutePath(), "-vals", "x1=2", "s1/k1=2", "s2/k1=3"});
+               FileUtils.modifyTimestamp(configFile);
+               cf.loadIfModified();
+               
assertObjectEquals("{'default':{x1:'2',x2:'true',x3:'null'},s1:{k1:'2',k2:'true',k3:'null'},s2:{k1:'3'}}",
 cf);
+
+               ConfigFileBuilder.main(new String[]{});
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
index 6e813a2..21c8287 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigFileTest.java
@@ -32,6 +32,8 @@ import org.junit.*;
 @SuppressWarnings("javadoc")
 public class ConfigFileTest {
 
+       private ConfigFileBuilder configFileBuilder = new ConfigFileBuilder();
+       
        private File getFreshFile() {
                String tempDir = System.getProperty("java.io.tmpdir");
                File f = new File(tempDir, "Test.cfg");
@@ -49,7 +51,7 @@ public class ConfigFileTest {
 
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f)
+               ConfigFile cf = configFileBuilder.build(f)
                        .addLines(null, "# c1", "\t# c2", " c3 ");
                ConfigFile cfw = cf.getResolving(VarResolver.DEFAULT);
 
@@ -58,7 +60,7 @@ public class ConfigFileTest {
                assertTextEquals(expected, cfw);
 
                cf.save();
-               cf = ConfigMgr.DEFAULT.create(f);
+               cf = configFileBuilder.build(f);
                expected = "# c1|\t# c2| c3 |";
                assertTextEquals(expected, cf);
                assertTextEquals(expected, cfw);
@@ -73,7 +75,7 @@ public class ConfigFileTest {
 
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f)
+               ConfigFile cf = configFileBuilder.build(f)
                        .addLines(null, "# c1", "\t# c2", " c3 ", "x1=1", 
"x2=true", "x3=null")
                        .addLines("s1", "#c4", "k1=1", "#c5 foo=bar", "k2 = 
true", "k3  = \tnull");
                ConfigFile cfw = cf.getResolving().getResolving();
@@ -83,7 +85,7 @@ public class ConfigFileTest {
                assertTextEquals(expected, cfw);
 
                cf.save();
-               cf = ConfigMgr.DEFAULT.create(f);
+               cf = configFileBuilder.build(f);
                cfw = cf.getResolving(VarResolver.DEFAULT);
                assertEquals(1, cf.getInt("x1"));
                assertEquals(true, cf.getBoolean("x2"));
@@ -138,7 +140,7 @@ public class ConfigFileTest {
        @Test
        public void testSerialization() throws Exception {
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                cf.put("x1", 1);
 
                String expected = "{'default':{x1:'1'}}";
@@ -153,8 +155,8 @@ public class ConfigFileTest {
        @Test
        public void testHeaderComments() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create(getFreshFile()).addLines(null, 
"x").addLines("s1", "#c3", "#c4").addHeaderComments("s1", "#c1", "#c2"),
-                       ConfigMgr.DEFAULT.create(getFreshFile()).addLines(null, 
"x").addLines("s1", "#c3", "#c4").addHeaderComments("s1", "#c1", 
"#c2").getResolving()
+                       configFileBuilder.build(getFreshFile()).addLines(null, 
"x").addLines("s1", "#c3", "#c4").addHeaderComments("s1", "#c1", "#c2"),
+                       configFileBuilder.build(getFreshFile()).addLines(null, 
"x").addLines("s1", "#c3", "#c4").addHeaderComments("s1", "#c1", 
"#c2").getResolving()
                };
 
                for (ConfigFile cf : cff) {
@@ -185,7 +187,7 @@ public class ConfigFileTest {
 
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f)
+               ConfigFile cf = configFileBuilder.build(f)
                        .addLines(null, "x1=1")
                        .addLines("s1", "x2=2");
                ConfigFile cfw = cf.getResolving(VarResolver.DEFAULT);
@@ -221,7 +223,7 @@ public class ConfigFileTest {
        @Test
        public void testPut() throws Exception {
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                ConfigFile cfw = cf.getResolving(VarResolver.DEFAULT);
 
                cf.addSection(null);
@@ -257,7 +259,7 @@ public class ConfigFileTest {
        @Test
        public void testExampleInConfigFile() throws Exception {
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "# Default section", "key1 = 1", "key2 
= true", "key3 = 1,2,3", "key4 = 'http://foo'", "")
                        .addHeaderComments("section1", "# Section 1")
                        .addLines("section1", "key1 = 2", "key2 = false", "key3 
= 4,5,6", "key4 = 'http://bar'");
@@ -287,7 +289,7 @@ public class ConfigFileTest {
                assertEquals(6, cfw.getObject(int[].class, "section1/key3")[2]);
                assertEquals(new URL("http://bar";).toString(), 
cfw.getObject(URL.class, "section1/key4").toString());
 
-               cf = ConfigMgr.DEFAULT.create(getFreshFile())
+               cf = configFileBuilder.build(getFreshFile())
                        .addLines(null, "# Default section")
                        .addHeaderComments("section1", "# Section 1");
                cfw = cf.getResolving(VarResolver.DEFAULT);
@@ -362,7 +364,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testEnum() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create(getFreshFile())
+               ConfigFile cf = configFileBuilder.build(getFreshFile())
                        .addLines(null, "key1 = 'MINUTES'");
                ConfigFile cfw = cf.getResolving(VarResolver.DEFAULT);
 
@@ -381,7 +383,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testBatchFileGeneration() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "# c1", "\t# c2", " c3 ", "", "  ", 
"x1=1", "x2=true", "x3=null")
                        .addHeaderComments(null, "header null", "", null)
                        .addLines("s1", "#c4", "k1=1", "#c5 foo=bar", "k2 = 
true", "k3  = \tnull")
@@ -404,7 +406,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testShellScriptGeneration() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "# c1", "\t# c2", " c3 ", "", " ", 
"x1=1", "x2=true", "x3=null")
                        .addHeaderComments(null, "header null", "", null)
                        .addLines("s1", "#c4", "k1=1", "#c5 foo=bar", "k2 = 
true", "k3  = \tnull")
@@ -429,7 +431,7 @@ public class ConfigFileTest {
        public void testEncodedValues() throws Exception {
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f)
+               ConfigFile cf = configFileBuilder.build(f)
                        .addLines("s1", "", "foo* = mypassword")
                        .getResolving(VarResolver.DEFAULT);
                ConfigFile cfw = cf.getResolving(VarResolver.DEFAULT);
@@ -479,7 +481,7 @@ public class ConfigFileTest {
        @Test
        public void testVariables() throws Exception {
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines("s1",
                                "f1 = $S{foo}",
                                "f2 = $S{foo,bar}",
@@ -550,7 +552,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testMultiLines() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines("s1",
                                "f1 = x \ny \n  z"
                );
@@ -574,7 +576,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testNumberShortcuts() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines("s1",
                                "f1 = 1M",
                                "f2 = 1K",
@@ -600,8 +602,8 @@ public class ConfigFileTest {
        @Test
        public void testListeners() throws Exception {
                ConfigFile[] cff = {
-                       
ConfigMgr.DEFAULT.create(FileUtils.createTempFile("ConfigFileTest.cfg")).addLines(null,
 "a1=1").addLines("B", "b1=1"),
-                       
ConfigMgr.DEFAULT.create(FileUtils.createTempFile("ConfigFileTest.cfg")).addLines(null,
 "a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
+                       
configFileBuilder.build(FileUtils.createTempFile("ConfigFileTest.cfg")).addLines(null,
 "a1=1").addLines("B", "b1=1"),
+                       
configFileBuilder.build(FileUtils.createTempFile("ConfigFileTest.cfg")).addLines(null,
 "a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
                };
 
                for (ConfigFile cf : cff) {
@@ -732,7 +734,7 @@ public class ConfigFileTest {
                        assertEquals(1, count[0]);
 
                        // putAll(map)
-                       ConfigFile cf2 = ConfigMgr.DEFAULT.create();
+                       ConfigFile cf2 = configFileBuilder.build();
                        cf2.addLines("D", "d1=1","d2=1").addLines("E", 
"e1=1","e2=2");
                        changes.clear();
                        count[0] = 0;
@@ -916,8 +918,8 @@ public class ConfigFileTest {
        @Test
        public void testEntryListener() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("B", "b1=1"),
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("B", "b1=1"),
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
                };
 
                for (ConfigFile cf : cff) {
@@ -960,8 +962,8 @@ public class ConfigFileTest {
        @Test
        public void testSectionListener() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("B", "b1=1"),
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("B", "b1=1"),
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("B", "b1=1").getResolving(VarResolver.DEFAULT)
                };
 
                for (ConfigFile cf : cff) {
@@ -1014,11 +1016,11 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testMerge() throws Exception {
-               ConfigFile cf1 = ConfigMgr.DEFAULT.create()
+               ConfigFile cf1 = configFileBuilder.build()
                        .addLines(null, "# comment a1", "a1=1")
                        .addLines("B", "# comment b1", 
"b1=1").addHeaderComments("B", "# comment B1")
                        .addLines("C", "# comment c1", 
"bc=1").addHeaderComments("C", "# comment C1");
-               ConfigFile cf2 = ConfigMgr.DEFAULT.create()
+               ConfigFile cf2 = configFileBuilder.build()
                        .addLines(null, "# comment a2", "a2=2")
                        .addLines("B", "# comment b2", 
"b2=2").addHeaderComments("B", "# comment B2")
                        .addLines("D", "# comment d2", 
"d2=2").addHeaderComments("D", "# comment D2");
@@ -1027,11 +1029,11 @@ public class ConfigFileTest {
                String expected = "# comment a2|a2 = 2|# comment B2|[B]|# 
comment b2|b2 = 2|# comment D2|[D]|# comment d2|d2 = 2|";
                assertTextEquals(expected, cf1);
 
-               cf1 = ConfigMgr.DEFAULT.create()
+               cf1 = configFileBuilder.build()
                        .addLines(null, "# comment a1", "a1=1")
                        .addLines("B", "# comment b1", 
"b1=1").addHeaderComments("B", "# comment B1")
                        .addLines("C", "# comment c1", 
"bc=1").addHeaderComments("C", "# comment 
C1").getResolving(VarResolver.DEFAULT);
-               cf2 = ConfigMgr.DEFAULT.create()
+               cf2 = configFileBuilder.build()
                        .addLines(null, "# comment a2", "a2=2")
                        .addLines("B", "# comment b2", 
"b2=2").addHeaderComments("B", "# comment B2")
                        .addLines("D", "# comment d2", 
"d2=2").addHeaderComments("D", "# comment 
D2").getResolving(VarResolver.DEFAULT);
@@ -1047,8 +1049,8 @@ public class ConfigFileTest {
        @Test
        public void testDefaultSection() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", "a3=3"),
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", 
"a3=3").getResolving(VarResolver.DEFAULT)
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", "a3=3"),
+                       configFileBuilder.build().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", 
"a3=3").getResolving(VarResolver.DEFAULT)
                };
 
                for (ConfigFile cf : cff) {
@@ -1095,7 +1097,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testContains() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", "a3=3").addLines("A", "a4=4");
+               ConfigFile cf = configFileBuilder.build().addLines(null, 
"a1=1").addLines("", "a2=2").addLines("default", "a3=3").addLines("A", "a4=4");
                ConfigFile cfw = cf.getResolving();
 
                assertTrue(cf.containsKey(null));
@@ -1141,7 +1143,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetObjectArray() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines("A", 
"a1=1,2,3");
+               ConfigFile cf = configFileBuilder.build().addLines("A", 
"a1=1,2,3");
                ConfigFile cfw = cf.getResolving();
                assertObjectEquals("[1,2,3]", cf.getObject(Integer[].class, 
"A/a1"));
                assertObjectEquals("[1,2,3]", cfw.getObject(Integer[].class, 
"A/a1"));
@@ -1152,7 +1154,7 @@ public class ConfigFileTest {
                assertObjectEquals("[]", cf.getObject(Integer[].class, "B/a1"));
                assertObjectEquals("[]", cfw.getObject(Integer[].class, 
"B/a1"));
 
-               cf = ConfigMgr.DEFAULT.create().addLines("A", "a1 = 1 ,\n\t2 
,\n\t3 ");
+               cf = configFileBuilder.build().addLines("A", "a1 = 1 ,\n\t2 
,\n\t3 ");
                assertObjectEquals("[1,2,3]", cf.getObject(Integer[].class, 
"A/a1"));
                assertObjectEquals("[1,2,3]", cfw.getObject(Integer[].class, 
"A/a1"));
 
@@ -1172,7 +1174,7 @@ public class ConfigFileTest {
                assertEquals("int", cf.getObject(int[].class, "A/a2", new 
int[]{4}).getClass().getComponentType().getSimpleName());
 
                System.setProperty("X", "4,5,6");
-               cf = ConfigMgr.DEFAULT.create().addLines(null, "x1=$C{A/a1}", 
"x2=$S{X}", "x3=$S{Y}").addLines("A", "a1=1,2,3").getResolving();
+               cf = configFileBuilder.build().addLines(null, "x1=$C{A/a1}", 
"x2=$S{X}", "x3=$S{Y}").addLines("A", "a1=1,2,3").getResolving();
                assertObjectEquals("[1,2,3]", cf.getObject(int[].class, "x1", 
new int[]{9}));
                assertObjectEquals("[4,5,6]", cf.getObject(int[].class, "x2", 
new int[]{9}));
                assertObjectEquals("[9]", cf.getObject(int[].class, "x3", new 
int[]{9}));
@@ -1185,7 +1187,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetStringArray() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines("A", 
"a1=1,2,3");
+               ConfigFile cf = configFileBuilder.build().addLines("A", 
"a1=1,2,3");
                ConfigFile cfw = cf.getResolving();
                assertObjectEquals("['1','2','3']", cf.getStringArray("A/a1"));
                assertObjectEquals("['1','2','3']", cfw.getStringArray("A/a1"));
@@ -1196,12 +1198,12 @@ public class ConfigFileTest {
                assertObjectEquals("[]", cf.getStringArray("B/a1"));
                assertObjectEquals("[]", cfw.getStringArray("B/a1"));
 
-               cf = ConfigMgr.DEFAULT.create().addLines("A", "a1 = 1 ,\n\t2 
,\n\t3 ");
+               cf = configFileBuilder.build().addLines("A", "a1 = 1 ,\n\t2 
,\n\t3 ");
                assertObjectEquals("['1','2','3']", cf.getStringArray("A/a1"));
                assertObjectEquals("['1','2','3']", cfw.getStringArray("A/a1"));
 
                System.setProperty("X", "4,5,6");
-               cf = ConfigMgr.DEFAULT.create().addLines(null, "x1=$C{A/a1}", 
"x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,$S{X}}").addLines("A", 
"a1=1,2,3").getResolving();
+               cf = configFileBuilder.build().addLines(null, "x1=$C{A/a1}", 
"x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,$S{X}}").addLines("A", 
"a1=1,2,3").getResolving();
                assertObjectEquals("['1','2','3']", cf.getStringArray("x1", new 
String[]{"9"}));
                assertObjectEquals("['4','5','6']", cf.getStringArray("x2", new 
String[]{"9"}));
                assertObjectEquals("['9']", cf.getStringArray("x3", new 
String[]{"9"}));
@@ -1216,7 +1218,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetSectionMap() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines("A", 
"a1=1", "").addLines("D", "d1=$C{A/a1}","d2=$S{X}");
+               ConfigFile cf = configFileBuilder.build().addLines("A", "a1=1", 
"").addLines("D", "d1=$C{A/a1}","d2=$S{X}");
 
                assertObjectEquals("{a1:'1'}", cf.getSectionMap("A"));
                assertNull(cf.getSectionMap("B"));
@@ -1242,8 +1244,8 @@ public class ConfigFileTest {
        @Test
        public void testLoadFromReader() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create().addLines(null, "a1=1"),
-                       ConfigMgr.DEFAULT.create().addLines(null, 
"a1=1").getResolving(VarResolver.DEFAULT)
+                       configFileBuilder.build().addLines(null, "a1=1"),
+                       configFileBuilder.build().addLines(null, 
"a1=1").getResolving(VarResolver.DEFAULT)
                };
 
                for (ConfigFile cf : cff) {
@@ -1258,7 +1260,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testToWritable() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "a=b");
                ConfigFile cfw = cf.getResolving();
 
@@ -1279,7 +1281,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testContainsNonEmptyKey() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "a=b","c=");
                ConfigFile cfw = cf.getResolving();
 
@@ -1306,7 +1308,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetSectionKeys() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1", "x2=")
                        .addLines("A", "a1=1", "a2=");
 
@@ -1330,7 +1332,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testAddLines() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1342,7 +1344,7 @@ public class ConfigFileTest {
                
assertObjectEquals("{'default':{x1:'2',x2:'1'},A:{a1:'2',a2:'1'},B:{b1:'2',b2:'1'},C:{}}",
 cf);
                assertTextEquals("# comment1|x1 = 2|x2 = 1|foobar|[A]|# 
comment2|a1 = 2|a2 = 1|foobar|[B]|# comment3|b1 = 2|b2 = 1|foobar|[C]||", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1355,7 +1357,7 @@ public class ConfigFileTest {
                
assertObjectEquals("{'default':{x1:'2',x2:'1'},A:{a1:'2',a2:'1'},B:{b1:'2',b2:'1'},C:{}}",
 cf);
                assertTextEquals("# comment1|x1 = 2|x2 = 1|foobar|[A]|# 
comment2|a1 = 2|a2 = 1|foobar|[B]|# comment3|b1 = 2|b2 = 1|foobar|[C]||", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=$C{A/a2}")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1376,7 +1378,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testAddHeaderComments() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1390,7 +1392,7 @@ public class ConfigFileTest {
 
                assertTextEquals("# h1|# h2|# h3|x1 = 1|# h4|[A]|a1 = 1|# 
h5|[B]|#|[C]|", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1407,7 +1409,7 @@ public class ConfigFileTest {
                
cf.clearHeaderComments(null).clearHeaderComments("A").clearHeaderComments("B").clearHeaderComments("C");
                assertTextEquals("x1 = 1|[A]|a1 = 1|[B]|[C]|", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1433,7 +1435,7 @@ public class ConfigFileTest {
        @Test
        public void testGetString() throws Exception {
                System.setProperty("S1", "1");
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1", "x2=$C{A/a2}", "x3=$S{S1,2}", 
"x4=$S{S2,3}")
                        .addLines("A", "a1=1", "a2=$C{A/a1}", "a3=$S{S1,2}", 
"a4=$S{S2,3}");
 
@@ -1497,7 +1499,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testPutString() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1510,7 +1512,7 @@ public class ConfigFileTest {
                
assertObjectEquals("{'default':{x1:'2',x2:'3'},A:{a1:'2',a2:'3'},B:{b1:'2'}}", 
cf);
                assertTextEquals("x1 = 2|x2 = 3|[A]|a1 = 2|a2 = 3|[B]|b1 = 2|", 
cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1545,7 +1547,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testPutStringEncoded() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1558,7 +1560,7 @@ public class ConfigFileTest {
                
assertObjectEquals("{'default':{x1:'2',x2:'3'},A:{a1:'2',a2:'3'},B:{b1:'2'}}", 
cf);
                assertTextEquals("x1* = {XA==}|x2* = {XQ==}|[A]|a1* = 
{XA==}|a2* = {XQ==}|[B]|b1* = {XA==}|", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1593,7 +1595,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testRemoveString() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create()
+               ConfigFile cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1");
 
@@ -1605,7 +1607,7 @@ public class ConfigFileTest {
                assertObjectEquals("{'default':{},A:{}}", cf);
                assertTextEquals("[A]|", cf);
 
-               cf = ConfigMgr.DEFAULT.create()
+               cf = configFileBuilder.build()
                        .addLines(null, "x1=1")
                        .addLines("A", "a1=1")
                        .getResolving();
@@ -1625,7 +1627,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetObject() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines("A", 
"a1=1,2,3", "a2=1", "a3=true", "a4=1.2", "a5=1.2,3.4");
+               ConfigFile cf = configFileBuilder.build().addLines("A", 
"a1=1,2,3", "a2=1", "a3=true", "a4=1.2", "a5=1.2,3.4");
                ConfigFile cfw = cf.getResolving();
 
                assertObjectEquals("['1','2','3']", 
cf.getObject(String[].class, "A/a1"));
@@ -1662,7 +1664,7 @@ public class ConfigFileTest {
        @Test
        public void testGetInt() throws Exception {
                System.setProperty("X", "1");
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines(null, 
"x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,2}").addLines("A", "a1=1");
+               ConfigFile cf = configFileBuilder.build().addLines(null, 
"x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,2}").addLines("A", "a1=1");
 
                try {
                        cf.getInt("x1");
@@ -1704,7 +1706,7 @@ public class ConfigFileTest {
        @Test
        public void testGetBoolean() throws Exception {
                System.setProperty("X", "true");
-               ConfigFile cf = ConfigMgr.DEFAULT.create().addLines(null, 
"x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,true}").addLines("A", 
"a1=true");
+               ConfigFile cf = configFileBuilder.build().addLines(null, 
"x1=$C{A/a1}", "x2=$S{X}", "x3=$S{Y}", "x4=$S{Y,true}").addLines("A", 
"a1=true");
 
                assertFalse(cf.getBoolean("x1"));
                assertFalse(cf.getBoolean("x2"));
@@ -1732,7 +1734,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testGetSectionAsBean() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                cf.put("A/a", "1");
                cf.put("A/b", "2");
 
@@ -1769,7 +1771,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testWriteProperties() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                cf.put("B/a", "1");
 
                B b = new B();
@@ -1865,8 +1867,8 @@ public class ConfigFileTest {
        @Test
        public void testBadInput() throws Exception {
                ConfigFile[] cff = {
-                       ConfigMgr.DEFAULT.create().addLines("A", "a1=1", ""),
-                       ConfigMgr.DEFAULT.create().addLines("A", "a1=1", 
"").getResolving()
+                       configFileBuilder.build().addLines("A", "a1=1", ""),
+                       configFileBuilder.build().addLines("A", "a1=1", 
"").getResolving()
                };
 
                for (ConfigFile cf : cff) {
@@ -2022,7 +2024,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testSerializedAsJson() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                cf.put("a", "1");
                cf.put("B/a", "2");
 
@@ -2039,7 +2041,7 @@ public class ConfigFileTest {
        
//====================================================================================================
        @Test
        public void testResolvingWithOverride() throws Exception {
-               ConfigFile cf = ConfigMgr.DEFAULT.create();
+               ConfigFile cf = configFileBuilder.build();
                cf.put("a", "$A{X}");
                cf.put("b", "$B{X}");
                cf.put("c", "$A{$B{X}}");
@@ -2115,7 +2117,7 @@ public class ConfigFileTest {
        public void testMultilineValues() throws Exception {
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f);
+               ConfigFile cf = configFileBuilder.build(f);
                cf.put("a", "a,\nb,\nc");
                cf.put("A/a", "a,\nb,\nc");
 
@@ -2138,7 +2140,7 @@ public class ConfigFileTest {
        public void testSpecialCharacterEncoding() throws Exception {
                File f = getFreshFile();
 
-               ConfigFile cf = ConfigMgr.DEFAULT.create(f);
+               ConfigFile cf = configFileBuilder.build(f);
                cf.put("a", "a,#b,=c");
                cf.put("A/a", "a,#b,=c");
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigMgrTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigMgrTest.java 
b/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigMgrTest.java
deleted file mode 100755
index 4039fcb..0000000
--- a/juneau-core-test/src/test/java/org/apache/juneau/ini/ConfigMgrTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.ini;
-
-import static org.apache.juneau.TestUtils.*;
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.nio.charset.*;
-
-import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.svl.*;
-import org.junit.*;
-
-@SuppressWarnings("javadoc")
-public class ConfigMgrTest {
-
-       private static File tempDir;
-
-       @BeforeClass
-       public static void setup() {
-               tempDir = new File(System.getProperty("java.io.tmpdir"), 
StringUtils.generateUUID(12));
-               FileUtils.mkdirs(tempDir, true);
-       }
-
-       @AfterClass
-       public static void teardown() {
-               FileUtils.delete(tempDir);
-       }
-
-       
//====================================================================================================
-       // get(String path)
-       // get(String path, boolean create)
-       
//====================================================================================================
-       @Test
-       public void testGet() throws Exception {
-               File f;
-               ConfigMgr cm = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), new 
String[]{tempDir.getAbsolutePath()});
-
-               ConfigFile cf = cm.get("TestGet.cfg", true);
-               cf.put("Test/A", "a");
-
-               f = new File(tempDir, "TestGet.cfg");
-               assertTrue(f.exists());
-
-               cf.save();
-               assertTextEquals("[Test]|A = a|", IOUtils.read(f));
-
-               cf = cm.get("TestGet.cfg");
-               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
-
-               ConfigFile cf2 = cm.get(tempDir.getAbsolutePath() + 
"/TestGet.cfg");
-               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf2);
-               assertTrue(cf == cf2);  // Relative and absolute paths must 
resolve to same config file.
-
-               try { cm.get("TestGet2.cfg"); fail(); } catch 
(FileNotFoundException e) {}
-               try { cm.get(tempDir.getAbsolutePath() + "TestGet2.cfg"); 
fail(); } catch (FileNotFoundException e) {}
-
-               cm.get(tempDir.getAbsolutePath() + "TestGet2.cfg", true);
-
-               ConfigMgr cm2 = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), new 
String[]{tempDir.getAbsolutePath()});
-               cf = cm2.get("TestGet.cfg");
-               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
-
-               cm2 = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), null);
-               try { cf = cm2.get("TestGet.cfg"); fail(); } catch 
(FileNotFoundException e) {}
-
-               String NL = System.getProperty("line.separator");
-               cf = cm2.create(new StringReader(("[Test]"+NL+"A = a"+NL)));
-               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
-
-               ConfigMgr cm3 = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, IOUtils.UTF8, new 
String[]{tempDir.getAbsolutePath()});
-               cf = cm3.get("TestGet.cfg");
-               assertObjectEquals("{'default':{},Test:{A:'a'}}", cf);
-
-               cm.deleteAll();
-               cm2.deleteAll();
-               cm3.deleteAll();
-       }
-
-       
//====================================================================================================
-       // loadIfModified()
-       
//====================================================================================================
-       @Test
-       public void testLoadIfModified() throws Exception {
-               ConfigMgr cm = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), new 
String[]{tempDir.getAbsolutePath()});
-               File f;
-               ConfigFile cf = cm.get("TestGet.cfg", true);
-               cf.put("Test/A", "a");
-
-               f = new File(tempDir, "TestGet.cfg");
-               String NL = System.getProperty("line.separator");
-               IOUtils.write(f, new StringReader("[Test]"+NL+"A = b"+NL));
-               FileUtils.modifyTimestamp(f);
-
-               cm.loadIfModified();
-               assertEquals("b", cf.getString("Test/A"));
-               cm.loadIfModified();
-               assertEquals("b", cf.getString("Test/A"));
-
-               // Config file with no backing file.
-               cf = cm.create();
-               cf.put("Test/B", "b");
-               cm.loadIfModified();
-               cf.loadIfModified();
-               assertEquals("b", cf.getString("Test/B"));
-
-               cm.deleteAll();
-       }
-
-       
//====================================================================================================
-       // read only
-       
//====================================================================================================
-       @Test
-       public void testReadOnly() throws Exception {
-               ConfigMgr cm = new ConfigMgr(true, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), new 
String[]{tempDir.getAbsolutePath()});
-               ConfigFile cf = cm.get("TestGet.cfg", true);
-
-               // All these should fail.
-               try { cf.loadIfModified(); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.load(); fail(); } catch (UnsupportedOperationException 
e) {}
-               try { cf.load(new StringReader("")); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.put("A","b"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.put("A","b",true); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.put("A","b"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.put("A","b",true); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.removeString("A"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.addLines("A","b=c"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.addHeaderComments("A", "b=c"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.clearHeaderComments("A"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.addSection("A"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.setSection("A",null); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.removeSection("A"); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.save(); fail(); } catch (UnsupportedOperationException 
e) {}
-               try { cf.merge(cf); fail(); } catch 
(UnsupportedOperationException e) {}
-               try { cf.addListener(new ConfigFileListener(){}); fail(); } 
catch (UnsupportedOperationException e) {}
-
-               // All these should succeed.
-               cf.getObject(String.class, "A");
-               cf.getObject(String.class, "A", "a");
-               cf.getString("A");
-               cf.getString("A","a");
-               cf.getObject(String.class, "A");
-               cf.getObject(String.class, "A", "a");
-               cf.getObject(String[].class, "A");
-               cf.getStringArray("A");
-               cf.getStringArray("A", null);
-               cf.getInt("A");
-               cf.getInt("A", 0);
-               cf.getBoolean("A");
-               cf.getBoolean("A", true);
-               cf.containsNonEmptyValue("A");
-               cf.getSectionMap("A");
-               cf.serializeTo(new StringWriter());
-               cf.serializeTo(new StringWriter(), ConfigFileFormat.INI);
-               cf.getResolving(VarResolver.DEFAULT);
-               cf.toWritable();
-       }
-
-       
//====================================================================================================
-       // main(String[] args)
-       
//====================================================================================================
-       @Test
-       public void testMain() throws Exception {
-               System.setProperty("exit.2", "0");
-               ConfigMgr cm = new ConfigMgr(false, new XorEncoder(), 
JsonSerializer.DEFAULT, JsonParser.DEFAULT, Charset.defaultCharset(), new 
String[]{tempDir.getAbsolutePath()});
-
-               ConfigFile cf = cm.get("Test.cfg", true)
-                       .addLines(null, "# c1", "\t# c2", " c3 ", "  ", "x1=1", 
"x2=true", "x3=null")
-                       .addLines("s1", "#c4", "k1=1", "#c5 foo=bar", "k2 = 
true", "k3  = \tnull");
-               cf.save();
-
-               File configFile = new File(tempDir, "Test.cfg");
-               File envFile = new File(tempDir, "Test.bat");
-
-               ConfigMgr.main(new String[]{"createBatchEnvFile", 
"-configFile", configFile.getAbsolutePath(), "-envFile", 
envFile.getAbsolutePath()});
-               String expected = "rem c1|rem c2|rem c3||set x1 = 1|set x2 = 
true|set x3 = null|rem c4|set s1_k1 = 1|rem c5 foo=bar|set s1_k2 = true|set 
s1_k3 = null|";
-               String actual = IOUtils.read(envFile);
-               assertTextEquals(expected, actual);
-
-               ConfigMgr.main(new String[]{"createShellEnvFile", 
"-configFile", configFile.getAbsolutePath(), "-envFile", 
envFile.getAbsolutePath()});
-               expected = "# c1|# c2|# c3||export x1=\"1\"|export 
x2=\"true\"|export x3=\"null\"|# c4|export s1_k1=\"1\"|# c5 foo=bar|export 
s1_k2=\"true\"|export s1_k3=\"null\"|";
-               actual = IOUtils.read(envFile);
-               assertTextEquals(expected, actual);
-
-               ConfigMgr.main(new String[]{"setVals", "-configFile", 
configFile.getAbsolutePath(), "-vals", "x1=2", "s1/k1=2", "s2/k1=3"});
-               FileUtils.modifyTimestamp(configFile);
-               cf.loadIfModified();
-               
assertObjectEquals("{'default':{x1:'2',x2:'true',x3:'null'},s1:{k1:'2',k2:'true',k3:'null'},s2:{k1:'3'}}",
 cf);
-
-               ConfigMgr.main(new String[]{});
-       }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFile.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFile.java 
b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFile.java
index 40a0f9e..d84242e 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFile.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFile.java
@@ -744,7 +744,6 @@ public abstract class ConfigFile implements 
Map<String,Section> {
                return null;
        }
 
-
        private static int parseIntWithSuffix(String s) {
                assertFieldNotNull(s, "s");
                int m = 1;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java 
b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
new file mode 100644
index 0000000..a699b4f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigFileBuilder.java
@@ -0,0 +1,311 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.ini;
+
+import static org.apache.juneau.ini.ConfigFileFormat.*;
+
+import java.io.*;
+import java.nio.charset.*;
+import java.util.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * Builder for creating instances of {@link ConfigFile ConfigFiles}.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bcode'>
+ *     ConfigFile cf = <jk>new</jk> 
ConfigFileBuilder().build(<js>"MyConfig.cfg"</js>);
+ *     String setting = cf.get(<js>"MySection/mysetting"</js>);
+ * </p>
+ */
+@SuppressWarnings("hiding")
+public class ConfigFileBuilder {
+
+       private WriterSerializer serializer = JsonSerializer.DEFAULT_LAX;
+       private ReaderParser parser = JsonParser.DEFAULT;
+       private Encoder encoder = new XorEncoder();
+       private boolean readOnly = false, createIfNotExists = false;
+       private Charset charset = Charset.defaultCharset();
+       private List<File> searchPaths = new AList<File>().append(new 
File("."));
+
+       /**
+        * Specify the encoder to use for encoded config file entries (e.g. 
<js>"mySecret*={...}"</js>).
+        * <p>
+        * The default value for this setting is an instance of {@link 
XorEncoder}.
+        *
+        * @param encoder The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder encoder(Encoder encoder) {
+               this.encoder = encoder;
+               return this;
+       }
+
+       /**
+        * Specify the serializer to use for serializing POJOs when using 
{@link ConfigFile#put(String, Object)}.
+        * <p>
+        * The default value for this setting is {@link 
JsonSerializer#DEFAULT_LAX}.
+        *
+        * @param serializer The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder serializer(WriterSerializer serializer) {
+               this.serializer = serializer;
+               return this;
+       }
+
+       /**
+        * Specify the parser to use for parsing POJOs when using {@link 
ConfigFile#getObject(Class,String)}.
+        * <p>
+        * The default value for this setting is {@link JsonParser#DEFAULT}
+        *
+        * @param parser The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder parser(ReaderParser parser) {
+               this.parser = parser;
+               return this;
+       }
+
+       /**
+        * Specify the config file character encoding.
+        * <p>
+        * The default value for this setting is {@link 
Charset#defaultCharset()}.
+        *
+        * @param charset The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder charset(Charset charset) {
+               this.charset = charset;
+               return this;
+       }
+
+       /**
+        * Specify the search paths for config files.
+        * <p>
+        * Can contain relative or absolute paths.
+        * <p>
+        * The default value for this setting is <code>[<js>"."</js>]</code>.
+        *
+        * @param searchPaths The new value for this setting.
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder paths(String...searchPaths) {
+               this.searchPaths = new LinkedList<File>();
+               for (String p : searchPaths)
+                       this.searchPaths.add(new File(p));
+               return this;
+       }
+
+       /**
+        * Make {@link ConfigFile ConfigFiles} read-only.
+        * <p>
+        * The default value of this setting is <jk>false</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder readOnly() {
+               this.readOnly = true;
+               return this;
+       }
+
+       /**
+        * Create config files if they cannot be found on the file system.
+        * <p>
+        * The default value for this setting is <jk>false</jk>.
+        *
+        * @return This object (for method chaining).
+        */
+       public ConfigFileBuilder createIfNotExists() {
+               this.createIfNotExists = true;
+               return this;
+       }
+
+       /**
+        * Returns the config file with the specified absolute or relative path.
+        *
+        * @param path The absolute or relative path of the config file.
+        * @return The config file.
+        * @throws IOException If config file could not be parsed.
+        * @throws FileNotFoundException If config file could not be found.
+        */
+       public ConfigFile build(String path) throws IOException {
+               return new ConfigFileImpl(resolve(path), readOnly, encoder, 
serializer, parser, charset);
+       }
+
+       /**
+        * Create a new empty config file not backed by any file.
+        *
+        * @return A new config file.
+        * @throws IOException
+        */
+       public ConfigFile build() throws IOException {
+               return new ConfigFileImpl(null, false, encoder, serializer, 
parser, charset);
+       }
+
+       /**
+        * Create a new config file backed by the specified file.
+        * <p>
+        * This method is provided primarily for testing purposes.
+        *
+        * @param f The file to create a config file from.
+        * @return A new config file.
+        * @throws IOException
+        */
+       public ConfigFile build(File f) throws IOException {
+               return new ConfigFileImpl(f, false, encoder, serializer, 
parser, charset);
+       }
+
+       /**
+        * Create a new config file not backed by a file.
+        *
+        * @param r The reader containing an INI-formatted file to initialize 
the config file from.
+        * @return A new config file.
+        * @throws IOException
+        */
+       public ConfigFile build(Reader r) throws IOException {
+               return new ConfigFileImpl(null, false, encoder, serializer, 
parser, charset).load(r);
+       }
+
+       private File resolve(String path) throws IOException {
+
+               // Handle absolute file.
+               File f = new File(path);
+               if (f.isAbsolute()) {
+                       if (createIfNotExists)
+                               FileUtils.create(f);
+                       if (f.exists())
+                               return f;
+                       throw new FileNotFoundException("Could not find config 
file '"+path+"'");
+               }
+
+               if (searchPaths.isEmpty())
+                       throw new FileNotFoundException("No search paths 
specified in ConfigFileBuilder.");
+
+               // Handle paths relative to search paths.
+               for (File sf : searchPaths) {
+                       f = new File(sf.getAbsolutePath() + "/" + path);
+                       if (f.exists())
+                               return f;
+               }
+
+               if (createIfNotExists) {
+                       f = new File(searchPaths.get(0).getAbsolutePath() + "/" 
+ path);
+                       FileUtils.create(f);
+                       return f;
+               }
+
+               throw new FileNotFoundException("Could not find config file 
'"+path+"'");
+       }
+
+       /**
+        * Implements command-line features for working with INI configuration 
files.
+        * <p>
+        * Invoke as a normal Java program...
+        * <p>
+        * <p class='bcode'>
+        *      java org.apache.juneau.ini.ConfigFileBuilder [args]
+        * </p>
+        * <p>
+        * Arguments can be any of the following...
+        * <ul class='spaced-list'>
+        *      <li>No arguments<br>
+        *              Prints usage message.<br>
+        *      <li><code>createBatchEnvFile -configfile &lt;configFile&gt; 
-envfile &lt;batchFile&gt; [-verbose]</code><br>
+        *              Creates a batch file that will set each config file 
entry as an environment variable.<br>
+        *              Characters in the keys that are not valid as 
environment variable names (e.g. <js>'/'</js> and <js>'.'</js>)
+        *                      will be converted to underscores.<br>
+        *      <li><code>createShellEnvFile -configFile &lt;configFile&gt; 
-envFile &lt;configFile&gt; [-verbose]</code>
+        *              Creates a shell script that will set each config file 
entry as an environment variable.<br>
+        *              Characters in the keys that are not valid as 
environment variable names (e.g. <js>'/'</js> and <js>'.'</js>)
+        *                      will be converted to underscores.<br>
+        *      <li><code>setVals -configFile &lt;configFile&gt; -vals 
[var1=val1 [var2=val2...]] [-verbose]</code>
+        *              Sets values in config files.<br>
+        * </ul>
+        * <p>
+        * For example, the following command will create the file 
<code>'MyConfig.bat'</code> from the contents of the file 
<code>'MyConfig.cfg'</code>.
+        * <p class='bcode'>
+        *      java org.apache.juneau.ini.ConfigFileBuilder createBatchEnvFile 
-configfile C:\foo\MyConfig.cfg -batchfile C:\foo\MyConfig.bat
+        * </p>
+        *
+        * @param args Command-line arguments
+        */
+       public static void main(String[] args) {
+
+               Args a = new Args(args);
+               String command = a.getArg(0);
+               String configFile = a.getArg("configFile");
+               String envFile = a.getArg("envFile");
+               List<String> vals = a.getArgs("vals");
+
+               if (command == null || ! (command.equals("createBatchEnvFile") 
|| command.equals("createShellEnvFile") || command.equals("setVals")))
+                       printUsageAndExit();
+               else if (configFile.isEmpty())
+                       printUsageAndExit();
+               else if (command.equals("setVals") && vals.isEmpty())
+                       printUsageAndExit();
+               else if ((command.equals("createBatchEnvFile") || 
command.equals("createShellEnvFile")) && envFile.isEmpty())
+                       printUsageAndExit();
+               else {
+                       try {
+                               ConfigFile cf = new 
ConfigFileBuilder().build(configFile);
+
+                               if (command.equalsIgnoreCase("setVals")) {
+                                       for (String val : vals) {
+                                               String[] x = val.split("\\=");
+                                               if (x.length != 2)
+                                                       throw new 
RuntimeException("Invalid format for value: '"+val+"'.  Must be in the format 
'key=value'");
+                                               cf.put(x[0], x[1]);
+                                       }
+                                       cf.save();
+                                       return;
+
+                               } else if 
(command.equalsIgnoreCase("createBatchEnvFile")) {
+                                       Writer fw = new OutputStreamWriter(new 
FileOutputStream(envFile), Charset.defaultCharset());
+                                       try {
+                                               cf.serializeTo(fw, BATCH);
+                                       } finally {
+                                               fw.close();
+                                       }
+                                       return;
+
+                               } else if 
(command.equalsIgnoreCase("createShellEnvFile")) {
+                                       Writer fw = new OutputStreamWriter(new 
FileOutputStream(envFile), Charset.defaultCharset());
+                                       try {
+                                               cf.serializeTo(fw, SHELL);
+                                       } finally {
+                                               fw.close();
+                                       }
+                                       return;
+                               }
+
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                       }
+               }
+       }
+
+       private static void printUsageAndExit() {
+               System.err.println("---Usage---"); // NOT DEBUG
+               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile createBatchEnvFile -configFile <configFile> 
-envFile <envFile> [-verbose]"); // NOT DEBUG
+               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile createShellEnvFile -configFile <configFile> 
-envFile <envFile> [-verbose]"); // NOT DEBUG
+               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile setVals -configFile <configFile> -vals [var1 
val1 [var2 val2...]] [-verbose]"); // NOT DEBUG
+               int rc = Integer.getInteger("exit.2", 2);
+               if (rc != 0)
+                       System.exit(rc);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/java/org/apache/juneau/ini/ConfigMgr.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigMgr.java 
b/juneau-core/src/main/java/org/apache/juneau/ini/ConfigMgr.java
deleted file mode 100644
index 0ebf523..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/ini/ConfigMgr.java
+++ /dev/null
@@ -1,314 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                
                                              *
-// *                                                                           
                                              *
-// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
-// *                                                                           
                                              *
-// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the 
License.                                              *
-// 
***************************************************************************************************************************
-package org.apache.juneau.ini;
-
-import static org.apache.juneau.ini.ConfigFileFormat.*;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.utils.*;
-
-/**
- * Manager for retrieving shared instances of {@link ConfigFile ConfigFiles}.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode'>
- *     ConfigFile cf = 
ConfigMgr.<jsf>DEFAULT</jsf>.get(<js>"MyConfig.cfg"</js>);
- *     String setting = cf.get(<js>"MySection/mysetting"</js>);
- * </p>
- */
-public class ConfigMgr {
-
-       /**
-        * Default reusable configuration manager.
-        * <ul class='spaced-list'>
-        *      <li>Read-only: <jk>false</jk>.
-        *      <li>Encoder: {@link XorEncoder}.
-        *      <li>Serializer: {@link JsonSerializer#DEFAULT}.
-        *      <li>Parser: {@link JsonParser#DEFAULT}.
-        *      <li>Charset: {@link Charset#defaultCharset()}.
-        *      <li>Search paths: [<js>"."</js>].
-        * </ul>
-        */
-       public static final ConfigMgr DEFAULT = new ConfigMgr(false, new 
XorEncoder(), JsonSerializer.DEFAULT, JsonParser.DEFAULT, 
Charset.defaultCharset(), new String[]{"."});
-
-       private ConcurrentHashMap<String,File> files = new 
ConcurrentHashMap<String,File>();
-       private ConcurrentHashMap<File,ConfigFile> configs = new 
ConcurrentHashMap<File,ConfigFile>();
-       private final WriterSerializer serializer;
-       private final ReaderParser parser;
-       private final Encoder encoder;
-       private final boolean readOnly;
-       private final Charset charset;
-       private final List<File> searchPaths = new LinkedList<File>();
-
-       /**
-        * Create a custom configuration manager.
-        *
-        * @param readOnly Make {@link ConfigFile ConfigFiles} read-only.
-        * @param encoder Optional.  Specify the encoder to use for encoded 
config file entries (e.g. <js>"mySecret*={...}"</js>).
-        * @param serializer Optional.  Specify the serializer to use for 
serializing POJOs when using {@link ConfigFile#put(String, Object)}.
-        * @param parser Optional.  Specify the parser to use for parsing POJOs 
when using {@link ConfigFile#getObject(Class,String)}.
-        * @param charset Optional.  Specify the config file character 
encoding.  If <jk>null</jk>, uses {@link Charset#defaultCharset()}.
-        * @param searchPaths Specify the search paths for config files.  Can 
contain relative or absolute paths.
-        */
-       public ConfigMgr(boolean readOnly, Encoder encoder, WriterSerializer 
serializer, ReaderParser parser, Charset charset, String[] searchPaths) {
-               this.readOnly = readOnly;
-               this.encoder = encoder;
-               this.serializer = serializer;
-               this.parser = parser;
-               this.charset = charset;
-               if (searchPaths != null)
-                       for (String p : searchPaths)
-                               this.searchPaths.add(new File(p));
-       }
-
-       /**
-        * Returns the config file with the specified absolute or relative path.
-        * <p>
-        * Multiple calls to the same path return the same 
<code>ConfigFile</code> instance.
-        *
-        * @param path The absolute or relative path of the config file.
-        * @return The config file.
-        * @throws IOException If config file could not be parsed.
-        * @throws FileNotFoundException If config file could not be found.
-        */
-       public ConfigFile get(String path) throws IOException {
-               return get(path, false);
-       }
-
-       /**
-        * Returns the config file with the specified absolute or relative path.
-        * <p>
-        * Multiple calls to the same path return the same 
<code>ConfigFile</code> instance.
-        * <p>
-        * If file doesn't exist and <code>create</code> is <jk>true</jk>, the 
configuration file will be
-        * create in the location identified by the first entry in the search 
paths.
-        *
-        * @param path The absolute or relative path of the config file.
-        * @param create Create the config file if it doesn't exist.
-        * @return The config file.
-        * @throws IOException If config file could not be parsed.
-        * @throws FileNotFoundException If config file could not be found or 
could not be created.
-        */
-       public ConfigFile get(String path, boolean create) throws IOException {
-
-               File f = resolve(path, create);
-
-               ConfigFile cf = configs.get(f);
-               if (cf != null)
-                       return cf;
-
-               cf = new ConfigFileImpl(f, readOnly, encoder, serializer, 
parser, charset);
-               configs.putIfAbsent(f, cf);
-               return configs.get(f);
-       }
-
-       /**
-        * Create a new empty config file not backed by any file.
-        *
-        * @return A new config file.
-        * @throws IOException
-        */
-       public ConfigFile create() throws IOException {
-               return new ConfigFileImpl(null, false, encoder, serializer, 
parser, charset);
-       }
-
-       /**
-        * Create a new config file backed by the specified file.
-        * Note that {@link #get(String)} is the preferred method for getting 
access to config files
-        *      since this method will create a new config file each time it is 
called.
-        * This method is provided primarily for testing purposes.
-        *
-        * @param f The file to create a config file from.
-        * @return A new config file.
-        * @throws IOException
-        */
-       public ConfigFile create(File f) throws IOException {
-               return new ConfigFileImpl(f, false, encoder, serializer, 
parser, charset);
-       }
-
-       /**
-        * Create a new config file not backed by a file.
-        *
-        * @param r The reader containing an INI-formatted file to initialize 
the config file from.
-        * @return A new config file.
-        * @throws IOException
-        */
-       public ConfigFile create(Reader r) throws IOException {
-               return new ConfigFileImpl(null, false, encoder, serializer, 
parser, charset).load(r);
-       }
-
-       /**
-        * Reloads any config files that were modified.
-        * @throws IOException
-        */
-       public void loadIfModified() throws IOException {
-               for (ConfigFile cf : configs.values())
-                       cf.loadIfModified();
-       }
-
-       /**
-        * Delete all configuration files registered with this config manager.
-        */
-       public void deleteAll() {
-               for (File f : Collections.list(configs.keys()))  // Don't use 
keySet(), otherwise fails on Java 6/7 if compiled using Java 8.
-                       FileUtils.delete(f);
-               files.clear();
-               configs.clear();
-       }
-
-       private File resolve(String path, boolean create) throws IOException {
-
-               // See if it's cached.
-               File f = files.get(path);
-               if (f != null)
-                       return f;
-
-               // Handle absolute file.
-               f = new File(path);
-               if (f.isAbsolute()) {
-                       if (create)
-                               FileUtils.create(f);
-                       if (f.exists())
-                               return addFile(path, f);
-                       throw new FileNotFoundException("Could not find config 
file '"+path+"'");
-               }
-
-               if (searchPaths.isEmpty())
-                       throw new FileNotFoundException("No search paths 
specified on ConfigMgr.");
-
-               // Handle paths relative to search paths.
-               for (File sf : searchPaths) {
-                       f = new File(sf.getAbsolutePath() + "/" + path);
-                       if (f.exists())
-                               return addFile(path, f);
-               }
-
-               if (create) {
-                       f = new File(searchPaths.get(0).getAbsolutePath() + "/" 
+ path);
-                       FileUtils.create(f);
-                               return addFile(path, f);
-               }
-
-               throw new FileNotFoundException("Could not find config file 
'"+path+"'");
-       }
-
-       private File addFile(String path, File f) {
-               files.putIfAbsent(path, f);
-               return files.get(path);
-       }
-
-       /**
-        * Implements command-line features for working with INI configuration 
files.
-        * <p>
-        * Invoke as a normal Java program...
-        * <p>
-        * <p class='bcode'>
-        *      java org.apache.juneau.ini.ConfigMgr [args]
-        * </p>
-        * <p>
-        * Arguments can be any of the following...
-        * <ul class='spaced-list'>
-        *      <li>No arguments<br>
-        *              Prints usage message.<br>
-        *      <li><code>createBatchEnvFile -configfile &lt;configFile&gt; 
-envfile &lt;batchFile&gt; [-verbose]</code><br>
-        *              Creates a batch file that will set each config file 
entry as an environment variable.<br>
-        *              Characters in the keys that are not valid as 
environment variable names (e.g. <js>'/'</js> and <js>'.'</js>)
-        *                      will be converted to underscores.<br>
-        *      <li><code>createShellEnvFile -configFile &lt;configFile&gt; 
-envFile &lt;configFile&gt; [-verbose]</code>
-        *              Creates a shell script that will set each config file 
entry as an environment variable.<br>
-        *              Characters in the keys that are not valid as 
environment variable names (e.g. <js>'/'</js> and <js>'.'</js>)
-        *                      will be converted to underscores.<br>
-        *      <li><code>setVals -configFile &lt;configFile&gt; -vals 
[var1=val1 [var2=val2...]] [-verbose]</code>
-        *              Sets values in config files.<br>
-        * </ul>
-        * <p>
-        * For example, the following command will create the file 
<code>'MyConfig.bat'</code> from the contents of the file 
<code>'MyConfig.cfg'</code>.
-        * <p class='bcode'>
-        *      java org.apache.juneau.ini.ConfigMgr createBatchEnvFile 
-configfile C:\foo\MyConfig.cfg -batchfile C:\foo\MyConfig.bat
-        * </p>
-        *
-        * @param args Command-line arguments
-        */
-       public static void main(String[] args) {
-
-               Args a = new Args(args);
-               String command = a.getArg(0);
-               String configFile = a.getArg("configFile");
-               String envFile = a.getArg("envFile");
-               List<String> vals = a.getArgs("vals");
-
-               if (command == null || ! (command.equals("createBatchEnvFile") 
|| command.equals("createShellEnvFile") || command.equals("setVals")))
-                       printUsageAndExit();
-               else if (configFile.isEmpty())
-                       printUsageAndExit();
-               else if (command.equals("setVals") && vals.isEmpty())
-                       printUsageAndExit();
-               else if ((command.equals("createBatchEnvFile") || 
command.equals("createShellEnvFile")) && envFile.isEmpty())
-                       printUsageAndExit();
-               else {
-                       try {
-                               ConfigFile cf = 
ConfigMgr.DEFAULT.get(configFile);
-
-                               if (command.equalsIgnoreCase("setVals")) {
-                                       for (String val : vals) {
-                                               String[] x = val.split("\\=");
-                                               if (x.length != 2)
-                                                       throw new 
RuntimeException("Invalid format for value: '"+val+"'.  Must be in the format 
'key=value'");
-                                               cf.put(x[0], x[1]);
-                                       }
-                                       cf.save();
-                                       return;
-
-                               } else if 
(command.equalsIgnoreCase("createBatchEnvFile")) {
-                                       Writer fw = new OutputStreamWriter(new 
FileOutputStream(envFile), Charset.defaultCharset());
-                                       try {
-                                               cf.serializeTo(fw, BATCH);
-                                       } finally {
-                                               fw.close();
-                                       }
-                                       return;
-
-                               } else if 
(command.equalsIgnoreCase("createShellEnvFile")) {
-                                       Writer fw = new OutputStreamWriter(new 
FileOutputStream(envFile), Charset.defaultCharset());
-                                       try {
-                                               cf.serializeTo(fw, SHELL);
-                                       } finally {
-                                               fw.close();
-                                       }
-                                       return;
-                               }
-
-                       } catch (Exception e) {
-                               e.printStackTrace();
-                       }
-               }
-       }
-
-       private static void printUsageAndExit() {
-               System.err.println("---Usage---"); // NOT DEBUG
-               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile createBatchEnvFile -configFile <configFile> 
-envFile <envFile> [-verbose]"); // NOT DEBUG
-               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile createShellEnvFile -configFile <configFile> 
-envFile <envFile> [-verbose]"); // NOT DEBUG
-               System.err.println("java -cp juneau.jar 
org.apache.juneau.ini.ConfigFile setVals -configFile <configFile> -vals [var1 
val1 [var2 val2...]] [-verbose]"); // NOT DEBUG
-               int rc = Integer.getInteger("exit.2", 2);
-               if (rc != 0)
-                       System.exit(rc);
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/java/org/apache/juneau/ini/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ini/package.html 
b/juneau-core/src/main/java/org/apache/juneau/ini/package.html
index a35c338..fd1d7fd 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ini/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/ini/package.html
@@ -72,7 +72,7 @@
 <h2 class='topic' onclick='toggle(this)'>1 - Overview</h2>
 <div class='topic'>
        <p>
-               The {@link org.apache.juneau.ini.ConfigMgr} and {@link 
org.apache.juneau.ini.ConfigFile} classes 
+               The {@link org.apache.juneau.ini.ConfigFileBuilder} and {@link 
org.apache.juneau.ini.ConfigFile} classes 
                implement an API for working with INI-style configuration files 
such as the following:
        </p>
        <p class='bcode'>
@@ -95,7 +95,7 @@
        </p>
        
        <p>
-               The {@link org.apache.juneau.ini.ConfigMgr} class is used to 
instantiate instances of 
+               The {@link org.apache.juneau.ini.ConfigFileBuilder} class is 
used to instantiate instances of 
                {@link org.apache.juneau.ini.ConfigFile} which can then be used 
to retrieve config file values through either <js>"key"</js> or 
<js>"Section/key"</js> identifiers.
        </p>
 
@@ -106,7 +106,7 @@
        URL key4;
        
        <jc>// Get our config file using the default config manager</jc>
-       ConfigFile f = 
ConfigMgr.<jsf>DEFAULT</jsf>.getConfig(<js>"C:/temp/MyConfig.cfg"</js>);
+       ConfigFile f = <jk>new</jk> 
ConfigFileBuilder().build(<js>"C:/temp/MyConfig.cfg"</js>);
 
        <jc>// Read values from default section</jc>
        key1 = f.getInt(<js>"key1"</js>);
@@ -127,7 +127,7 @@
        
        <p class='bcode'>
        <jc>// Construct the sample INI file programmatically</jc>
-       ConfigFile f = 
ConfigMgr.<jsf>DEFAULT</jsf>.getConfig(<js>"C:/temp/MyConfig.cfg"</js>, 
<jk>true</jk>)
+       ConfigFile f = <jk>new</jk> 
ConfigFileBuilder().build(<js>"C:/temp/MyConfig.cfg"</js>, <jk>true</jk>)
                .addLines(<jk>null</jk>,                     <jc>// The default 
'null' section</jc>
                        <js>"# Default section"</js>,             <jc>// A 
regular comment</jc>
                        <js>"key1 = 1"</js>,                      <jc>// A 
numeric entry</jc>
@@ -150,7 +150,7 @@
                Note how we're setting values as POJOs which will be 
automatically converted to strings when persisted to disk.
        <p class='bcode'>
        <jc>// Construct the sample INI file programmatically</jc>
-       ConfigFile f = 
ConfigMgr.<jsf>DEFAULT</jsf>.getConfig(<js>"C:/temp/MyConfig.cfg"</js>, 
<jk>true</jk>)
+       ConfigFile f = <jk>new</jk> 
ConfigFileBuilder().build(<js>"C:/temp/MyConfig.cfg"</js>, <jk>true</jk>)
                .addLines(<jk>null</jk>,
                        <js>"# Default section"</js>)
                .addHeaderComments(<js>"Section1"</js>,
@@ -250,11 +250,6 @@
        <ck>customMessage</ck> = <cv>Java home is $C{MyProperties/javaHome} and 
the environment path is $C{MyProperties/path}.</cv>
        </p>
        <p>
-               Resolving config files (and any config files retrieved through 
the same <code>ConfigMgr</code> that point to the same physical file)
-               share the same underlying config files in memory.  
-               This allows changes in one instance of the config file to be 
reflected in all.
-       </p>
-       <p>
                Support for variables is extensible.  You can add support for 
your own variables by implementing custom 
                {@link org.apache.juneau.svl.VarResolver VarResolvers}.<br>
                For example, the microservice <code>Resource</code> class 
provides access to config files that
@@ -305,8 +300,8 @@
        <p>
                The default encoder is {@link org.apache.juneau.ini.XorEncoder} 
which is a simple XOR+Base64 encoder.<br>
                If desired, custom encoder can be used by implementing the 
{@link org.apache.juneau.ini.Encoder}
-               interface and creating your own <code>ConfigMgr</code> using 
the {@link 
org.apache.juneau.ini.ConfigMgr#ConfigMgr(boolean,Encoder,WriterSerializer,ReaderParser,Charset,String[])}
-               constructor.
+               interface and creating your own <code>ConfigFileBuilder</code> 
using the {@link org.apache.juneau.ini.ConfigFileBuilder#encoder(Encoder)}
+               method.
        </p>
 </div>
 
@@ -331,7 +326,7 @@
        <h6 class="topic">Example:</h6>
        <p class='bcode'>
        <jc>// Get our config file using the default config manager</jc>
-       ConfigFile f = 
ConfigMgr.<jsf>DEFAULT</jsf>.getConfig(<js>"C:/temp/MyConfig.cfg"</js>);
+       ConfigFile f = <jk>new</jk> 
ConfigFileBuilder().build(<js>"C:/temp/MyConfig.cfg"</js>);
 
        <jc>// Add a listener for an entry</jc>
        f.addListener(
@@ -343,10 +338,6 @@
                }
        );
        </p>
-       <p>
-               Note that since {@link org.apache.juneau.ini.ConfigFile} 
instances for the same physical files are shared in {@link 
org.apache.juneau.ini.ConfigMgr}, a change made
-               in once instance of a config file will trigger all listeners 
defined on that physical file.
-       </p>
 </div>
 
 <!-- 
========================================================================================================
 -->
@@ -354,12 +345,12 @@
 <h2 class='topic' onclick='toggle(this)'>5 - Command Line API</h2>
 <div class='topic'>
        <p>
-               The {@link org.apache.juneau.ini.ConfigMgr} class contains a 
{@link org.apache.juneau.ini.ConfigMgr#main(String[])}
+               The {@link org.apache.juneau.ini.ConfigFileBuilder} class 
contains a {@link org.apache.juneau.ini.ConfigFileBuilder#main(String[])}
                        method that can be used to work with config files 
through a command-line prompt.<br>
                This is invoked as a normal Java command:
        </p>
        <p class='bcode'>
-       java -jar juneau.jar org.apache.juneau.ini.ConfigMgr [args]
+       java -jar juneau.jar org.apache.juneau.ini.ConfigFileBuilder [args]
        </p>
        <p>
                Arguments can be any of the following...
@@ -382,7 +373,7 @@
                For example, the following command will create the file 
<code>'MyConfig.bat'</code> from the contents of the file 
<code>'MyConfig.cfg'</code>.
        </p>
        <p class='bcode'>
-               java org.apache.juneau.ini.ConfigMgr createBatchEnvFile 
-configfile C:\foo\MyConfig.cfg -batchfile C:\foo\MyConfig.bat
+               java org.apache.juneau.ini.ConfigFileBuilder createBatchEnvFile 
-configfile C:\foo\MyConfig.cfg -batchfile C:\foo\MyConfig.bat
        </p>
 </div>
 
@@ -637,7 +628,7 @@
        <jk>public</jk> ConfigFile setConfigContents(<ja>@Body</ja> Reader 
contents) <jk>throws</jk> Exception {
                
                <jc>// Create a new in-memory config file based on the contents 
of the HTTP request.</jc>
-               ConfigFile cf2 = 
ConfigMgr.<jsf>DEFAULT</jsf>.create().load(contents);
+               ConfigFile cf2 = new ConfigFileBuilder.build().load(contents);
                
                <jc>// Merge the in-memory config file into the existing config 
file and save it.
                // Then return the modified config file to be parsed as a 
POJO.</jc>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/java/org/apache/juneau/svl/vars/ConfigFileVar.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/svl/vars/ConfigFileVar.java 
b/juneau-core/src/main/java/org/apache/juneau/svl/vars/ConfigFileVar.java
index a6f96c9..77023dc 100644
--- a/juneau-core/src/main/java/org/apache/juneau/svl/vars/ConfigFileVar.java
+++ b/juneau-core/src/main/java/org/apache/juneau/svl/vars/ConfigFileVar.java
@@ -27,7 +27,7 @@ import org.apache.juneau.svl.*;
  * <h5 class='section'>Example:</h5>
  * <p class='bcode'>
  *     <jc>// Create a config file object.</jc>
- *     ConfigFile configFile = 
ConfigMgr.<jsf>DEFAULT</jsf>.get(<js>"MyConfig.cfg"</js>);
+ *     ConfigFile configFile = new 
ConfigFileBuilder().build(<js>"MyConfig.cfg"</js>);
  *
  *     <jc>// Create a variable resolver that resolves config file entries 
(e.g. "$C{MySection/myKey}")</jc>
  *     VarResolver r = <jk>new</jk> 
VarResolver().addVars(ConfigVar.<js>class</js>).addContextObject(<jsf>SESSION_config</jsf>,
 configFile);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/26155757/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html 
b/juneau-core/src/main/javadoc/overview.html
index 8ca14b2..3b99922 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -1389,7 +1389,7 @@
        URL key4;
        
        <jc>// Load our config file</jc>
-       ConfigFile f = 
ConfigMgr.<jsf>DEFAULT</jsf>.get(<js>"MyIniFile.cfg"</js>);
+       ConfigFile f = <jk>new</jk> 
ConfigFileBuilder().build(<js>"MyIniFile.cfg"</js>);
        
        <jc>// Read values from default section</jc>
        key1 = f.getInt(<js>"key1"</js>);
@@ -1408,7 +1408,7 @@
                </p>
                <p class='bcode'>
        <jc>// Construct the sample INI file programmatically</jc>
-       ConfigFile cf = 
ConfigMgr.<jsf>DEFAULT</jsf>.create(<js>"MyIniFile.cfg"</js>)
+       ConfigFile cf = <jk>new</jk> 
ConfigFileBuilder().build(<js>"MyIniFile.cfg"</js>)
                .addLines(<jk>null</jk>,
                        <js>"# Default section"</js>,
                        <js>"key1 = 1"</js>,
@@ -1430,7 +1430,7 @@
                </p>
                <p class='bcode'>
        <jc>// Construct the sample INI file programmatically</jc>
-       ConfigFile cf = 
ConfigMgr.<jsf>DEFAULT</jsf>.create(<js>"MyIniFile.cfg"</js>)
+       ConfigFile cf = <jk>new</jk> 
ConfigFileBuilder().build(<js>"MyIniFile.cfg"</js>)
                .addLines(<jk>null</jk>,
                        <js>"# Default section"</js>)
                .addHeaderComments(<js>"section1"</js>,
@@ -5323,7 +5323,7 @@
                        } 
                ) 
                <jk>public</jk> ConfigFile setConfigContents(<ja>@Body</ja> 
Reader contents) <jk>throws</jk> Exception { 
-                       ConfigFile cf2 = 
ConfigMgr.<jsf>DEFAULT</jsf>.create().load(contents); 
+                       ConfigFile cf2 = <jk>new</jk> 
ConfigFileBuilder().build().load(contents); 
                        <jk>return</jk> getConfig().merge(cf2).save(); 
                } 
                
@@ -5704,7 +5704,7 @@
 
                <h6 class='topic'>org.apache.juneau</h6>
                <ul class='spaced-list'>
-                       <li>Revamped the serializer and parser classes to use 
builders for creation.
+                       <li>Revamped the serializer, parser classes to use 
builders for creation.
                                Serializers and parsers are now unmodifiable 
objects once they are created.
                                This is a breaking code change that will 
require adoption.
                                <p class='bcode'>
@@ -5729,8 +5729,7 @@
                                <li>{@link 
org.apache.juneau.serializer.SerializerGroupBuilder}
                                <li>{@link 
org.apache.juneau.parser.ParserGroupBuilder}
                                <li>{@link 
org.apache.juneau.encoders.EncoderGroupBuilder}
-                       </ul>
-                               Also introduced                         
+                       <li>Revamped the config file API to use a build:  
{@link org.apache.juneau.ini.ConfigFileBuilder}.
                        <li>Removed the <code><del>Lockable</del></code> 
interface.
                        <li>New <code>addBeanTypeProperties</code> setting 
added to serializers to override the 
                                {@link 
org.apache.juneau.serializer.SerializerContext#SERIALIZER_addBeanTypeProperties}
 setting
@@ -6386,10 +6385,10 @@
                                                        <li>{@link 
org.apache.juneau.ini.ConfigFile#toWritable()} - Wraps the config file in a 
{@link org.apache.juneau.Writable} interface so that it can be serialized by 
the REST interface as a plain-text INI file instead of as a serialized POJO.
                                                        <li>{@link 
org.apache.juneau.ini.ConfigFile#getInt(String)} - Now supports <js>"M"</js> 
and <js>"K"</js> to identify millions and thousands.
                                                </ul>
-                                       <li>New methods in {@link 
org.apache.juneau.ini.ConfigMgr}:
+                                       <li>New methods in 
<code><del>ConfigMgr</del></code>:
                                                <ul>
-                                                       <li>{@link 
org.apache.juneau.ini.ConfigMgr#create()}, {@link 
org.apache.juneau.ini.ConfigMgr#create(Reader)}, {@link 
org.apache.juneau.ini.ConfigMgr#create(File)}
-                                                       <li>{@link 
org.apache.juneau.ini.ConfigMgr#deleteAll()} 
+                                                       
<li><code><del>ConfigMgr.create()</del></code>, 
<code><del>ConfigMgr.create(Reader)</del></code>, 
<code><del>ConfigMgr.create(File)</del></code>
+                                                       
<li><code><del>ConfigMgr.deleteAll()</del></code>       
                                                </ul>
                                        <li>New methods in {@link 
org.apache.juneau.ini.Section}:
                                                <ul>
@@ -6796,7 +6795,7 @@
                        <li>Significant API changes to <a class='doclink' 
href='org/apache/juneau/ini/package-summary.html#TOC'>org.apache.juneau.ini</a> 
API.
                                <ul>
                                        <li>{@link 
org.apache.juneau.ini.ConfigFile} is now thread safe and can be shared across 
multiple threads.
-                                       <li>New {@link 
org.apache.juneau.ini.ConfigMgr} class for managing configuration files.
+                                       <li>New 
<code><del>ConfigMgr</del></code> class for managing configuration files.
                                        <li>Serializers and parsers can be 
associated with config files for storing and retrieving POJOs.  
                                                Default support provided for 
JSON.
                                </ul>

Reply via email to