Package org.wso2.carbon.mediation.configadmin

Source Code of org.wso2.carbon.mediation.configadmin.ConfigurationUpdater

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you 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.configadmin;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.ManagedLifecycle;
import org.apache.synapse.ServerContextInformation;
import org.apache.synapse.Startup;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.commons.executors.PriorityExecutor;
import org.apache.synapse.config.Entry;
import org.apache.synapse.config.SynapseConfigUtils;
import org.apache.synapse.config.SynapseConfiguration;
import org.apache.synapse.config.xml.MultiXMLConfigurationBuilder;
import org.apache.synapse.config.xml.XMLConfigurationBuilder;
import org.apache.synapse.core.SynapseEnvironment;
import org.apache.synapse.core.axis2.Axis2SynapseEnvironment;
import org.apache.synapse.core.axis2.MessageContextCreatorForAxis2;
import org.apache.synapse.core.axis2.ProxyService;
import org.apache.synapse.endpoints.Endpoint;
import org.apache.synapse.endpoints.Template;
import org.apache.synapse.eventing.SynapseEventSource;
import org.apache.synapse.mediators.base.SequenceMediator;
import org.apache.synapse.mediators.template.TemplateMediator;
import org.apache.synapse.message.processors.MessageProcessor;
import org.apache.synapse.message.store.MessageStore;
import org.apache.synapse.task.TaskDescriptionRepository;
import org.apache.synapse.task.TaskScheduler;
import org.osgi.framework.ServiceRegistration;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.core.multitenancy.SuperTenantCarbonContext;
import org.wso2.carbon.mediation.configadmin.util.ConfigHolder;
import org.wso2.carbon.mediation.dependency.mgt.services.ConfigurationTrackingService;
import org.wso2.carbon.mediation.initializer.ServiceBusConstants;
import org.wso2.carbon.mediation.initializer.configurations.ConfigurationInitilizerException;
import org.wso2.carbon.mediation.initializer.configurations.ConfigurationManager;
import org.wso2.carbon.mediation.initializer.configurations.ConfigurationUtils;
import org.wso2.carbon.mediation.initializer.persistence.MediationPersistenceManager;
import org.wso2.carbon.mediation.initializer.services.SynapseConfigurationService;
import org.wso2.carbon.mediation.initializer.services.SynapseEnvironmentService;
import org.wso2.carbon.mediation.initializer.services.SynapseRegistrationsService;
import org.wso2.carbon.registry.core.session.UserRegistry;

import javax.xml.stream.XMLStreamException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;

/**
* Use an instance of this class to update the existing SynapseConfiguration of a server. This will
* gracefully cleanup the existing configuration and apply the provided new configuration. In
* case of an error, it will fallback to the old configuration. This class is not thread safe and
* hence should not be used by multiple threads.
*/
public class ConfigurationUpdater {

    private static final Log log = LogFactory.getLog(ConfigurationUpdater.class);

    private ServerContextInformation serverContextInformation;
    private ConfigurationContext configurationContext;
    private MediationPersistenceManager persistenceManager;
    private UserRegistry configRegistry;

    private final SynapseConfiguration currentConfig;
    private SynapseEnvironment currentEnvironment;
    private AxisConfiguration axisCfg;

    private TaskDescriptionRepository taskRepository;
    private TaskScheduler taskScheduler;

    public ConfigurationUpdater(ServerContextInformation serverContextInformation,
                                ConfigurationContext configurationContext,
                                MediationPersistenceManager persistenceManager,
                                UserRegistry configRegistry) {

        this.serverContextInformation = serverContextInformation;
        this.configurationContext = configurationContext;
        this.persistenceManager = persistenceManager;
        this.configRegistry = configRegistry;

        currentConfig = serverContextInformation.getSynapseConfiguration();
        currentEnvironment = serverContextInformation.getSynapseEnvironment();
        axisCfg = currentConfig.getAxisConfiguration();
    }

    public void update(OMElement configElement) throws AxisFault {
        synchronized (currentConfig) {
            cleanupCurrentConfiguration();
        }

        SynapseConfiguration newConfig = null;
        try {
            newConfig = createNewConfiguration(configElement);
        } catch (Exception e) {
            // Something went wrong while constructing the new SynapseConfiguration -
            // Fall back to the old one...
            newConfig = currentConfig;
        } finally {
            synchronized (newConfig) {
                prepareNewConfiguration(newConfig);
            }
        }
    }

