Author: markt
Date: Thu Mar  4 18:07:59 2010
New Revision: 919102

URL: http://svn.apache.org/viewvc?rev=919102&view=rev
Log:
Lifecycle refactoring.
In an effort to reduce code duplication and improve consistency, provide a base 
Lifecycle implementation. This will be used as the basis of the refactoring of 
the components that implement Lifecycle
Added:
    tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java
Modified:
    tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties

Added: tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java?rev=919102&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java (added)
+++ tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java Thu Mar  4 
18:07:59 2010
@@ -0,0 +1,260 @@
+/*
+ * 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);
+    }
+
+    
+    /**
+     * {...@inheritdoc}
+     */
+    @Override
+    public final void start() throws LifecycleException {
+        
+        synchronized (this) {
+            if(LifecycleState.STARTING_PREP.equals(state) ||
+                    LifecycleState.STARTING.equals(state) ||
+                    LifecycleState.STARTED.equals(state)) {
+                
+                if(log.isInfoEnabled()) {
+                    log.info(sm.getString("lifecycleBase.alreadyStarted",
+                            toString()));
+                }
+                
+                return;
+            }
+            
+            if (!state.equals(LifecycleState.NEW) &&
+                    !state.equals(LifecycleState.STOPPED)) {
+                invalidTransition(Lifecycle.BEFORE_START_EVENT);
+            }
+
+            // Set state and fire event separately rather than via setState()
+            // so event fires outside of sync boundary
+            state = LifecycleState.STARTING_PREP;
+        }
+        
+        lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);
+
+        startInternal();
+
+        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:
+     * <ul>
+     * <li>the {...@link Lifecycle#START_EVENT} is fired during the execution 
of
+     *     this method</li>
+     * <li>the state is changed to {...@link LifecycleState#STARTING} when the
+     *     {...@link Lifecycle#START_EVENT} is fired
+     * </ul>
+     * 
+     * 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 void stop() throws LifecycleException {
+
+        synchronized (this) {
+            if(LifecycleState.STOPPING_PREP.equals(state) ||
+                    LifecycleState.STOPPING.equals(state) ||
+                    LifecycleState.STOPPED.equals(state)) {
+    
+                if(log.isInfoEnabled()) {
+                    log.info(sm.getString("lifecycleBase.alreadyStopped",
+                            toString()));
+                }
+                
+                return;
+            }
+            
+            if (!state.equals(LifecycleState.STARTED) &&
+                    !state.equals(LifecycleState.FAILED)) {
+                invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
+            }
+            
+            // Set state and fire event separately rather than via setState()
+            // so event fires outside of sync boundary
+            state = LifecycleState.STOPPING_PREP;
+        }
+        
+        lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_STOP_EVENT, null);
+
+        stopInternal();
+
+        // 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:
+     * <ul>
+     * <li>the {...@link Lifecycle#STOP_EVENT} is fired during the execution of
+     *     this method</li>
+     * <li>the state is changed to {...@link LifecycleState#STOPPING} when the
+     *     {...@link Lifecycle#STOP_EVENT} is fired
+     * </ul>
+     * 
+     * @throws LifecycleException
+     */
+    protected abstract void stopInternal() throws LifecycleException;
+
+
+    /**
+     * {...@inheritdoc}
+     */
+    public LifecycleState getState() {
+        return state;
+    }
+
+
+    /**
+     * 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 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 void setState(LifecycleState state, Object data) {
+        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);
+    }
+}

Modified: tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties?rev=919102&r1=919101&r2=919102&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties Thu Mar  
4 18:07:59 2010
@@ -19,9 +19,12 @@
 hexUtil.odd=Odd number of hexadecimal digits
 #Default Messages Utilized by the ExtensionValidator
 extensionValidator.web-application-manifest=Web Application Manifest
-extensionValidator.extension-not-found-error=ExtensionValidator[{0}][{1}]: 
Required extension "{2}" not found.
-extensionValidator.extension-validation-error=ExtensionValidator[{0}]: Failure 
to find {1} required extension(s).
-extensionValidator.failload=Failure loading extension {0}
+extensionValidator.extension-not-found-error=ExtensionValidator[{0}][{1}]: 
Required extension [{2}] not found.
+extensionValidator.extension-validation-error=ExtensionValidator[{0}]: Failure 
to find [{1}] required extension(s).
+extensionValidator.failload=Failure loading extension [{0}]
+lifecycleBase.alreadyStarted=The start() method was called on component [{0}] 
after start() had already been called. The second call will be ignored.
+lifecycleBase.alreadyStopped=The stop() method was called on component [{0}] 
after stop() had already been called. The second call will be ignored.
+lifecycleBase.invalidTransition=An invalid Lifecycle transition was attempted 
([{0}]) for component [{1}] in state [{2}]
 requestUtil.convertHexDigit.notHex=[{0}] is not a hexadecimal digit
 requestUtil.parseParameters.uee=Unable to parse the parameters since the 
encoding [{0}] is not supported.
 requestUtil.urlDecode.missingDigit=The % character must be followed by two 
hexademical digits



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to