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;
+	}
+}
+