    /**
     * Stops the mediation persistence manager, cleans up the Synapse task scheduler and
     * destroys the current SynapseConfiguration. This method is considered to be failure
     * proof and hence does not throw any checked exceptions. Any faults encountered by
     * this method are due to programming errors and therefore they are translated into
     * instances of RuntimeException.
     */
    private void cleanupCurrentConfiguration() {
        persistenceManager.destroy();

        // We must get references to following task objects at this point
        // Once the SynapseConfiguration is destroyed they become unreachable
        taskRepository = currentEnvironment.getTaskManager().getTaskDescriptionRepository();
        taskScheduler = currentEnvironment.getTaskManager().getTaskScheduler();

        log.trace("Stopping and undeploying proxy services");
        for (ProxyService proxyService : currentConfig.getProxyServices()) {
            proxyService.stop(currentConfig);
            safeRemoveService(proxyService.getName());
        }

        for (SequenceMediator sequence : currentConfig.getDefinedSequences().values()) {
            sequence.destroy();
        }

        for (Endpoint endpoint : currentConfig.getDefinedEndpoints().values()) {
            endpoint.destroy();
        }

        log.trace("Stopping active scheduled tasks");
        for (Startup startup : currentConfig.getStartups()) {
            startup.destroy();
        }
        TaskDescriptionRepository repository = currentEnvironment.getTaskManager()
                .getTaskDescriptionRepository();
        if (repository != null) {
            repository.clear();
        }
        currentEnvironment.getTaskManager().cleanup();

        for (SynapseEventSource eventSource : currentConfig.getEventSources()) {
            safeRemoveService(eventSource.getName());
        }

        for (PriorityExecutor executor : currentConfig.getPriorityExecutors().values()) {
            executor.destroy();
        }

        for(MessageStore ms : currentConfig.getMessageStores().values()) {
            ((ManagedLifecycle)ms).destroy();
        }

        for(MessageProcessor mp : currentConfig.getMessageProcessors().values()) {
            ((ManagedLifecycle)mp).destroy();
        }

        for (TemplateMediator tm : currentConfig.getSequenceTemplates().values()) {
            ((ManagedLifecycle) tm).destroy();
        }

        log.trace("Successfully cleaned up the current SynapseConfiguration");
    }

    /**
     * Parses the given XML configuration and creates a new SynapseConfiguration instance.
     * This method follows general Synapse fail-safe rules to handle faults that are encountered
     * while creating the SynapseConfiguration. If fail-safe mode is enabled (default), this
     * method will not throw any exceptions. Otherwise it may throw runtime exceptions. It may
     * also throw an XMLStreamException if the provided XML configuration is malformed.
     *
     * @param configElement OMElement containing the Synapse XML configuration
     * @return a new SynapseConfiguration instance
     * @throws XMLStreamException if the provided OMElement is malformed
     */
    private SynapseConfiguration createNewConfiguration(OMElement configElement)
            throws XMLStreamException {

        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        configElement.serialize(stream);
        return XMLConfigurationBuilder.getConfiguration(
                new ByteArrayInputStream(stream.toByteArray()), currentConfig.getProperties());
    }

    private void prepareNewConfiguration(SynapseConfiguration newConfig) throws AxisFault {
        newConfig.setPathToConfigFile(currentConfig.getPathToConfigFile());
        newConfig.addEntry(SynapseConstants.SERVER_HOST,
                currentConfig.getEntryDefinition(SynapseConstants.SERVER_HOST));
        newConfig.addEntry(SynapseConstants.SERVER_IP,
                currentConfig.getEntryDefinition(SynapseConstants.SERVER_IP));

        // Check for the main sequence and add a default main sequence if not present
        if (newConfig.getMainSequence() == null) {
            SynapseConfigUtils.setDefaultMainSequence(newConfig);
        }

        // Check for the fault sequence and add a default fault sequence if not present
        if (newConfig.getFaultSequence() == null) {
            SynapseConfigUtils.setDefaultFaultSequence(newConfig);
        }

        // The show must go on - So set the file names to the new configuration
        setFileNames(newConfig);

        newConfig.setAxisConfiguration(axisCfg);
        Parameter synapseCtxParam = new Parameter(SynapseConstants.SYNAPSE_CONFIG, null);
        synapseCtxParam.setValue(newConfig);
        MessageContextCreatorForAxis2.setSynConfig(newConfig);

        //set up synapse env
        Axis2SynapseEnvironment synEnv = new Axis2SynapseEnvironment(
                configurationContext, newConfig, serverContextInformation);
        Parameter synapseEnvParam = new Parameter(SynapseConstants.SYNAPSE_ENV, null);
        synapseEnvParam.setValue(synEnv);
        MessageContextCreatorForAxis2.setSynEnv(synEnv);

        try {
            axisCfg.addParameter(synapseCtxParam);
            axisCfg.addParameter(synapseEnvParam);
        } catch (AxisFault axisFault) {
            // This condition should not occur unless there is a programming error
            handleException("Error while adding SynapseConfiguration and/or SynapseEnvironment " +
                    "to the AxisConfiguration", axisFault);
        }

        synEnv.getTaskManager().init(taskRepository, taskScheduler);
        Parameter suspendPersistence = new Parameter(ServiceBusConstants.SUSPEND_PERSISTENCE, "true");
        try {
            axisCfg.addParameter(suspendPersistence);
            deployServices(newConfig);
        } finally {
            serverContextInformation.setSynapseConfiguration(newConfig);
            serverContextInformation.setSynapseEnvironment(synEnv);
            newConfig.init(synEnv);
            synEnv.setInitialized(true);
            axisCfg.removeParameter(suspendPersistence);

            initPersistence(newConfig);
            publishConfiguration(newConfig, synEnv);
        }
    }

