Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=50836
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Sun, 27 Feb 2011 11:00:12 +0000 (11:00 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Sun, 27 Feb 2011 11:00:12 +0000 (11:00 +0000)
Better documentation of the meaning of Lifecycle.isAvailable() and correct a couple of cases where this could incorrectly return true.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1075022 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/Lifecycle.java
java/org/apache/catalina/LifecycleListener.java
java/org/apache/catalina/LifecycleState.java
java/org/apache/catalina/util/LifecycleBase.java
webapps/docs/changelog.xml

index e141e6d..d1e3cde 100644 (file)
@@ -25,7 +25,8 @@ package org.apache.catalina;
  * the functionality they support) in order to provide a consistent mechanism
  * to start and stop the component.
  * <br>
- * The valid state transitions for components that support Lifecycle are:
+ * The valid state transitions for components that support {@link Lifecycle}
+ * are:
  * <pre>
  *    init()
  * NEW ->-- INITIALIZING
@@ -44,9 +45,11 @@ package org.apache.catalina;
  * |  |          |                                                             |
  * |  |         \|/            auto                 auto              start()  |
  * |  |     STOPPING_PREP ------>----- STOPPING ------>----- STOPPED ---->------
- * |  |          ^                                           |  |  ^
+ * |  |                                   ^                  |  |  ^
+ * |  |                  stop()           |                  |  |  |
+ * |  |          --------------------------                  |  |  |
  * |  |          |                                  auto     |  |  |
- * |  |          |stop()            MUST_DESTROY------<-------  |  |
+ * |  |          |                  MUST_DESTROY------<-------  |  |
  * |  |          |                    |                         |  |
  * |  |          |                    |auto                     |  |
  * |  |          |    destroy()      \|/              destroy() |  |
