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: [email protected]
For additional commands, e-mail: [email protected]