/**
* Copyright (c) 2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wso2.carbon.mediation.initializer.configurations;
import org.apache.synapse.ServerContextInformation;
import org.apache.synapse.task.TaskDescriptionRepository;
import org.apache.synapse.task.TaskScheduler;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.wso2.carbon.core.multitenancy.SuperTenantCarbonContext;
import org.wso2.carbon.mediation.initializer.services.*;
import org.wso2.carbon.mediation.initializer.utils.ConfigurationHolder;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.mediation.initializer.ServiceBusConstants;
import org.wso2.carbon.mediation.initializer.ServiceBusUtils;
import org.wso2.carbon.mediation.initializer.persistence.MediationPersistenceManager;
import org.wso2.carbon.mediation.registry.WSO2Registry;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.AxisFault;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.apache.synapse.config.*;
import org.apache.synapse.config.xml.MultiXMLConfigurationBuilder;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.MessageContextCreatorForAxis2;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.core.axis2.ProxyService;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.ServerConfigurationInformation;
import org.apache.synapse.mediators.base.SequenceMediator;
import org.apache.synapse.registry.Registry;
import org.apache.synapse.eventing.SynapseEventSource;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.io.File;
import java.util.Properties;
import java.util.Enumeration;
import java.util.List;
/**
* Responsible for managing the differrence configurations inside a single ConfigurationContext.
*/
public class ConfigurationManager {
private static Log log = LogFactory.getLog(ConfigurationManager.class);
public static final String CONFIGURATION_MANAGER = "CONFIGURATION_MANAGER";
/** We are defaulting to this, we need to take this from a configuration */
private String synpaseConfigurationsRoot = ServiceBusConstants.DEFAULT_SYNAPSE_CONFIGS_LOCATION;
/** Class to track the multiple configurations */
private ConfigurationTracker tracker;
/** Registry */
private UserRegistry registry = null;
/** The configuration context of the server */
private ConfigurationContext configurationContext;
/** Tenant for this configuration belongs */
private int tenantId = MultitenantConstants.SUPER_TENANT_ID;
/**
*
* @param registry the configuration registry
* @param configurationContext servers configuration context
*/
public ConfigurationManager(UserRegistry registry,
ConfigurationContext configurationContext) {
if (registry == null) {
throw new IllegalArgumentException("Registry is required");
}
if (configurationContext == null) {
throw new IllegalArgumentException("ConfigurationContext is required");
}
this.registry = registry;
this.configurationContext = configurationContext;
}
/**
* Initilize the configuration manager
*
* @throws ConfigurationInitilizerException if an error occurs
*/
public void init() throws ConfigurationInitilizerException {
tracker = new ConfigurationTracker(registry);
try {
tracker.init();
Parameter parameter = configurationContext.getAxisConfiguration().getParameter(
SynapseConstants.Axis2Param.SYNAPSE_CONFIG_LOCATION);
if (parameter != null && parameter.getValue() != null) {
synpaseConfigurationsRoot = parameter.getValue().toString();
}
tenantId = SuperTenantCarbonContext.
getCurrentContext(configurationContext).getTenantId();
} catch (RegistryException e) {
handleException("Cannot initialize the configuration tracker: ", e);
}
}
/**
* Get the configuration tracker
* @return configuration tracker used by this manager
*/
public ConfigurationTracker getTracker() {
return tracker;
}
/**
* Activate the given configuration. This will intern deactivate the current
* configuration and then activate the new configuration.
*
* @param name name of the configuration to be activated
* @return true if activation is successful
* @throws ConfigurationInitilizerException if an error occurs while activating
*/
public boolean activate(String name) throws ConfigurationInitilizerException {
try {
if (!tracker.isConfigurationExists(name)) {
handleException("Trying to load the configuration: " + name +
" that doesn't have a record");
}
SynapseConfiguration newSynapseConfiguration = null;
SynapseConfiguration oldSynapseConfiguration = getSynapseConfiguration();
SynapseEnvironment oldSynapseEnvironment = getSynapseEnvironment();
TaskDescriptionRepository repository = getSynapseEnvironment().getTaskManager().
getTaskDescriptionRepository();
TaskScheduler taskScheduler = getSynapseEnvironment().getTaskManager().
getTaskScheduler();
int loadLocation = 0;
// if this configuration is not created before we are going to
// create a default configuration
if (!tracker.isConfigurationCreated(name)) {
ConfigurationInformation information = tracker.getConfigurationInformation(name);
newSynapseConfiguration = createDefaultConfiguration();
if (information != null && information.getDescription() != null) {
newSynapseConfiguration.setDescription(information.getDescription());
}
loadLocation = 1;
log.info("A default Synapse Configuration is created " +
"for the configuration: " + name);
}
Properties properties = SynapsePropertiesLoader.loadSynapseProperties();
if (getServerConfigurationInformation().getResolveRoot() != null) {
properties.put(SynapseConstants.RESOLVE_ROOT,
getServerConfigurationInformation().getResolveRoot());
}
if (getServerConfigurationInformation().getSynapseHome() != null) {
properties.put(SynapseConstants.SYNAPSE_HOME,
getServerConfigurationInformation().getSynapseHome());
}
if (loadLocation != 1) {
if (isLoadFromRegistry()) {
newSynapseConfiguration = ConfigurationUtils.loadFromRegistry(
registry, name, synpaseConfigurationsRoot +
File.separator + name, properties);
if (newSynapseConfiguration != null) {
log.info("Successfully loaded the Synapse Configuration: "
+ name + " from the registry");
loadLocation = 2;
} else {
log.warn("Failed to load Synapse Configuration: " +
name + " from the registry, "
+ "trying to load from the file system");
}
}
// we have to try to load the configuration from the file system
if (newSynapseConfiguration == null) {
newSynapseConfiguration = SynapseConfigurationBuilder.
getConfiguration(synpaseConfigurationsRoot + File.separator + name,
properties);
if (newSynapseConfiguration != null) {
log.info("Successfully loaded the Synapse Configuration: " +
name + " from the file system");
loadLocation = 3;
} else {
log.warn("Failed to load the Synapse Configuration: " + name);
return false;
}
}
}
// destroy the old configuration
synchronized (oldSynapseConfiguration) {
// first make sure we have completed all the persistence requests
getMediationPersistenceManager().destroy();
try {
ConfigurationUtils.destroyConfiguration(oldSynapseConfiguration,
configurationContext.getAxisConfiguration(), oldSynapseEnvironment);
} catch (Exception e) {
// we are going to ignore and continue
log.warn("Error while destroying the current configuration.. " +
"Continuing to load the new configuration");
}
}
// we are going to switch to the new configuration location
newSynapseConfiguration.setPathToConfigFile(
synpaseConfigurationsRoot + File.separator + name);
getServerConfigurationInformation().
setSynapseXMLLocation(synpaseConfigurationsRoot + File.separator + name);
if (loadLocation == 1) {
ConfigurationUtils.saveToRegistry(registry, newSynapseConfiguration, name);
ConfigurationUtils.saveToFileSystem(newSynapseConfiguration);
} else if (loadLocation == 2) {
if ("true".equals(ConfigurationUtils.getParameter(ServiceBusConstants.SAVE_TO_FILE))) {
// If the configuration was loaded from the registry and the 'saveConfigToFile'
// system property is set we should serialize the current configuration to the
// file system
ConfigurationUtils.saveToFileSystem(newSynapseConfiguration);
}
} else {
// If the configuration was loaded from the file system we should
// save it to the registry
ConfigurationUtils.saveToRegistry(registry, newSynapseConfiguration, name);
}
tracker.activate(name);
configurationContext.getAxisConfiguration().addParameter(
new Parameter(ServiceBusConstants.SYNAPSE_CURRENT_CONFIGURATION, name));
tracker.update(name, true);
// initilze the configuration
initializeConfiguration(synpaseConfigurationsRoot + File.separator + name,
oldSynapseConfiguration, newSynapseConfiguration, repository, taskScheduler);
// initialize the persistence
ConfigurationUtils.initPersistence(newSynapseConfiguration, registry,
synpaseConfigurationsRoot + File.separator + name,
configurationContext.getAxisConfiguration(), name);
// un-register the old configuration
unregisterServices();
registerServices();
return true;
} catch (RegistryException e) {
handleException("Error accessing the registry resources", e);
} catch (AxisFault axisFault) {
handleException("Error while setting up the new configuration");
}
return false;
}
private void registerServices() {
SynapseEnvironment synEnv = getSynapseEnvironment();
SynapseConfiguration synConfig = getSynapseConfiguration();
SynapseConfigurationService synCfgSvc
= new SynapseConfigurationServiceImpl(synConfig,
tenantId, configurationContext);
Properties props = new Properties();
ServiceRegistration confRegistration =
ConfigurationHolder.getInstance().getBundleContext().registerService(
SynapseConfigurationService.class.getName(), synCfgSvc, props);
props = new Properties();
SynapseEnvironmentService synEnvSvc
= new SynapseEnvironmentServiceImpl(synEnv,
tenantId, configurationContext);
ServiceRegistration envRegistration =
ConfigurationHolder.getInstance().getBundleContext().registerService(
SynapseEnvironmentService.class.getName(), synEnvSvc, props);
props = new Properties();
SynapseRegistrationsService synRegistrationsSvc
= new SynapseRegistrationsServiceImpl(
confRegistration, envRegistration, tenantId, configurationContext);
ServiceRegistration synapseRegistration =
ConfigurationHolder.getInstance().getBundleContext().registerService(
SynapseRegistrationsService.class.getName(),
synRegistrationsSvc, props);
}
private void unregisterServices() {
BundleContext bundleContext = ConfigurationHolder.getInstance().getBundleContext();
ServiceRegistration serviceRegistration = ConfigurationHolder.getInstance().
getSynapseRegistration(tenantId);
if (serviceRegistration != null) {
SynapseRegistrationsService synapseRegistrationsService =
(SynapseRegistrationsService) bundleContext.getService(serviceRegistration.getReference());
ServiceRegistration synConfigServiceRegistration =
synapseRegistrationsService.getSynapseConfigurationServiceRegistration();
if (synConfigServiceRegistration != null) {
bundleContext.ungetService(synConfigServiceRegistration.getReference());
}
ServiceRegistration synEnvServiceRegistration =
synapseRegistrationsService.getSynapseEnvironmentServiceRegistration();
if (synEnvServiceRegistration != null) {
bundleContext.ungetService(synEnvServiceRegistration.getReference());
}
bundleContext.ungetService(serviceRegistration.getReference());
}
}
/**
* Create the default configuration
*
* @return the default configuration
*/
private SynapseConfiguration createDefaultConfiguration() {
SynapseConfiguration newSynapseConfiguration;
newSynapseConfiguration = SynapseConfigurationBuilder.getDefaultConfiguration();
SequenceMediator mainSequence = (SequenceMediator)
newSynapseConfiguration.getMainSequence();
mainSequence.setFileName(mainSequence.getName());
SequenceMediator faultSequence = (SequenceMediator)
newSynapseConfiguration.getFaultSequence();
faultSequence.setFileName(faultSequence.getName());
// set the governance registry
Registry registry = new WSO2Registry();
newSynapseConfiguration.setRegistry(registry);
newSynapseConfiguration.setProperty(
MultiXMLConfigurationBuilder.SEPARATE_REGISTRY_DEFINITION, "true");
return newSynapseConfiguration;
}
/**
* Delete a configuration. This will delete the registry entry, but it won't delete the
* actual files and registry persitant information.
*
* @param name name of the configuration to be deleted
* @throws ConfigurationInitilizerException if an error occurs
*/
public void delete(String name) throws ConfigurationInitilizerException {
try {
tracker.delete(name);
} catch (RegistryException e) {
handleException("Failed to delete the configuration: " + name, e);
}
}
/**
* Create a new configuration. This won't write anything to the disk until this
* configuration is activated.
*
* @param name name of the configuration
* @param description description of the configuration
* @throws ConfigurationInitilizerException if an error occurs
*/
public void create(String name, String description) throws ConfigurationInitilizerException {
try {
tracker.create(name, description);
} catch (RegistryException e) {
handleException("Failed to create configuration: " + name, e);
}
}
/**
* Return the list of configurations available.
* @return list of configuration information
* @throws ConfigurationInitilizerException if an error occurs
*/
public List<ConfigurationInformation> getConfigurationsList()
throws ConfigurationInitilizerException {
try {
return tracker.getConfigurationList();
} catch (RegistryException e) {
handleException("Failed to get the configurations list", e);
}
return null;
}
public void addExistingConfiguration(String name) throws ConfigurationInitilizerException {
// try to see weather file or registry entry exists
// if exists delete it
// add the information to the tracker
try {
if (tracker.isConfigurationExists(name)) {
String msg = "Configuration already exists in the " +
"available configurations list. Cannot add it again.";
log.warn(msg);
throw new ConfigurationInitilizerException(msg);
} else {
tracker.create(name, "");
tracker.update(name, true);
}
} catch (RegistryException e) {
handleException("Failed to add the existing configuration: " + name, e);
}
}
/**
* Initialize a newly created configuration. This will initialize the Synapse Env as well.
*
* @param configurationLocation file path which this configuration is based on
* @param oldSynapseConfiguration previous synapse configuration
* @param newSynapseConfiguration newly created synapse configuration
* @param repository task repository
* @param taskScheduler @throws ConfigurationInitilizerException if an error occurs
* @throws org.apache.axis2.AxisFault if an error occurs
* @throws ConfigurationInitilizerException if an error occurs
*/
private void initializeConfiguration(String configurationLocation,
SynapseConfiguration oldSynapseConfiguration,
SynapseConfiguration newSynapseConfiguration,
TaskDescriptionRepository repository,
TaskScheduler taskScheduler)
throws ConfigurationInitilizerException, AxisFault {
AxisConfiguration axisConfiguration = configurationContext.getAxisConfiguration();
// Set the Axis2 ConfigurationContext to the SynapseConfiguration
newSynapseConfiguration.setAxisConfiguration(axisConfiguration);
Entry hostEntry = oldSynapseConfiguration.getEntryDefinition(SynapseConstants.SERVER_HOST);
Entry ipEntry = oldSynapseConfiguration.getEntryDefinition(SynapseConstants.SERVER_IP);
// setup the properties
Properties properties = SynapsePropertiesLoader.loadSynapseProperties();
if (properties != null) {
Enumeration keys = properties.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
newSynapseConfiguration.setProperty(key, properties.getProperty(key));
}
}
// Add the old parameters to the new configuration
newSynapseConfiguration.setPathToConfigFile(configurationLocation);
newSynapseConfiguration.addEntry(SynapseConstants.SERVER_HOST, hostEntry);
newSynapseConfiguration.addEntry(SynapseConstants.SERVER_IP, ipEntry);
// Check for the main sequence and add a default main sequence if not present
if (newSynapseConfiguration.getMainSequence() == null) {
SynapseConfigUtils.setDefaultMainSequence(newSynapseConfiguration);
}
// Check for the fault sequence and add a deafult fault sequence if not present
if (newSynapseConfiguration.getFaultSequence() == null) {
SynapseConfigUtils.setDefaultFaultSequence(newSynapseConfiguration);
}
ServerContextInformation contextInformation = getServerContextInformation();
// set the synapse configuration to the axis2 configuration
newSynapseConfiguration.setAxisConfiguration(axisConfiguration);
Parameter synapseCtxParam = new Parameter(SynapseConstants.SYNAPSE_CONFIG, null);
synapseCtxParam.setValue(newSynapseConfiguration);
MessageContextCreatorForAxis2.setSynConfig(newSynapseConfiguration);
//set up synapse env
Parameter synapseEnvParam = new Parameter(SynapseConstants.SYNAPSE_ENV, null);
Axis2SynapseEnvironment synEnv = new Axis2SynapseEnvironment(configurationContext,
newSynapseConfiguration, contextInformation);
synapseEnvParam.setValue(synEnv);
MessageContextCreatorForAxis2.setSynEnv(synEnv);
if (contextInformation != null) {
// set the new information to the server context
contextInformation.setSynapseEnvironment(synEnv);
contextInformation.setSynapseConfiguration(newSynapseConfiguration);
} else {
throw new IllegalStateException("ServerContextInformation not found");
}
try {
axisConfiguration.addParameter(synapseCtxParam);
axisConfiguration.addParameter(synapseEnvParam);
} catch (AxisFault e) {
String msg =
"Could not set parameters '" + SynapseConstants.SYNAPSE_CONFIG +
"' and/or '" + SynapseConstants.SYNAPSE_ENV +
"'to the Axis2 configuration : " + e.getMessage();
throw new ConfigurationInitilizerException(msg, e);
}
// redeploy proxy services
if (log.isTraceEnabled()) {
log.trace("Re-deploying Proxy services...");
}
for (ProxyService proxyService : newSynapseConfiguration.getProxyServices()) {
if (proxyService != null) {
proxyService.buildAxisService(newSynapseConfiguration, axisConfiguration);
if (log.isDebugEnabled()) {
log.debug("Deployed Proxy service : " + proxyService.getName());
}
if (!proxyService.isStartOnLoad()) {
proxyService.stop(newSynapseConfiguration);
}
}
}
if (log.isTraceEnabled()) {
log.trace("Re-deploying Event Sources...");
}
for (SynapseEventSource eventSource : newSynapseConfiguration.getEventSources()) {
if (eventSource != null) {
eventSource.buildService(axisConfiguration);
if (log.isDebugEnabled()) {
log.debug("Deployed Event Source : " + eventSource.getName());
}
}
}
synEnv.getTaskManager().init(repository, taskScheduler);
// init the synapse configuration
newSynapseConfiguration.init(synEnv);
synEnv.setInitialized(true);
}
/**
* Return true if we have to load the configuration from the registry
* @return true if we have to load the configuration from the registry
*/
private boolean isLoadFromRegistry() {
return "true".equals(
ConfigurationUtils.getParameter(ServiceBusConstants.LOAD_FROM_REGISTRY));
}
private SynapseEnvironment getSynapseEnvironment() {
return (SynapseEnvironment) configurationContext.getAxisConfiguration().getParameter(
SynapseConstants.SYNAPSE_ENV).getValue();
}
private SynapseConfiguration getSynapseConfiguration() {
return (SynapseConfiguration) configurationContext.getAxisConfiguration().getParameter(
SynapseConstants.SYNAPSE_CONFIG).getValue();
}
private MediationPersistenceManager getMediationPersistenceManager() {
return ServiceBusUtils.getMediationPersistenceManager(
configurationContext.getAxisConfiguration());
}
private ServerConfigurationInformation getServerConfigurationInformation() {
Parameter p = configurationContext.getAxisConfiguration().
getParameter(SynapseConstants.SYNAPSE_SERVER_CONFIG_INFO);
if (p != null) {
return (ServerConfigurationInformation) p.getValue();
}
return null;
}
private ServerContextInformation getServerContextInformation() {
Parameter p = configurationContext.getAxisConfiguration().
getParameter(SynapseConstants.SYNAPSE_SERVER_CTX_INFO);
if (p != null) {
return (ServerContextInformation) p.getValue();
}
return null;
}
private void handleException(String msg) throws ConfigurationInitilizerException {
log.warn(msg);
throw new ConfigurationInitilizerException(msg);
}
private void handleException(String msg, Exception e) throws ConfigurationInitilizerException {
log.warn(msg, e);
throw new ConfigurationInitilizerException(msg, e);
}
}