    /**
     * This method deploys the proxy services and event sources available in the provided
     * SynapseConfiguration. If an error occurs while deploying a service, this method will
     * follow the Synapse fail-safe rules. In case fail-safe is disabled, and an exception
     * occurs, no service beyond that point will be deployed.
     *
     * @param newConfig SynapseConfiguration with the services to be initialized
     * @throws AxisFault if an error occurs while deploying a service
     */
    private void deployServices(SynapseConfiguration newConfig) throws AxisFault {


        for (ProxyService proxyService : newConfig.getProxyServices()) {
            try {
                proxyService.buildAxisService(newConfig, axisCfg);
                if (log.isDebugEnabled()) {
                    log.debug("Deployed Proxy service : " + proxyService.getName());
                }
                if (!proxyService.isStartOnLoad()) {
                    proxyService.stop(newConfig);
                }
            } catch (Exception e) {
                handleServiceInitializationError(proxyService.getName(),
                        SynapseConstants.FAIL_SAFE_MODE_PROXY_SERVICES, e);
            }
        }

        for (SynapseEventSource eventSource : newConfig.getEventSources()) {
            try {
                eventSource.buildService(axisCfg);
            } catch (Exception e) {
                handleServiceInitializationError(eventSource.getName(),
                        SynapseConstants.FAIL_SAFE_MODE_EVENT_SOURCE, e);
            }
        }
    }

    private void handleServiceInitializationError(String serviceName, String type,
                                                  Exception e) throws AxisFault {
        if (SynapseConfigUtils.isFailSafeEnabled(type)) {
            log.warn("Error while initializing the service: " + serviceName + " - " +
                    "Continue in fail-safe mode", e);
        } else {
            String msg = "Error while initializing the service: " + serviceName;
            log.error(msg, e);
            throw new AxisFault(msg, e);
        }
    }

    private void initPersistence(SynapseConfiguration newConfig) {
        ConfigurationManager configurationManager = (ConfigurationManager)
                configurationContext.getProperty(ConfigurationManager.CONFIGURATION_MANAGER);
        try {
            ConfigurationUtils.initPersistence(newConfig,
                    configRegistry,
                    newConfig.getPathToConfigFile(),
                    axisCfg, configurationManager.getTracker().getCurrentConfigurationName());
        } catch (ConfigurationInitilizerException e) {
            log.error("Error while initializing mediation persistence", e);
        }
    }

