package ru.vyarus.dropwizard.orient.configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.orientechnologies.common.parser.OSystemVariableResolver;
import com.orientechnologies.orient.server.config.OServerConfiguration;
import com.orientechnologies.orient.server.config.OServerConfigurationLoaderXml;
import com.orientechnologies.orient.server.security.ODefaultServerSecurity;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
/**
* Orient configuration object.
* Defines database files storage path and orient server configuration.
* Server configuration could be provided inside yaml file (yaml representation of xml format)
* or using external xml configuration file (native orient format).
* <p>
* Orient security configuration (security.json) may be declared with yaml in "security:" section or with
* file path (security-file). May work without security config (but with warning in log).
* <p>
* Server start could be disabled with 'start' option.
*
* @see <a href="http://orientdb.com/docs/last/DB-Server.html#configuration">configuration documentation</a>
*/
public class OrientServerConfiguration {
private static final String APP_HOME = Paths.get(".").toAbsolutePath().normalize().toString();
private static final String TMP = System.getProperty("java.io.tmpdir");
private final Logger logger = LoggerFactory.getLogger(OrientServerConfiguration.class);
@NotEmpty
private String filesPath;
private boolean start = true;
private String configFile;
private boolean adminServlet = true;
@NotNull
private OServerConfiguration config;
private JsonNode security;
private String securityFile;
/**
* @return true if orient server must be started, false to avoid starting orient server
*/
public boolean isStart() {
return start;
}
/**
* @param start true to start server, false to avoid starting
*/
public void setStart(final boolean start) {
this.start = start;
}
/**
* @return path to database files storage
*/
public String getFilesPath() {
return filesPath;
}
/**
* Directory may not exist - orient will create it when necessary.
* Any system property or environment variable may be used with ${prop} syntax.
* Special variables: $TMP for ${java.io.tmpdir}, $APP_HOME for application starting directory.
*
* @param filesPath path to store database files.
*/
@JsonProperty("files-path")
public void setFilesPath(final String filesPath) {
this.filesPath = parsePath(filesPath);
}
/**
* As an alternative to inline yaml configuration, external xml file could be used (but not both).
* Any system property or environment variable may be used with ${prop} syntax.
* Special variables: $TMP for ${java.io.tmpdir}, $FILES_HOME for configured files path and
* $APP_HOME for application starting directory.
*
* @param configFile path to server xml configuration file
*/
@JsonProperty("config-file")
public void setConfigFile(final String configFile) {
this.configFile = parsePath(configFile);
Preconditions.checkState(this.config == null,
"Orient configuration already declared manually. "
+ "Use either xml file or direct yaml config, but not both.");
this.config = parseXmlConfigFile(configFile);
}
/**
* @return true to deploy orient info servlet (/orient) on admin context, false to avoid installing
*/
public boolean isAdminServlet() {
return adminServlet;
}
/**
* @param adminServlet true to start orient info servlet on admin context, false to avoid installation
*/
@JsonProperty("admin-servlet")
public void setAdminServlet(final boolean adminServlet) {
this.adminServlet = adminServlet;
}
/**
* @return orient server configuration object (from yaml config or external xml file)
*/
public OServerConfiguration getConfig() {
return config;
}
/**
* @param config configuration object defined in yaml configuration file
*/
public void setConfig(final OServerConfiguration config) {
Preconditions.checkState(this.config == null,
"Orient configuration already loaded from file '" + configFile
+ "'. Use either xml file or direct yaml config, but not both.");
this.config = config;
}
/**
* @param security orient security definition
*/
public void setSecurity(final JsonNode security) {
Preconditions.checkState(this.securityFile == null,
"Orient security configuration already defined as file '" + securityFile
+ "'. Use either json file or direct yaml config, but not both.");
this.security = security;
}
/**
* Orient 2.2 and above provides advanced security configuration. In distribution, this is the file is
* "config/security.json". It could be loaded only as separate file (not part of main configuration).
* <p>
* Optional - orient server will work without it, but print error message about missed file.
* <p>
* Security config may be declared inside yaml configuration under "security:" section. Write security json
* in yaml format. Later it would be stored as json file and configured for orient automatically.
* <p>
* NOTE: it is not required to specify security only in yaml. You can ignore this section and use separate json
* file. You may use "server.security.file" system property to configure it's location or place file inside
* your files path (files-path property) as "${files/path}/config/security.json.
*
* @return security configuration
* @see <a href="http://orientdb.com/docs/2.2/Security-Config.html">orient securty config</a>
* @see ODefaultServerSecurity#onBeforeActivate() for details about configuration loading
*/
public JsonNode getSecurity() {
return security;
}
/**
* If orient security file (security.json) is not provided with security property in yaml, then it may be
* specified as path to security file (but not both!).
* Special variables: $TMP for ${java.io.tmpdir}, $FILES_HOME for configured files path and
* $APP_HOME for application starting directory.
*
* @param securityFile path to security file
*/
@JsonProperty("security-file")
public void setSecurityFile(final String securityFile) {
Preconditions.checkState(this.security == null, "Orient security already defined in yaml. "
+ "Use either json file or yaml, but not both.");
this.securityFile = parsePath(securityFile);
}
/**
* @return orient security file path
*/
public String getSecurityFile() {
return securityFile;
}
private OServerConfiguration parseXmlConfigFile(final String configFile) {
logger.info("Loading orient configuration from file {}", configFile);
final OServerConfigurationLoaderXml configurationLoader =
new OServerConfigurationLoaderXml(OServerConfiguration.class, new File(configFile));
try {
return configurationLoader.load();
} catch (IOException e) {
throw new IllegalStateException("Failed to load configuration from file: " + configFile, e);
}
}
private String parsePath(final String path) {
String trimmedPath = Strings.emptyToNull(path);
if (trimmedPath != null) {
trimmedPath = trimmedPath.replace("$TMP", TMP);
if (filesPath != null) {
trimmedPath = trimmedPath.replace("$FILES_HOME", filesPath);
}
trimmedPath = trimmedPath.replace("$APP_HOME", APP_HOME);
trimmedPath = OSystemVariableResolver.resolveSystemVariables(trimmedPath);
}
return trimmedPath;
}
}