@@ -197,8 +200,8 @@ public interface Lifecycle {
 
 
     /**
-     * Get the lifecycle listeners associated with this lifecycle. If this 
-     * Lifecycle has no listeners registered, a zero-length array is returned.
+     * Get the life cycle listeners associated with this life cycle. If this 
+     * component has no listeners registered, a zero-length array is returned.
      */
     public LifecycleListener[] findLifecycleListeners();
 
@@ -226,10 +229,12 @@ public interface Lifecycle {
     public void init() throws LifecycleException;
 
     /**
-     * Prepare for the beginning of active use of the public methods of this
-     * component.  This method should be called before any of the public
-     * methods of this component are utilized. The following
-     * {@link LifecycleEvent}s will be fired in the following order:
+     * Prepare for the beginning of active use of the public methods other than
+     * property getters/setters and life cycle methods of this component. This
+     * method should be called before any of the public methods other than
+     * property getters/setters and life cycle methods of this component are
+     * utilized. The following {@link LifecycleEvent}s will be fired in the
+     * following order:
      * <ol>
      *   <li>BEFORE_START_EVENT: At the beginning of the method. It is as this
      *                           point the state transitions to
@@ -237,7 +242,9 @@ public interface Lifecycle {
      *   <li>START_EVENT: During the method once it is safe to call start() for
      *                    any child components. It is at this point that the
      *                    state transitions to {@link LifecycleState#STARTING}
-     *                    and that the public methods may be used.</li>
+     *                    and that the public methods other than property
+     *                    getters/setters and life cycle methods may be 
+     *                    used.</li>
      *   <li>AFTER_START_EVENT: At the end of the method, immediately before it
      *                          returns. It is at this point that the state
      *                          transitions to {@link LifecycleState#STARTED}.
@@ -251,10 +258,11 @@ public interface Lifecycle {
 
 
     /**
-     * Gracefully terminate the active use of the public methods of this
-     * component. Once the STOP_EVENT is fired, the public methods should not
-     * be used. The following {@link LifecycleEvent}s will be fired in the
-     * following order:
+     * Gracefully terminate the active use of the public methods other than
+     * property getters/setters and life cycle methods of this component. Once
+     * the STOP_EVENT is fired, the public methods other than property
+     * getters/setters and life cycle methods should not be used. The following
+     * {@link LifecycleEvent}s will be fired in the following order:
      * <ol>
      *   <li>BEFORE_STOP_EVENT: At the beginning of the method. It is at this
      *                          point that the state transitions to
@@ -262,13 +270,21 @@ public interface Lifecycle {
      *   <li>STOP_EVENT: During the method once it is safe to call stop() for
      *                   any child components. It is at this point that the
      *                   state transitions to {@link LifecycleState#STOPPING}
-     *                   and that the public methods may no longer be used.</li>
+     *                   and that the public methods other than property
+     *                   getters/setters and life cycle methods may no longer be
+     *                   used.</li>
      *   <li>AFTER_STOP_EVENT: At the end of the method, immediately before it
      *                         returns. It is at this point that the state
      *                         transitions to {@link LifecycleState#STOPPED}.
      *                         </li>
      * </ol>
      * 
+     * Note that if transitioning from {@link LifecycleState#FAILED} then the
+     * three events above will be fired but the component will transition
+     * directly from {@link LifecycleState#FAILED} to
+     * {@link LifecycleState#STOPPING}, bypassing
+     * {@link LifecycleState#STOPPING_PREP}
+     * 
      * @exception LifecycleException if this component detects a fatal error
      *  that needs to be reported
      */
index 741bf5b..4f75f04 100644 (file)
@@ -22,7 +22,8 @@ package org.apache.catalina;
 /**
  * Interface defining a listener for significant events (including "component
  * start" and "component stop" generated by a component that implements the
- * Lifecycle interface.
+ * Lifecycle interface. The listener will be fired after the associated state
+ * change has taken place.
  *
  * @author Craig R. McClanahan
  * @version $Id$
index 3ddd48d..46c80fc 100644 (file)
@@ -35,7 +35,7 @@ public enum LifecycleState {
     DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
     FAILED(false, null),
     MUST_STOP(true, null),
-    MUST_DESTROY(true, null);
+    MUST_DESTROY(false, null);
     
     private final boolean available;
     private final String lifecycleEvent;
@@ -46,7 +46,15 @@ public enum LifecycleState {
     }
     
     /**
-     * Is a component in this state available for use?
+     * May the public methods other than property getters/setters and lifecycle
+     * methods be called for a component in this state? It returns
+     * <code>true</code> for any component in any of the following states:
+     * <ul>
+     * <li>{@link #STARTING}</li>
+     * <li>{@link #STARTED}</li>
+     * <li>{@link #STOPPING_PREP}</li>
+     * <li>{@link #MUST_STOP}</li>
+     * </ul>
      */
     public boolean isAvailable() {
         return available;
index efdc593..66b6be2 100644 (file)
@@ -212,7 +212,14 @@ public abstract class LifecycleBase implements Lifecycle {
             invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
         }
         
-        setStateInternal(LifecycleState.STOPPING_PREP, null, false);
+        if (state.equals(LifecycleState.FAILED)) {
+            // Don't transition to STOPPING_PREP as that would briefly mark the
+            // component as available but do ensure the BEFORE_STOP_EVENT is
+            // fired
+            fireLifecycleEvent(BEFORE_STOP_EVENT, null);
+        } else {
+            setStateInternal(LifecycleState.STOPPING_PREP, null, false);
+        }
 
         try {
             stopInternal();
@@ -352,11 +359,14 @@ public abstract class LifecycleBase implements Lifecycle {
             
             // Any method can transition to failed
             // startInternal() permits STARTING_PREP to STARTING
-            // stopInternal() permits STOPPING_PREP to STOPPING
+            // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
+            // STOPPING
             if (!(state == LifecycleState.FAILED ||
                     (this.state == LifecycleState.STARTING_PREP &&
                             state == LifecycleState.STARTING) ||
                     (this.state == LifecycleState.STOPPING_PREP &&
+                            state == LifecycleState.STOPPING) ||
+                    (this.state == LifecycleState.FAILED &&
                             state == LifecycleState.STOPPING))) {
                 // No other transition permitted
                 invalidTransition(state.name());
index 250ef0f..b255c37 100644 (file)
         Ensure Servlet 2.2 jspFile elements are correctly converted to use a
         leading &apos;/&apos; if missing. (markt)
       </fix>
+      <fix>
+        <bug>50836</bug>: Better documentation of the meaning of
+        <code>Lifecycle.isAvailable()</code> and correct a couple of cases where
+        this could incorrectly return true. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">