    private void setFileNames(SynapseConfiguration newConfig) {
        Map<String, Endpoint> endpoints = newConfig.getDefinedEndpoints();
        for (String name : endpoints.keySet()) {
            Endpoint newEndpoint = endpoints.get(name);
            Endpoint oldEndpoint = currentConfig.getDefinedEndpoints().get(name);
            if (oldEndpoint != null) {
                newEndpoint.setFileName(oldEndpoint.getFileName());
            }
        }

        Map<String, SequenceMediator> sequences = newConfig.getDefinedSequences();
        for (String name : sequences.keySet()) {
            SequenceMediator oldSequence = currentConfig.getDefinedSequences().get(name);
            if (oldSequence != null) {
                sequences.get(name).setFileName(oldSequence.getFileName());
            }
        }

        Collection<ProxyService> proxyServices = newConfig.getProxyServices();
        for (ProxyService proxy : proxyServices) {
            ProxyService oldProxy = currentConfig.getProxyService(proxy.getName());
            if (oldProxy != null) {
                proxy.setFileName(oldProxy.getFileName());
            }
        }

        Map<String,Entry> localEntries = newConfig.getDefinedEntries();
        for (String key : localEntries.keySet()) {
            Entry newEntry = localEntries.get(key);
            Entry oldEntry = currentConfig.getDefinedEntries().get(key);
            if (oldEntry != null) {
                newEntry.setFileName(oldEntry.getFileName());
            }
        }

        Collection<Startup> tasks = newConfig.getStartups();
        for (Startup task : tasks) {
            Startup oldTask = currentConfig.getStartup(task.getName());
            if (oldTask != null) {
                task.setFileName(oldTask.getFileName());
            }
        }

        Collection<SynapseEventSource> eventSources = newConfig.getEventSources();
        for (SynapseEventSource eventSource : eventSources) {
            SynapseEventSource oldEventSource = currentConfig.getEventSource(eventSource.getName());
            if (oldEventSource != null) {
                eventSource.setFileName(oldEventSource.getFileName());
            }
        }

        Collection<PriorityExecutor> executors = newConfig.getPriorityExecutors().values();
        for (PriorityExecutor exec : executors) {
            PriorityExecutor oldExec = currentConfig.getPriorityExecutors().get(exec.getName());
            if (oldExec != null) {
                exec.setFileName(oldExec.getFileName());
            }
        }

        Collection<MessageStore> messageStores = newConfig.getMessageStores().values();

        for(MessageStore store : messageStores) {
            MessageStore oldStore = currentConfig.getMessageStore(store.getName());
            if (oldStore != null) {
                store.setFileName(oldStore.getFileName());
            }
        }

        Collection<MessageProcessor> messageProcessors = newConfig.getMessageProcessors().values();

        for(MessageProcessor processor : messageProcessors) {
            MessageProcessor oldProcessor =
                    currentConfig.getMessageProcessors().get(processor.getName());
            if(oldProcessor != null) {
                processor.setFileName(oldProcessor.getFileName());
            }
        }

        Map<String, TemplateMediator> sequenceTemplates = newConfig.getSequenceTemplates();
        for (String name : sequenceTemplates.keySet()) {
            TemplateMediator oldSequenceTempl = currentConfig.getSequenceTemplates().get(name);
            if (oldSequenceTempl != null) {
                sequenceTemplates.get(name).setFileName(oldSequenceTempl.getFileName());
            }
        }

        Map<String, Template> endpointTemplates = newConfig.getEndpointTemplates();
        for (String name : endpointTemplates.keySet()) {
            Template oldEndpointTempl = currentConfig.getEndpointTemplates().get(name);
            if (oldEndpointTempl != null) {
                endpointTemplates.get(name).setFileName(oldEndpointTempl.getFileName());
            }
        }

        if (Boolean.valueOf(currentConfig.getProperty(
                MultiXMLConfigurationBuilder.SEPARATE_REGISTRY_DEFINITION))) {
            newConfig.getProperties().setProperty(
                    MultiXMLConfigurationBuilder.SEPARATE_REGISTRY_DEFINITION, "true");
        }
    }

    private void safeRemoveService(String serviceName) {
        AxisService service = axisCfg.getServiceForActivation(serviceName);
        if (service != null) {
            try {
                service.getParent().addParameter(CarbonConstants.KEEP_SERVICE_HISTORY_PARAM,
                            "true");
                axisCfg.removeService(serviceName);
            } catch (AxisFault axisFault) {
                handleException("Error while removing the service: " + serviceName, axisFault);
            }
        }
    }

    private void publishConfiguration(SynapseConfiguration synCfg, Axis2SynapseEnvironment synEnv) {

        int tenantId = SuperTenantCarbonContext.getCurrentContext(configurationContext).getTenantId();

        SynapseRegistrationsService registrationsService =
                ConfigHolder.getInstance().getSynapseRegistrationService(tenantId);

        if (registrationsService != null) {
            serverContextInformation.setSynapseConfiguration(synCfg);

            // populate the Synapse Configuration
            ServiceRegistration configRegistration =
                    registrationsService.getSynapseConfigurationServiceRegistration();
            SynapseConfigurationService synCfgSvc = (SynapseConfigurationService)
                    ConfigHolder.getInstance().getBundleContext().getService(
                            configRegistration.getReference());
            synCfgSvc.setSynapseConfiguration(synCfg);
            configRegistration.setProperties(new Properties());

            // populate the Synapse Environment
            ServiceRegistration synEnvSvcRegistration =
                    registrationsService.getSynapseEnvironmentServiceRegistration();
            SynapseEnvironmentService synEnvSvc = (SynapseEnvironmentService)
                    ConfigHolder.getInstance().getBundleContext().getService(
                            synEnvSvcRegistration.getReference());
            synEnvSvc.setSynapseEnvironment(synEnv);
            synEnvSvcRegistration.setProperties(new Properties());

            ConfigurationTrackingService trackingSvc = ConfigHolder.getInstance().
                    getSynapseConfigTrackingService();
            if (trackingSvc != null) {
                trackingSvc.setSynapseConfiguration(synCfg);
            }
        } else {
            String msg = "Couldn't find the OSGi service information about this " +
                    "ESB Configuration";
            log.error(msg);
            throw new ConfigAdminException(msg);
        }
    }

    private void handleException(String msg, Exception e) {
        log.error(msg, e);
        throw new ConfigAdminException(msg, e);
    }
}
TOP

Related Classes of org.wso2.carbon.mediation.configadmin.ConfigurationUpdater

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.