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 <[email protected]>
Authored: Fri Oct 6 10:43:58 2017 -0400
Committer: JamesBognar <[email protected]>
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;
+       }
+}
+

Reply via email to