net.sf.aguacate.script.spi.DynamicCacheSpi Maven / Gradle / Ivy
package net.sf.aguacate.script.spi;
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.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.sf.aguacate.script.DynamicCache;
import net.sf.aguacate.util.dynamic.bridge.Dynamic;
import net.sf.aguacate.util.dynamic.bridge.DynamicFactoryCoupling;
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 DynamicCacheSpi implements DynamicCache, EventHandler {
private static final Logger LOGGER = LogManager.getLogger(DynamicCacheSpi.class);
private static final Logger LOGGER2 = LogManager.getLogger("aguacate.file.script");
private static final String ENVIRONMENT = "DIRECTORY_SCRIPT";
private static final File DIRECTORY;
private static final String EXTENSION = "js";
private static final String SUFFIX = "." + EXTENSION;
private static final int SUFFIX_LENGTH = 3;
private final ResourceLocator locator;
private Map cache;
static {
assert SUFFIX.equals("." + EXTENSION);
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);
}
}
public DynamicCacheSpi() {
cache = Collections.emptyMap();
assert cache != null && cache.isEmpty();
if (DIRECTORY == null) {
locator = new ResourceLocatorClassImpl(DynamicCache.class);
} else {
locator = new ResourceLocatorFileImpl(DIRECTORY);
FileSystemObserver.watch(DIRECTORY.toPath(), this);
}
}
@Override
public Dynamic get(String scriptName) {
Dynamic dynamic = cache.get(scriptName);
if (dynamic == null) {
synchronized (this) {
dynamic = cache.get(scriptName);
if (dynamic == null) {
Map temp = new HashMap<>(cache);
dynamic = load0(scriptName.concat(SUFFIX));
temp.put(scriptName, dynamic);
cache = temp;
}
}
}
return dynamic;
}
Dynamic load0(String filename) {
LOGGER.debug(filename);
LOGGER2.info("Loading script: {}", filename);
try {
InputStream inputStream = locator.open(filename);
if (inputStream == null) {
throw new IllegalArgumentException(filename);
} else {
try {
return DynamicFactoryCoupling.getByExtension(EXTENSION)
.createFrom(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
} finally {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.warn("On closing resource", e);
}
}
}
} catch (IOException e) {
throw new IllegalStateException(filename, e);
}
}
@Override
public void onDelete(Path directory, Path deleted) {
String file = deleted.toString();
if (file.endsWith(SUFFIX)) {
LOGGER2.warn("Removing script 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 script: {}", 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);
}
}