Author: remy.maucherat(a)jboss.com
Date: 2009-10-19 07:28:13 -0400 (Mon, 19 Oct 2009)
New Revision: 1209
Modified:
trunk/java/org/apache/catalina/Context.java
trunk/java/org/apache/catalina/core/ApplicationContext.java
trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java
trunk/java/org/apache/catalina/core/LocalStrings.properties
trunk/java/org/apache/catalina/core/StandardContext.java
trunk/java/org/apache/catalina/core/StandardWrapper.java
trunk/java/org/apache/catalina/session/StandardSession.java
Log:
- Refactor Context.start. This may cause regressions.
- Now three listener structures: context, session and the rest. Custom session
implementations may need to be updated
to use the right array (in AS, CLusteredSession does need an update).
- Add more error conditions.
Modified: trunk/java/org/apache/catalina/Context.java
===================================================================
--- trunk/java/org/apache/catalina/Context.java 2009-10-19 00:54:10 UTC (rev 1208)
+++ trunk/java/org/apache/catalina/Context.java 2009-10-19 11:28:13 UTC (rev 1209)
@@ -160,6 +160,27 @@
/**
+ * Return the set of initialized application lifecycle listener objects,
+ * in the order they were specified in the web application deployment
+ * descriptor, for this application.
+ *
+ * @exception IllegalStateException if this method is called before
+ * this application has started, or after it has been stopped
+ */
+ public Object[] getApplicationSessionLifecycleListeners();
+
+
+ /**
+ * Store the set of initialized application lifecycle listener objects,
+ * in the order they were specified in the web application deployment
+ * descriptor, for this application.
+ *
+ * @param listeners The set of instantiated listener objects.
+ */
+ public void setApplicationSessionLifecycleListeners(Object listeners[]);
+
+
+ /**
* Return the application available flag for this Context.
*/
public boolean getAvailable();
Modified: trunk/java/org/apache/catalina/core/ApplicationContext.java
===================================================================
--- trunk/java/org/apache/catalina/core/ApplicationContext.java 2009-10-19 00:54:10 UTC
(rev 1208)
+++ trunk/java/org/apache/catalina/core/ApplicationContext.java 2009-10-19 11:28:13 UTC
(rev 1209)
@@ -900,7 +900,16 @@
if (context.findFilterDef(filterName) != null) {
return null;
}
- // FIXME: Filter instance unicity nonsense
+ // Filter instance unicity
+ for (Container container : context.getParent().findChildren()) {
+ if (container instanceof StandardContext) {
+ for (ApplicationFilterConfig filterConfig : ((StandardContext)
container).findApplicationFilterConfigs()) {
+ if (filterConfig.getFilterInstance() == filter) {
+ return null;
+ }
+ }
+ }
+ }
FilterDef filterDef = new FilterDef();
filterDef.setFilterName(filterName);
filterDef.setFilterClass(filter.getClass().getName());
@@ -958,7 +967,14 @@
if (context.findChild(servletName) != null) {
return null;
}
- // FIXME: Servlet instance unicity nonsense
+ // Servlet instance unicity
+ for (Container container : context.getParent().findChildren()) {
+ for (Container wrapper : container.findChildren()) {
+ if (((Wrapper) wrapper).getServlet() == servlet) {
+ return null;
+ }
+ }
+ }
Wrapper wrapper = context.createWrapper();
wrapper.setDynamic(true);
wrapper.setName(servletName);
@@ -1082,6 +1098,10 @@
if (restricted) {
throw new
UnsupportedOperationException(sm.getString("applicationContext.restricted"));
}
+ if (!context.isStarting()) {
+ throw new
IllegalStateException(sm.getString("applicationContext.alreadyInitialized",
+ getContextPath()));
+ }
mergeParameters();
if (parameters.get(name) != null) {
return false;
@@ -1097,8 +1117,7 @@
throw new
UnsupportedOperationException(sm.getString("applicationContext.restricted"));
}
if (!context.isStarting()) {
- throw new IllegalStateException(
- sm.getString("applicationContext.setSessionTracking.ise",
+ throw new
IllegalStateException(sm.getString("applicationContext.alreadyInitialized",
getContextPath()));
}
// Check that only supported tracking modes have been requested
@@ -1109,7 +1128,11 @@
sessionTrackingMode.toString(), getContextPath()));
}
}
- // TODO: Possible SSL tracking mode
+ // If SSL is specified, it should be the only one used
+ if (sessionTrackingModes.contains(SessionTrackingMode.SSL) &&
sessionTrackingModes.size() > 1) {
+ throw new IllegalArgumentException(sm.getString(
+ "applicationContext.setSessionTracking.ssl",
getContextPath()));
+ }
context.setSessionTrackingModes(sessionTrackingModes);
}
Modified: trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java
===================================================================
--- trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java 2009-10-19 00:54:10
UTC (rev 1208)
+++ trunk/java/org/apache/catalina/core/ApplicationFilterConfig.java 2009-10-19 11:28:13
UTC (rev 1209)
@@ -479,6 +479,14 @@
/**
+ * Return the filter instance.
+ */
+ public Filter getFilterInstance() {
+ return (filterInstance != null) ? filterInstance : filter;
+ }
+
+
+ /**
* Return the filter definition we are configured for.
*/
public FilterDef getFilterDef() {
Modified: trunk/java/org/apache/catalina/core/LocalStrings.properties
===================================================================
--- trunk/java/org/apache/catalina/core/LocalStrings.properties 2009-10-19 00:54:10 UTC
(rev 1208)
+++ trunk/java/org/apache/catalina/core/LocalStrings.properties 2009-10-19 11:28:13 UTC
(rev 1209)
@@ -22,8 +22,8 @@
applicationContext.requestDispatcher.iae=Path {0} does not start with a "/"
character
applicationContext.resourcePaths.iae=Path {0} does not start with a "/"
character
applicationContext.setAttribute.namenull=Name cannot be null
-applicationContext.setSessionTracking.ise=The session tracking modes for context {0}
cannot be set whilst the context is running
applicationContext.setSessionTracking.iae=The session tracking mode {0} requested for
context {1} is not supported by that context
+applicationContext.setSessionTracking.ssl=The session tracking mode SSL requested for
context {1} cannot be combined with other tracking modes
applicationContext.badListenerClass=Bad listener class {0} for context {1}
applicationDispatcher.allocateException=Allocate exception for servlet {0}
applicationDispatcher.deallocateException=Deallocate exception for servlet {0}
Modified: trunk/java/org/apache/catalina/core/StandardContext.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardContext.java 2009-10-19 00:54:10 UTC (rev
1208)
+++ trunk/java/org/apache/catalina/core/StandardContext.java 2009-10-19 11:28:13 UTC (rev
1209)
@@ -234,18 +234,28 @@
/**
* The set of instantiated application event listener objects</code>.
*/
- protected Object applicationEventListenersObjects[] =
- new Object[0];
+ protected Object applicationEventListenersInstances[] = null;
/**
* The set of instantiated application lifecycle listener objects</code>.
*/
- protected Object applicationLifecycleListenersObjects[] =
- new Object[0];
+ protected Object applicationLifecycleListenersInstances[] = null;
/**
+ * The set of instantiated application session lifecycle listener
objects</code>.
+ */
+ protected Object applicationSessionLifecycleListenersInstances[] = null;
+
+
+ /**
+ * The set of instantiated application lifecycle listener objects</code>.
+ */
+ protected Object otherListenersInstances[] = null;
+
+
+ /**
* The set of application parameters defined for this application.
*/
protected ApplicationParameter applicationParameters[] =
@@ -330,9 +340,8 @@
/**
* Session tracking modes.
*/
- // FIXME: see about SSL tracking mode
protected Set<SessionTrackingMode> defaultSessionTrackingModes =
- EnumSet.of(SessionTrackingMode.URL, SessionTrackingMode.COOKIE /*,
SessionTrackingMode.SSL*/);
+ EnumSet.of(SessionTrackingMode.URL, SessionTrackingMode.COOKIE /*TODO:,
SessionTrackingMode.SSL*/);
/**
@@ -944,7 +953,7 @@
* this application has started, or after it has been stopped
*/
public Object[] getApplicationEventListeners() {
- return (applicationEventListenersObjects);
+ return (applicationEventListenersInstances);
}
@@ -956,7 +965,7 @@
* @param listeners The set of instantiated listener objects.
*/
public void setApplicationEventListeners(Object listeners[]) {
- applicationEventListenersObjects = listeners;
+ applicationEventListenersInstances = listeners;
}
@@ -968,8 +977,33 @@
* @exception IllegalStateException if this method is called before
* this application has started, or after it has been stopped
*/
+ public Object[] getApplicationSessionLifecycleListeners() {
+ return (applicationSessionLifecycleListenersInstances);
+ }
+
+
+ /**
+ * Store the set of initialized application lifecycle listener objects,
+ * in the order they were specified in the web application deployment
+ * descriptor, for this application.
+ *
+ * @param listeners The set of instantiated listener objects.
+ */
+ public void setApplicationSessionLifecycleListeners(Object listeners[]) {
+ applicationSessionLifecycleListenersInstances = listeners;
+ }
+
+
+ /**
+ * Return the set of initialized application lifecycle listener objects,
+ * in the order they were specified in the web application deployment
+ * descriptor, for this application.
+ *
+ * @exception IllegalStateException if this method is called before
+ * this application has started, or after it has been stopped
+ */
public Object[] getApplicationLifecycleListeners() {
- return (applicationLifecycleListenersObjects);
+ return (applicationLifecycleListenersInstances);
}
@@ -981,7 +1015,7 @@
* @param listeners The set of instantiated listener objects.
*/
public void setApplicationLifecycleListeners(Object listeners[]) {
- applicationLifecycleListenersObjects = listeners;
+ applicationLifecycleListenersInstances = listeners;
}
@@ -3818,8 +3852,10 @@
* Configure the set of instantiated application event listeners
* for this Context. Return <code>true</code> if all listeners wre
* initialized successfully, or <code>false</code> otherwise.
+ * Only context listeners are actually set in stone at this point,
+ * all others are stored in a temporary location.
*/
- public boolean listenerStart() {
+ public boolean contextListenerStart() {
if (log.isDebugEnabled())
log.debug("Configuring application event listeners");
@@ -3845,29 +3881,25 @@
for (int i = 0; i < listenerInstances.length; i++) {
results[i + listeners.length] = listenerInstances[i];
}
+ applicationListenerInstances = new EventListener[0];
if (!ok) {
getLogger().error(sm.getString("standardContext.applicationSkipped"));
return (false);
}
// Sort listeners in two arrays
- ArrayList<EventListener> eventListeners = new
ArrayList<EventListener>();
- ArrayList<EventListener> lifecycleListeners = new
ArrayList<EventListener>();
+ ArrayList<EventListener> otherListeners = new
ArrayList<EventListener>();
+ ArrayList<EventListener> contextLifecycleListeners = new
ArrayList<EventListener>();
for (int i = 0; i < results.length; i++) {
- if ((results[i] instanceof ServletContextAttributeListener)
- || (results[i] instanceof ServletRequestAttributeListener)
- || (results[i] instanceof ServletRequestListener)
- || (results[i] instanceof HttpSessionAttributeListener)) {
- eventListeners.add(results[i]);
+ if (results[i] instanceof ServletContextListener) {
+ contextLifecycleListeners.add(results[i]);
+ } else {
+ otherListeners.add(results[i]);
}
- if ((results[i] instanceof ServletContextListener)
- || (results[i] instanceof HttpSessionListener)) {
- lifecycleListeners.add(results[i]);
- }
}
- setApplicationEventListeners(eventListeners.toArray());
- setApplicationLifecycleListeners(lifecycleListeners.toArray());
+ this.otherListenersInstances = otherListeners.toArray();
+ setApplicationLifecycleListeners(contextLifecycleListeners.toArray());
// Send application start events
@@ -3907,6 +3939,66 @@
/**
+ * Configure the set of instantiated application event listeners
+ * for this Context. Return <code>true</code> if all listeners wre
+ * initialized successfully, or <code>false</code> otherwise.
+ */
+ public boolean listenerStart() {
+
+ if (log.isDebugEnabled())
+ log.debug("Configuring application event listeners");
+
+ // Instantiate the required listeners
+ Object listeners[] = otherListenersInstances;
+ otherListenersInstances = null;
+ EventListener listenerInstances[] = applicationListenerInstances;
+ EventListener results[] = new EventListener[listeners.length +
listenerInstances.length];
+ boolean ok = true;
+ for (int i = 0; i < listeners.length; i++) {
+ if (getLogger().isDebugEnabled())
+ getLogger().debug(" Configuring event listener class '" +
+ listeners[i] + "'");
+ try {
+ results[i] = (EventListener) listeners[i];
+ } catch (Throwable t) {
+ getLogger().error
+ (sm.getString("standardContext.applicationListener",
+ listeners[i]), t);
+ ok = false;
+ }
+ }
+ for (int i = 0; i < listenerInstances.length; i++) {
+ results[i + listeners.length] = listenerInstances[i];
+ }
+ if (!ok) {
+
getLogger().error(sm.getString("standardContext.applicationSkipped"));
+ return (false);
+ }
+
+ // Sort listeners in two arrays
+ ArrayList<EventListener> eventListeners = new
ArrayList<EventListener>();
+ ArrayList<EventListener> sessionLifecycleListeners = new
ArrayList<EventListener>();
+ for (int i = 0; i < results.length; i++) {
+ if ((results[i] instanceof ServletContextAttributeListener)
+ || (results[i] instanceof ServletRequestAttributeListener)
+ || (results[i] instanceof ServletRequestListener)
+ || (results[i] instanceof HttpSessionAttributeListener)) {
+ eventListeners.add(results[i]);
+ }
+ if (results[i] instanceof HttpSessionListener) {
+ sessionLifecycleListeners.add(results[i]);
+ }
+ }
+
+ setApplicationEventListeners(eventListeners.toArray());
+ setApplicationSessionLifecycleListeners(sessionLifecycleListeners.toArray());
+
+ return (ok);
+
+ }
+
+
+ /**
* Send an application stop event to all interested listeners.
* Return <code>true</code> if all events were sent successfully,
* or <code>false</code> otherwise.
@@ -3951,6 +4043,23 @@
}
// Annotation processing
+ listeners = getApplicationSessionLifecycleListeners();
+ if (listeners != null && (listeners.length > 0)) {
+ for (int i = listeners.length - 1; i >= 0; i--) {
+ if (listeners[i] == null)
+ continue;
+ try {
+ getInstanceManager().destroyInstance(listeners[i]);
+ } catch (Throwable t) {
+ getLogger().error
+ (sm.getString("standardContext.listenerStop",
+ listeners[i].getClass().getName()), t);
+ ok = false;
+ }
+ }
+ }
+
+ // Annotation processing
listeners = getApplicationEventListeners();
if (listeners != null && (listeners.length > 0)) {
for (int i = listeners.length - 1; i >= 0; i--) {
@@ -3969,6 +4078,7 @@
setApplicationEventListeners(null);
setApplicationLifecycleListeners(null);
+ setApplicationSessionLifecycleListeners(null);
return (ok);
@@ -4362,25 +4472,14 @@
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
- // FIXME: listener start order is wrong: context listeners should be started
there,
- // but all others should be after complete config
// Configure and call application event listeners
if (ok) {
- if (!listenerStart()) {
+ if (!contextListenerStart()) {
log.error( "Error listenerStart");
ok = false;
}
}
- if (ok) {
- // Notify our interested LifecycleListeners
- lifecycle.fireLifecycleEvent(COMPLETE_CONFIG_EVENT, null);
- }
-
- if (!getConfigured()) {
- ok = false;
- }
-
// Start manager
if (ok && (manager != null) && (manager instanceof
Lifecycle)) {
ok = false;
@@ -4388,11 +4487,6 @@
ok = true;
}
- // Start ContainerBackgroundProcessor thread
- if (ok) {
- super.threadStart();
- }
-
// Configure and call application filters
if (ok) {
if (!filterStart()) {
@@ -4406,6 +4500,27 @@
loadOnStartup(findChildren());
}
+ if (ok) {
+ if (!listenerStart()) {
+ log.error( "Error listenerStart");
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ // Notify our interested LifecycleListeners
+ lifecycle.fireLifecycleEvent(COMPLETE_CONFIG_EVENT, null);
+ }
+
+ if (!getConfigured()) {
+ ok = false;
+ }
+
+ // Start ContainerBackgroundProcessor thread
+ if (ok) {
+ super.threadStart();
+ }
+
} catch (Throwable t) {
// This can happen in rare cases with custom components
ok = false;
@@ -4653,8 +4768,10 @@
distributable = false;
applicationListeners = new String[0];
- applicationEventListenersObjects = new Object[0];
- applicationLifecycleListenersObjects = new Object[0];
+ applicationEventListenersInstances = null;
+ applicationLifecycleListenersInstances = null;
+ applicationSessionLifecycleListenersInstances = null;
+ otherListenersInstances = null;
instanceManager = null;
authenticator = null;
Modified: trunk/java/org/apache/catalina/core/StandardWrapper.java
===================================================================
--- trunk/java/org/apache/catalina/core/StandardWrapper.java 2009-10-19 00:54:10 UTC (rev
1208)
+++ trunk/java/org/apache/catalina/core/StandardWrapper.java 2009-10-19 11:28:13 UTC (rev
1209)
@@ -949,7 +949,7 @@
* Return the associated servlet instance.
*/
public Servlet getServlet() {
- return instance;
+ return (servletInstance != null) ? servletInstance : instance;
}
Modified: trunk/java/org/apache/catalina/session/StandardSession.java
===================================================================
--- trunk/java/org/apache/catalina/session/StandardSession.java 2009-10-19 00:54:10 UTC
(rev 1208)
+++ trunk/java/org/apache/catalina/session/StandardSession.java 2009-10-19 11:28:13 UTC
(rev 1209)
@@ -354,7 +354,7 @@
// Notify interested application event listeners
Context context = (Context) manager.getContainer();
- Object listeners[] = context.getApplicationLifecycleListeners();
+ Object listeners[] = context.getApplicationSessionLifecycleListeners();
if (listeners != null) {
HttpSessionEvent event =
new HttpSessionEvent(getSession());
@@ -674,7 +674,7 @@
// Notify interested application event listeners
Context context = (Context) manager.getContainer();
- Object listeners[] = context.getApplicationLifecycleListeners();
+ Object listeners[] = context.getApplicationSessionLifecycleListeners();
if (notify && listeners != null && (listeners.length > 0))
{
HttpSessionEvent event =
new HttpSessionEvent(getSession());