package org.ovirt.engine.core.utils.osinfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Properties;
import java.util.prefs.Preferences;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.common.osinfo.MapBackedPreferences;
import org.ovirt.engine.core.utils.OsLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public enum OsInfoPreferencesLoader implements OsLoader {
INSTANCE;
/**
* The source properties from which all values are loaded.
*/
private Properties properties;
/**
* The configuration tree. See {@link java.util.prefs.Preferences}
*/
private MapBackedPreferences preferences = new MapBackedPreferences(null, "");
private Logger log = LoggerFactory.getLogger(OsInfoPreferencesLoader.class);
public void init(Path directoryPath) {
load(directoryPath);
loadPreferencesFromProperties();
}
void load(Path directoryPath) {
File dir = directoryPath.toFile();
if (dir.exists()) {
File[] files = directoryPath.toFile().listFiles((dir1, name) -> name.endsWith(".properties"));
// load files by name order. 00-osinfo.properties should be loaded first
if (files != null) {
Arrays.sort(files);
for (File file : files) {
log.info("Loading file '{}'", file.getPath());
OsinfoPropertiesParser.parse(file.getAbsolutePath());
loadFile(file.toPath());
}
}
} else {
log.error("Directory '{}' doesn't exist.", dir.getPath());
}
}
@Override
public MapBackedPreferences getPreferences() {
return preferences;
}
private void loadFile(Path path) {
try(BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
properties = new Properties(properties);
properties.load(reader);
} catch (IOException e) {
log.error("Failed loading file '{}': {}", path, e.getMessage());
log.debug("Exception", e);
}
}
/**
* convert the property key namepaces (key.name.space) to the hierarchical preferences node<br>
* is done by breaking each dot separated part and creating a node out of it.<br>
* The last node is being set with the value. Versioned value path are denoted as "key.name.space.value.x.y" and non<br>
* versioned value are just "key.name.space.value" or just "key.name.space"<br>
*/
private void loadPreferencesFromProperties() {
if (properties != null) {
for (String propertyKey : properties.stringPropertyNames()) {
Preferences node = preferences;
Iterator<String> iterator = Arrays.asList(propertyKey.split("\\.|\\.value")).iterator();
String key = null;
while (iterator.hasNext()) {
key = iterator.next();
// create a node from each dot separated part of the key
// if its "value" joining the reset of the iterator so "value" or "value.3.1" are
// considered as the leaf and should be set with the designated value
if (key.startsWith("value")) {
key = iterator.hasNext() ? key + "." + StringUtils.join(iterator, ".") : key;
break;
} else if (!iterator.hasNext()) {
// its a key without a multiple version values
break;
} else {
node = node.node(key);
}
}
putValue(node, key, properties.getProperty(propertyKey));
}
}
// properties isn't needed anymore
properties = null;
}
private void putValue(Preferences node, String key, String value) {
node.put(key, value);
}
}