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

net.sf.aguacate.configuration.impl.ConfigurationBridgeImpl Maven / Gradle / Ivy

There is a newer version: 0.10.9
Show newest version
package net.sf.aguacate.configuration.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.sf.aguacate.configuration.Configuration;
import net.sf.aguacate.configuration.ConfigurationBridge;
import net.sf.aguacate.configuration.compiler.ConfigurationCompiler;
import net.sf.aguacate.util.codec.bridge.CodecCoupling;
import net.sf.aguacate.util.filesystem.EventHandler;
import net.sf.aguacate.util.filesystem.FileSystemObserver;
import net.sf.aguacate.util.resource.ResourceLocator;
import net.sf.aguacate.util.resource.impl.ResourceLocatorClassImpl;
import net.sf.aguacate.util.resource.impl.ResourceLocatorFileImpl;

public class ConfigurationBridgeImpl implements ConfigurationBridge, EventHandler {

	private static final Logger LOGGER = LogManager.getLogger(ConfigurationBridgeImpl.class);

	private static final Logger LOGGER2 = LogManager.getLogger("aguacate.file.configuration");

	private static final String SUFFIX = ".json";

	private static final int SUFFIX_LENGTH = 5;

	private static final String ENVIRONMENT = "DIRECTORY_CONFIGURATION";

	private static final File DIRECTORY;

	private static final Map SPECS;

	private final ResourceLocator locator;

	private final ConfigurationCompiler compiler;

	private Map cache;

	static {
		assert SUFFIX_LENGTH == SUFFIX.length();
		String temp = System.getProperty(ENVIRONMENT);
		if (temp == null || temp.isEmpty()) {
			temp = System.getenv(ENVIRONMENT);
			if (temp == null || temp.isEmpty()) {
				LOGGER.info("No " + ENVIRONMENT + " defined, using default");
				DIRECTORY = null;
			} else {
				LOGGER.info("using " + ENVIRONMENT + " (env): {}", temp);
				DIRECTORY = new File(temp);
			}
		} else {
			LOGGER.info("using " + ENVIRONMENT + " (prop): {}", temp);
			DIRECTORY = new File(temp);
		}
		Map spec = new HashMap<>();
		spec.put("kind", "configuration");
		spec.put("format", "1.0");
		SPECS = spec;
	}

	public ConfigurationBridgeImpl(ConfigurationCompiler compiler) {
		if (DIRECTORY == null) {
			this.locator = new ResourceLocatorClassImpl(ConfigurationBridge.class);
		} else {
			this.locator = new ResourceLocatorFileImpl(DIRECTORY);
			FileSystemObserver.watch(DIRECTORY.toPath(), this);
		}
		this.compiler = compiler;
		this.cache = new HashMap<>();
	}

	@Override
	public Configuration load(String entity) {
		return get(entity);
	}

	Configuration get(String entity) {
		Configuration info = cache.get(entity);
		if (info == null) {
			synchronized (this) {
				info = cache.get(entity);
				if (info == null) {
					String resource = entity.concat(SUFFIX);
					info = load0(resource);
					if (info != null) {
						LOGGER.trace("original: {}", cache);
						Map temp = new HashMap<>(cache);
						temp.put(entity, info);
						LOGGER.trace("new: {}", temp);
						cache = temp;
					}
				}
			}
		}
		return info;
	}

	Configuration load0(String file) {
		LOGGER2.info("Loading configuration: {}", file);
		try {
			Configuration info;
			InputStream inputStream = locator.open(file);
			if (inputStream == null) {
				LOGGER.warn("Not Found: {}", file);
				info = null;
			} else {
				Map data;
				try {
					data = checkSpecs(CodecCoupling.jsonCodecBridge()
							.decodeMap(new InputStreamReader(inputStream, StandardCharsets.UTF_8)));
				} finally {
					try {
						inputStream.close();
					} catch (IOException e) {
						LOGGER.warn("when closing a resource", e);
					}
				}
				LOGGER.trace("decoded: {}", data);
				info = compiler.compile(data);
			}
			return info;
		} catch (IOException e) {
			throw new IllegalStateException(e);
		}
	}

	Map checkSpecs(Map data) {
		@SuppressWarnings("unchecked")
		Map specs = (Map) data.get("specs");
		if (specs == null) {
			throw new IllegalArgumentException("no specs");
		} else {
			if (SPECS.equals(specs)) {
				return data;
			} else {
				throw new IllegalArgumentException(
						"unsupported specs: ".concat(CodecCoupling.jsonCodecBridge().encode(specs)));
			}
		}
	}

	@Override
	public ResourceLocator getLocator() {
		return locator;
	}

	@Override
	public void onDelete(Path directory, Path deleted) {
		String file = deleted.toString();
		if (file.endsWith(SUFFIX)) {
			LOGGER2.warn("Removing configuration definition: {}", deleted);
			String name = removeSufix(file);
			synchronized (this) {
				if (cache.containsKey(name)) {
					Map temp = new HashMap<>(cache);
					temp.remove(name);
					cache = temp;
				}
			}
		} else {
			LOGGER.debug("ignore deleted file: {}", deleted);
		}
	}

	@Override
	public void onUpdate(Path directory, Path updated) {
		String file = updated.toString();
		if (file.endsWith(SUFFIX)) {
			LOGGER2.info("Change detected on configuration: {}", updated);
			String name = removeSufix(file);
			synchronized (this) {
				if (cache.containsKey(name)) {
					Map temp = new HashMap<>(cache);
					temp.put(name, load0(file));
					cache = temp;
				}
			}
		} else {
			LOGGER2.warn("Ignored : {}", updated);
			LOGGER.debug("ignore updated file: {}", updated);
		}
	}

	String removeSufix(String name) {
		return name.substring(0, name.length() - SUFFIX_LENGTH);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy