package io.cattle.platform.configitem.server.model.impl;
import io.cattle.platform.archaius.util.ArchaiusUtil;
import io.cattle.platform.configitem.context.ConfigItemContextFactory;
import io.cattle.platform.configitem.server.model.ConfigItem;
import io.cattle.platform.configitem.server.model.ConfigItemFactory;
import io.cattle.platform.configitem.server.model.util.ConfigItemResourceUtil;
import io.cattle.platform.configitem.server.resource.AbstractCachingResourceRoot;
import io.cattle.platform.configitem.server.resource.FileBasedResourceRoot;
import io.cattle.platform.configitem.server.resource.URLBaseResourceRoot;
import io.cattle.platform.configitem.server.template.TemplateFactory;
import io.cattle.platform.configitem.server.template.TemplatesBasedArchiveItem;
import io.cattle.platform.configitem.version.ConfigItemStatusManager;
import io.cattle.platform.util.type.Named;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.config.DynamicBooleanProperty;
public class GenericConfigItemFactory implements ConfigItemFactory, Named {
private static final Logger log = LoggerFactory.getLogger(GenericConfigItemFactory.class);
private static final DynamicBooleanProperty IGNORE_FS = ArchaiusUtil.getBoolean("config.item.ignore.filesystem");
ConfigItemStatusManager versionManager;
List<ConfigItem> items = new ArrayList<ConfigItem>();
List<ConfigItemContextFactory> factories;
Map<String, Callable<byte[]>> additionalRevisionData = new HashMap<>();
TemplateFactory templateFactory;
String root;
String devRelativePath;
URL[] resources;
String name;
boolean ignoreNotFound = false;
protected File findDevRoot() {
if (IGNORE_FS.get()) {
return null;
}
URL url = GenericConfigItemFactory.class.getClassLoader().getResource(root);
if (url != null && "file".equals(url.getProtocol())) {
File scriptsRoot = new File(url.getPath(), devRelativePath);
if (scriptsRoot.exists()) {
try {
return new File(scriptsRoot.getCanonicalPath());
} catch (IOException e) {
log.error("Failed to get canonical path of [{}]", scriptsRoot, e);
}
}
}
return null;
}
protected void locateResourceRoot() throws IOException {
File devRoot = findDevRoot();
if (devRoot == null) {
log.info("Using classpath for location [{}]", name);
processUrlRoot();
} else {
log.info("Using filesytem for location [{}] at [{}]", name, devRoot);
processFileRoot(devRoot);
}
}
protected void processUrlRoot() throws IOException {
Map<String, Map<String, URL>> config = ConfigItemResourceUtil.processUrlRoot(ignoreNotFound, root, resources);
for (Map.Entry<String, Map<String, URL>> entry : config.entrySet()) {
String item = entry.getKey();
URLBaseResourceRoot resourceRoot = new URLBaseResourceRoot(entry.getValue());
log.info("Adding item [{}] resources [{}]", item, entry.getValue().size());
addTemplate(item, resourceRoot);
}
}
protected void addTemplate(String item, AbstractCachingResourceRoot resourceRoot) throws IOException {
resourceRoot.setAdditionalRevisionData(additionalRevisionData.get(item));
resourceRoot.scan();
items.add(new TemplatesBasedArchiveItem(item, versionManager, resourceRoot, templateFactory, getFactories(item)));
}
protected List<ConfigItemContextFactory> getFactories(String item) {
return ConfigItemResourceUtil.getFactories(factories, item);
}
protected void processFileRoot(File root) throws IOException {
String[] children = root.list();
if (children == null)
return;
for (String child : children) {
File childFile = new File(root, child);
if (!child.startsWith(".") && childFile.isDirectory()) {
FileBasedResourceRoot itemResource = new FileBasedResourceRoot(childFile);
addTemplate(child, itemResource);
}
}
}
@Override
public Collection<ConfigItem> getConfigItems() throws IOException {
locateResourceRoot();
return items;
}
public ConfigItemStatusManager getVersionManager() {
return versionManager;
}
@Inject
public void setVersionManager(ConfigItemStatusManager versionManager) {
this.versionManager = versionManager;
}
public TemplateFactory getTemplateFactory() {
return templateFactory;
}
@Inject
public void setTemplateFactory(TemplateFactory templateFactory) {
this.templateFactory = templateFactory;
}
public String getRoot() {
return root;
}
public void setRoot(String root) {
this.root = root;
}
public String getDevRelativePath() {
return devRelativePath;
}
public void setDevRelativePath(String devRelativePath) {
this.devRelativePath = devRelativePath;
}
public URL[] getResources() {
return resources;
}
public void setResources(URL[] resources) {
this.resources = resources;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isIgnoreNotFound() {
return ignoreNotFound;
}
public void setIgnoreNotFound(boolean ignoreNotFound) {
this.ignoreNotFound = ignoreNotFound;
}
public List<ConfigItemContextFactory> getFactories() {
return factories;
}
@Inject
public void setFactories(List<ConfigItemContextFactory> factories) {
this.factories = factories;
}
public Map<String, Callable<byte[]>> getAdditionalRevisionData() {
return additionalRevisionData;
}
public void setAdditionalRevisionData(Map<String, Callable<byte[]>> additionalRevisionData) {
this.additionalRevisionData = additionalRevisionData;
}
}