All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.petals.microkernel.container.lifecycle.ServiceAssemblyLifeCycleImpl Maven / Gradle / Ivy

There is a newer version: 4.3.0
Show newest version
/**
 * Copyright (c) 2005-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.container.lifecycle;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.jbi.JBIException;
import javax.jbi.management.DeploymentServiceMBean;

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.annotations.Requires;
import org.objectweb.fractal.fraclet.types.Step;
import org.ow2.petals.jbi.descriptor.original.generated.ServiceAssembly;
import org.ow2.petals.microkernel.api.container.IsolatingThread;
import org.ow2.petals.microkernel.api.container.ServiceAssemblyLifeCycle;
import org.ow2.petals.microkernel.api.container.ServiceUnitLifeCycle;
import org.ow2.petals.microkernel.api.system.SystemStateService;
import org.ow2.petals.microkernel.jbi.management.util.ManagementMessageUtil;

import com.ebmwebsourcing.easycommons.lang.ExceptionHelper;
import com.ebmwebsourcing.easycommons.log.LoggingUtil;

/**
 * This class manages the life cycle of deployed service assemblies.
 * 
 * The synchonisation and ordering of lifecycle actions is managed using synchronization on this and all the actual
 * actions are done on the service units which relies on the component {@link IsolatingThread}.
 * 
 * @author Olivier Fabre - EBM WebSourcing
 * @author ddesjardins - EBM WebSourcing
 * @author vnoel
 */
@Component(provides = @Interface(name = ServiceAssemblyLifeCycle.FRACTAL_SRV_ITF_NAME, signature = ServiceAssemblyLifeCycle.class))
public class ServiceAssemblyLifeCycleImpl implements ServiceAssemblyLifeCycle {

    private final LoggingUtil log = new LoggingUtil(Logger.getLogger(ServiceAssemblyLifeCycle.COMPONENT_LOGGER_NAME));

    private String name;

    private String state;

    /**
     * Platform component :: SystemState Service
     */
    @Requires(name = "systemstate")
    private SystemStateService systemState;

    /**
     * The SA JBI descriptor
     */
    private ServiceAssembly serviceAssembly;

    /**
     * List of SU life-cycles
     * 
     * We use a LinkedHashMap to preserve insert ordering and make it synchronized to avoid concurrency problems
     */
    private final Map serviceUnitsLifeCycles = Collections
            .synchronizedMap(new LinkedHashMap());

    private boolean firstStart = true;

    @Override
    public void init(ServiceAssembly serviceAssembly) throws JBIException {
        this.serviceAssembly = serviceAssembly;
        this.name = serviceAssembly.getIdentification().getName();

        // set the state to SHUTDOWN, as the JBI specifications specifies
        this.setState(DeploymentServiceMBean.SHUTDOWN);
    }

    @Override
    public synchronized List init() throws JBIException {
        final List results = new ArrayList<>();
        if (isShutdownState()) {
            doInit(results);
            setState(DeploymentServiceMBean.STOPPED);
        }
        return results;
    }

    private void doInit(final List results) throws JBIException {
        boolean allFailed = true;
        final List exceptions = new ArrayList<>();
        for (final ServiceUnitLifeCycle suLifeCycle : serviceUnitsLifeCycles.values()) {
            try {
                // it is only executed if the SU is shutdown
                suLifeCycle.init();
                results.add(ManagementMessageUtil.getComponentTaskResult(
                        suLifeCycle.getTargetComponentName(), "init", ManagementMessageUtil.TASK_RESULT_SUCCESS));
                allFailed = false;
            } catch (final Exception e) {
                exceptions.add(e);
                results.add(ManagementMessageUtil.getComponentTaskResult(
                        suLifeCycle.getTargetComponentName(), "init", ManagementMessageUtil.TASK_RESULT_FAILED,
                        ManagementMessageUtil.MESSAGE_TYPE_ERROR, "2", "Failed to initialise SU: {1}",
                        new String[] { suLifeCycle.getSuName() }, ExceptionHelper.getStackTrace(e)));
                this.log.error(
                        String.format("The initialization of service unit '%s' fails.", suLifeCycle.getSuName()), e);
            }
        }

        // if exceptions is empty, it means there was nothing executed!
        if (allFailed && !exceptions.isEmpty()) {
            final JBIException ex = new JBIException("SA start failed");
            for (final Exception e : exceptions) {
                ex.addSuppressed(e);
            }
            throw ex;
        }
    }

    @Override
    public synchronized void shutDown() throws JBIException {
        if (isStartedState()) {
            doStop();
            setState(DeploymentServiceMBean.STOPPED);
        }
        if (isStoppedState()) {
            doShutdown();
            setState(DeploymentServiceMBean.SHUTDOWN);
        }
    }

    public void doShutdown() {
        final List reversedSuLifeCycles = new ArrayList(
                serviceUnitsLifeCycles.values());
        Collections.reverse(reversedSuLifeCycles);

        for (final ServiceUnitLifeCycle suLifeCycle : reversedSuLifeCycles) {
            try {
                suLifeCycle.shutDown();
            } catch (final Exception e) {
                this.log.error(String.format("The shutdown of service unit '%s' fails.", suLifeCycle.getSuName()), e);
            }
        }
    }

