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

org.apache.catalina.util.LifecycleBase Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.apache.catalina.util;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.LifecycleState;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;


/**
 * Base implementation of the {@link Lifecycle} interface that implements the
 * state transition rules for {@link Lifecycle#start()} and
 * {@link Lifecycle#stop()}
 */
public abstract class LifecycleBase implements Lifecycle {

    private static Log log = LogFactory.getLog(LifecycleBase.class);
    
    private static StringManager sm =
        StringManager.getManager("org.apache.catalina.util");


    /**
     * Used to handle firing lifecycle events.
     * TODO: Consider merging LifecycleSupport into this class.
     */
    private LifecycleSupport lifecycle = new LifecycleSupport(this);


    /**
     * The current state of the source component.
     */
    private volatile LifecycleState state = LifecycleState.NEW;


    /**
     * {@inheritDoc}
     */
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }

    
    /**
     * Allow sub classes to fire {@link Lifecycle} events.
     * 
     * @param type  Event type
     * @param data  Data associated with event.
     */
    protected void fireLifecycleEvent(String type, Object data) {
        lifecycle.fireLifecycleEvent(type, data);
    }

    
    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        setState(LifecycleState.INITIALIZING);

        try {
            initInternal();
        } catch (LifecycleException e) {
            setState(LifecycleState.FAILED);
            throw e;
        }

        setState(LifecycleState.INITIALIZED);
    }
    
    
    protected abstract void initInternal() throws LifecycleException;
    
    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized void start() throws LifecycleException {
        
        if (LifecycleState.STARTING_PREP.equals(state) ||
                LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
            
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted",
                        toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted",
                        toString()));
            }
            
            return;
        }
        
        if (state.equals(LifecycleState.NEW)) {
            init();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }

        setState(LifecycleState.STARTING_PREP);

        try {
            startInternal();
        } catch (LifecycleException e) {
            setState(LifecycleState.FAILED);
            throw e;
        }

        if (state.equals(LifecycleState.FAILED) ||
                state.equals(LifecycleState.MUST_STOP)) {
            stop();
        } else {
            // Shouldn't be necessary but acts as a check that sub-classes are
            // doing what they are supposed to.
            if (!state.equals(LifecycleState.STARTING)) {
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            }
            
            setState(LifecycleState.STARTED);
        }
    }


    /**
     * Sub-classes must ensure that:
     * 
    *
  • the {@link Lifecycle#START_EVENT} is fired during the execution of * this method
  • *
  • the state is changed to {@link LifecycleState#STARTING} when the * {@link Lifecycle#START_EVENT} is fired *
* * If a component fails to start it may either throw a * {@link LifecycleException} which will cause it's parent to fail to start * or it can place itself in the error state in which case {@link #stop()} * will be called on the failed component but the parent component will * continue to start normally. * * @throws LifecycleException */ protected abstract void startInternal() throws LifecycleException; /** * {@inheritDoc} */ @Override public final synchronized void stop() throws LifecycleException { if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStopped", toString())); } return; } if (state.equals(LifecycleState.NEW)) { state = LifecycleState.STOPPED; return; } if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED) && !state.equals(LifecycleState.MUST_STOP)) { invalidTransition(Lifecycle.BEFORE_STOP_EVENT); } setState(LifecycleState.STOPPING_PREP); try { stopInternal(); } catch (LifecycleException e) { setState(LifecycleState.FAILED); throw e; } if (state.equals(LifecycleState.MUST_DESTROY)) { // Complete stop process first setState(LifecycleState.STOPPED); destroy(); } else { // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. if (!state.equals(LifecycleState.STOPPING)) { invalidTransition(Lifecycle.AFTER_STOP_EVENT); } setState(LifecycleState.STOPPED); } } /** * Sub-classes must ensure that: *
    *
  • the {@link Lifecycle#STOP_EVENT} is fired during the execution of * this method
  • *
  • the state is changed to {@link LifecycleState#STOPPING} when the * {@link Lifecycle#STOP_EVENT} is fired *
* * @throws LifecycleException */ protected abstract void stopInternal() throws LifecycleException; @Override public final synchronized void destroy() throws LifecycleException { if (LifecycleState.DESTROYING.equals(state) || LifecycleState.DESTROYED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString())); } return; } if (!state.equals(LifecycleState.STOPPED) && !state.equals(LifecycleState.FAILED) && !state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT); } setState(LifecycleState.DESTROYING); try { destroyInternal(); } catch (LifecycleException e) { setState(LifecycleState.FAILED); throw e; } setState(LifecycleState.DESTROYED); } protected abstract void destroyInternal() throws LifecycleException; /** * {@inheritDoc} */ @Override public LifecycleState getState() { return state; } /** * {@inheritDoc} */ @Override public String getStateName() { return getState().toString(); } /** * Provides a mechanism for sub-classes to update the component state. * Calling this method will automatically fire any associated * {@link Lifecycle} event. * * @param state The new state for this component */ protected synchronized void setState(LifecycleState state) { setState(state, null); } /** * Provides a mechanism for sub-classes to update the component state. * Calling this method will automatically fire any associated * {@link Lifecycle} event. * * @param state The new state for this component * @param data The data to pass to the associated {@link Lifecycle} event */ protected synchronized void setState(LifecycleState state, Object data) { if (log.isDebugEnabled()) { log.debug(sm.getString("lifecycleBase.setState", this, state)); } this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } } private void invalidTransition(String type) throws LifecycleException { String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state); throw new LifecycleException(msg); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy