This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 2da2017 Config API changes.
2da2017 is described below
commit 2da2017e37944d6a574aa6d73f6c6e164482cdf2
Author: JamesBognar <[email protected]>
AuthorDate: Sun Feb 25 20:10:32 2018 -0500
Config API changes.
---
.../main/java/org/apache/juneau/config/Config.java | 27 +-
.../apache/juneau/config/event/ConfigEvent.java | 2 +-
.../org/apache/juneau/config/store/ConfigMap.java | 30 +-
.../apache/juneau/config/ConfigBuilderTest.java | 4 +-
.../juneau/config/ConfigMapListenerTest.java | 24 +-
.../org/apache/juneau/config/ConfigMapTest.java | 78 +-
.../java/org/apache/juneau/config/ConfigTest.java | 74 +-
juneau-doc/src/main/javadoc/overview.html | 953 +++++++++------------
8 files changed, 506 insertions(+), 686 deletions(-)
diff --git
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
index 9d99aa1..3630319 100644
---
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
+++
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
@@ -275,7 +275,6 @@ public final class Config extends Context implements
ConfigEventListener, Writab
private final boolean beansOnSeparateLines, readOnly;
private final ConfigMap configMap;
private final BeanSession beanSession;
- private volatile boolean closed;
private final List<ConfigEventListener> listeners =
Collections.synchronizedList(new LinkedList<ConfigEventListener>());
@@ -1015,7 +1014,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @return
* An unmodifiable set of keys, or an empty set if the section
doesn't exist.
@@ -1029,7 +1028,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @param bean The bean to set the properties on.
* @param ignoreUnknownProperties
@@ -1070,7 +1069,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @param c The bean class to create.
* @return A new bean instance.
@@ -1113,7 +1112,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @param c The bean class to create.
* @param ignoreUnknownProperties
@@ -1150,7 +1149,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @return A new {@link ObjectMap}, or <jk>null</jk> if the section
doesn't exist.
* @throws ParseException
@@ -1229,7 +1228,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*
* @param section
* The section name to write from.
- * <br>If empty or <js>"default"</js>, refers to the default
section.
+ * <br>If empty, refers to the default section.
* <br>Must not be <jk>null</jk>.
* @param c The proxy interface class.
* @return The proxy interface.
@@ -1280,7 +1279,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
* @param name
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use blank or <js>"default"</js> for the default section.
+ * <br>Use blank for the default section.
* @param preLines
* Optional comment and blank lines to add immediately before the
section.
* <br>If <jk>null</jk>, previous pre-lines will not be replaced.
@@ -1301,7 +1300,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
* @param name
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> for the default section.
+ * <br>Use blank for the default section.
* @param preLines
* Optional comment and blank lines to add immediately before the
section.
* <br>If <jk>null</jk>, previous pre-lines will not be replaced.
@@ -1411,7 +1410,6 @@ public final class Config extends Context implements
ConfigEventListener, Writab
*/
public void close() throws IOException {
configMap.unregister(this);
- closed = true;
}
/**
@@ -1604,7 +1602,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
assertFieldNotNull(key, "key");
int i = key.indexOf('/');
if (i == -1)
- return "default";
+ return "";
return key.substring(0, i);
}
@@ -1618,7 +1616,7 @@ public final class Config extends Context implements
ConfigEventListener, Writab
private String section(String section) {
assertFieldNotNull(section, "section");
if (isEmpty(section))
- return "default";
+ return "";
return section;
}
@@ -1639,9 +1637,6 @@ public final class Config extends Context implements
ConfigEventListener, Writab
@Override /* Object */
protected void finalize() throws Throwable {
- // If Config objects are not closed, listeners on the
underlying ConfigMap don't get cleaned up.
- if (! closed) {
- System.err.println("Config object not closed.");
- }
+ close();
}
}
diff --git
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/event/ConfigEvent.java
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/event/ConfigEvent.java
index 70fd1ce..1870dfa 100644
---
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/event/ConfigEvent.java
+++
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/event/ConfigEvent.java
@@ -189,7 +189,7 @@ public class ConfigEvent {
case REMOVE_SECTION:
return "REMOVE_SECTION("+section+")";
case REMOVE_ENTRY:
- return "REMOVE_ENTRY("+section+"/"+key+")";
+ return
"REMOVE_ENTRY("+section+(section.isEmpty() ? "" : "/")+key+")";
case SET_SECTION:
return "SET_SECTION("+section+",
preLines="+StringUtils.join(preLines, '|')+")";
case SET_ENTRY:
diff --git
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/ConfigMap.java
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/ConfigMap.java
index efa837d..89f0747 100644
---
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/ConfigMap.java
+++
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/ConfigMap.java
@@ -93,7 +93,7 @@ public class ConfigMap implements ConfigStoreListener {
}
}
- // Add [default] section.
+ // Add [blank] section.
boolean inserted = false;
boolean foundComment = false;
for (ListIterator<String> li = lines.listIterator();
li.hasNext();) {
@@ -101,7 +101,7 @@ public class ConfigMap implements ConfigStoreListener {
char c = StringUtils.firstNonWhitespaceChar(l);
if (c != '#') {
if (c == 0 && foundComment) {
- li.set("[default]");
+ li.set("[]");
inserted = true;
}
break;
@@ -109,7 +109,7 @@ public class ConfigMap implements ConfigStoreListener {
foundComment = true;
}
if (! inserted)
- lines.add(0, "[default]");
+ lines.add(0, "[]");
// Collapse any multi-lines.
ListIterator<String> li = lines.listIterator(lines.size());
@@ -181,7 +181,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @param key
* The entry key.
* <br>Must not be <jk>null</jk>.
@@ -208,7 +208,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @return
* An unmodifiable list of lines, or <jk>null</jk> if the section
doesn't exist.
*/
@@ -239,7 +239,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @return
* An unmodifiable set of keys, or an empty set if the section
doesn't exist.
*/
@@ -255,7 +255,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @return <jk>true</jk> if this config has the specified section.
*/
public boolean hasSection(String section) {
@@ -273,7 +273,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @param preLines
* The pre-lines on the section.
* <br>If <jk>null</jk>, the previous value will not be
overwritten.
@@ -290,7 +290,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @param key
* The entry key.
* <br>Must not be <jk>null</jk>.
@@ -325,7 +325,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @return This object (for method chaining).
*/
public ConfigMap removeSection(String section) {
@@ -339,7 +339,7 @@ public class ConfigMap implements ConfigStoreListener {
* @param section
* The section name.
* <br>Must not be <jk>null</jk>.
- * <br>Use <js>"default"</js> to refer to the default section.
+ * <br>Use blank to refer to the default section.
* @param key
* The entry key.
* <br>Must not be <jk>null</jk>.
@@ -606,7 +606,7 @@ public class ConfigMap implements ConfigStoreListener {
}
private void checkSectionName(String s) {
- if (! ("default".equals(s) || isValidNewSectionName(s)))
+ if (! ("".equals(s) || isValidNewSectionName(s)))
throw new IllegalArgumentException("Invalid section
name: '" + s + "'");
}
@@ -635,8 +635,6 @@ public class ConfigMap implements ConfigStoreListener {
s = s.trim();
if (s.isEmpty())
return false;
- if ("default".equals(s))
- return false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '/' || c == '\\' || c == '[' || c == ']')
@@ -705,7 +703,7 @@ public class ConfigMap implements ConfigStoreListener {
class ConfigSection {
- final String name; // The config section name, or "default"
if the default section. Never null.
+ final String name; // The config section name, or blank if
the default section. Never null.
final List<String> preLines = Collections.synchronizedList(new
ArrayList<String>());
private final String rawLine;
@@ -778,7 +776,7 @@ public class ConfigMap implements ConfigStoreListener {
for (String s : preLines)
w.append(s).append('\n');
- if (! name.equals("default"))
+ if (! name.equals(""))
w.append(rawLine).append('\n');
else {
// Need separation between default prelines and
first-entry prelines.
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigBuilderTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigBuilderTest.java
index 9cebe35..1e2aee8 100755
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigBuilderTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigBuilderTest.java
@@ -51,10 +51,10 @@ public class ConfigBuilderTest {
assertFalse(f.exists());
cf.save();
- assertObjectEquals("{'default':{},Test:{A:'a'}}", cf.asMap());
+ assertObjectEquals("{'':{},Test:{A:'a'}}", cf.asMap());
String NL = System.getProperty("line.separator");
cf = cf.write("[Test]"+NL+"A = b"+NL, true);
- assertObjectEquals("{'default':{},Test:{A:'b'}}", cf.asMap());
+ assertObjectEquals("{'':{},Test:{A:'b'}}", cf.asMap());
}
}
\ No newline at end of file
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapListenerTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapListenerTest.java
index ee2fbca..52b0e50 100644
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapListenerTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapListenerTest.java
@@ -46,7 +46,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setEntry("default", "foo", "baz", null, null, null);
+ cm.setEntry("", "foo", "baz", null, null, null);
cm.save();
wait(latch);
assertNull(l.error);
@@ -102,7 +102,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setEntry("default", "k", "vb", null, null, null);
+ cm.setEntry("", "k", "vb", null, null, null);
cm.setEntry("S1", "k1", "v1b", null, null, null);
cm.save();
wait(latch);
@@ -128,7 +128,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setEntry("default", "k", "kb", "^*", "C",
Arrays.asList("#k"));
+ cm.setEntry("", "k", "kb", "^*", "C", Arrays.asList("#k"));
cm.setEntry("S1", "k1", "k1b", "^*", "C1",
Arrays.asList("#k1"));
cm.save();
wait(latch);
@@ -160,7 +160,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setEntry("default", "k", "kb", "^*", "Cb",
Arrays.asList("#kb"));
+ cm.setEntry("", "k", "kb", "^*", "Cb", Arrays.asList("#kb"));
cm.setEntry("S1", "k1", "k1b", "^*", "Cb1",
Arrays.asList("#k1b"));
cm.save();
wait(latch);
@@ -187,13 +187,13 @@ public class ConfigMapListenerTest {
LatchedListener l = new LatchedListener(latch) {
@Override
public void check(List<ConfigEvent> events) throws
Exception {
-
assertObjectEquals("['REMOVE_ENTRY(default/k)','REMOVE_ENTRY(S1/k1)']", events);
+
assertObjectEquals("['REMOVE_ENTRY(k)','REMOVE_ENTRY(S1/k1)']", events);
}
};
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.removeEntry("default", "k");
+ cm.removeEntry("", "k");
cm.removeEntry("S1", "k1");
cm.save();
wait(latch);
@@ -219,13 +219,13 @@ public class ConfigMapListenerTest {
LatchedListener l = new LatchedListener(latch) {
@Override
public void check(List<ConfigEvent> events) throws
Exception {
-
assertObjectEquals("['REMOVE_ENTRY(default/k)','REMOVE_ENTRY(S1/k1)']", events);
+
assertObjectEquals("['REMOVE_ENTRY(k)','REMOVE_ENTRY(S1/k1)']", events);
}
};
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.removeEntry("default", "k");
+ cm.removeEntry("", "k");
cm.removeEntry("S1", "k1");
cm.save();
wait(latch);
@@ -255,7 +255,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setSection("default", Arrays.asList("#D1"));
+ cm.setSection("", Arrays.asList("#D1"));
cm.setSection("S1", Arrays.asList("#S1"));
cm.setSection("S2", null);
cm.setSection("S3", Collections.<String>emptyList());
@@ -290,7 +290,7 @@ public class ConfigMapListenerTest {
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.setSection("default", Arrays.asList("#Db"));
+ cm.setSection("", Arrays.asList("#Db"));
cm.setSection("S1", Arrays.asList("#S1b"));
cm.setSection("S2", null);
cm.setSection("S3", Collections.<String>emptyList());
@@ -329,13 +329,13 @@ public class ConfigMapListenerTest {
LatchedListener l = new LatchedListener(latch) {
@Override
public void check(List<ConfigEvent> events) throws
Exception {
-
assertObjectEquals("['REMOVE_ENTRY(default/k)','REMOVE_ENTRY(S1/k1)','REMOVE_ENTRY(S2/k2)']",
events);
+
assertObjectEquals("['REMOVE_ENTRY(k)','REMOVE_ENTRY(S1/k1)','REMOVE_ENTRY(S2/k2)']",
events);
}
};
ConfigMap cm = s.getMap("Foo.cfg");
cm.register(l);
- cm.removeSection("default");
+ cm.removeSection("");
cm.removeSection("S1");
cm.removeSection("S2");
cm.removeSection("S3");
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapTest.java
index fb6c865..b70bf84 100644
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigMapTest.java
@@ -64,10 +64,10 @@ public class ConfigMapTest {
assertTextEquals("foo=bar|", cm);
- assertEquals("", join(cm.getPreLines("default"), '|'));
- assertEquals("", join(cm.getEntry("default",
"foo").getPreLines(), '|'));
+ assertEquals("", join(cm.getPreLines(""), '|'));
+ assertEquals("", join(cm.getEntry("", "foo").getPreLines(),
'|'));
- assertEquals("bar", cm.getEntry("default", "foo").getValue());
+ assertEquals("bar", cm.getEntry("", "foo").getValue());
// Round trip.
s.update("Foo.cfg", cm.toString());
@@ -88,10 +88,10 @@ public class ConfigMapTest {
assertTextEquals("#comment|foo=bar|", cm);
- assertEquals("", join(cm.getPreLines("default"), '|'));
- assertEquals("#comment", join(cm.getEntry("default",
"foo").getPreLines(), '|'));
+ assertEquals("", join(cm.getPreLines(""), '|'));
+ assertEquals("#comment", join(cm.getEntry("",
"foo").getPreLines(), '|'));
- assertEquals("bar", cm.getEntry("default", "foo").getValue());
+ assertEquals("bar", cm.getEntry("", "foo").getValue());
// Round trip.
s.update("Foo.cfg", cm.toString());
@@ -112,7 +112,7 @@ public class ConfigMapTest {
assertTextEquals("[MySection]|foo=bar|", cm);
- assertEquals("", join(cm.getPreLines("default"), '|'));
+ assertEquals("", join(cm.getPreLines(""), '|'));
assertEquals("", join(cm.getPreLines("MySection"), '|'));
assertEquals("", join(cm.getEntry("MySection",
"foo").getPreLines(), '|'));
@@ -137,7 +137,7 @@ public class ConfigMapTest {
assertTextEquals("[MySection]|foo=bar|", cm);
- assertEquals("", join(cm.getPreLines("default"), '|'));
+ assertEquals("", join(cm.getPreLines(""), '|'));
assertNull(cm.getPreLines("XXX"));
@@ -163,7 +163,7 @@ public class ConfigMapTest {
ConfigMap cm = s.getMap("Foo.cfg");
assertTextEquals("#S1|[S1]|#k1|k1=v1|#S2|[S2]|#k2|k2=v2|", cm);
- assertEquals("", join(cm.getPreLines("default"), '|'));
+ assertEquals("", join(cm.getPreLines(""), '|'));
assertEquals("#S1", join(cm.getPreLines("S1"), '|'));
assertEquals("#k1", join(cm.getEntry("S1", "k1").getPreLines(),
'|'));
assertEquals("#S2", join(cm.getPreLines("S2"), '|'));
@@ -196,12 +196,12 @@ public class ConfigMapTest {
ConfigMap cm = s.getMap("Foo.cfg");
assertTextEquals("#D||#k|k=v|#S1|[S1]|#k1|k1=v1|", cm);
- assertEquals("#D", join(cm.getPreLines("default"), '|'));
- assertEquals("#k", join(cm.getEntry("default",
"k").getPreLines(), '|'));
+ assertEquals("#D", join(cm.getPreLines(""), '|'));
+ assertEquals("#k", join(cm.getEntry("", "k").getPreLines(),
'|'));
assertEquals("#S1", join(cm.getPreLines("S1"), '|'));
assertEquals("#k1", join(cm.getEntry("S1", "k1").getPreLines(),
'|'));
- assertEquals("v", cm.getEntry("default", "k").getValue());
+ assertEquals("v", cm.getEntry("", "k").getValue());
assertEquals("v1", cm.getEntry("S1", "k1").getValue());
// Round trip.
@@ -240,12 +240,12 @@ public class ConfigMapTest {
ConfigMap cm = s.getMap("Foo.cfg");
assertTextEquals("#Da|#Db||#ka||#kb||k=v||#S1a||#S1b||[S1]||#k1a||#k1b||k1=v1|",
cm);
- assertEquals("#Da|#Db", join(cm.getPreLines("default"), '|'));
- assertEquals("#ka||#kb|", join(cm.getEntry("default",
"k").getPreLines(), '|'));
+ assertEquals("#Da|#Db", join(cm.getPreLines(""), '|'));
+ assertEquals("#ka||#kb|", join(cm.getEntry("",
"k").getPreLines(), '|'));
assertEquals("|#S1a||#S1b|", join(cm.getPreLines("S1"), '|'));
assertEquals("|#k1a||#k1b|", join(cm.getEntry("S1",
"k1").getPreLines(), '|'));
- assertEquals("v", cm.getEntry("default", "k").getValue());
+ assertEquals("v", cm.getEntry("", "k").getValue());
assertEquals("v1", cm.getEntry("S1", "k1").getValue());
// Round trip.
@@ -261,7 +261,7 @@ public class ConfigMapTest {
public void testMalformedSectionHeaders() throws Exception {
String[] test = {
- "[default]", "[ default ]", " [ default ] ",
"\t[\tdefault\t]\t",
+ "[]", "[ ]", " [ ] ", "\t[\t\t]\t",
"[/]", "[[]", "[]]", "[\\]",
"[foo/bar]", "[foo[bar]", "[foo]bar]", "[foo\\bar]",
"[]", "[ ]", "[\t]", " [] ",
@@ -315,13 +315,13 @@ public class ConfigMapTest {
);
ConfigMap cm = s.getMap("Foo.cfg");
- assertEquals("", join(cm.getEntry("default",
"k1").getPreLines(), '|'));
- assertEquals("", join(cm.getEntry("default",
"k2").getPreLines(), '|'));
+ assertEquals("", join(cm.getEntry("", "k1").getPreLines(),
'|'));
+ assertEquals("", join(cm.getEntry("", "k2").getPreLines(),
'|'));
assertTextEquals("k1 = v1a,|\tv1b,|\tv1c|k2 =
v2a,|\tv2b,|\tv2c|", cm);
- assertEquals("v1a,\nv1b,\nv1c", cm.getEntry("default",
"k1").getValue());
- assertEquals("v2a,\nv2b,\nv2c", cm.getEntry("default",
"k2").getValue());
+ assertEquals("v1a,\nv1b,\nv1c", cm.getEntry("",
"k1").getValue());
+ assertEquals("v2a,\nv2b,\nv2c", cm.getEntry("",
"k2").getValue());
// Round trip.
s.update("Foo.cfg", cm.toString());
@@ -347,13 +347,13 @@ public class ConfigMapTest {
);
ConfigMap cm = s.getMap("Foo.cfg");
- assertEquals("|#k1|", join(cm.getEntry("default",
"k1").getPreLines(), '|'));
- assertEquals("|#k2|", join(cm.getEntry("default",
"k2").getPreLines(), '|'));
+ assertEquals("|#k1|", join(cm.getEntry("", "k1").getPreLines(),
'|'));
+ assertEquals("|#k2|", join(cm.getEntry("", "k2").getPreLines(),
'|'));
assertTextEquals("|#k1||k1 = v1a,| v1b,| v1c||#k2||k2 =
v2a,| v2b,| v2c|", cm);
- assertEquals("v1a,\nv1b,\nv1c", cm.getEntry("default",
"k1").getValue());
- assertEquals("v2a,\nv2b,\nv2c", cm.getEntry("default",
"k2").getValue());
+ assertEquals("v1a,\nv1b,\nv1c", cm.getEntry("",
"k1").getValue());
+ assertEquals("v2a,\nv2b,\nv2c", cm.getEntry("",
"k2").getValue());
// Round trip.
s.update("Foo.cfg", cm.toString());
@@ -549,12 +549,12 @@ public class ConfigMapTest {
ConfigStore s = initStore("Foo.cfg");
ConfigMap cm = s.getMap("Foo.cfg");
- cm.setEntry("default", "k", "v1\nv2\nv3", null, null, null);
+ cm.setEntry("", "k", "v1\nv2\nv3", null, null, null);
cm.setEntry("S1", "k1", "v1\nv2\nv3", null, null, null);
assertTextEquals("k = v1| v2| v3|[S1]|k1 = v1|
v2| v3|", cm);
- assertEquals("v1\nv2\nv3", cm.getEntry("default",
"k").getValue());
+ assertEquals("v1\nv2\nv3", cm.getEntry("", "k").getValue());
assertEquals("v1\nv2\nv3", cm.getEntry("S1", "k1").getValue());
cm.save();
assertTextEquals("k = v1| v2| v3|[S1]|k1 = v1|
v2| v3|", cm);
@@ -569,12 +569,12 @@ public class ConfigMapTest {
ConfigStore s = initStore("Foo.cfg");
ConfigMap cm = s.getMap("Foo.cfg");
- cm.setEntry("default", "k", "v1 \n v2 \n v3", null, null, null);
+ cm.setEntry("", "k", "v1 \n v2 \n v3", null, null, null);
cm.setEntry("S1", "k1", "v1\t\n\tv2\t\n\tv3", null, null, null);
assertTextEquals("k = v1 | v2 | v3|[S1]|k1 = v1
| v2 | v3|", cm);
- assertEquals("v1 \n v2 \n v3", cm.getEntry("default",
"k").getValue());
+ assertEquals("v1 \n v2 \n v3", cm.getEntry("", "k").getValue());
assertEquals("v1\t\n\tv2\t\n\tv3", cm.getEntry("S1",
"k1").getValue());
cm.save();
assertTextEquals("k = v1 | v2 | v3|[S1]|k1 = v1
| v2 | v3|", cm);
@@ -611,11 +611,11 @@ public class ConfigMapTest {
);
ConfigMap cm = s.getMap("Foo.cfg");
- cm.setSection("default", Arrays.asList("#D"));
+ cm.setSection("", Arrays.asList("#D"));
assertTextEquals("#D||[S1]|k1 = v1|", cm);
- cm.setSection("default", Collections.<String>emptyList());
+ cm.setSection("", Collections.<String>emptyList());
assertTextEquals("[S1]|k1 = v1|", cm);
- cm.setSection("default", null);
+ cm.setSection("", null);
assertTextEquals("[S1]|k1 = v1|", cm);
}
@@ -643,7 +643,7 @@ public class ConfigMapTest {
String[] test = {
"/", "[", "]",
"foo/bar", "foo[bar", "foo]bar",
- "", " ",
+ " ",
null
};
@@ -711,12 +711,6 @@ public class ConfigMapTest {
assertTextEquals("[S1]|k1 = v1|[S2]|k2 = v2|", cm);
try {
- cm.removeSection("");
- fail();
- } catch (IllegalArgumentException e) {
- assertEquals("Invalid section name: ''",
e.getLocalizedMessage());
- }
- try {
cm.removeSection(null);
fail();
} catch (IllegalArgumentException e) {
@@ -736,7 +730,7 @@ public class ConfigMapTest {
);
ConfigMap cm = s.getMap("Foo.cfg");
- cm.removeSection("default");
+ cm.removeSection("");
assertTextEquals("[S1]|k1 = v1|[S2]|k2 = v2|", cm);
}
@@ -755,7 +749,7 @@ public class ConfigMapTest {
);
ConfigMap cm = s.getMap("Foo.cfg");
- cm.removeSection("default");
+ cm.removeSection("");
assertTextEquals("[S1]|k1 = v1|[S2]|k2 = v2|", cm);
}
@@ -890,7 +884,7 @@ public class ConfigMapTest {
String[] test = {
"/", "[", "]",
"foo/bar", "foo[bar", "foo]bar",
- "", " ",
+ " ",
null
};
@@ -1086,7 +1080,7 @@ public class ConfigMapTest {
String[] test = {
"/", "[", "]",
"foo/bar", "foo[bar", "foo]bar",
- "", " ",
+ " ",
null
};
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
index 0bd1bfe..9795ace 100755
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
@@ -49,7 +49,7 @@ public class ConfigTest {
Config c = init("a=1", "[S]", "b=2");
assertEquals("1", c.get("a"));
- assertEquals("1", c.get("default/a"));
+ assertEquals("1", c.get("a"));
assertEquals("2", c.get("S/b"));
assertNull(c.get("b"));
assertNull(c.get("S/c"));
@@ -73,13 +73,13 @@ public class ConfigTest {
c.set("a1", "2");
c.set("a2", "3");
- c.set("default/a3", "4");
+ c.set("a3", "4");
c.set("S/b1", "5");
c.set("S/b2", "6");
c.set("T/c1", "7");
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -88,7 +88,7 @@ public class ConfigTest {
c.save();
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -97,7 +97,7 @@ public class ConfigTest {
c = cb.build();
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -115,13 +115,13 @@ public class ConfigTest {
c.set("a1", 2);
c.set("a2", 3);
- c.set("default/a3", 4);
+ c.set("a3", 4);
c.set("S/b1", 5);
c.set("S/b2", 6);
c.set("T/c1", 7);
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -130,7 +130,7 @@ public class ConfigTest {
c.save();
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -139,7 +139,7 @@ public class ConfigTest {
c = cb.build();
assertEquals("2", c.get("a1"));
- assertEquals("3", c.get("default/a2"));
+ assertEquals("3", c.get("a2"));
assertEquals("4", c.get("a3"));
assertEquals("5", c.get("S/b1"));
assertEquals("6", c.get("S/b2"));
@@ -158,13 +158,13 @@ public class ConfigTest {
ABean b = new ABean().init();
c.set("a1", b, UonSerializer.DEFAULT);
c.set("a2", b, UonSerializer.DEFAULT);
- c.set("default/a3", b, UonSerializer.DEFAULT);
+ c.set("a3", b, UonSerializer.DEFAULT);
c.set("S/b1", b, UonSerializer.DEFAULT);
c.set("S/b2", b, UonSerializer.DEFAULT);
c.set("T/c1", b, UonSerializer.DEFAULT);
assertEquals("(foo=bar)", c.get("a1"));
- assertEquals("(foo=bar)", c.get("default/a2"));
+ assertEquals("(foo=bar)", c.get("a2"));
assertEquals("(foo=bar)", c.get("a3"));
assertEquals("(foo=bar)", c.get("S/b1"));
assertEquals("(foo=bar)", c.get("S/b2"));
@@ -181,7 +181,7 @@ public class ConfigTest {
ABean b = new ABean().init();
c.set("a1", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
c.set("a2", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
- c.set("default/a3", b, UonSerializer.DEFAULT, ENCODED,
"comment", Arrays.asList("#c1","#c2"));
+ c.set("a3", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
c.set("S/b1", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
c.set("S/b2", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
c.set("T/c1", b, UonSerializer.DEFAULT, ENCODED, "comment",
Arrays.asList("#c1","#c2"));
@@ -193,7 +193,7 @@ public class ConfigTest {
assertTextEquals("#c1|#c2|a1* = {RhMWWFIFVksf} #
comment|#c1|#c2|a2* = {RhMWWFIFVksf} # comment|#c1|#c2|a3* = {RhMWWFIFVksf} #
comment|[S]|#c1|#c2|b1* = {RhMWWFIFVksf} # comment|#c1|#c2|b2* = {RhMWWFIFVksf}
# comment|[T]|#c1|#c2|c1* = {RhMWWFIFVksf} # comment|", c.toString());
assertEquals("(foo=bar)", c.get("a1"));
- assertEquals("(foo=bar)", c.get("default/a2"));
+ assertEquals("(foo=bar)", c.get("a2"));
assertEquals("(foo=bar)", c.get("a3"));
assertEquals("(foo=bar)", c.get("S/b1"));
assertEquals("(foo=bar)", c.get("S/b2"));
@@ -208,8 +208,8 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1");
c.remove("a1");
- c.remove("default/a2");
- c.remove("default/a3");
+ c.remove("a2");
+ c.remove("a3");
c.remove("S/b1");
c.remove("T/c1");
@@ -228,7 +228,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals("1", c.getString("a1"));
- assertEquals("2", c.getString("default/a2"));
+ assertEquals("2", c.getString("a2"));
assertEquals(null, c.getString("a3"));
assertEquals("1", c.getString("S/b1"));
assertEquals("", c.getString("S/b2"));
@@ -244,7 +244,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals("1", c.getString("a1", "foo"));
- assertEquals("2", c.getString("default/a2", "foo"));
+ assertEquals("2", c.getString("a2", "foo"));
assertEquals("foo", c.getString("a3", "foo"));
assertEquals("1", c.getString("S/b1", "foo"));
assertEquals("foo", c.getString("S/b2", "foo"));
@@ -260,7 +260,7 @@ public class ConfigTest {
Config c = init("a1=1,2", "a2= 2 , 3 ", "[S]", "b1=1", "b2=");
assertObjectEquals("['1','2']", c.getStringArray("a1"));
- assertObjectEquals("['2','3']", c.getStringArray("default/a2"));
+ assertObjectEquals("['2','3']", c.getStringArray("a2"));
assertObjectEquals("[]", c.getStringArray("a3"));
assertObjectEquals("['1']", c.getStringArray("S/b1"));
assertObjectEquals("[]", c.getStringArray("S/b2"));
@@ -276,7 +276,7 @@ public class ConfigTest {
Config c = init("a1=1,2", "a2= 2 , 3 ", "[S]", "b1=1", "b2=");
assertObjectEquals("['1','2']", c.getStringArray("a1", new
String[] {"foo"}));
- assertObjectEquals("['2','3']", c.getStringArray("default/a2",
new String[] {"foo"}));
+ assertObjectEquals("['2','3']", c.getStringArray("a2", new
String[] {"foo"}));
assertObjectEquals("['foo']", c.getStringArray("a3", new
String[] {"foo"}));
assertObjectEquals("['1']", c.getStringArray("S/b1", new
String[] {"foo"}));
assertObjectEquals("['foo']", c.getStringArray("S/b2", new
String[] {"foo"}));
@@ -292,7 +292,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals(1, c.getInt("a1"));
- assertEquals(2, c.getInt("default/a2"));
+ assertEquals(2, c.getInt("a2"));
assertEquals(0, c.getInt("a3"));
assertEquals(1, c.getInt("S/b1"));
assertEquals(0, c.getInt("S/b2"));
@@ -330,7 +330,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals(1, c.getInt("a1", -1));
- assertEquals(2, c.getInt("default/a2", -1));
+ assertEquals(2, c.getInt("a2", -1));
assertEquals(-1, c.getInt("a3", -1));
assertEquals(1, c.getInt("S/b1", -1));
assertEquals(-1, c.getInt("S/b2", -1));
@@ -368,7 +368,7 @@ public class ConfigTest {
Config c = init("a1=true", "a2=false", "[S]", "b1=TRUE", "b2=");
assertEquals(true, c.getBoolean("a1"));
- assertEquals(false, c.getBoolean("default/a2"));
+ assertEquals(false, c.getBoolean("a2"));
assertEquals(false, c.getBoolean("a3"));
assertEquals(true, c.getBoolean("S/b1"));
assertEquals(false, c.getBoolean("S/b2"));
@@ -394,7 +394,7 @@ public class ConfigTest {
Config c = init("a1=true", "a2=false", "[S]", "b1=TRUE", "b2=");
assertEquals(true, c.getBoolean("a1", true));
- assertEquals(false, c.getBoolean("default/a2", true));
+ assertEquals(false, c.getBoolean("a2", true));
assertEquals(true, c.getBoolean("a3", true));
assertEquals(true, c.getBoolean("S/b1", true));
assertEquals(true, c.getBoolean("S/b2", true));
@@ -420,7 +420,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals(1l, c.getLong("a1"));
- assertEquals(2l, c.getLong("default/a2"));
+ assertEquals(2l, c.getLong("a2"));
assertEquals(0l, c.getLong("a3"));
assertEquals(1l, c.getLong("S/b1"));
assertEquals(0l, c.getLong("S/b2"));
@@ -458,7 +458,7 @@ public class ConfigTest {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
assertEquals(1l, c.getLong("a1", Long.MAX_VALUE));
- assertEquals(2l, c.getLong("default/a2", Long.MAX_VALUE));
+ assertEquals(2l, c.getLong("a2", Long.MAX_VALUE));
assertEquals(Long.MAX_VALUE, c.getLong("a3", Long.MAX_VALUE));
assertEquals(1l, c.getLong("S/b1", Long.MAX_VALUE));
assertEquals(Long.MAX_VALUE, c.getLong("S/b2", Long.MAX_VALUE));
@@ -496,7 +496,7 @@ public class ConfigTest {
Config c = init("a1=Zm9v", "a2=Zm", "\t9v", "a3=");
assertObjectEquals("[102,111,111]", c.getBytes("a1"));
- assertObjectEquals("[102,111,111]", c.getBytes("default/a2"));
+ assertObjectEquals("[102,111,111]", c.getBytes("a2"));
assertObjectEquals("[]", c.getBytes("a3"));
assertNull(null, c.getBytes("a4"));
}
@@ -509,7 +509,7 @@ public class ConfigTest {
Config c = init("a1=Zm9v", "a2=Zm", "\t9v", "a3=");
assertObjectEquals("[102,111,111]", c.getBytes("a1", new byte[]
{1}));
- assertObjectEquals("[102,111,111]", c.getBytes("default/a2",
new byte[] {1}));
+ assertObjectEquals("[102,111,111]", c.getBytes("a2", new byte[]
{1}));
assertObjectEquals("[1]", c.getBytes("a3", new byte[] {1}));
assertObjectEquals("[1]", c.getBytes("a4", new byte[] {1}));
}
@@ -865,7 +865,7 @@ public class ConfigTest {
public void getKeys() throws Exception {
Config c = init("a1=1", "a2=2", "[S]", "b1=1", "b2=");
- assertObjectEquals("['a1','a2']", c.getKeys("default"));
+ assertObjectEquals("['a1','a2']", c.getKeys(""));
assertObjectEquals("['a1','a2']", c.getKeys(""));
assertObjectEquals("['b1','b2']", c.getKeys("S"));
assertTrue(c.getKeys("T").isEmpty());
@@ -913,7 +913,7 @@ public class ConfigTest {
c.writeProperties("", b, true);
assertObjectEquals("{foo:'qux'}", b);
- c.writeProperties("default", a, true);
+ c.writeProperties("", a, true);
assertObjectEquals("{foo:'qux'}", a);
try {
@@ -935,14 +935,14 @@ public class ConfigTest {
a = c.getSectionAsBean("", ABean.class);
assertObjectEquals("{foo:'qux'}", a);
- a = c.getSectionAsBean("default", ABean.class);
+ a = c.getSectionAsBean("", ABean.class);
assertObjectEquals("{foo:'qux'}", a);
a = c.getSectionAsBean("S", ABean.class);
assertObjectEquals("{foo:'baz'}", a);
b = c.getSectionAsBean("", BBean.class);
assertObjectEquals("{foo:'qux'}", b);
- b = c.getSectionAsBean("default", BBean.class);
+ b = c.getSectionAsBean("", BBean.class);
assertObjectEquals("{foo:'qux'}", b);
b = c.getSectionAsBean("S", BBean.class);
assertObjectEquals("{foo:'baz'}", b);
@@ -1026,7 +1026,7 @@ public class ConfigTest {
Config c = init("a=1", "[S]", "b=2", "[T]");
assertObjectEquals("{a:'1'}", c.getSectionAsMap(""));
- assertObjectEquals("{a:'1'}", c.getSectionAsMap("default"));
+ assertObjectEquals("{a:'1'}", c.getSectionAsMap(""));
assertObjectEquals("{b:'2'}", c.getSectionAsMap("S"));
assertObjectEquals("{}", c.getSectionAsMap("T"));
assertNull(c.getSectionAsMap("U"));
@@ -1049,7 +1049,7 @@ public class ConfigTest {
a = c.getSectionAsInterface("", AInterface.class);
assertEquals("qux", a.getFoo());
- a = c.getSectionAsInterface("default", AInterface.class);
+ a = c.getSectionAsInterface("", AInterface.class);
assertEquals("qux", a.getFoo());
a = c.getSectionAsInterface("S", AInterface.class);
@@ -1101,7 +1101,7 @@ public class ConfigTest {
c.setSection("", Arrays.asList("#C1", "#C2"));
assertTextEquals("#C1|#C2||", c);
- c.setSection("default", Arrays.asList("#C3", "#C4"));
+ c.setSection("", Arrays.asList("#C3", "#C4"));
assertTextEquals("#C3|#C4||", c);
c.setSection("S1", Arrays.asList("", "#C5", "#C6"));
@@ -1132,7 +1132,7 @@ public class ConfigTest {
c.setSection("", Arrays.asList("#C1", "#C2"), m);
assertTextEquals("#C1|#C2||a = b|", c);
- c.setSection("default", Arrays.asList("#C3", "#C4"), m);
+ c.setSection("", Arrays.asList("#C3", "#C4"), m);
assertTextEquals("#C3|#C4||a = b|", c);
c.setSection("S1", Arrays.asList("", "#C5", "#C6"), m);
@@ -1164,7 +1164,7 @@ public class ConfigTest {
assertTextEquals("a=1|", c);
- c.removeSection("default");
+ c.removeSection("");
assertTextEquals("", c);
}
@@ -1426,7 +1426,7 @@ public class ConfigTest {
@Override
public void onConfigChange(List<ConfigEvent>
events) {
for (ConfigEvent ce : events) {
- String key =
(ce.getSection().equals("default") ? "" : (ce.getSection() + '/')) +
ce.getKey();
+ String key =
(ce.getSection().equals("") ? "" : (ce.getSection() + '/')) + ce.getKey();
if (ce.getType() ==
ConfigEventType.REMOVE_ENTRY) {
changes.add("REMOVE_ENTRY("+key+")");
} else if (ce.getType() ==
ConfigEventType.REMOVE_SECTION) {
diff --git a/juneau-doc/src/main/javadoc/overview.html
b/juneau-doc/src/main/javadoc/overview.html
index ed2ca98..e15f399 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -4672,372 +4672,276 @@
<a id="juneau-config.Overview"></a>
<h3 class='topic' onclick='toggle(this)'>6.1 - Overview</h3>
<div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.EntryTypes"></a>
- <h3 class='topic' onclick='toggle(this)'>6.2 - Entry Types</h3>
- <div class='topic'>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.PrimitiveTypes"></a>
- <h4 class='topic' onclick='toggle(this)'>6.2.1 - Primitive
Types</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.POJOs"></a>
- <h4 class='topic' onclick='toggle(this)'>6.2.2 - POJOs</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Arrays"></a>
- <h4 class='topic' onclick='toggle(this)'>6.2.3 - Arrays</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Collections"></a>
- <h4 class='topic' onclick='toggle(this)'>6.2.4 -
Collections</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.BinaryData"></a>
- <h4 class='topic' onclick='toggle(this)'>6.2.5 - Binary
Data</h4>
- <div class='topic'>
- </div>
-
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Variables"></a>
- <h3 class='topic' onclick='toggle(this)'>6.3 - Variables</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.EncodedEntries"></a>
- <h3 class='topic' onclick='toggle(this)'>6.4 - Encoded Entries</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.SectionMaps"></a>
- <h3 class='topic' onclick='toggle(this)'>6.5 - Section Maps</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.SectionBeans"></a>
- <h3 class='topic' onclick='toggle(this)'>6.6 - Section Beans</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.SectionInterfaces"></a>
- <h3 class='topic' onclick='toggle(this)'>6.7 - Section Interfaces</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.SettingValues"></a>
- <h3 class='topic' onclick='toggle(this)'>6.8 - Setting Values</h3>
- <div class='topic'>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.CustomEntrySerialization"></a>
- <h4 class='topic' onclick='toggle(this)'>6.8.1 - Custom Entry
Serialization</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.BulkSettingValues"></a>
- <h4 class='topic' onclick='toggle(this)'>6.8.2 - Setting Values
in Bulk</h4>
- <div class='topic'>
- </div>
-
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Listeners"></a>
- <h3 class='topic' onclick='toggle(this)'>6.9 - Listeners</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Serializing"></a>
- <h3 class='topic' onclick='toggle(this)'>6.10 - Serializing</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.ConfigStores"></a>
- <h3 class='topic' onclick='toggle(this)'>6.11 - Config Stores</h3>
- <div class='topic'>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.ConfigMemoryStore"></a>
- <h4 class='topic' onclick='toggle(this)'>6.11.1 -
ConfigMemoryStore</h4>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.ConfigFileStore"></a>
- <h4 class='topic' onclick='toggle(this)'>6.11.2 -
ConfigFileStoren</h4>
- <div class='topic'>
- </div>
-
- </div>
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.ReadOnlyConfigs"></a>
- <h3 class='topic' onclick='toggle(this)'>6.12 - Read-only Configs</h3>
- <div class='topic'>
- </div>
-
- <!--
========================================================================================================
-->
- <a id="#juneau-config.ClosingConfigs"></a>
- <h3 class='topic' onclick='toggle(this)'>6.13 - Closing Configs</h3>
- <div class='topic'>
- </div>
-
-
- <!--
========================================================================================================
-->
- <a id="juneau-config.Overview"></a>
- <h3 class='topic' onclick='toggle(this)'>6.1 - Overview</h3>
- <div class='topic'>
<p>
The <code>juneau-config</code> library contains a
powerful API for creating and using INI-style config files.
</p>
<p>
- An example of the cotents of a config file:
+ An example of the contents of a config file:
</p>
<p class='bcode'>
- <cc># Default section</cc>
+ <cs>[Section1]</cs>
+
+ <cc># An integer</cc>
<ck>key1</ck> = <cv>1</cv>
+
+ <cc># A boolean</cc>
<ck>key2</ck> = <cv>true</cv>
- <ck>key3</ck> = <cv>[1,2,3]</cv>
- <ck>key4</ck> = <cv>http://foo</cv>
- <cc># Section 1</cc>
- <cs>[Section1]</cs>
- <ck>key1</ck> = <cv>2</cv>
- <ck>key2</ck> = <cv>false</cv>
- <ck>key3</ck> = <cv>[4,5,6]</cv>
+ <cc># An array</cc>
+ <ck>key3</ck> = <cv>1,2,3</cv>
+
+ <cc># A POJO</cc>
<ck>key4</ck> = <cv>http://bar</cv>
</p>
<p>
- This class can be used to easily access contents of the
file:
+ This code shows how the file can be accessed:
</p>
<p class='bcode'>
- <jk>int</jk> key1;
- <jk>boolean</jk> key2;
- <jk>int</jk>[] key3;
- URL key4;
-
<jc>// Load our config file</jc>
- Config f =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
-
- <jc>// Read values from default section</jc>
- key1 = f.getInt(<js>"key1"</js>);
- key2 = f.getBoolean(<js>"key2"</js>);
- key3 = f.getObject(<jk>int</jk>[].<jk>class</jk>, <js>"key3"</js>);
- key4 = f.getObject(URL.<jk>class</jk>, <js>"key4"</js>);
+ Config c =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
<jc>// Read values from section #1</jc>
- key1 = f.getInt(<js>"Section1/key1"</js>);
- key2 = f.getBoolean(<js>"Section1/key2"</js>);
- key3 = f.getObject(<jk>int</jk>[].<jk>class</jk>,
<js>"Section1/key3"</js>);
- key4 = f.getObject(URL.<jk>class</jk>, <js>"Section1/key4"</js>);
+ <jk>int</jk> key1 = c.getInt(<js>"Section1/key1"</js>);
+ <jk>boolean</jk>key2 = c.getBoolean(<js>"Section1/key2"</js>);
+ <jk>int</jk>[]key3 = c.getObject(<js>"Section1/key3"</js>,
<jk>int</jk>[].<jk>class</jk>, );
+ URL key4 = c.getObject(<js>"Section1/key4"</js>, URL.<jk>class</jk>);
</p>
<p>
- The interface also allows a config file to be easily
constructed programmatically:
- </p>
- <p class='bcode'>
- <jc>// Construct the sample config file programmatically</jc>
- Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build()
- .addLines(<jk>null</jk>,
- <js>"# Default section"</js>,
- <js>"key1 = 1"</js>,
- <js>"key2 = true"</js>,
- <js>"key3 = [1,2,3]"</js>,
- <js>"key4 = http://foo"</js>,
- <js>""</js>)
- .addHeaderComments(<js>"Section1"</js>,
- <js>"# Section 1"</js>)
- .addLines(<js>"Section1"</js>,
- <js>"key1 = 2"</js>,
- <js>"key2 = false"</js>,
- <js>"key3 = [4,5,6]"</js>,
- <js>"key4 = http://bar"</js>)
- .save();
- </p>
- <p>
- The following is equivalent, except that it uses
<code><del>Config#put(String, Object)</del></code>
- to set values:
- </p>
- <p class='bcode'>
- <jc>// Construct the sample config file programmatically</jc>
- Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build()
- .addLines(<jk>null</jk>,
- <js>"# Default section"</js>)
- .addHeaderComments(<js>"section1"</js>,
- <js>"# Section 1"</js>);
- cf.put(<js>"key1"</js>, 1);
- cf.put(<js>"key2"</js>, <jk>true</jk>);
- cf.put(<js>"key3"</js>, <jk>new int</jk>[]{1,2,3});
- cf.put(<js>"key4"</js>, <jk>new</jk> URL(<js>"http://foo"</js>));
- cf.put(<js>"Section1/key1"</js>, 2);
- cf.put(<js>"Section1/key2"</js>, <jk>false</jk>);
- cf.put(<js>"Section1/key3"</js>, <jk>new int</jk>[]{4,5,6});
- cf.put(<js>"Section1/key4"</js>, <jk>new</jk>
URL(<js>"http://bar"</js>));
- cf.save();
- </p>
- <p>
- Values are LAX JSON (i.e. unquoted attributes, single
quotes) except for top-level strings which are left
- unquoted.
- <br>Any <a class='doclink'
href='#juneau-marshall.PojoCategories'>parsable</a> types are supported as
values (e.g. arrays, collections, beans, swappable objects,
- enums, etc...).
- </p>
- <p>
- The config file looks deceptively simple, the config
file API is a very powerful feature with many
- capabilities, including:
+ The config language may look simple, but it is a very
powerful feature with many capabilities including:
</p>
<ul class='spaced-list'>
<li>
- The ability to use variables to reference
environment variables, system properties, other config file
- entries, and a host of other types.
- <li>
APIs for updating, modifying, and saving
configuration files <b style='text-decoration: underline;'>without losing
comments or formatting</b>!
<li>
+ The ability to use variables to reference
environment variables, system properties, other config file entries, and a host
of other types.
+ <li>
Extensive listener APIs.
+ <li>
+ Full file system watcher integration.
+ <li>
+ Support for user-defined storage mechanisms.
</ul>
- <h5 class='figure'>Example:</h5>
- <p class='bcode'>
- <cc>#--------------------------</cc>
- <cc># My section</cc>
- <cc>#--------------------------</cc>
- <cs>[MySection]</cs>
-
- <cc># An integer</cc>
- <ck>anInt</ck> = <cv>1</cv>
-
- <cc># A boolean</cc>
- <ck>aBoolean</ck> = <cv>true</cv>
-
- <cc># An int array</cc>
- <ck>anIntArray</ck> = <cv>[1,2,3]</cv>
-
- <cc># A POJO that can be converted from a String</cc>
- <ck>aURL</ck> = <cv>http://foo </cv>
-
- <cc># A POJO that can be converted from JSON</cc>
- <ck>aBean</ck> = <cv>{foo:'bar',baz:123}</cv>
- </p>
- <p class='bcode'>
- <jc>// Java code for accessing config entries above.</jc>
- Config cf =
Config.<jsf>create</jsf>().name(<js>"MyConfig.cfg"</js>).build();
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.EntryTypes"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.1.1 - Formatting
Rules</h4>
+ <div class='topic'>
+ <p>
+ Each config file contains zero or more sections
containing zero or more entries:
+ </p>
+ <p class='bcode'>
+ <cs>[Section1]</cs>
+ <ck>key1</ck> = <cv>1</cv>
- <jk>int</jk> anInt = cf.getInt(<js>"MySection/anInt"</js>);
- <jk>boolean</jk> aBoolean =
cf.getBoolean(<js>"MySection/aBoolean"</js>);
- <jk>int</jk>[] anIntArray = cf.getObject(<jk>int</jk>[].<jk>class</jk>,
<js>"MySection/anIntArray"</js>);
- URL aURL = cf.getObject(URL.<jk>class</jk>, <js>"MySection/aURL"</js>);
- MyBean aBean = cf.getObject(MyBean.<jk>class</jk>,
<js>"MySection/aBean"</js>);
- </p>
+ <cs>[Section2]</cs>
+ <ck>key1</ck> = <cv>2</cv>
+ </p>
+ <p>
+ Comments start with the <js>'#'</js> character
and can be placed on lines before sections and entries:
+ </p>
+ <p class='bcode'>
+ <cs># A comment about this section</cs>
+ <cs>[Section1]</cs>
+
+ <cs># A comment about this entry</cs>
+ <ck>key1</ck> = <cv>1</cv>
+ </p>
+ <p>
+ Comments can also be placed on the same line as
entries:
+ </p>
+ <p class='bcode'>
+
+ <ck>key1</ck> = <cv>1</cv> <cs># A comment about this entry
+ </p>
+ <p>
+ Values containing <js>'#'</js> must be escaped
to prevent identification as a comment character:
+ </p>
+ <p class='bcode'>
+ <ck>valueContainingPound</ck> = <cv>Value containing \#
character</cv>
+ </p>
+ <p>
+ Values containing newlines can span multiple
lines.
+ <br>Subsequent lines start with a tab character.
+ </p>
+ <p class='bcode'>
+ <ck>multiLineValue</ck> = <cv>Line 1,</cv>
+ <cv>Line 2,</cv>
+ <cv>Line 3</cv>
+ </p>
+ <p>
+ Blank lines can be used anywhere in the file.
+ </p>
+ <p class='bcode'>
+ <cs># A comment line</cs>
+
+ <cs># Another comment line</cs>
+ <cs>[Section1]</cs>
+ </p>
+ <p>
+ Values located before any sections are
considered part of the no-name section, meaning
+ they are accessed simply by key and not
section+key.
+ </p>
+ <p class='bcode'>
+ <cs># Top of file</cs>
+
+ <cs># A value in the no-name section</cs>
+ <ck>key1</ck> = <cv>val1</cv>
+
+ <cs># The first section</cs>
+ <cs>[Section1]</cs>
+ </p>
+ <p>
+ Section and key names must be at least one
character long and not consist of any of the following
+ characters:
+ <br><code>/ \ [ ] = #</code>
+ </p>
+ <p>
+ Leading and trailing whitespace on values are
ignored.
+ </p>
+ </div>
</div>
-
+
<!--
========================================================================================================
-->
- <a id="juneau-config.SectionBeans"></a>
- <h3 class='topic' onclick='toggle(this)'>6.2 - Section Beans</h3>
+ <a id="juneau-config.EntryTypes"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.2 - Entry Types</h3>
<div class='topic'>
<p>
- Config files can also be used to directly populate
beans using the
- {@link
org.apache.juneau.config.Config#getSectionAsBean(String,Class,boolean)}:
+ Configuration files can contain entries for anything
from primitive types up to complex hierarchies of POJOs consisting of maps,
collections, and/or beans.
</p>
- <p class='bcode'>
- <jc>// Example config file</jc>
- <cs>[MyAddress]</cs>
- <ck>name</ck> = <cv>John Smith</cv>
- <ck>street</ck> = <cv>123 Main Street</cv>
- <ck>city</ck> = <cv>Anywhere</cv>
- <ck>state</ck> = <cv>NY</cv>
- <ck>zip</ck> = <cv>12345</cv>
-
- <jc>// Example bean</jc>
- <jk>public class</jk> Address {
- public String name, street, city;
- public StateEnum state;
- public int zip;
- }
-
- <jc>// Example usage</jc>
- Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
- Address myAddress = cf.getSectionAsBean(<js>"MySection"</js>,
Address.<jk>class</jk>);
- </p>
- </div>
- <!--
========================================================================================================
-->
- <a id="juneau-config.SectionInterfaces"></a>
- <h3 class='topic' onclick='toggle(this)'>6.3 - Section Interfaces</h3>
- <div class='topic'>
- <p>
- Config file sections can also be accessed via interface
proxies using
- {@link
org.apache.juneau.config.Config#getSectionAsInterface(String,Class)}:
- </p>
- <p class='bcode'>
- <jc>// Example config file</jc>
- <cs>[MySection]</cs>
- <ck>string</ck> = <cv>foo</cv>
- <ck>int</ck> = <cv>123</cv>
- <ck>enum</ck> = <cv>ONE</cv>
- <ck>bean</ck> = <cv>{foo:'bar',baz:123}</cv>
- <ck>int3dArray</ck> = <cv>[[[123,null],null],null]</cv>
- <ck>bean1d3dListMap</ck> = <cv>{key:[[[[{foo:'bar',baz:123}]]]]}</cv>
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.PrimitiveTypes"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.2.1 - Primitive
Types</h4>
+ <div class='topic'>
+ <p>
+ The most common case for configuration values
are primitives.
+ </p>
+ <p class='bcode'>
+ <cc># A string</cc>
+ <ck>key1</ck> = <cv>foo</cv>
- <jc>// Example interface.</jc>
- <jc>// Setters are optional.</jc>
- <jk>public interface</jk> MyConfigInterface {
+ <cc># A boolean</cc>
+ <ck>key2</ck> = <cv>true</cv>
- String getString();
- <jk>void</jk> setString(String x);
+ <cc># An integer</cc>
+ <ck>key3</ck> = <cv>123</cv>
+
+ <cc># A long</cc>
+ <ck>key4</ck> = <cv>10000000000</cv>
+ </p>
+ <p>
+ The following methods are provided for
accessing primitive values:
+ </p>
+ <ul class='doctree'>
+ <li class='jc'>{@link
org.apache.juneau.config.Config}
+ <ul>
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getString(String) getString(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getString(String,String)
getString(String,String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getBoolean(String) getBoolean(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getBoolean(String,boolean)
getBoolean(String,boolean)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getInt(String) getInt(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getInt(String,int) getInt(String,int)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getLong(String) getLong(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getLong(String,long) getLong(String,long)}
+ </ul>
+ </ul>
+ <p>
+ On integers and longs, <js>"K"</js>,
<js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
+ </p>
+ <p class='bcode'>
+ <ck>key1</ck> = <cv>100K</cv> <cc># Same as 1024000</cc>
+ <ck>key2</ck> = <cv>100M</cv> <cc># Same as 104857600</cc>
+ </p>
+ <p>
+ Strings can be broken into separate lines by
starting the next line with a tab:
+ </p>
+ <p class='bcode'>
+ <ck>key1</ck> = <cv>This is a particularly long sentence that we want
to split</cv>
+ <cv>onto separate lines</cv>.
+ </p>
+ <p>
+ Broken lines are not trimmed between lines, and
are concatenated with newlines.
+ <br>The example above translates to <js>"This
is a particularly....split\nonto separate lines"</js>, but
+ could could pad the start and end of lines with
spaces if you wish.
+ </p>
- <jk>int</jk> getInt();
- <jk>void</jk> setInt(<jk>int</jk> x);
+ </div>
- MyEnum getEnum();
- <jk>void</jk> setEnum(MyEnum x);
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.POJOs"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.2.2 - POJOs</h4>
+ <div class='topic'>
+ <p>
+ The following methods are provided for
accessing POJO values:
+ </p>
+ <ul class='doctree'>
+ <li class='jc'>{@link
org.apache.juneau.config.Config}
+ <ul>
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Class) getObject(String,Class)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Parser,Class)
getObject(String,Parser,Class)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObjectWithDefault(String,T,Class)
getObjectWithDefault(String,T,Class)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObjectWithDefault(String,T,Parser,Class)
getObjectWithDefault(String,T,Parser,Class)}
+ </ul>
+ </ul>
+ </div>
- MyBean getBean();
- <jk>void</jk> setBean(MyBean x);
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.Arrays"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.2.3 - Arrays</h4>
+ <div class='topic'>
+ <p>
+ The following methods are provided for
accessing arrays:
+ </p>
+ <ul class='doctree'>
+ <li class='jc'>{@link
org.apache.juneau.config.Config}
+ <ul>
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getStringArray(String) getStringArray(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getStringArray(String,String[])
getStringArray(String,String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Class) getObject(String,Class)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Parser,Class)
getObject(String,Parser,Class)}
+ </ul>
+ </ul>
+ </div>
- <jk>int</jk>[][][] getInt3dArray();
- <jk>void</jk> setInt3dArray(<jk>int</jk>[][][] x);
-
- Map<String,List<MyBean[][][]>> getBean1d3dListMap();
- <jk>void</jk>
setBean1d3dListMap(Map<String,List<MyBean[][][]>> x);
- }
-
- <jc>// Example usage.</jc>
- Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
- MyConfigInterface ci = cf.getSectionAsInterface(<js>"MySection"</js>,
MyConfigInterface.<jk>class</jk>);
-
- <jc>// Read a value.</jc>
- <jk>int</jk> myInt = ci.getInt();
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.Collections"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.2.4 -
Collections</h4>
+ <div class='topic'>
+ <p>
+ The following methods are provided for
accessing maps and collections:
+ </p>
+ <ul class='doctree'>
+ <li class='jc'>{@link
org.apache.juneau.config.Config}
+ <ul>
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Type,Type...)
getObject(String,Type,Type...)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObject(String,Parser,Type,Type...)
getObject(String,Parser,Type,Type...)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObjectWithDefault(String,T,Type,Type...)
getObjectWithDefault(String,T,Type,Type...)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getObjectWithDefault(String,T,Parser,Type,Type...)
getObjectWithDefault(String,T,Parser,Type,Type...)}
+ </ul>
+ </ul>
+ </div>
- <jc>// Write a value.</jc>
- ci.setBean(<jk>new</jk> MyBean());
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.BinaryData"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.2.5 - Binary
Data</h4>
+ <div class='topic'>
+ <p>
+ The following methods are provided for
accessing maps and collections:
+ </p>
+ <ul class='doctree'>
+ <li class='jc'>{@link
org.apache.juneau.config.Config}
+ <ul>
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getBytes(String) getBytes(String)}
+ <li class='jm'>{@link
org.apache.juneau.config.Config#getBytes(String,byte[]) getBytes(String,byte[])}
+ </ul>
+ </ul>
+ </div>
- <jc>// Save your changes.</jc>
- cf.save();
- </p>
</div>
<!--
========================================================================================================
-->
<a id="juneau-config.Variables"></a>
- <h3 class='topic' onclick='toggle(this)'>6.4 - Variables</h3>
+ <h3 class='topic' onclick='toggle(this)'>6.3 - Variables</h3>
<div class='topic'>
<p>
Config files can contain variables that get resolved
dynamically using the
@@ -5134,10 +5038,10 @@
<li><code>$UE</code> - URL-encoding function.
</ul>
</div>
-
+
<!--
========================================================================================================
-->
<a id="juneau-config.EncodedEntries"></a>
- <h3 class='topic' onclick='toggle(this)'>6.5 - Encoded Entries</h3>
+ <h3 class='topic' onclick='toggle(this)'>6.4 - Encoded Entries</h3>
<div class='topic'>
<p>
If a config file contains sensitive information such as
passwords, those values can be
@@ -5169,10 +5073,138 @@
<code><del>ConfigBuilder#encoder(Encoder)</del></code>
method.
</p>
</div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.SectionMaps"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.5 - Section Maps</h3>
+ <div class='topic'>
+ </div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.SectionBeans"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.6 - Section Beans</h3>
+ <div class='topic'>
+ <p>
+ Config files can also be used to directly populate
beans using the
+ {@link
org.apache.juneau.config.Config#getSectionAsBean(String,Class,boolean)}:
+ </p>
+ <p class='bcode'>
+ <jc>// Example config file</jc>
+ <cs>[MyAddress]</cs>
+ <ck>name</ck> = <cv>John Smith</cv>
+ <ck>street</ck> = <cv>123 Main Street</cv>
+ <ck>city</ck> = <cv>Anywhere</cv>
+ <ck>state</ck> = <cv>NY</cv>
+ <ck>zip</ck> = <cv>12345</cv>
+
+ <jc>// Example bean</jc>
+ <jk>public class</jk> Address {
+ public String name, street, city;
+ public StateEnum state;
+ public int zip;
+ }
+
+ <jc>// Example usage</jc>
+ Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
+ Address myAddress = cf.getSectionAsBean(<js>"MySection"</js>,
Address.<jk>class</jk>);
+ </p>
+ </div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.SectionInterfaces"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.7 - Section Interfaces</h3>
+ <div class='topic'>
+ <p>
+ Config file sections can also be accessed via interface
proxies using
+ {@link
org.apache.juneau.config.Config#getSectionAsInterface(String,Class)}:
+ </p>
+ <p class='bcode'>
+ <jc>// Example config file</jc>
+ <cs>[MySection]</cs>
+ <ck>string</ck> = <cv>foo</cv>
+ <ck>int</ck> = <cv>123</cv>
+ <ck>enum</ck> = <cv>ONE</cv>
+ <ck>bean</ck> = <cv>{foo:'bar',baz:123}</cv>
+ <ck>int3dArray</ck> = <cv>[[[123,null],null],null]</cv>
+ <ck>bean1d3dListMap</ck> = <cv>{key:[[[[{foo:'bar',baz:123}]]]]}</cv>
+
+ <jc>// Example interface.</jc>
+ <jc>// Setters are optional.</jc>
+ <jk>public interface</jk> MyConfigInterface {
+
+ String getString();
+ <jk>void</jk> setString(String x);
+
+ <jk>int</jk> getInt();
+ <jk>void</jk> setInt(<jk>int</jk> x);
+
+ MyEnum getEnum();
+ <jk>void</jk> setEnum(MyEnum x);
+
+ MyBean getBean();
+ <jk>void</jk> setBean(MyBean x);
+
+ <jk>int</jk>[][][] getInt3dArray();
+ <jk>void</jk> setInt3dArray(<jk>int</jk>[][][] x);
+
+ Map<String,List<MyBean[][][]>> getBean1d3dListMap();
+ <jk>void</jk>
setBean1d3dListMap(Map<String,List<MyBean[][][]>> x);
+ }
+
+ <jc>// Example usage.</jc>
+ Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
+ MyConfigInterface ci = cf.getSectionAsInterface(<js>"MySection"</js>,
MyConfigInterface.<jk>class</jk>);
+ <jc>// Read a value.</jc>
+ <jk>int</jk> myInt = ci.getInt();
+
+ <jc>// Write a value.</jc>
+ ci.setBean(<jk>new</jk> MyBean());
+
+ <jc>// Save your changes.</jc>
+ cf.save();
+ </p>
+ </div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.SettingValues"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.8 - Setting Values</h3>
+ <div class='topic'>
+
+ <p>
+ The interface also allows a config file to be easily
constructed programmatically:
+ </p>
+ <p class='bcode'>
+ <jc>// Construct the sample config file programmatically</jc>
+ Config cf =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build()
+ .set(<js>"key1"</js>, 1)
+ .set(<js>"key2"</js>, <jk>true</jk>)
+ .set(<js>"key3"</js>, <jk>new int</jk>[]{1,2,3})
+ .set(<js>"key4"</js>, <jk>new</jk> URI(<js>"http://foo"</js>))
+ .set(<js>"Section1/key1"</js>, 2)
+ .set(<js>"Section1/key2"</js>, <jk>false</jk>)
+ .set(<js>"Section1/key3"</js>, <jk>new int</jk>[]{4,5,6})
+ .set(<js>"Section1/key4"</js>, <jk>new</jk>
URI(<js>"http://bar"</js>))
+ .save();
+ </p>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.CustomEntrySerialization"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.8.1 - Custom Entry
Serialization</h4>
+ <div class='topic'>
+ </div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.BulkSettingValues"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.8.2 - Setting Values
in Bulk</h4>
+ <div class='topic'>
+ </div>
+
+ </div>
+
<!--
========================================================================================================
-->
<a id="juneau-config.Listeners"></a>
- <h3 class='topic' onclick='toggle(this)'>6.6 - Listeners</h3>
+ <h3 class='topic' onclick='toggle(this)'>6.9 - Listeners</h3>
<div class='topic'>
<p>
The following method is provided for listening to
changes made on config files:
@@ -5208,256 +5240,57 @@
);
</p>
</div>
-
-
+
<!--
========================================================================================================
-->
<a id="juneau-config.Serializing"></a>
- <h3 class='topic' onclick='toggle(this)'>6.8 - Serializing Config
Files</h3>
+ <h3 class='topic' onclick='toggle(this)'>6.10 - Serializing</h3>
<div class='topic'>
- <p>
- Instances of {@link org.apache.juneau.config.Config}
are POJOs that can be serialized to and parsed from
- all supported Juneau languages.
- </p>
- <p>
- The
<code>org.apache.juneau.microservice.resources.ConfigResource</code> is a
predefined REST interface that
- allows access to the config file used by a microservice.
- <br>The <code>juneau-examples-rest</code> project is a
microservice that includes this resource
- at <code>http://localhost:10000/sample/config</code>.
- <br>The sample microservice uses the following config
file <code>juneau-examples.cfg</code>:
- </p>
- <p class='bcode'>
-
<cc>#================================================================================
- # Basic configuration file for SaaS microservices
- # Subprojects can use this as a starting point.
-
#================================================================================</cc>
-
-
<cc>#================================================================================
- # REST settings
-
#================================================================================</cc>
- <cs>[REST]</cs>
-
- <cc># The HTTP port number to use.
- # Default is Rest-Port setting in manifest file, or 8000.</cc>
- <ck>port</ck> = <cv>10000</cv>
-
- <cc># A JSON map of servlet paths to servlet classes.
- # Example:
- # resourceMap = {'/*':'com.foo.MyServlet'}
- # Either resourceMap or resources must be specified.</cc>
- <ck>resourceMap</ck> =
-
- <cc># A comma-delimited list of names of classes that extend from
Servlet.
- # Resource paths are pulled from @RestResource.path() annotation, or
- # "/*" if annotation not specified.
- # Example:
- # resources = com.foo.MyServlet
- # Default is Rest-Resources in manifest file.
- # Either resourceMap or resources must be specified.</cc>
- <ck>resources</ck> =
-
- <cc># The context root of the Jetty server.
- # Default is Rest-ContextPath in manifest file, or "/".</cc>
- <ck>contextPath</ck> =
+ </div>
- <cc># Authentication: NONE, BASIC.</cc>
- <ck>authType</ck> = <cv>NONE</cv>
-
- <cc># The BASIC auth username.
- # Default is Rest-LoginUser in manifest file.</cc>
- <ck>loginUser</ck> =
-
- <cc># The BASIC auth password.
- # Default is Rest-LoginPassword in manifest file.</cc>
- <ck>loginPassword</ck> =
-
- <cc># The BASIC auth realm.
- # Default is Rest-AuthRealm in manifest file.</cc>
- <ck>authRealm</ck> =
-
- <cc># Stylesheet to use for HTML views.
- # The default options are:
- # - styles/juneau.css
- # - styles/devops.css
- # Other stylesheets can be referenced relative to the servlet package
or working
- # directory.</cc>
- <ck>stylesheet</ck> = <cv>styles/devops.css</cv>
-
- <cc># What to do when the config file is saved.
- # Possible values:
- # NOTHING - Don't do anything.
- # RESTART_SERVER - Restart the Jetty server.
- # RESTART_SERVICE - Shutdown and exit with code '3'.</cc>
- <ck>saveConfigAction</ck> = <cv>RESTART_SERVER</cv>
-
- <cc># Enable SSL support.</cc>
- <ck>useSsl</ck> = false
-
-
<cc>#================================================================================
- # Bean properties on the org.eclipse.jetty.util.ssl.SslSocketFactory
class
-
#--------------------------------------------------------------------------------
- # Ignored if REST/useSsl is false.
-
#================================================================================</cc>
- <cs>[REST-SslContextFactory]</cs>
- <ck>keyStorePath</ck> = <cv>client_keystore.jks</cv>
- <ck>keyStorePassword*</ck> = <cv>{HRAaRQoT}</cv>
- <ck>excludeCipherSuites</ck> = <cv>TLS_DHE.*, TLS_EDH.*</cv>
- <ck>excludeProtocols</ck> = <cv>SSLv3</cv>
- <ck>allowRenegotiate</ck> = <cv>false</cv>
-
-
<cc>#================================================================================
- # Logger settings
- # See FileHandler Java class for details.
-
#================================================================================</cc>
- <cs>[Logging]</cs>
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.ConfigStores"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.11 - Config Stores</h3>
+ <div class='topic'>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.ConfigMemoryStore"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.11.1 -
ConfigMemoryStore</h4>
+ <div class='topic'>
+ </div>
+
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.ConfigFileStore"></a>
+ <h4 class='topic' onclick='toggle(this)'>6.11.2 -
ConfigFileStoren</h4>
+ <div class='topic'>
+ </div>
- <cc># The directory where to create the log file.
- # Default is "."</cc>
- <ck>logDir</ck> = <cv>logs</cv>
-
- <cc># The name of the log file to create for the main logger.
- # The logDir and logFile make up the pattern that's passed to the
FileHandler
- # constructor.
- # If value is not specified, then logging to a file will not be set
up.</cc>
- <ck>logFile</ck> = <cv>microservice.%g.log</cv>
-
- <cc># Whether to append to the existing log file or create a new one.
- # Default is false.</cc>
- <ck>append</ck> =
-
- <cc># The SimpleDateFormat format to use for dates.
- # Default is "yyyy.MM.dd hh:mm:ss".</cc>
- <ck>dateFormat</ck> =
-
- <cc># The log message format.
- # The value can contain any of the following variables:
- # {date} - The date, formatted per dateFormat.
- # {class} - The class name.
- # {method} - The method name.
- # {logger} - The logger name.
- # {level} - The log level name.
- # {msg} - The log message.
- # {threadid} - The thread ID.
- # {exception} - The localized exception message.
- # Default is "[{date} {level}] {msg}%n".</cc>
- <ck>format</ck> =
-
- <cc># The maximum log file size.
- # Suffixes available for numbers.
- # See ConfigFile.getInt(String,int) for details.
- # Default is 1M.</cc>
- <ck>limit</ck> = <cv>10M</cv>
-
- <cc># Max number of log files.
- # Default is 1.</cc>
- <ck>count</ck> = <cv>5</cv>
-
- <cc># Default log levels.
- # Keys are logger names.
- # Values are serialized Level POJOs.</cc>
- <ck>levels</ck> = <cv>{ org.apache.juneau:'INFO' }</cv>
-
- <cc># Only print unique stack traces once and then refer to them by a
simple 8 character hash identifier.
- # Useful for preventing log files from filling up with duplicate stack
traces.
- # Default is false.</cc>
- <ck>useStackTraceHashes</ck> = <cv>true</cv>
-
- <cc># The default level for the console logger.
- # Default is WARNING.</cc>
- <ck>consoleLevel</ck> =
-
-
<cc>#================================================================================
- # System properties
-
#--------------------------------------------------------------------------------
- # These are arbitrary system properties that are set during startup.
-
#================================================================================</cc>
- <cs>[SystemProperties]</cs>
-
- <cc># Configure Jetty for StdErrLog Logging</cc>
- <ck>org.eclipse.jetty.util.log.class</ck> =
<cv>org.eclipse.jetty.util.log.StrErrLog</cv>
-
- <cc># Jetty logging level</cc>
- <ck>org.eclipse.jetty.LEVEL</ck> = <cv>WARN</cv>
- </p>
- <p>
- The config file looks deceivingly simple.
- However, it should be noticed that the config file is a
VERY powerful feature with many capabilities including:
- </p>
- <p>
- When you point your browser to this resource, you'll
notice that the contents of the config file are being
- serialized to HTML as a POJO:
- </p>
- <img class='bordered'
src="doc-files/juneau-config.Serializing.1.png">
- <p>
- Likewise, the config file can also be serialized as any
of the supported languages such as JSON:
- </p>
- <img class='bordered'
src="doc-files/juneau-config.Serializing.2.png">
- <p>
- The code for implementing this page could not be any
simpler, since it simply returns the config file returned
- by the <code>RestServlet.getConfig()</code> method.
- </p>
- <p class='bcode'>
- <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/"</js>,
description=<js>"Show contents of config file."</js>)
- <jk>public</jk> Config getConfigContents() <jk>throws</jk> Exception {
- <jk>return</jk> getConfig();
- }
- </p>
- <p>
- The edit page takes you to an editor that allows you to
modify the contents of the config file:
- </p>
- <img class='bordered'
src="doc-files/juneau-config.Serializing.3.png">
- <p>
- This latter page uses the {@link
org.apache.juneau.config.Config#toString()} method to retrieve the
- contents of the config file in INI format.
- </p>
- <p>
- Since config files are serializable, that mean they can
also be retrieved through the <code>RestClient</code>
- API.
- </p>
- <p class='bcode'>
- <jc>// Create a new REST client with JSON support</jc>
- RestClient c = RestClient.<jsm>create</jsm>().build();
+ </div>
- <jc>// Retrieve config file through REST interface</jc>
- Config cf =
c.doGet(<js>"http://localhost:10000/sample/config"</js>).getResponse(Config.<jk>class</jk>);
- </p>
+ <!--
========================================================================================================
-->
+ <a id="juneau-config.ReadOnlyConfigs"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.12 - Read-only Configs</h3>
+ <div class='topic'>
</div>
-
+
<!--
========================================================================================================
-->
- <a id="juneau-config.Merging"></a>
- <h3 class='topic' onclick='toggle(this)'>6.9 - Merging Config Files</h3>
+ <a id="#juneau-config.ClosingConfigs"></a>
+ <h3 class='topic' onclick='toggle(this)'>6.13 - Closing Configs</h3>
<div class='topic'>
- <!--p>
- In the previous example, an edit page was shown that
allows you to edit config files through
- a REST interface.
- <br>Note that if only a single entry is modified in the
config file, we only want to trigger
- listeners for that change, not trigger all listeners.
- <br>This is where the
<code><del>Config#merge(ConfigFile)</del></code> method comes into play.
- <br>This method will copy the contents of one config
file over to another config file, but only
- trigger listeners when the values are different.
- </p>
<p>
- The edit page is implemented with this method which is
a simple PUT with the contents of the new config file as
- the body of the HTTP request:
+ In general, it's good practice to close Config if
you're only creating them temporarily so that
+ their listeners get unregistered from the underlying
storage APIs.
</p>
<p class='bcode'>
- <ja>@RestMethod</ja>(name=<jsf>PUT</jsf>, path=<js>"/"</js>,
- description=<js>"Sets contents of config file."</js>,
- parameters={
- <ja>@Parameter</ja>(in=<js>"body"</js>,
description=<js>"New contents in INI file format."</js>)
- }
- )
- <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 = 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>
- <jk>return</jk> getConfig().merge(cf2).save();
- }
- </p-->
+ <jc>// Create a transient config.</jc>
+ Config c =
Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
+
+ <jc>// Do stuff with it.</jc>
+
+ <jc>// Then close the config to unregister the
listeners.</jc>
+ c.close();
+ </p>
</div>
-
+
</div>
<!--
===========================================================================================================
-->
--
To stop receiving notification emails like this one, please contact
[email protected].