    @Override
    public synchronized List start() throws JBIException {
        final List results = new ArrayList<>();
        // note: do start calls init by itself
        if (isShutdownState() || isStoppedState()) {
            doStart(results);
            setState(DeploymentServiceMBean.STARTED);
        }
        return results;
    }

    private void doStart(final List results) throws JBIException {
        // The JBI specifications force to initialize ALL the SUs of the SA before all starting them
        doInit(results);

        boolean allFailed = true;
        final List exceptions = new ArrayList<>();
        for (final ServiceUnitLifeCycle suLifeCycle : serviceUnitsLifeCycles.values()) {
            try {
                // it is only executed if the SU is stopped!
                suLifeCycle.start();
                results.add(ManagementMessageUtil.getComponentTaskResult(
                        suLifeCycle.getTargetComponentName(), "start", ManagementMessageUtil.TASK_RESULT_SUCCESS));
                allFailed = false;
            } catch (final Exception e) {
                exceptions.add(e);
                results.add(
                        ManagementMessageUtil.getComponentTaskResult(suLifeCycle.getTargetComponentName(), "start",
                        ManagementMessageUtil.TASK_RESULT_FAILED, ManagementMessageUtil.MESSAGE_TYPE_ERROR, "2",
                        "Failed to start SU: {1}", new String[] { suLifeCycle.getSuName() },
                                ExceptionHelper.getStackTrace(e)));
                this.log.error(String.format("The start-up of service unit '%s' fails.", suLifeCycle.getSuName()), e);
            }
        }

        // if exceptions is empty, it means there was nothing executed!
        if (allFailed && !exceptions.isEmpty()) {
            final JBIException ex = new JBIException("SA start failed");
            for (final Exception e : exceptions) {
                ex.addSuppressed(e);
            }
            throw ex;
        }
    }

    @Override
    public synchronized void stop() throws JBIException {
        if (isStartedState()) {
            doStop();
            setState(DeploymentServiceMBean.STOPPED);
        }
    }

    private void doStop() {
        final List reversedSuLifeCycles = new ArrayList(
                serviceUnitsLifeCycles.values());
        Collections.reverse(reversedSuLifeCycles);
        for (final ServiceUnitLifeCycle suLifeCycle : reversedSuLifeCycles) {
            try {
                suLifeCycle.stop();
            } catch (final Exception e) {
                this.log.error(String.format("The stop of service unit '%s' fails.", suLifeCycle.getSuName()), e);
            }
        }
    }

    @Override
    public ServiceAssembly getServiceAssembly() {
        return this.serviceAssembly;
    }

    @Override
    public Collection getServiceUnitLifeCycles() {
        return Collections.unmodifiableCollection(this.serviceUnitsLifeCycles.values());
    }

    @Override
    public void registerSU(final ServiceUnitLifeCycle serviceUnitLifeCycle) throws JBIException {
        final String suName = serviceUnitLifeCycle.getSuName();
        if (this.serviceUnitsLifeCycles.containsKey(suName)) {
            throw new JBIException("Duplicate service unit: same name (" + suName + ")");
        }
        this.serviceUnitsLifeCycles.put(suName, serviceUnitLifeCycle);
    }

    @Override
    public void unregisterSU(final ServiceUnitLifeCycle serviceUnitLifeCycle) {
        this.serviceUnitsLifeCycles.remove(serviceUnitLifeCycle.getSuName());
    }

    @Override
    public String getCurrentState() {
        return this.state;
    }

    public boolean isShutdownState() {
        return DeploymentServiceMBean.SHUTDOWN.equals(this.getCurrentState());
    }

    public boolean isStartedState() {
        return DeploymentServiceMBean.STARTED.equals(this.getCurrentState());
    }

    public boolean isStoppedState() {
        return DeploymentServiceMBean.STOPPED.equals(this.getCurrentState());
    }

    private void setState(final String state) throws JBIException {
        if (!(DeploymentServiceMBean.SHUTDOWN.equals(state) || DeploymentServiceMBean.STARTED.equals(state)
                || DeploymentServiceMBean.STOPPED.equals(state))) {
            throw new JBIException(
                    "State '" + state + "' isn't defined by the JBI specification. No state changement done.");
        }

        this.state = state;

        try {
            this.systemState.updateServiceAssemblyState(this.name, state);
        } catch (final Exception e) {
            throw new JBIException("Failed to persist the state of the Service Assembly '" + this.name + "'", e);
        }
    }

    @Lifecycle(step = Step.START)
    public void startFractalComponent() throws JBIException {
        this.log.call();

        if (!firstStart) {
            // the first start is handled by init
            // Note: this method is never really called after stopFractalComponent has been called,
            // but the following is present for coherence: this is NOT related to restoration (for restoration, init and
            // start are called as needed by the restoration subsystem)
            final List results = new ArrayList<>();
            if (isStartedState()) {
                this.doStart(results);
            } else if (isStoppedState()) {
                this.doInit(results);
            }

            if (this.log.isInfoEnabled()) {
                this.log.info("started service assembly lifecycle for " + this.name + ": " + results);
            }
        } else {
            firstStart = false;
        }
    }

    /**
     * Stop of the petals component
     * 
     */
    @Lifecycle(step = Step.STOP)
    public void stopFractalComponent() {
        this.log.start();

        if (isStartedState()) {
            this.doStop();
            this.doShutdown();
        }

        if (isStoppedState()) {
            this.doShutdown();
        }

        this.log.end();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy