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

org.mule.lifecycle.AbstractLifecycleManager Maven / Gradle / Ivy

There is a newer version: 3.9.0
Show newest version
/*
 * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */
package org.mule.lifecycle;

import org.mule.api.MuleContext;
import org.mule.api.lifecycle.Disposable;
import org.mule.api.lifecycle.Initialisable;
import org.mule.api.lifecycle.LifecycleCallback;
import org.mule.api.lifecycle.LifecycleException;
import org.mule.api.lifecycle.LifecycleManager;
import org.mule.api.lifecycle.LifecycleState;
import org.mule.api.lifecycle.Startable;
import org.mule.api.lifecycle.Stoppable;
import org.mule.lifecycle.phases.NotInLifecyclePhase;
import org.mule.transport.AbstractConnector;
import org.mule.transport.ConnectException;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This is a base implementation of the {@link org.mule.api.lifecycle.LifecycleManager} interface
 * and provides almost all the plumbing required to write a {@link org.mule.api.lifecycle.LifecycleManager}
 * implementation. This class handles the tracking ofg the phases, transition validation and
 * checking state.
 *
 * @param  The object type being managed by this {@link org.mule.api.lifecycle.LifecycleManager}
 * @since 3.0
 */
public abstract class AbstractLifecycleManager implements LifecycleManager
{
    /**
     * logger used by this class
     */
    protected transient final Log logger = LogFactory.getLog(AbstractLifecycleManager.class);

    protected String lifecycleManagerId;
    protected String currentPhase = NotInLifecyclePhase.PHASE_NAME;
    protected String executingPhase = null;
    private Set directTransitions = new HashSet();
    protected Set phaseNames = new LinkedHashSet(4);
    protected Set completedPhases = new LinkedHashSet(4);
    protected O object;
    protected LifecycleState state;

    private TreeMap callbacks = new TreeMap();

    public AbstractLifecycleManager(String id, O object)
    {
        lifecycleManagerId = id;
        this.object = object;
        state = createLifecycleState();

        currentPhase = NotInLifecyclePhase.PHASE_NAME;
        completedPhases.add(currentPhase);
        registerTransitions();
    }

    protected abstract void registerTransitions();

    public void registerLifecycleCallback(String phaseName, LifecycleCallback callback)
    {
        callbacks.put(phaseName, callback);
    }

    protected LifecycleState createLifecycleState()
    {
        return new DefaultLifecycleState(this);
    }

    protected void addDirectTransition(String phase1, String phase2)
    {
        directTransitions.add(phase1 + "-" + phase2);
        phaseNames.add(phase1);
        phaseNames.add(phase2);
    }

    public void checkPhase(String name) throws IllegalStateException
    {
        if (executingPhase != null)
        {
            if (name.equalsIgnoreCase(executingPhase))
            {
                throw new IllegalStateException("Phase '" + name + "' is already currently being executed");
            }
            else
            {
                throw new IllegalStateException("Cannot fire phase '" + name + "', currently executing lifecycle phase: " + executingPhase);
            }
        }

        if (name.equalsIgnoreCase(currentPhase))
        {
            throw new IllegalStateException("Already in lifecycle phase '" + name + "', cannot fire the same phase twice");
        }


        if (!phaseNames.contains(name))
        {
            throw new IllegalStateException("Phase does not exist: " + name);
        }
        else
        {
            if (isDirectTransition(name))
            {
                return;
            }

            throw new IllegalStateException("Lifecycle Manager '" + lifecycleManagerId + "' phase '" + currentPhase + "' does not support phase '" + name + "'");
        }
    }

    public O getLifecycleObject()
    {
        return object;
    }

    public void fireLifecycle(String phase) throws LifecycleException
    {
        checkPhase(phase);
        invokePhase(phase, object, callbacks.get(phase));
    }

    protected void invokePhase(String phase, Object object, LifecycleCallback callback) throws LifecycleException
    {
        try
        {
            setExecutingPhase(phase);
            callback.onTransition(phase, object);
            setCurrentPhase(phase);
        }
        // In the case of a connection exception, trigger the reconnection strategy.
        catch (ConnectException ce)
        {
            MuleContext muleContext = ((AbstractConnector) ce.getFailed()).getMuleContext();
            muleContext.getExceptionListener().handleException(ce);
        }
        catch (LifecycleException le)
        {
            throw le;
        }
        catch (Exception e)
        {
            throw new LifecycleException(e, object);
        }
        finally
        {
            setExecutingPhase(null);
        }

    }

    public boolean isDirectTransition(String destinationPhase)
    {
        return isDirectTransition(getCurrentPhase(), destinationPhase);
    }

    protected boolean isDirectTransition(String startPhase, String endPhase)
    {
        String key = startPhase + "-" + endPhase;
        return directTransitions.contains(key);
    }

    public String getCurrentPhase()
    {
        return currentPhase;
    }

    protected void setCurrentPhase(String currentPhase)
    {
        this.currentPhase = currentPhase;
        completedPhases.add(currentPhase);
        //remove irrelevant phases
        if (currentPhase.equals(Stoppable.PHASE_NAME))
        {
            completedPhases.remove(Startable.PHASE_NAME);
        }
        else  if (currentPhase.equals(Startable.PHASE_NAME))
        {
            completedPhases.remove(Stoppable.PHASE_NAME);
        }
        else if (currentPhase.equals(Disposable.PHASE_NAME))
        {
            completedPhases.remove(Initialisable.PHASE_NAME);
        }

        notifyTransition(currentPhase);

    }

    public String getExecutingPhase()
    {
        return executingPhase;
    }

    protected void setExecutingPhase(String executingPhase)
    {
        this.executingPhase = executingPhase;
    }

    /**
     * Allows any for any state adjustments in sub classes.  For example, it may be necessary to remove a
     * state from the 'completedPhases' collection once a transition occurs. This is only necessary for a Lifecycle
     * Manager that introduces a new phase pair.
     *
     * @param phase the currently completed phase
     */
    protected void notifyTransition(String phase)
    {
        //do nothing
    }

    public void reset()
    {
        completedPhases.clear();
        setExecutingPhase(null);
        setCurrentPhase(NOT_IN_LIFECYCLE_PHASE.getName());
        completedPhases.add(getCurrentPhase());
    }

    public boolean isPhaseComplete(String phaseName)
    {
        return completedPhases.contains(phaseName);
    }

    public LifecycleState getState()
    {
        return state;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy