/*
* R Service Bus
*
* Copyright (c) Copyright of Open Analytics NV, 2010-2015
*
* ===========================================================================
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.openanalytics.rsb.config;
import java.io.File;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.pool.impl.GenericKeyedObjectPool.Config;
import eu.openanalytics.rsb.config.Configuration.AdminSecurityAuthorization;
import eu.openanalytics.rsb.config.Configuration.ApplicationSecurityAuthorization;
import eu.openanalytics.rsb.config.Configuration.DepositDirectoryConfiguration;
import eu.openanalytics.rsb.config.Configuration.DepositEmailConfiguration;
import eu.openanalytics.rsb.config.Configuration.JmxConfiguration;
import eu.openanalytics.rsb.config.Configuration.JobStatisticsHandlerConfiguration;
import eu.openanalytics.rsb.config.Configuration.RServiClientPoolValidationStrategy;
import eu.openanalytics.rsb.config.Configuration.SmtpConfiguration;
/**
* Defines the persisted configuration of RSB, from which the actual {@link Configuration} is
* derived.
*
* @see Configuration
* @author "OpenAnalytics <rsb.development@openanalytics.eu>"
*/
public class PersistedConfiguration
{
public static class PersistedSmtpConfiguration implements SmtpConfiguration
{
private static final long serialVersionUID = 1L;
private String host;
private int port;
private String username;
private String password;
public PersistedSmtpConfiguration(final String host,
final int port,
final String username,
final String password)
{
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public PersistedSmtpConfiguration()
{
// NOOP
}
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public String getHost()
{
return host;
}
public void setHost(final String host)
{
this.host = host;
}
@Override
public int getPort()
{
return port;
}
public void setPort(final int port)
{
this.port = port;
}
@Override
public String getUsername()
{
return username;
}
public void setUsername(final String username)
{
this.username = username;
}
@Override
public String getPassword()
{
return password;
}
public void setPassword(final String password)
{
this.password = password;
}
}
public static class PersistedJmxConfiguration implements JmxConfiguration
{
private static final long serialVersionUID = 2L;
private int stubPort, registryPort, httpPort;
private String httpAuthenticationUsername, httpAuthenticationPassword;
public PersistedJmxConfiguration(final int stubPort, final int registryPort, final int httpPort)
{
this(stubPort, registryPort, httpPort, null, null);
}
public PersistedJmxConfiguration(final int stubPort,
final int registryPort,
final int httpPort,
final String httpAuthenticationUsername,
final String httpAuthenticationPassword)
{
this.stubPort = stubPort;
this.registryPort = registryPort;
this.httpPort = httpPort;
this.httpAuthenticationUsername = httpAuthenticationUsername;
this.httpAuthenticationPassword = httpAuthenticationPassword;
}
public PersistedJmxConfiguration()
{
// NOOP
}
@Override
public int getStubPort()
{
return stubPort;
}
public void setStubPort(final int stubPort)
{
this.stubPort = stubPort;
}
@Override
public int getRegistryPort()
{
return registryPort;
}
public void setRegistryPort(final int registryPort)
{
this.registryPort = registryPort;
}
@Override
public int getHttpPort()
{
return httpPort;
}
public void setHttpPort(final int httpPort)
{
this.httpPort = httpPort;
}
@Override
public String getHttpAuthenticationUsername()
{
return httpAuthenticationUsername;
}
public void setHttpAuthenticationUsername(final String httpAuthenticationUsername)
{
this.httpAuthenticationUsername = httpAuthenticationUsername;
}
@Override
public String getHttpAuthenticationPassword()
{
return httpAuthenticationPassword;
}
public void setHttpAuthenticationPassword(final String httpAuthenticationPassword)
{
this.httpAuthenticationPassword = httpAuthenticationPassword;
}
}
public static class PersistedJobStatisticsHandlerConfiguration
implements JobStatisticsHandlerConfiguration
{
private static final long serialVersionUID = 1L;
private String className;
private Map<String, Object> parameters;
public PersistedJobStatisticsHandlerConfiguration(final String className,
final Map<String, Object> parameters)
{
this.className = className;
this.parameters = parameters;
}
public PersistedJobStatisticsHandlerConfiguration()
{
// NOOP
}
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public String getClassName()
{
return className;
}
public void setClassName(final String className)
{
this.className = className;
}
@Override
public Map<String, Object> getParameters()
{
return parameters;
}
public void setParameters(final Map<String, Object> parameters)
{
this.parameters = parameters;
}
}
public static class PersistedDepositDirectoryConfiguration implements DepositDirectoryConfiguration
{
private static final long serialVersionUID = 1L;
private File rootDirectory;
private String applicationName;
private long pollingPeriod;
private String jobConfigurationFileName;
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public File getRootDirectory()
{
return rootDirectory;
}
public void setRootDirectory(final File rootDirectory)
{
this.rootDirectory = rootDirectory;
}
@Override
public String getApplicationName()
{
return applicationName;
}
public void setApplicationName(final String applicationName)
{
this.applicationName = applicationName;
}
@Override
public long getPollingPeriod()
{
return pollingPeriod;
}
public void setPollingPeriod(final long pollingPeriod)
{
this.pollingPeriod = pollingPeriod;
}
@Override
public String getJobConfigurationFileName()
{
return jobConfigurationFileName;
}
public void setJobConfigurationFileName(final String jobConfigurationFileName)
{
this.jobConfigurationFileName = jobConfigurationFileName;
}
}
public static class PersistedDepositEmailConfiguration implements DepositEmailConfiguration
{
private static final long serialVersionUID = 1L;
private URI accountURI;
private String applicationName;
private long pollingPeriod;
private String responseFileName;
private String jobConfigurationFileName;
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
@Override
public URI getAccountURI()
{
return accountURI;
}
public void setAccountURI(final URI accountURI)
{
this.accountURI = accountURI;
}
@Override
public String getApplicationName()
{
return applicationName;
}
public void setApplicationName(final String applicationName)
{
this.applicationName = applicationName;
}
@Override
public long getPollingPeriod()
{
return pollingPeriod;
}
public void setPollingPeriod(final long pollingPeriod)
{
this.pollingPeriod = pollingPeriod;
}
@Override
public String getResponseFileName()
{
return responseFileName;
}
public void setResponseFileName(final String responseFileName)
{
this.responseFileName = responseFileName;
}
@Override
public String getJobConfigurationFileName()
{
return jobConfigurationFileName;
}
public void setJobConfigurationFileName(final String jobConfigurationFileName)
{
this.jobConfigurationFileName = jobConfigurationFileName;
}
}
public static class PersistedAdminSecurityAuthorization implements AdminSecurityAuthorization
{
private static final long serialVersionUID = 2L;
private Set<String> adminPrincipals;
private Set<String> adminRoles;
@Override
public Set<String> getAdminPrincipals()
{
return adminPrincipals;
}
public void setAdminPrincipals(final Set<String> adminPrincipals)
{
this.adminPrincipals = adminPrincipals;
}
@Override
public Set<String> getAdminRoles()
{
return adminRoles;
}
public void setAdminRoles(final Set<String> adminRoles)
{
this.adminRoles = adminRoles;
}
}
public static class PersistedApplicationSecurityAuthorization extends PersistedAdminSecurityAuthorization
implements ApplicationSecurityAuthorization
{
private static final long serialVersionUID = 3L;
private Set<String> userPrincipals;
private Set<String> userRoles;
private boolean functionCallAllowed;
private boolean scriptSubmissionAllowed;
@Override
public Set<String> getUserPrincipals()
{
return userPrincipals;
}
public void setUserPrincipals(final Set<String> userPrincipals)
{
this.userPrincipals = userPrincipals;
}
@Override
public Set<String> getUserRoles()
{
return userRoles;
}
public void setUserRoles(final Set<String> userRoles)
{
this.userRoles = userRoles;
}
@Override
public boolean isFunctionCallAllowed()
{
return functionCallAllowed;
}
public void setFunctionCallAllowed(final boolean functionCallAllowed)
{
this.functionCallAllowed = functionCallAllowed;
}
@Override
public boolean isScriptSubmissionAllowed()
{
return scriptSubmissionAllowed;
}
public void setScriptSubmissionAllowed(final boolean scriptSubmissionAllowed)
{
this.scriptSubmissionAllowed = scriptSubmissionAllowed;
}
}
private String nodeName;
private File activeMqWorkDirectory;
private URI defaultRserviPoolUri;
private int jobTimeOut;
private int numberOfConcurrentJobWorkersPerQueue;
private File catalogRootDirectory;
private File resultsDirectory;
private Map<String, ?> applicationSpecificRserviPoolUris;
private PersistedJobStatisticsHandlerConfiguration jobStatisticsHandlerConfiguration;
private String administratorEmail;
private PersistedSmtpConfiguration smtpConfiguration;
private PersistedJmxConfiguration jmxConfiguration;
private List<PersistedDepositDirectoryConfiguration> depositRootDirectories;
private List<PersistedDepositEmailConfiguration> depositEmailAccounts;
private List<File> dataDirectories;
private Config rServiClientPoolConfig;
private RServiClientPoolValidationStrategy rServiClientPoolValidationStrategy;
private boolean checkHealthOnStart;
private Map<String, PersistedApplicationSecurityAuthorization> applicationSecurityConfiguration;
private PersistedAdminSecurityAuthorization rsbSecurityConfiguration;
private boolean applicationAwareCatalog;
private boolean propagateSecurityContext;
public PersistedConfiguration()
{
// NOOP
}
@SuppressWarnings({"unchecked", "rawtypes"})
public PersistedConfiguration(final Configuration configuration)
{
setActiveMqWorkDirectory(configuration.getActiveMqWorkDirectory());
setAdministratorEmail(configuration.getAdministratorEmail());
setApplicationAwareCatalog(configuration.isApplicationAwareCatalog());
setApplicationSpecificRserviPoolUris(configuration.getApplicationSpecificRserviPoolUris());
setApplicationSecurityConfiguration((Map) configuration.getApplicationSecurityConfiguration());
setCatalogRootDirectory(configuration.getCatalogRootDirectory());
setCheckHealthOnStart(configuration.isCheckHealthOnStart());
setDataDirectories(configuration.getDataDirectories());
setDefaultRserviPoolUri(configuration.getDefaultRserviPoolUri());
setDepositEmailAccounts((List) configuration.getDepositEmailAccounts());
setDepositRootDirectories((List) configuration.getDepositRootDirectories());
setJmxConfiguration((PersistedJmxConfiguration) configuration.getJmxConfiguration());
setJobStatisticsHandlerConfiguration((PersistedJobStatisticsHandlerConfiguration) configuration.getJobStatisticsHandlerConfiguration());
setJobTimeOut(configuration.getJobTimeOut());
setNodeName(configuration.getNodeName());
setNumberOfConcurrentJobWorkersPerQueue(configuration.getNumberOfConcurrentJobWorkersPerQueue());
setPropagateSecurityContext(configuration.isPropagateSecurityContext());
setResultsDirectory(configuration.getResultsDirectory());
setRsbSecurityConfiguration(getRsbSecurityConfiguration());
setrServiClientPoolConfig(configuration.getRServiClientPoolConfig());
setrServiClientPoolValidationStrategy(configuration.getRServiClientPoolValidationStrategy());
setSmtpConfiguration((PersistedSmtpConfiguration) configuration.getSmtpConfiguration());
}
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
/**
* Logical name of the RSB node.
*/
public String getNodeName()
{
return nodeName;
}
public void setNodeName(final String nodeName)
{
this.nodeName = nodeName;
}
/**
* Directory under which RSB catalog sections are located. The catalog sections are:
* <ul>
* <li>{@link eu.openanalytics.rsb.config.Configuration#R_SCRIPTS_CATALOG_SUBDIR} : catalog of R
* scripts</li>
* <li>
* {@link eu.openanalytics.rsb.config.Configuration#SWEAVE_FILES_CATALOG_SUBDIR}: catalog of
* Sweave files</li>
* <li>
* {@link eu.openanalytics.rsb.config.Configuration#JOB_CONFIGURATIONS_CATALOG_SUBDIR} :
* catalog of ready made job configurations</li>
* <li>
* {@link eu.openanalytics.rsb.config.Configuration#EMAIL_REPLIES_CATALOG_SUBDIR} : catalog
* of Email replies</li>
* </ul>
* If any of these sub-directories do not pre-exist, RSB will try to create it.
*/
public File getCatalogRootDirectory()
{
return catalogRootDirectory;
}
public void setCatalogRootDirectory(final File catalogRootDirectory)
{
this.catalogRootDirectory = catalogRootDirectory;
}
/**
* Directory where ActiveMQ stores its persisted data.
*/
public File getActiveMqWorkDirectory()
{
return activeMqWorkDirectory;
}
public void setActiveMqWorkDirectory(final File activeMqWorkDirectory)
{
this.activeMqWorkDirectory = activeMqWorkDirectory;
}
/**
* URI of the RServi RMI pool.
*/
public URI getDefaultRserviPoolUri()
{
return defaultRserviPoolUri;
}
public void setDefaultRserviPoolUri(final URI defaultRserviPoolUri)
{
this.defaultRserviPoolUri = defaultRserviPoolUri;
}
/**
* Maximum time a job request can be pending its response (in milliseconds).
*/
public int getJobTimeOut()
{
return jobTimeOut;
}
public void setJobTimeOut(final int jobTimeOut)
{
this.jobTimeOut = jobTimeOut;
}
/**
* Number of concurrent job workers per queue, which must be computed based on the number of
* nodes in the RServi pool and the number of job queues (one global plus one per "boosted"
* application).
*/
public int getNumberOfConcurrentJobWorkersPerQueue()
{
return numberOfConcurrentJobWorkersPerQueue;
}
public void setNumberOfConcurrentJobWorkersPerQueue(final int numberOfConcurrentJobWorkersPerQueue)
{
this.numberOfConcurrentJobWorkersPerQueue = numberOfConcurrentJobWorkersPerQueue;
}
/**
* Directory where result files are written.
*/
public File getResultsDirectory()
{
return resultsDirectory;
}
public void setResultsDirectory(final File resultsDirectory)
{
this.resultsDirectory = resultsDirectory;
}
/**
* Mapping of application names and RServi RMI pool URIs, or null if no specific mapping is
* required.
*/
public Map<String, ?> getApplicationSpecificRserviPoolUris()
{
return applicationSpecificRserviPoolUris;
}
public void setApplicationSpecificRserviPoolUris(final Map<String, ?> applicationSpecificRserviPoolUris)
{
this.applicationSpecificRserviPoolUris = applicationSpecificRserviPoolUris;
}
/**
* Optional job statistics handler.
*/
public PersistedJobStatisticsHandlerConfiguration getJobStatisticsHandlerConfiguration()
{
return jobStatisticsHandlerConfiguration;
}
public void setJobStatisticsHandlerConfiguration(final PersistedJobStatisticsHandlerConfiguration jobStatisticsHandlerConfiguration)
{
this.jobStatisticsHandlerConfiguration = jobStatisticsHandlerConfiguration;
}
/**
* Optional email address where RSB should send permanent error reports and other service
* related messages.
*/
public String getAdministratorEmail()
{
return administratorEmail;
}
public void setAdministratorEmail(final String administratorEmail)
{
this.administratorEmail = administratorEmail;
}
/**
* The SMTP server that will be used for all outbound email exchanges.
*/
public PersistedSmtpConfiguration getSmtpConfiguration()
{
return smtpConfiguration;
}
public void setSmtpConfiguration(final PersistedSmtpConfiguration smtpConfiguration)
{
this.smtpConfiguration = smtpConfiguration;
}
/**
* The JMX configuration used to manage RSB. If not specified default ports will be used. See
* {@link JmxConfiguration}.
*/
public PersistedJmxConfiguration getJmxConfiguration()
{
return jmxConfiguration;
}
public void setJmxConfiguration(final PersistedJmxConfiguration jmxRmiConfiguration)
{
this.jmxConfiguration = jmxRmiConfiguration;
}
/**
* Optional configuration of root directories where jobs and results will respectively be
* dropped and retrieved. The map entry element has the root directory for key and the
* application name for value. RSB must have full right on the root directory as it will need to
* create sub-directories (
* {@link eu.openanalytics.rsb.config.Configuration#DEPOSIT_JOBS_SUBDIR} ,
* {@link eu.openanalytics.rsb.config.Configuration#DEPOSIT_ACCEPTED_SUBDIR} and
* {@link eu.openanalytics.rsb.config.Configuration#DEPOSIT_RESULTS_SUBDIR}) and files below it.
*/
public List<PersistedDepositDirectoryConfiguration> getDepositRootDirectories()
{
return depositRootDirectories;
}
public void setDepositRootDirectories(final List<PersistedDepositDirectoryConfiguration> depositRootDirectories)
{
this.depositRootDirectories = depositRootDirectories;
}
/**
* Optional configuration of email accounts that will be polled for jobs.
*/
public List<PersistedDepositEmailConfiguration> getDepositEmailAccounts()
{
return depositEmailAccounts;
}
public void setDepositEmailAccounts(final List<PersistedDepositEmailConfiguration> depositEmailAccounts)
{
this.depositEmailAccounts = depositEmailAccounts;
}
/**
* Optional configuration of directories where data is accessible.
*/
public List<File> getDataDirectories()
{
return dataDirectories;
}
public void setDataDirectories(final List<File> dataDirectories)
{
this.dataDirectories = dataDirectories;
}
/**
* Optional pooling configuration for RServi clients.
*/
public Config getrServiClientPoolConfig()
{
return rServiClientPoolConfig;
}
public void setrServiClientPoolConfig(final Config rServiClientPoolConfig)
{
this.rServiClientPoolConfig = rServiClientPoolConfig;
}
public RServiClientPoolValidationStrategy getrServiClientPoolValidationStrategy()
{
return rServiClientPoolValidationStrategy;
}
/**
* Optional validation strategy for pooled RServi clients.
*/
public void setrServiClientPoolValidationStrategy(final RServiClientPoolValidationStrategy rServiClientPoolValidationStrategy)
{
this.rServiClientPoolValidationStrategy = rServiClientPoolValidationStrategy;
}
/**
* Should health be checked when RSB starts (recommended for deployments where RServi is not
* colocated in the same web container).
*/
public boolean isCheckHealthOnStart()
{
return checkHealthOnStart;
}
public void setCheckHealthOnStart(final boolean checkHealthOnStart)
{
this.checkHealthOnStart = checkHealthOnStart;
}
/**
* Optional application security.
*/
public Map<String, PersistedApplicationSecurityAuthorization> getApplicationSecurityConfiguration()
{
return applicationSecurityConfiguration;
}
public void setApplicationSecurityConfiguration(final Map<String, PersistedApplicationSecurityAuthorization> applicationSecurityConfiguration)
{
this.applicationSecurityConfiguration = applicationSecurityConfiguration;
}
/**
* Optional RSB security.
*/
public PersistedAdminSecurityAuthorization getRsbSecurityConfiguration()
{
return rsbSecurityConfiguration;
}
public void setRsbSecurityConfiguration(final PersistedAdminSecurityAuthorization rsbSecurityConfiguration)
{
this.rsbSecurityConfiguration = rsbSecurityConfiguration;
}
/**
* Optionally partition the catalog by application name.
*/
public boolean isApplicationAwareCatalog()
{
return applicationAwareCatalog;
}
public void setApplicationAwareCatalog(final boolean applicationAwareCatalog)
{
this.applicationAwareCatalog = applicationAwareCatalog;
}
/**
* Optionally propagate the security context to RServi calls.
*/
public boolean isPropagateSecurityContext()
{
return propagateSecurityContext;
}
public void setPropagateSecurityContext(final boolean propagateSecurityContext)
{
this.propagateSecurityContext = propagateSecurityContext;
}
}