/** * Constructor. * * @param store The config store. * @param name The config name. * @throws IOException */ public ConfigMap(ConfigStore store, String name) throws IOException { this.store = store; this.name = name; load(store.read(name)); }
/** * Overwrites the contents of the config file. * * @param contents The new contents of the config file. * @param synchronous Wait until the change has been persisted before returning this map. * @return This object (for method chaining). * @throws IOException * @throws InterruptedException */ public ConfigMap load(String contents, boolean synchronous) throws IOException, InterruptedException { if (synchronous) { final CountDownLatch latch = new CountDownLatch(1); ConfigStoreListener l = new ConfigStoreListener() { @Override public void onChange(String contents) { latch.countDown(); } }; store.register(name, l); store.write(name, null, contents); latch.await(30, TimeUnit.SECONDS); store.unregister(name, l); } else { store.write(name, null, contents); } return this; }
/** * Convenience method for updating the contents of a file with lines. * * @param name The config name (e.g. the filename without the extension). * @param contentLines The new contents. * @return This object (for method chaining). */ public synchronized ConfigStore update(String name, String...contentLines) { name = resolveName(name); StringBuilder sb = new StringBuilder(); for (String l : contentLines) sb.append(l).append('\n'); return update(name, sb.toString()); }
/** * Returns a map file containing the parsed contents of a configuration. * * @param name The configuration name. * @return * The parsed configuration. * <br>Never <jk>null</jk>. * @throws IOException */ public synchronized ConfigMap getMap(String name) throws IOException { name = resolveName(name); ConfigMap cm = configMaps.get(name); if (cm != null) return cm; cm = new ConfigMap(this, name); ConfigMap cm2 = configMaps.putIfAbsent(name, cm); if (cm2 != null) return cm2; register(name, cm); return cm; }
@Test public void testSetPrelinesOnExistingEntryWithAtrributes() throws Exception { ConfigStore s = initStore("Foo.cfg", "[S1]", "#k1a", "k1 = v1 # comment" ); ConfigMap cm = s.getMap("Foo.cfg"); cm.setEntry("S1", "k1", null, null, null, Arrays.asList("#k1b")); assertTextEquals("[S1]|#k1b|k1 = v1 # comment|", cm); }
@Override /* ConfigStore */ public synchronized ConfigFileStore update(String name, String newContents) { cache.put(name, newContents); super.update(name, newContents); return this; }
@Test public void testSettingEntries() throws Exception { ConfigStore s = initStore("Foo.cfg", "[S1]", "k1 = v1a", "k2 = v2a" ); ConfigMap cm = s.getMap("Foo.cfg"); cm.setEntry("S1", "k1", "v1b", null, null, null); cm.setEntry("S1", "k2", null, null, null, null); cm.setEntry("S1", "k3", "v3b", null, null, null); assertTextEquals("[S1]|k1 = v1b|k2 = v2a|k3 = v3b|", cm); cm.commit(); assertTextEquals("[S1]|k1 = v1b|k2 = v2a|k3 = v3b|", s.read("Foo.cfg")); // Round trip. cm = s.getMap("Foo.cfg"); assertTextEquals("[S1]|k1 = v1b|k2 = v2a|k3 = v3b|", cm); }
/** * Unregisters a listener from this store. * * @param name The configuration name to listen for. * @param l The listener to unregister. * @return This object (for method chaining). */ public synchronized ConfigStore unregister(String name, ConfigStoreListener l) { name = resolveName(name); Set<ConfigStoreListener> s = listeners.get(name); if (s != null) s.remove(l); return this; }
if (i == 10) throw new ConfigException("Unable to store contents of config to store."); String currentContents = store.write(name, contents, newContents); if (currentContents == null) break;
/** * Returns a map file containing the parsed contents of a configuration. * * @param name The configuration name. * @return * The parsed configuration. * <br>Never <jk>null</jk>. * @throws IOException */ public synchronized ConfigMap getMap(String name) throws IOException { ConfigMap cm = configMaps.get(name); if (cm != null) return cm; cm = new ConfigMap(this, name); ConfigMap cm2 = configMaps.putIfAbsent(name, cm); if (cm2 != null) return cm2; register(name, cm); return cm; }
for (String name : getCandidateConfigNames()) { if (store != null) { if (store.exists(name)) { configBuilder.store(store).name(name); break;
@Test public void testSetEntryInvalidSectionNames() throws Exception { ConfigStore s = initStore("Foo.cfg"); ConfigMap cm = s.getMap("Foo.cfg"); String[] test = { "/", "[", "]", "foo/bar", "foo[bar", "foo]bar", " ", null }; for (String t : test) { try { cm.setEntry(t, "k1", "foo", null, null, null); fail("Exception expected."); } catch (IllegalArgumentException e) { assertTrue(e.getLocalizedMessage().startsWith("Invalid section name")); } } }
@Override /* ConfigStore */ public synchronized ConfigFileStore update(String name, String newContents) { cache.put(name, newContents); super.update(name, newContents); return this; }
@Test public void testSettingEntriesWithPreLines() throws Exception { ConfigStore s = initStore("Foo.cfg", "", "#S1", "", "[S1]", "", "#k1", "", "k1 = v1a", "", "#k2", "", "k2 = v2a" ); ConfigMap cm = s.getMap("Foo.cfg"); cm.setEntry("S1", "k1", "v1b", null, null, null); cm.setEntry("S1", "k2", null, null, null, null); cm.setEntry("S1", "k3", "v3b", null, null, null); cm.setEntry("S1", "k4", "v4b", null, null, Arrays.asList("","#k4","")); assertTextEquals("|#S1||[S1]||#k1||k1 = v1b||#k2||k2 = v2a|k3 = v3b||#k4||k4 = v4b|", cm); cm.commit(); assertTextEquals("|#S1||[S1]||#k1||k1 = v1b||#k2||k2 = v2a|k3 = v3b||#k4||k4 = v4b|", s.read("Foo.cfg")); // Round trip. cm = s.getMap("Foo.cfg"); assertTextEquals("|#S1||[S1]||#k1||k1 = v1b||#k2||k2 = v2a|k3 = v3b||#k4||k4 = v4b|", cm); }
/** * Convenience method for updating the contents of a file with lines. * * @param name The config name (e.g. the filename without the extension). * @param contentLines The new contents. * @return This object (for method chaining). */ public synchronized ConfigStore update(String name, String...contentLines) { name = resolveName(name); StringBuilder sb = new StringBuilder(); for (String l : contentLines) sb.append(l).append('\n'); return update(name, sb.toString()); }
/** * Returns a map file containing the parsed contents of a configuration. * * @param name The configuration name. * @return * The parsed configuration. * <br>Never <jk>null</jk>. * @throws IOException */ public synchronized ConfigMap getMap(String name) throws IOException { name = resolveName(name); ConfigMap cm = configMaps.get(name); if (cm != null) return cm; cm = new ConfigMap(this, name); ConfigMap cm2 = configMaps.putIfAbsent(name, cm); if (cm2 != null) return cm2; register(name, cm); return cm; }
/** * Unregisters a listener from this store. * * @param name The configuration name to listen for. * @param l The listener to unregister. * @return This object (for method chaining). */ public synchronized ConfigStore unregister(String name, ConfigStoreListener l) { name = resolveName(name); Set<ConfigStoreListener> s = listeners.get(name); if (s != null) s.remove(l); return this; }
if (i == 10) throw new ConfigException("Unable to store contents of config to store."); String currentContents = store.write(name, contents, newContents); if (currentContents == null) break;
@Test public void testMergeWithOverwrite() throws Exception { ConfigStore s = initStore("Foo.cfg", "[S1]", "k1 = v1a" ); final CountDownLatch latch = new CountDownLatch(2); final Queue<String> eventList = new ConcurrentLinkedQueue<>(); eventList.add("['SET(S1/k1 = v1b)']"); eventList.add("['SET(S1/k1 = v1c)']"); LatchedListener l = new LatchedListener(latch) { @Override public void check(ConfigEvents events) throws Exception { assertObjectEquals(eventList.poll(), events); } }; ConfigMap cm = s.getMap("Foo.cfg"); cm.register(l); cm.setEntry("S1", "k1", "v1c", null, null, null); s.update("Foo.cfg", "[S1]", "k1 = v1b" ); cm.commit(); wait(latch); assertNull(l.error); cm.unregister(l); assertTextEquals("[S1]|k1 = v1c|", cm.toString()); }