All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.ini.ConfigSourceFile Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * 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 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 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+"'");
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy