/**
* Copyright (c) 2011-2012 Optimax Software Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Optimax Software, ElasticInbox, nor the names
* of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.elasticinbox.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.error.YAMLException;
import com.elasticinbox.common.utils.Assert;
import com.elasticinbox.config.blob.BlobStoreProfile;
import com.elasticinbox.config.crypto.SymmetricKeyStorage;
/**
* Main configuration class which loads options from YAML and provides to the
* rest of the application.
*
* Path to the YAML config file should be provided in the
* <code>elasticinbox.config</code> system property.
*
* @author Rustam Aliyev
*/
public class Configurator
{
private static final Logger logger = LoggerFactory.getLogger(Configurator.class);
private static final String DEFAULT_CONFIGURATION = "elasticinbox.yaml";
private static Config conf;
private static SymmetricKeyStorage keyManager;
/**
* Inspect the classpath to find storage configuration file
*/
static URI getStorageConfigURL() throws ConfigurationException
{
URI uri;
String configUrl = System.getProperty("elasticinbox.config");
if (configUrl == null) {
configUrl = DEFAULT_CONFIGURATION;
}
try {
File file = new File(configUrl);
if(!file.canRead()) {
throw new ConfigurationException("Cannot read config file: " + configUrl);
}
uri = file.toURI();
} catch (Exception e) {
logger.error("Error opening logfile: ", e);
throw new ConfigurationException("Cannot locate " + configUrl);
}
return uri;
}
static
{
try {
URI uri = getStorageConfigURL();
InputStream input = null;
File configFile;
try {
configFile = new File(uri);
input = new FileInputStream(configFile);
} catch (IOException e) {
logger.error("Cannot read config file: {}", e.getMessage());
// getStorageConfigURL should have ruled this out
throw new AssertionError(e);
}
Constructor constructor = new Constructor(Config.class);
constructor.addTypeDescription(new TypeDescription(Config.class));
Yaml yaml = new Yaml(constructor);
conf = (Config) yaml.load(input);
// TODO: add config verification here
// ...
// verify max database blob size
if(conf.database_blob_max_size > DatabaseConstants.MAX_BLOB_SIZE) {
throw new ConfigurationException("Blobs larger than "
+ DatabaseConstants.MAX_BLOB_SIZE + " bytes cannot be stored in the database");
}
// verify that blobstore profile name is not conflicting with internal name
if (conf.blobstore_profiles.containsKey(DatabaseConstants.DATABASE_PROFILE)) {
throw new ConfigurationException("BlobStore profile name cannot be '"
+ DatabaseConstants.DATABASE_PROFILE + "'");
}
// verify that default blobstore profile exists
if (!conf.blobstore_profiles.containsKey(conf.blobstore_write_profile)) {
throw new ConfigurationException("Default BlobStore Profile '"
+ conf.blobstore_write_profile + "' not found");
}
if (conf.encryption.keystore != null)
{
// keystore path is relative to the config file
File keystoreFile = new File(configFile.getParent() + "/" + conf.encryption.keystore);
// initialise symmetric key storage
keyManager = new SymmetricKeyStorage(keystoreFile, conf.encryption.keystore_password);
// verify that default blobstore encryption key exists
if (!keyManager.containsKey(conf.blobstore_default_encryption_key)) {
throw new ConfigurationException("Default encryption key for BlobStore '"
+ conf.blobstore_default_encryption_key + "' not found");
}
} else {
// initialize empty key store
keyManager = new SymmetricKeyStorage();
}
} catch (ConfigurationException e) {
logger.error("Fatal configuration error", e);
System.err.println(e.getMessage()
+ "\nFatal configuration error; unable to start server. See log for stacktrace.");
System.exit(1);
} catch (YAMLException e) {
logger.error("Fatal configuration error error", e);
System.err.println(e.getMessage()
+ "\nInvalid yaml; unable to start server. See log for stacktrace.");
System.exit(1);
}
}
public static Integer getLmtpPort() {
return conf.lmtp_port;
}
public static Integer getLmtpMaxConnections() {
return conf.lmtp_max_connections;
}
public static boolean isLmtpPop3Enabled() {
return conf.lmtp_enable_pop3;
}
public static Integer getPop3Port() {
return conf.pop3_port;
}
public static Integer getPop3MaxConnections() {
return conf.pop3_max_connections;
}
public static String getDatabaseDriver() {
return (conf.database_driver.equalsIgnoreCase("cassandra")) ? "CASSANDRA" : "UNKNOWN";
}
public static Long getDatabaseBlobMaxSize() {
return conf.database_blob_max_size;
}
public static List<String> getCassandraHosts() {
return conf.cassandra_hosts;
}
public static Boolean isCassandraAutodiscoveryEnabled() {
return conf.cassandra_autodiscovery;
}
public static String getCassandraClusterName() {
return conf.cassandra_cluster_name;
}
public static String getCassandraKeyspace() {
return conf.cassandra_keyspace;
}
public static Long getDefaultQuotaBytes() {
return conf.mailbox_quota_bytes;
}
public static Long getDefaultQuotaCount() {
return conf.mailbox_quota_count;
}
public static Boolean isPerformanceCountersEnabled() {
return conf.enable_performance_counters;
}
public static Integer getPerformanceCountersInterval() {
return conf.performance_counters_interval;
}
/**
* Store HTML message body within metadata
*
* @return
*/
public static Boolean isStoreHtmlWithMetadata() {
return conf.store_html_message;
}
/**
* Store plain text message body within metadata
*
* @return
*/
public static Boolean isStorePlainWithMetadata() {
return conf.store_plain_message;
}
/**
* Get {@link BlobStoreProfile} based on profile name
*
* @param profileName
* @return
*/
public static BlobStoreProfile getBlobStoreProfile(String profileName)
{
Assert.isTrue(conf.blobstore_profiles.containsKey(profileName),
"Unknown BlobStore Profile: " + profileName);
return conf.blobstore_profiles.get(profileName);
}
/**
* Get blobstore profile name for storing data
*
* @return
*/
public static String getBlobStoreWriteProfileName() {
return conf.blobstore_write_profile;
}
/**
* Compress BLOB before writing to the object store
*
* @return
*/
public static Boolean isBlobStoreCompressionEnabled() {
return conf.blobstore_enable_compression;
}
public static Boolean isBlobStoreEncryptionEnabled() {
return conf.blobstore_enable_encryption;
}
public static String getBlobStoreDefaultEncryptionKeyAlias() {
return conf.blobstore_default_encryption_key;
}
public static java.security.Key getEncryptionKey(String alias) {
return keyManager.getKey(alias);
}
public static java.security.Key getBlobStoreDefaultEncryptionKey() {
return keyManager.getKey(conf.blobstore_default_encryption_key);
}
}