org.ow2.petals.microkernel.configuration.ConfigurationServiceImpl Maven / Gradle / Ivy
/**
* Copyright (c) 2007-2012 EBM WebSourcing, 2012-2016 Linagora
*
* This program/library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or (at your
* option) any later version.
*
* This program/library 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program/library; If not, see http://www.gnu.org/licenses/
* for the GNU Lesser General Public License version 2.1.
*/
package org.ow2.petals.microkernel.configuration;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Logger;
import org.objectweb.fractal.fraclet.annotations.Component;
import org.objectweb.fractal.fraclet.annotations.Interface;
import org.objectweb.fractal.fraclet.annotations.Lifecycle;
import org.objectweb.fractal.fraclet.types.Step;
import org.ow2.petals.commons.log.PetalsExecutionContext;
import org.ow2.petals.launcher.api.server.conf.ConfigurationProperties;
import org.ow2.petals.microkernel.api.communication.sharedarea.SharedAreaService;
import org.ow2.petals.microkernel.api.communication.topology.TopologyService;
import org.ow2.petals.microkernel.api.configuration.ConfigurationService;
import org.ow2.petals.microkernel.api.configuration.ContainerConfiguration;
import org.ow2.petals.microkernel.api.configuration.ContainerConfigurationListener;
import org.ow2.petals.microkernel.api.configuration.DomainConfiguration;
import org.ow2.petals.microkernel.api.configuration.exception.ConfigurationException;
import org.ow2.petals.microkernel.api.configuration.exception.MissingServerPropertyException;
import org.ow2.petals.microkernel.api.jbi.messaging.RouterService;
import org.ow2.petals.microkernel.api.transport.FastRemoteTransportService;
import org.ow2.petals.microkernel.api.util.ConfigurationServiceUtils;
import org.ow2.petals.topology.TopologyBuilder;
import org.ow2.petals.topology.TopologyException;
import org.ow2.petals.topology.TopologyHelper;
import org.ow2.petals.topology.generated.Container;
import org.ow2.petals.topology.generated.Topology;
import com.ebmwebsourcing.easycommons.log.LoggingUtil;
import com.ebmwebsourcing.easycommons.properties.PropertiesException;
import com.ebmwebsourcing.easycommons.properties.PropertiesHelper;
/**
*
* The Configuration service that handles the configuration of the local PEtALS
* container.
*
*
* At its starting, it retrieves the configuration from the {@link Topology} and
* the local container configuration (ie, content of the file
* 'server.properties'), it performs a first level validation of the
* consistency, then it fill the local {@link ContainerConfiguration}.
*
*
* @author Roland NAUDIN - EBM WebSourcing
* @author Christophe Hamerling - EBM WebSourcing
* @author Charles Casadei - EBM WebSourcing
* @since Petals 2.0
*/
@Component(provides = @Interface(name = "service", signature = ConfigurationService.class))
public class ConfigurationServiceImpl implements ConfigurationService {
/**
* File name, in the working area, of the persisted topology definition
*/
private static final String PERSISTED_TOPOLOGY_DEFINITION = "topology.xml";
/**
* Logging utilities
*/
protected final LoggingUtil log = new LoggingUtil(Logger.getLogger(ConfigurationService.COMPONENT_LOGGER_NAME));
/**
* The configuration of the current container
*/
private final ContainerConfiguration containerConfiguration = new ContainerConfiguration();
/**
* The domain configuration of the domain for which the current container is a member.
*/
private DomainConfiguration domainConfiguration = new DomainConfiguration();
/**
* List of remote container configuration created from the topology. Key is the container name.
*
* TODO this maybe should be moved to {@link TopologyService} or even {@link SharedAreaService}...
* {@link ConfigurationService} is more used to hold non-dynamic information!
*/
private final ConcurrentMap knownContainers = new ConcurrentHashMap<>();
/**
* The local topology read from the local topology definition (i.e., default topology.xml or persisted one)
*/
private Topology localTopology;
private final List containerConfigListeners = Collections
.synchronizedList(new ArrayList());
@Override
public void registerContainerConfigurationListener(final ContainerConfigurationListener listener) {
this.containerConfigListeners.add(listener);
}
@Override
public void deregisterContainerConfigurationListener(final ContainerConfigurationListener listener) {
this.containerConfigListeners.remove(listener);
}
@Override
public ContainerConfiguration getContainerConfiguration() {
return this.containerConfiguration;
}
@Override
public Map getAllServerProperties() {
final Map containerLocalProperties = new HashMap<>();
containerLocalProperties.put(ConfigurationProperties.CONTAINER_NAME, this.containerConfiguration.getName());
containerLocalProperties.put(ConfigurationProperties.DATA_ROOT_DIRECTORY_PROPERTY_NAME,
this.containerConfiguration.getDataRootPath());
containerLocalProperties.put(ConfigurationProperties.REPOSITORY_PATH_PROPERTY_NAME,
this.containerConfiguration.getRepositoryDirectoryPath());
containerLocalProperties.put(ConfigurationProperties.WORKING_AREA_PATH_PROPERTY_NAME,
this.containerConfiguration.getWorkDirectoryPath());
containerLocalProperties.put(ConfigurationProperties.EXCHANGE_VALIDATION,
Boolean.toString(this.containerConfiguration.isExchangeValidation()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_QUEUE_MAXSIZE,
Integer.toString(this.containerConfiguration.getTransporterQueueMaxSize()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_QUEUE_OFFERING_TIMEOUT,
Long.toString(this.containerConfiguration.getTransporterQueueOfferingTimeout()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_RECEIVERS,
Integer.toString(this.containerConfiguration.getTCPReceivers()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_LISTEN,
this.containerConfiguration.getTCPListen());
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_SENDERS,
Integer.toString(this.containerConfiguration.getTCPSenders()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_CONNECTION_TIMEOUT,
Long.toString(this.containerConfiguration.getTCPConnectionTimeout()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_SEND_TIMEOUT,
Long.toString(this.containerConfiguration.getTCPSendTimeout()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_SEND_EVICTOR_DELAY,
Long.toString(this.containerConfiguration.getTCPSenderEvictorDelay()));
containerLocalProperties.put(ConfigurationProperties.TRANSPORT_TCP_SEND_EVICTABLE_DELAY,
Long.toString(this.containerConfiguration.getTCPSenderEvictableDelay()));
containerLocalProperties.put(ConfigurationProperties.ROUTER_QOS,
this.containerConfiguration.getRouterQOS());
containerLocalProperties.put(ConfigurationProperties.ROUTER_STRATEGY,
this.containerConfiguration.getRouterStrategy());
containerLocalProperties.put(ConfigurationProperties.ROUTER_SEND_ATTEMPT,
Short.toString(this.containerConfiguration.getRouterSendAttempt()));
containerLocalProperties.put(ConfigurationProperties.ROUTER_SEND_DELAY,
Integer.toString(this.containerConfiguration.getRouterSendDelay()));
containerLocalProperties.put(ConfigurationProperties.TASK_TIMEOUT,
Long.toString(this.containerConfiguration.getTaskTimeout()));
containerLocalProperties.put(ConfigurationProperties.CLASSLOADER_ISOLATED,
Boolean.toString(this.containerConfiguration.isIsolateJBIClassLoaders()));
containerLocalProperties.put(ConfigurationProperties.SSL_KEY_PASSWORD,
this.containerConfiguration.getSSLKeyPassword());
containerLocalProperties.put(ConfigurationProperties.SSL_KEYSTORE_FILE,
this.containerConfiguration.getSSLKeystore());
containerLocalProperties.put(ConfigurationProperties.SSL_KEYSTORE_PASSWORD,
this.containerConfiguration.getSSLKeystorePassword());
containerLocalProperties.put(ConfigurationProperties.SSL_TRUSTSTORE_FILE,
this.containerConfiguration.getSSLTruststore());
containerLocalProperties.put(ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD,
this.containerConfiguration.getSSLTruststorePassword());
containerLocalProperties.put(ConfigurationProperties.RECOVERY_CORE_POOL_SIZE,
Integer.toString(this.containerConfiguration.getRecoveryCorePoolSize()));
containerLocalProperties.put(ConfigurationProperties.RECOVERY_KEEP_ALIVE_TIME,
Long.toString(this.containerConfiguration.getRecoveryKeepAliveTime()));
containerLocalProperties.put(ConfigurationProperties.TOPOLOGY_LOCKS_MAX_WAIT_TIME,
Integer.toString(this.containerConfiguration.getTopologyLocksMaxWaitTime()));
// Add user properties
final Map userConfiguration = this.containerConfiguration
.getUserConfiguration();
if (userConfiguration != null) {
containerLocalProperties.putAll(userConfiguration);
}
// Add extra properties
final Map extraConfiguration = this.containerConfiguration
.getExtraConfiguration();
if (extraConfiguration != null) {
containerLocalProperties.putAll(extraConfiguration);
}
return containerLocalProperties;
}
@Override
public Properties getServerProperties() {
final Properties serverProperties = new Properties();
for (final Map.Entry entry : this.getAllServerProperties().entrySet()) {
final String value = entry.getValue();
if (value != null) {
serverProperties.setProperty(entry.getKey(), value);
}
}
return serverProperties;
}
@Override
public ContainerConfiguration getContainerConfiguration(final String containerName) {
final ContainerConfiguration result;
if (this.containerConfiguration.getName().equals(containerName)) {
result = this.getContainerConfiguration();
} else {
result = this.knownContainers.get(containerName);
}
return result;
}
@Override
public synchronized Set getContainersConfiguration() {
final Set res = new HashSet<>(this.knownContainers.values());
res.add(this.containerConfiguration);
return res;
}
@Override
public synchronized DomainConfiguration getDomainConfiguration() {
this.log.call();
return this.domainConfiguration;
}
@Override
public synchronized Topology getLocalTopology() {
this.log.call();
return this.localTopology;
}
@Lifecycle(step = Step.START)
public void start() throws Exception {
this.log.call();
}
@Lifecycle(step = Step.STOP)
public void stop() {
this.log.call();
}
@Override
public void loadConfiguration(final Properties serverLocalProperties, final Topology topology)
throws ConfigurationException {
assert serverLocalProperties != null;
assert topology != null;
this.log.start();
try {
initializeLocalProperties(this.containerConfiguration, serverLocalProperties, this.log);
// Checks if the container name has been set in the
// server local configuration (ie. content of 'server.properties'
// or equivalent) or as a system property
final String containerName = this.containerConfiguration.getName();
if (containerName == null || containerName.isEmpty()) {
throw new MissingServerPropertyException(
ConfigurationProperties.CONTAINER_NAME,
"The property '"
+ ConfigurationProperties.CONTAINER_NAME
+ "' must be set in the server local configuration (ie. in the content of file 'server.properties' or equivalent) or as system property");
}
// Check if a persisted topology definition exists
final String workingAreaValue = this.containerConfiguration.getWorkDirectoryPath();
final File workingArea = new File(workingAreaValue);
if (workingArea.exists()) {
if (workingArea.isDirectory()) {
final File persistedTopologyFile = new File(workingArea, PERSISTED_TOPOLOGY_DEFINITION);
if (persistedTopologyFile.exists()) {
if (persistedTopologyFile.isFile()) {
try {
this.log.debug("A persisted topology definition exists, we use it.");
this.localTopology = TopologyBuilder.createTopology(persistedTopologyFile);
} catch (final TopologyException e) {
throw new ConfigurationException(String.format(
"An error occurs parsing the persisted topology definition '%s'.",
persistedTopologyFile.getAbsolutePath()), e);
}
} else {
throw new ConfigurationException(String.format(
"Invalid persisted topology definition '%s' (not a file).",
persistedTopologyFile.getAbsolutePath()));
}
} else {
this.log.debug("No persisted topology definition exists.");
this.localTopology = topology;
}
} else {
throw new ConfigurationException(String.format("Invalid working area '%s' (not a directory).",
workingAreaValue));
}
} else {
this.log.info(String
.format("The working area '%s' does not exists. Probably it's the first startup of the container, or the data area has been cleaned manually.",
workingArea.getAbsoluteFile()));
if (!workingArea.mkdirs()) {
log.warning(String.format(
"Unable to create the working area '%s'. Potential problems can occurs later.",
workingAreaValue));
}
this.localTopology = topology;
}
// all these validations will be done again (and must be because we are maybe moving between
// topologies) when the shared area update the topology with updateTopology, but let's validate as early as
// we can
ConfigurationServiceUtils.validateTopology(this.containerConfiguration, this.localTopology);
// this is needed so that the domain contains the correct informations (including shared area specificities)
// for the shared area to initialise
ConfigurationServiceUtils.initializeDomainConfiguration(this.domainConfiguration, this.localTopology);
// this is needed to initialise things like ports and stuffs (TODO that could actually be in the server conf
// and not the topology.... but putting it in the topology avoids duplication...)
ConfigurationServiceUtils.initializeContainerConfiguration(this.containerConfiguration, this.localTopology);
// post validate platform configuration
validateContainerConfiguration(this.containerConfiguration, this.log);
// TODO this doesn't really make sense to update that now, because updateTopology will do it with the real
// informations when it will be called during the shared area startup
// but many components relies on this information being filled after loadConfiguration has been called
// e.g.: sometimes, to start the shared area, we need the embedded registry to be started, and to start it,
// we need to know this information (it is activated if and only if it is needed)
this.updateKnownContainers(this.localTopology);
if (this.log.isConfigEnabled()) {
this.log.config("Configuration used: " + this.containerConfiguration.toString());
}
} finally {
this.log.end();
}
}
/**
*
* Registers the containers defined in the domain.
*
*
* If a container is already registered but not declared in the topology, it is unregistered
*
*
* @param topology
* A topology configuration coming from its XML definition. Can not be null
.
*/
private void updateKnownContainers(final Topology topology) {
// add the containers of the topology (except us)
for (final Container container : topology.getDomain().getContainer()) {
if (!container.getName().equals(this.containerConfiguration.getName())) {
final ContainerConfiguration cc = new ContainerConfiguration();
ConfigurationServiceUtils.initializeContainerConfiguration(cc, container);
this.knownContainers.put(cc.getName(), cc);
}
}
// remove containers not here anymore
final Iterator itContainerCfg = this.knownContainers.values().iterator();
while (itContainerCfg.hasNext()) {
if (TopologyHelper.findContainer(itContainerCfg.next().getName(), topology) == null) {
// The container is not in the topology anymore
itContainerCfg.remove();
}
}
}
/**
* Initialize a container configuration with the server properties.
*
* @param containerConfiguration
* The container configuration to initialize. Can be null
.
* @param serverLocalProperties
* The local properties of the current container (ie: the content of 'server.properties' or equivalent).
* Can be null
.
* @throws MissingServerPropertyException
* A required server property is missing.
* @throws ConfigurationException
* An error occurs about a property value
*/
private static void initializeLocalProperties(final ContainerConfiguration containerConfiguration,
final Properties serverLocalProperties, final LoggingUtil log)
throws MissingServerPropertyException, ConfigurationException {
log.start();
final Map userProperties = new HashMap<>();
final Map extraProperties = new HashMap<>();
if (serverLocalProperties != null) {
for (final Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy