You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/10/06 14:44:07 UTC
incubator-juneau git commit: Updates to config API.
Repository: incubator-juneau
Updated Branches:
refs/heads/master 39cecfc7a -> 0ab9c5261
Updates to config API.
Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/0ab9c526
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/0ab9c526
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/0ab9c526
Branch: refs/heads/master
Commit: 0ab9c5261ea6251bd205389d22bcf84c87744c14
Parents: 39cecfc
Author: JamesBognar <ja...@apache.org>
Authored: Fri Oct 6 10:43:58 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Fri Oct 6 10:43:58 2017 -0400
----------------------------------------------------------------------
.../org/apache/juneau/ini/ConfigSource.java.off | 74 +++++++++++
.../apache/juneau/ini/ConfigSourceFile.java.off | 133 +++++++++++++++++++
.../juneau/ini/ConfigSourceMemory.java.off | 131 ++++++++++++++++++
.../juneau/ini/ConfigSourceSettings.java.off | 104 +++++++++++++++
4 files changed, 442 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ab9c526/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSource.java.off
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSource.java.off b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSource.java.off
new file mode 100644
index 0000000..a8a337a
--- /dev/null
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSource.java.off
@@ -0,0 +1,74 @@
+// ***************************************************************************************************************************
+// * 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;
+
+/**
+ * Represents a storage location of a configuration file.
+ */
+public abstract class ConfigSource {
+
+ /** The path of the config file. */
+ private final ConfigSourceSettings settings;
+
+ /**
+ * Constructor.
+ *
+ * @param settings
+ * The settings for this config source.
+ */
+ protected ConfigSource(ConfigSourceSettings settings) {
+ this.settings = settings;
+ }
+
+ /**
+ * Returns the name of the config file.
+ *
+ * @return The name of the config file.
+ */
+ protected final ConfigSourceSettings getSettings() {
+ return settings;
+ }
+
+ /**
+ * Returns the contents of the configuration file.
+ *
+ * @param name The config file name.
+ * @return The contents of the configuration file.
+ * @throws Exception
+ */
+ protected abstract String read(String name) throws Exception;
+
+ /**
+ * Saves the contents of the configuration file if the underlying storage hasn't been modified.
+ *
+ * @param name The config file name.
+ * @param contents The new contents of the configuration file.
+ * @return <jk>true</jk> if we successfully saved the new configuration file contents, or <jk>false</jk> if the
+ * underlying storage changed since the last time the {@link #read(String)} method was called.
+ * @throws Exception
+ */
+ protected abstract boolean write(String name, String contents) throws Exception;
+
+ /**
+ * Returns whether the underlying configuration contents have changed.
+ *
+ * <p>
+ * For example, if the configuration source is a file, this method would return <jk>true</jk> if the
+ * file on the filesystem has been modified since the {@link #read(String)} method was called.
+ *
+ * @param name The config file name.
+ * @return <jk>true</jk> if the persisted contents of the config file have changed.
+ * @throws Exception
+ */
+ protected abstract boolean hasBeenModified(String name) throws Exception;
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ab9c526/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceFile.java.off
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceFile.java.off b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceFile.java.off
new file mode 100644
index 0000000..723c03b
--- /dev/null
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceFile.java.off
@@ -0,0 +1,133 @@
+// ***************************************************************************************************************************
+// * 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 java.io.*;
+import java.nio.channels.*;
+import java.nio.charset.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Implementation of a configuration source that's a file on the local file system.
+ */
+public class ConfigSourceFile extends ConfigSource {
+
+ private ConcurrentHashMap<String,CacheEntry> cache = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor.
+ *
+ * @param settings
+ * The settings for this config source.
+ */
+ public ConfigSourceFile(ConfigSourceSettings settings) {
+ super(settings);
+ }
+
+ @Override /* ConfigSource */
+ public synchronized String read(String name) throws Exception {
+ CacheEntry fe = cache.get(name);
+
+ if (fe == null || fe.hasBeenModified()) {
+ File f = findFile(name);
+ try (FileInputStream fis = new FileInputStream(f)) {
+ try (FileLock lock = fis.getChannel().lock()) {
+ try (Reader r = new InputStreamReader(fis, Charset.defaultCharset())) {
+ String contents = IOUtils.read(r);
+ long lastModified = f.lastModified();
+ fe = new CacheEntry(f, lastModified, contents);
+ cache.put(name, fe);
+ }
+ }
+ }
+ }
+
+ return fe.contents;
+ }
+
+ @Override /* ConfigSource */
+ public synchronized boolean write(String name, String contents) throws Exception {
+ if (hasBeenModified(name))
+ return false;
+
+ CacheEntry fe = cache.get(name);
+ File f = fe != null ? fe.file : findFile(name);
+
+ try (FileOutputStream fos = new FileOutputStream(f)) {
+ try (FileLock lock = fos.getChannel().lock()) {
+ if (hasBeenModified(name))
+ return false;
+ try (Writer w = new OutputStreamWriter(fos, Charset.defaultCharset())) {
+ IOUtils.pipe(contents, w);
+ }
+ fe = new CacheEntry(f, f.lastModified(), contents);
+ cache.put(name, fe);
+ return true;
+ }
+ }
+ }
+
+ @Override /* ConfigSource */
+ public boolean hasBeenModified(String name) throws Exception {
+ CacheEntry fe = cache.get(name);
+ return (fe != null && fe.hasBeenModified());
+ }
+
+ private static class CacheEntry {
+ final File file;
+ final long lastModified;
+ final String contents;
+
+ CacheEntry(File file, long lastModified, String contents) {
+ this.file = file;
+ this.lastModified = lastModified;
+ this.contents = contents;
+ }
+
+ boolean hasBeenModified() {
+ return file.lastModified() != lastModified;
+ }
+ }
+
+ private File findFile(String name) throws IOException {
+
+ List<String> searchPaths = getSettings().getSearchPaths();
+
+ if (searchPaths.isEmpty())
+ throw new FileNotFoundException("No search paths specified in ConfigFileBuilder.");
+
+ // Handle paths relative to search paths.
+ for (String sp : searchPaths) {
+ File pf = new File(sp);
+ File f = new File(pf, name);
+ if (f.exists())
+ return f;
+ }
+
+ if (getSettings().isCreateIfNotExists()) {
+ for (String sf : searchPaths) {
+ File pf = new File(sf);
+ if (pf.exists() && pf.isDirectory() && pf.canWrite()) {
+ File f = new File(pf, name);
+ if (f.createNewFile())
+ return f;
+ }
+ }
+ }
+
+ throw new FileNotFoundException("Could not find config file '"+name+"'");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ab9c526/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceMemory.java.off
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceMemory.java.off b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceMemory.java.off
new file mode 100644
index 0000000..9f73675
--- /dev/null
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceMemory.java.off
@@ -0,0 +1,131 @@
+// ***************************************************************************************************************************
+// * 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 java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Implementation of a configuration source entirely in memory.
+ */
+public class ConfigSourceMemory extends ConfigSource {
+
+ private static final ConcurrentHashMap<String,MemoryFile> MEMORY = new ConcurrentHashMap<>();
+
+ private ConcurrentHashMap<String,CacheEntry> cache = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor.
+ *
+ * @param settings
+ * The settings for this config source.
+ */
+ public ConfigSourceMemory(ConfigSourceSettings settings) {
+ super(settings);
+ }
+
+ @Override /* ConfigSource */
+ public synchronized String read(String name) throws Exception {
+ CacheEntry ce = cache.get(name);
+
+ if (ce == null || ce.hasBeenModified()) {
+ MemoryFile f = findFile(name);
+ synchronized(f) {
+ ce = new CacheEntry(f, f.lastModified, f.contents);
+ cache.put(name, ce);
+ }
+ }
+
+ return ce.contents;
+ }
+
+ @Override /* ConfigSource */
+ public synchronized boolean write(String name, String contents) throws Exception {
+ if (hasBeenModified(name))
+ return false;
+
+ CacheEntry ce = cache.get(name);
+ MemoryFile f = ce != null ? ce.file : findFile(name);
+
+ synchronized(f) {
+ if (hasBeenModified(name))
+ return false;
+ f.contents = contents;
+ f.lastModified = System.currentTimeMillis();
+ ce = new CacheEntry(f, f.lastModified, f.contents);
+ cache.put(name, ce);
+ }
+
+ return true;
+ }
+
+ @Override /* ConfigSource */
+ public boolean hasBeenModified(String name) throws Exception {
+ CacheEntry ce = cache.get(name);
+ return (ce != null && ce.hasBeenModified());
+ }
+
+ private MemoryFile findFile(String name) throws IOException {
+
+ List<String> searchPaths = getSettings().getSearchPaths();
+
+ if (searchPaths.isEmpty())
+ throw new FileNotFoundException("No search paths specified in ConfigFileBuilder.");
+
+ // Handle paths relative to search paths.
+ for (String sp : searchPaths) {
+ String pf = sp + '/' + name;
+ MemoryFile mf = MEMORY.get(pf);
+ if (mf != null)
+ return mf;
+ }
+
+ if (getSettings().isCreateIfNotExists()) {
+ for (String sf : searchPaths) {
+ String path = sf + '/' + name;
+ MemoryFile mf = new MemoryFile("");
+ MEMORY.putIfAbsent(path, mf);
+ return MEMORY.get(path);
+ }
+ }
+
+ throw new FileNotFoundException("Could not find config file '"+name+"'");
+ }
+
+ private static class MemoryFile {
+ private String contents;
+ private long lastModified;
+
+ private MemoryFile(String contents) {
+ this.contents = contents;
+ this.lastModified = System.currentTimeMillis();
+ }
+ }
+
+ private static class CacheEntry {
+ final MemoryFile file;
+ final long lastModified;
+ final String contents;
+
+ CacheEntry(MemoryFile file, long lastModified, String contents) {
+ this.file = file;
+ this.lastModified = lastModified;
+ this.contents = contents;
+ }
+
+ boolean hasBeenModified() {
+ return file.lastModified != lastModified;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ab9c526/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceSettings.java.off
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceSettings.java.off b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceSettings.java.off
new file mode 100644
index 0000000..7a72bae
--- /dev/null
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigSourceSettings.java.off
@@ -0,0 +1,104 @@
+// ***************************************************************************************************************************
+// * 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 java.nio.charset.*;
+import java.util.*;
+
+/**
+ * Configuration settings for the {@link ConfigSource} class.
+ */
+public class ConfigSourceSettings {
+
+ private final List<String> searchPaths;
+ private final Charset charset;
+ private final boolean readonly, createIfNotExists;
+
+ @SuppressWarnings("hiding")
+ static class Builder {
+ private List<String> searchPaths = Arrays.asList(new String[]{"."});
+ private Charset charset = Charset.defaultCharset();
+ private boolean readonly = false, createIfNotExists = true;
+
+ Builder searchPaths(String[] searchPaths) {
+ this.searchPaths = Arrays.asList(searchPaths);
+ return this;
+ }
+
+ Builder charset(Charset charset) {
+ this.charset = charset;
+ return this;
+ }
+
+ Builder readonly(boolean readonly) {
+ this.readonly = readonly;
+ return this;
+ }
+
+ Builder createIfNotExists(boolean createIfNotExists) {
+ this.createIfNotExists = createIfNotExists;
+ return this;
+ }
+
+ ConfigSourceSettings build() {
+ return new ConfigSourceSettings(this);
+ }
+ }
+
+ ConfigSourceSettings(Builder b) {
+ this.searchPaths = b.searchPaths;
+ this.charset = b.charset;
+ this.readonly = b.readonly;
+ this.createIfNotExists = b.createIfNotExists;
+ }
+
+ /**
+ * Returns the paths to search to find config files.
+ *
+ * @return The paths to search to find config files.
+ */
+ public List<String> getSearchPaths() {
+ return searchPaths;
+ }
+
+ /**
+ * Returns the charset of the config file.
+ *
+ * @return The charset of the config file.
+ */
+ public Charset getCharset() {
+ return charset;
+ }
+
+ /**
+ * Specifies whether the config file should be opened in read-only mode.
+ *
+ * @return <jk>true</jk> if the config file should be opened in read-only mode.
+ */
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ /**
+ * Specifies whether config files should be created if they're not found in the search paths.
+ *
+ * <p>
+ * Note that the first writable path will be used for the location of the file.
+ *
+ * @return <jk>true</jk> if the config file should be created if not found.
+ */
+ public boolean isCreateIfNotExists() {
+ return createIfNotExists;
+ }
+}
+