struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From craig...@apache.org
Subject svn commit: r405360 - in /struts/shale/trunk/core-library/src: conf/ java/org/apache/shale/view/ java/org/apache/shale/view/faces/ test/org/apache/shale/view/
Date Tue, 09 May 2006 09:39:21 GMT
Author: craigmcc
Date: Tue May  9 02:39:17 2006
New Revision: 405360

URL: http://svn.apache.org/viewcvs?rev=405360&view=rev
Log:
Implement init and destroy event callbacks for arbitrary request, session, and
application scope beans that extend a corresponding base class.  These events
are fired when the corresponding beans are added to, or removed from, the
specified scope.

JIRA Issue:  SHALE-137

This integration also includes partial support for queuing exceptions in
preparation for completion of SHALE-125 but does not rethrow them yet.

Added:
    struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractApplicationBean.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractRequestBean.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractSessionBean.java
    struts/shale/trunk/core-library/src/java/org/apache/shale/view/faces/LifecycleListener.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractApplicationBeanTestCase.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractRequestBeanTestCase.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractSessionBeanTestCase.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/ApplicationAttributeListener.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteApplicationBean.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteRequestBean.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteSessionBean.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/RequestAttributeListener.java
    struts/shale/trunk/core-library/src/test/org/apache/shale/view/SessionAttributeListener.java
Modified:
    struts/shale/trunk/core-library/src/conf/taglib.tld
    struts/shale/trunk/core-library/src/java/org/apache/shale/view/Constants.java

Modified: struts/shale/trunk/core-library/src/conf/taglib.tld
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/conf/taglib.tld?rev=405360&r1=405359&r2=405360&view=diff
==============================================================================
--- struts/shale/trunk/core-library/src/conf/taglib.tld (original)
+++ struts/shale/trunk/core-library/src/conf/taglib.tld Tue May  9 02:39:17 2006
@@ -34,6 +34,14 @@
   </description>
 
 
+  <!-- ===================== Servlet Listeners ============================= -->
+
+
+  <listener>
+    <listener-class>org.apache.shale.view.faces.LifecycleListener</listener-class>
+  </listener>
+  
+
   <!-- ================= JSF Component Tags ================================ -->
 
 

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractApplicationBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractApplicationBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractApplicationBean.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractApplicationBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import java.util.Locale;
+
+/**
+ * <p><strong>AbstractApplicationBean</strong> is the abstract base class for
+ * data bean(s) that are stored in application scope attributes.  It extends
+ * {@link AbstractFacesBean}, so it inherits all of the default behavior
+ * found there.  In addition, the following lifecycle methods are called
+ * automatically when the corresponding events occur:</p>
+ * <ul>
+ * <li><code>init()</code> - Called when this bean is initially added as an
+ *     application scope attribute (typically as the result of
+ *     evaluating a value binding or method binding expression).</li>
+ * <li><code>destroy()</code> - Called when the bean is removed from the
+ *     application attributes (typically as a result of the application
+ *     being shut down by the servlet container).</li>
+ * </ul>
+ *
+ * $Id$
+ */
+public abstract class AbstractApplicationBean extends AbstractFacesBean {
+
+
+    // ------------------------------------------------------------- Constructor
+
+
+    /**
+     * <p>Create a new application scope bean.</p>
+     */
+    public AbstractApplicationBean() {
+    }
+
+
+    // ------------------------------------------------------- Lifecycle Methods
+
+
+    /**
+     * <p>This method is called when this bean is initially added to
+     * application scope.  Typically, this occurs as a result of evaluating
+     * a value binding or method binding expression, which utilizes the
+     * managed bean facility to instantiate this bean and store it into
+     * application scope.</p>
+     *
+     * <p>You may customize this method to initialize and cache application wide
+     * data values (such as the lists of valid options for dropdown list
+     * components), or to allocate resources that are required for the
+     * lifetime of the application.</p>
+     */
+    public void init() {
+
+        // The default implementation does nothing
+
+    }
+
+
+    /**
+     * <p>This method is called when this bean is removed from
+     * application scope.  Typically, this occurs as a result of
+     * the application being shut down by its owning container.</p>
+     *
+     * <p>You may customize this method to clean up resources allocated
+     * during the execution of the <code>init()</code> method, or
+     * at any later time during the lifetime of the application.</p>
+     */
+    public void destroy() {
+
+        // The default implementation does nothing
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractRequestBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractRequestBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractRequestBean.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractRequestBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+/**
+ * <p><strong>AbstractRequestBean</strong> is the abstract base class for
+ * data bean(s) that are stored in request scope attributes.  It extends
+ * {@link AbstractFacesBean}, so it inherits all of the default behavior
+ * found there.  In addition, the following lifecycle methods are called
+ * automatically when the corresponding events occur:</p>
+ * <ul>
+ * <li><code>init()</code> - Called when this bean is initially added as a
+ *     request scope attribute (typically as the result of
+ *     evaluating a value binding or method binding expression).</li>
+ * <li><code>destroy()</code> - Called when the bean is removed from the
+ *     request attributes (typically as a result of the application
+ *     being shut down by the servlet container).</li>
+ * </ul>
+ *
+ * $Id$
+ */
+public abstract class AbstractRequestBean extends AbstractFacesBean {
+    
+
+    // ------------------------------------------------------------- Constructor
+
+
+    /**
+     * <p>Create a new request scope bean.</p>
+     */
+    public AbstractRequestBean() {      
+    }
+    
+
+    // ------------------------------------------------------- Lifecycle Methods
+
+
+    /**
+     * <p>This method is called when this bean is initially added to
+     * request scope.  Typically, this occurs as a result of evaluating
+     * a value binding or method binding expression, which utilizes the
+     * managed bean facility to instantiate this bean and store it into
+     * request scope.</p>
+     *
+     * <p>You may customize this method to allocate resources that are required
+     * for the lifetime of the current request.</p>
+     */
+    public void init() {
+
+        // The default implementation does nothing
+
+    }
+
+
+    /**
+     * <p>This method is called when this bean is removed from
+     * request scope.  This occurs automatically when the corresponding
+     * HTTP response has been completed and sent to the client.</p>
+     *
+     * <p>You may customize this method to clean up resources allocated
+     * during the execution of the <code>init()</code> method, or
+     * at any later time during the lifetime of the request.</p>
+     */
+    public void destroy() {
+
+        // The default implementation does nothing
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractSessionBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractSessionBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractSessionBean.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/view/AbstractSessionBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import java.io.Serializable;
+
+/**
+ * <p><strong>AbstractSessionBean</strong> is the abstract base class for
+ * data bean(s) that are stored in session scope attributes.  It extends
+ * {@link AbstractFacesBean}, so it inherits all of the default behavior
+ * found there.  In addition, the following lifecycle methods are called
+ * automatically when the corresponding events occur:</p>
+ * <ul>
+ * <li><code>init()</code> - Called when this bean is initially added
+ *     as a session attribute (typically as the result of evaluating a
+ *     value binding or method binding expression).</li>
+ * <li><code>passivate()</code> - Called when the servlet container is about
+ *     to serialize and remove this session from its current container.</li>
+ * <li><code>activate()</code> - Called when the servlet container has
+ *     finished deserializing this session and making it available in a
+ *     (potentially different) container.</li>
+ * <li><code>destroy()</code> - Called when the bean is removed from the
+ *     session attributes (typically as a result of the session timing out
+ *     or being terminated by the application).</li>
+ * </ul>
+ *
+ * $Id$
+ */
+public abstract class AbstractSessionBean
+  extends AbstractFacesBean implements Serializable {
+    
+
+    // ------------------------------------------------------------- Constructor
+
+
+    /**
+     * <p>Create a new session scope bean.</p>
+     */
+    public AbstractSessionBean() {      
+    }
+    
+
+    // ------------------------------------------------------- Lifecycle Methods
+
+
+    /**
+     * <p>This method is called when this bean is initially added to
+     * session scope.  Typically, this occurs as a result of evaluating
+     * a value binding or method binding expression, which utilizes the
+     * managed bean facility to instantiate this bean and store it into
+     * session scope.</p>
+     *
+     * <p>You may customize this method to initialize and cache data values
+     * or resources that are required for the lifetime of a particular
+     * user session.</p>
+     */
+    public void init() {
+
+        // The default implementation does nothing
+
+    }
+
+
+    /**
+     * <p>This method is called when the session containing it is about to be
+     * passivated.  Typically, this occurs in a distributed servlet container
+     * when the session is about to be transferred to a different
+     * container instance, after which the <code>activate()</code> method
+     * will be called to indicate that the transfer is complete.</p>
+     *
+     * <p>You may customize this method to release references to session data
+     * or resources that can not be serialized with the session itself.</p>
+     */
+    public void passivate() {
+
+        // The default implementation does nothing
+
+    }
+
+
+    /**
+     * <p>This method is called when the session containing it was
+     * reactivated.</p>
+     * 
+     * <p>You may customize this method to reacquire references to session
+     * data or resources that could not be serialized with the
+     * session itself.</p>
+     */
+    public void activate() {
+
+        // The default implementation does nothing
+
+    }
+
+
+    /**
+     * <p>This method is called when this bean is removed from
+     * session scope.  Typically, this occurs as a result of
+     * the session timing out or being terminated by the application.</p>
+     *
+     * <p>You may customize this method to clean up resources allocated
+     * during the execution of the <code>init()</code> method, or
+     * at any later time during the lifetime of the application.</p>
+     */
+    public void destroy() {
+
+        // The default implementation does nothing
+
+    }
+
+
+}

Modified: struts/shale/trunk/core-library/src/java/org/apache/shale/view/Constants.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/view/Constants.java?rev=405360&r1=405359&r2=405360&view=diff
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/view/Constants.java (original)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/view/Constants.java Tue May  9 02:39:17 2006
@@ -36,6 +36,16 @@
 
 
     /**
+     * <p>Request scope attribute key under which a <code>java.util.List</code>
+     * of exceptions accumulated during the current request processing lifecycle
+     * are accumulated.  If there is no such <code>List</code> present, then
+     * no exceptions have been accumulated for the current request.</p>
+     */
+    public static final String EXCEPTIONS_LIST =
+      "org.apache.shale.view.EXCEPTIONS_LIST";
+
+
+    /**
      * <p>Application scope attribute under which the
      * <code>ViewControllerCallbacks</code> instance for this application
      * is stored.</p>

Added: struts/shale/trunk/core-library/src/java/org/apache/shale/view/faces/LifecycleListener.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/java/org/apache/shale/view/faces/LifecycleListener.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/java/org/apache/shale/view/faces/LifecycleListener.java (added)
+++ struts/shale/trunk/core-library/src/java/org/apache/shale/view/faces/LifecycleListener.java Tue May  9 02:39:17 2006
@@ -0,0 +1,793 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view.faces;
+
+import java.util.Map;
+import org.apache.shale.view.AbstractApplicationBean;
+import org.apache.shale.view.AbstractRequestBean;
+import org.apache.shale.view.AbstractSessionBean;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionActivationListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+import org.apache.shale.view.Constants;
+
+
+/**
+ * <p><strong>LifecycleListener</strong> implements the lifecycle startup
+ * and shutdown calls (<code>init()</code> and <code>destroy()</code>) for
+ * subclasses of {@link AbstractApplicationBean}, {@link AbstractRequestBean},
+ * and {@link AbstractSessionBean}.</p>
+ * 
+ * <p>It must be registered with the servlet container as a listener,
+ * through an entry in either the <code>/WEB-INF/web.xml</code> resource
+ * or a tag library descriptor included in the web application.</p>
+ *
+ * $Id$
+ */
+public class LifecycleListener
+    implements ServletContextAttributeListener,
+               ServletContextListener,
+               HttpSessionActivationListener,
+               HttpSessionAttributeListener,
+               HttpSessionListener,
+               ServletRequestAttributeListener,
+               ServletRequestListener
+    {
+    
+
+    // ------------------------------------------------------------- Constructor
+
+
+    /**
+     * <p>Create a new lifecycle listener.</p>
+     */
+    public LifecycleListener() {      
+    }
+    
+
+    // ------------------------------------------------------ Manifest Constants
+
+
+    /**
+     * <p>The fully qualified class name of the <em>Tiger Extensions</em>
+     * verison of this listener class.</p>
+     */
+    private static final String TIGER_LISTENER =
+            "org.apache.shale.tiger.view.faces.LifecycleListener";
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    /**
+     * <p>The <em>Tiger Extensions</em> implementation of this listener, if
+     * such a class exists in the application classpath.  This value is lazily
+     * instantiated.</p>
+     */
+    private LifecycleListener tiger = null;
+
+
+    /**
+     * <p>Flag indicating whether the <code>tiger</code> value has been calculated
+     * already.</p>
+     */
+    private boolean tigerInitialized = false;
+
+
+    // ------------------------------------------ ServletContextListener Methods
+
+
+    /**
+     * <p>Respond to a context created event.  No special processing
+     * is required.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void contextInitialized(ServletContextEvent event) {
+
+        // No processing is required
+        ;
+
+    }
+
+
+    /**
+     * <p>Respond to a context destroyed event.  Causes any application
+     * scope attribute that implements {@link AbstractApplicationBean}
+     * to be removed, triggering an <code>attributeRemoved()</code> event.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void contextDestroyed(ServletContextEvent event) {
+
+        // Remove any AbstractApplicationBean attributes, which will
+        // trigger an attributeRemoved event
+        List list = new ArrayList();
+        Enumeration names = event.getServletContext().getAttributeNames();
+        while (names.hasMoreElements()) {
+            String name = (String) names.nextElement();
+            list.add(name);
+        }
+        Iterator keys = list.iterator();
+        while (keys.hasNext()) {
+            String key = (String) keys.next();
+            event.getServletContext().removeAttribute(key);
+        }
+
+    }
+
+
+    // --------------------------------- ServletContextAttributeListener Methods
+
+
+    /**
+     * <p>Respond to an application scope attribute being added.  If the
+     * value is an {@link AbstractApplicationBean}, call its
+     * <code>init()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeAdded(ServletContextAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeAdded(event);
+            return;
+        }
+
+        // If the new value is an AbstractApplicationBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractApplicationBean)) {
+            fireApplicationInit(value);
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to an application scope attribute being replaced.
+     * If the old value was an {@link AbstractApplicationBean}, call
+     * its <code>destroy()</code> method.  If the new value is an
+     * {@link AbstractApplicationBean}, call its <code>init()</code>
+     * method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeReplaced(ServletContextAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeReplaced(event);
+            return;
+        }
+
+        // If the old value is an AbstractApplicationBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractApplicationBean)) {
+            fireApplicationDestroy(value);
+        }
+
+        // If the new value is an AbstractApplicationBean, notify it
+        value = event.getServletContext().getAttribute(event.getName());
+        if ((value != null) && (value instanceof AbstractApplicationBean)) {
+            fireApplicationInit(value);
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to an application scope attribute being removed.
+     * If the old value was an {@link AbstractApplicationBean}, call
+     * its <code>destroy()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeRemoved(ServletContextAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeRemoved(event);
+            return;
+        }
+
+        // If the old value is an AbstractApplicationBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractApplicationBean)) {
+            fireApplicationDestroy(value);
+        }
+
+    }
+
+
+    // --------------------------------------------- HttpSessionListener Methods
+
+
+    /**
+     * <p>Respond to a session created event.  No special processing
+     * is required.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void sessionCreated(HttpSessionEvent event) {
+
+        // No processing is required
+        ;
+
+    }
+
+
+    /**
+     * <p>Respond to a session destroyed event.  Causes any session
+     * scope attribute that implements {@link AbstractSessionBean}
+     * to be removed, triggering an <code>attributeRemoved()</code> event.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void sessionDestroyed(HttpSessionEvent event) {
+
+        // Remove any AbstractSessionBean attributes, which will
+        // trigger an attributeRemoved event
+        List list = new ArrayList();
+        try {
+            Enumeration names = event.getSession().getAttributeNames();
+            while (names.hasMoreElements()) {
+                String name = (String) names.nextElement();
+                list.add(name);
+            }
+            Iterator keys = list.iterator();
+            while (keys.hasNext()) {
+                String key = (String) keys.next();
+                event.getSession().removeAttribute(key);
+            }
+        } catch (IllegalStateException e) {
+            // If the session has already been invalidated, there is nothing
+            // we can do.  In a Servlet 2.4 or later container, this should not
+            // happen, because the event handler is supposed to be called before
+            // invalidation occurs, rather than after.
+        }
+
+    }
+
+
+    // ----------------------------------- HttpSessionActivationListener Methods
+
+
+    /**
+     * <p>Respond to a "session will passivate" event.  Notify all session
+     * scope attributes that are {@link AbstractSessionBean}s.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void sessionWillPassivate(HttpSessionEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.sessionWillPassivate(event);
+            return;
+        }
+
+        // Notify any AbstractSessionBean attributes
+        Enumeration names = event.getSession().getAttributeNames();
+        while (names.hasMoreElements()) {
+            String name = (String) names.nextElement();
+            Object value = event.getSession().getAttribute(name);
+            if ((value != null) && (value instanceof AbstractSessionBean)) {
+                fireSessionPassivate(value);
+            }
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to a "session did activate" event.  Notify all session
+     * scope attributes that are {@link AbstractSessionBean}s.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void sessionDidActivate(HttpSessionEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.sessionDidActivate(event);
+            return;
+        }
+
+        // Notify any AbstractSessionBean attributes
+        Enumeration names = event.getSession().getAttributeNames();
+        while (names.hasMoreElements()) {
+            String name = (String) names.nextElement();
+            Object value = event.getSession().getAttribute(name);
+            if ((value != null) && (value instanceof AbstractSessionBean)) {
+                fireSessionActivate(value);
+            }
+        }
+
+    }
+
+
+    // ------------------------------------ HttpSessionAttributeListener Methods
+
+
+    /**
+     * <p>Respond to a session scope attribute being added.  If the
+     * value is an {@link AbstractSessionBean}, call its
+     * <code>init()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeAdded(HttpSessionBindingEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeAdded(event);
+            return;
+        }
+
+        // If the new value is an AbstractSessionBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractSessionBean)) {
+            fireSessionInit(value);
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to a session scope attribute being replaced.
+     * If the old value was an {@link AbstractSessionBean}, call
+     * its <code>destroy()</code> method.  If the new value is an
+     * {@link AbstractSessionBean}, call its <code>init()</code>
+     * method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeReplaced(HttpSessionBindingEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeReplaced(event);
+            return;
+        }
+
+        // If the old value is an AbstractSessionBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractSessionBean)) {
+            fireSessionDestroy(value);
+        }
+
+        // If the new value is an AbstractSessionBean, notify it
+        value = event.getSession().getAttribute(event.getName());
+        if ((value != null) && (value instanceof AbstractSessionBean)) {
+            fireSessionInit(value);
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to a session scope attribute being removed.
+     * If the old value was an {@link AbstractSessionBean}, call
+     * its <code>destroy()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeRemoved(HttpSessionBindingEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeRemoved(event);
+            return;
+        }
+
+        // If the old value is an AbstractSessionBean, notify it
+        Object value = event.getValue();
+        if ((value != null) && (value instanceof AbstractSessionBean)) {
+            fireSessionDestroy(value);
+        }
+
+    }
+
+
+    // ------------------------------------------ ServletRequestListener Methods
+
+
+    /**
+     * <p>Respond to a request created event.  No special processing
+     * is required.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void requestInitialized(ServletRequestEvent event) {
+
+        // No processing is required
+        ;
+
+    }
+
+
+    /**
+     * <p>Respond to a request destroyed event.  Causes any request
+     * scope attribute that implements {@link AbstractRequestBean}
+     * or {@link AbstractFragmentBean} to be removed, triggering an
+     * <code>attributeRemoved()</code> event.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void requestDestroyed(ServletRequestEvent event) {
+
+        // Remove any AbstractRequestBean attributes,
+        // which will trigger an attributeRemoved event
+        List list = new ArrayList();
+        Enumeration names = event.getServletRequest().getAttributeNames();
+        while (names.hasMoreElements()) {
+            String name = (String) names.nextElement();
+            list.add(name);
+        }
+        Iterator keys = list.iterator();
+        while (keys.hasNext()) {
+            String key = (String) keys.next();
+            event.getServletRequest().removeAttribute(key);
+        }
+
+    }
+
+
+    // --------------------------------- ServletRequestAttributeListener Methods
+
+
+    /**
+     * <p>Respond to a request scope attribute being added.  If the
+     * value is an {@link AbstractRequestBean}, call its <code>init()</code> method.
+     * </p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeAdded(ServletRequestAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeAdded(event);
+            return;
+        }
+
+        Object value = event.getValue();
+        if (value != null) {
+            if (value instanceof AbstractRequestBean) {
+                fireRequestInit(value);
+            }
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to a request scope attribute being replaced.
+     * If the old value was an {@link AbstractRequestBean},
+     * call its <code>destroy()</code> method.  If the new value is an
+     * {@link AbstractRequestBean}, call its <code>init()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeReplaced(ServletRequestAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeReplaced(event);
+            return;
+        }
+
+        Object value = event.getValue();
+        if (value != null) {
+            if (value instanceof AbstractRequestBean) {
+                fireRequestDestroy(value);
+            }
+        }
+
+        value = event.getServletRequest().getAttribute(event.getName());
+        if (value != null) {
+            if (value instanceof AbstractRequestBean) {
+                fireRequestInit(value);
+            }
+        }
+
+    }
+
+
+    /**
+     * <p>Respond to a request scope attribute being removed.
+     * If the old value was an {@link AbstractRequestBean},
+     * call its <code>destroy()</code> method.</p>
+     *
+     * @param event Event to be processed
+     */
+    public void attributeRemoved(ServletRequestAttributeEvent event) {
+
+        // Delegate to the Tiger Extensions instance if it exists
+        LifecycleListener tiger = tiger();
+        if (tiger != null) {
+            tiger.attributeRemoved(event);
+            return;
+        }
+
+        Object value = event.getValue();
+        if (value != null) {
+            if (value instanceof AbstractRequestBean) {
+                fireRequestDestroy(value);
+            }
+        }
+
+    }
+
+
+    // ------------------------------------------------------- Protected Methods
+
+
+    /**
+     * <p>Log the specified exception, and cache it on the list of exceptions
+     * to be reported after all of the appropriate <code>destroy()</code> calls
+     * have been completed.</p>
+     *
+     * @param exception Exception to be cached
+     */
+    protected void cacheException(Exception exception) {
+
+        // Log the exception unconditionally
+        log(exception.getMessage(), exception);
+
+        // Are we within the context of a JavaServer Faces request?
+        // If so, accumulate this exception to the list that can be
+        // reported at the completion of the request.
+        FacesContext context = FacesContext.getCurrentInstance();
+        if (context == null) {
+            return;
+        }
+        List list = (List) context.getExternalContext().getRequestMap().
+                get(Constants.EXCEPTIONS_LIST);
+        if (list == null) {
+            list = new ArrayList(4);
+            context.getExternalContext().getRequestMap().
+                    put(Constants.EXCEPTIONS_LIST, list);
+        }
+        list.add(exception);
+
+    }
+
+
+    /**
+     * <p>Fire a destroy event on an @{link AbstractApplicationBean}.</p>
+     *
+     * @param bean {@link AbstractApplicationBean} to fire event on
+     */
+    protected void fireApplicationDestroy(Object bean) {
+
+        try {
+            ((AbstractApplicationBean) bean).destroy();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire an init event on an {@link AbstractApplicationBean}.</p>
+     *
+     * @param bean {@link AbstractApplicationBean} to fire event on
+     */
+    protected void fireApplicationInit(Object bean) {
+
+        try {
+            ((AbstractApplicationBean) bean).init();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire a destroy event on an @{link AbstractRequestBean}.</p>
+     *
+     * @param bean {@link AbstractRequestBean} to fire event on
+     */
+    protected void fireRequestDestroy(Object bean) {
+
+        try {
+            ((AbstractRequestBean) bean).destroy();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire an init event on an {@link AbstractRequestBean}.</p>
+     *
+     * @param bean {@link AbstractRequestBean} to fire event on
+     */
+    protected void fireRequestInit(Object bean) {
+
+        try {
+            ((AbstractRequestBean) bean).init();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire an activate event on an @{link AbstractSessionBean}.</p>
+     *
+     * @param bean {@link AbstractSessionBean} to fire event on
+     */
+    protected void fireSessionActivate(Object bean) {
+
+        try {
+            ((AbstractSessionBean) bean).activate();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire a destroy event on an @{link AbstractSessionBean}.</p>
+     *
+     * @param bean {@link AbstractSessionBean} to fire event on
+     */
+    protected void fireSessionDestroy(Object bean) {
+
+        try {
+            ((AbstractSessionBean) bean).destroy();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire an init event on an {@link AbstractSessionBean}.</p>
+     *
+     * @param bean {@link AbstractSessionBean} to fire event on
+     */
+    protected void fireSessionInit(Object bean) {
+
+        try {
+            ((AbstractSessionBean) bean).init();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Fire an passivate event on an @{link AbstractSessionBean}.</p>
+     *
+     * @param bean {@link AbstractSessionBean} to fire event on
+     */
+    protected void fireSessionPassivate(Object bean) {
+
+        try {
+            ((AbstractSessionBean) bean).passivate();
+        } catch (Exception e) {
+            cacheException(e);
+        }
+
+    }
+
+
+    /**
+     * <p>Log the specified message via <code>FacesContext</code> if it is
+     * not null, or directly to the container otherwise.</p>
+     *
+     * @param message Message to be logged
+     */
+    protected void log(String message) {
+
+        FacesContext context = FacesContext.getCurrentInstance();
+        if (context != null) {
+            context.getExternalContext().log(message);
+        } else {
+            System.out.println(message);
+        }
+
+    }
+
+
+    /**
+     * <p>Log the specified message and exception via <code>FacesContext</code>
+     * if it is not null, or directly to the container otherwise.</p>
+     *
+     * @param message Message to be logged
+     * @param throwable Exception to be logged
+     */
+    protected void log(String message, Throwable throwable) {
+
+        FacesContext context = FacesContext.getCurrentInstance();
+        if (context != null) {
+            context.getExternalContext().log(message);
+        } else {
+            System.out.println(message);
+        }
+
+    }
+
+
+    // --------------------------------------------------------- Private Methods
+
+
+    /**
+     * <p>Return the <em>Tiger Extensions</em> implementation of this listener
+     * if one exists; otherwise, return <code>null</code>.</p>
+     */
+    private LifecycleListener tiger() {
+
+        // If we have already attempted to load the Tiger Extensions version
+        // of this class, return the calculated result
+        if (tigerInitialized) {
+            return tiger;
+        }
+
+        // Attempt to load the Tiger Extensions version of this class, and
+        // instantiate an appropriate instance
+        try {
+            Class clazz = this.getClass().getClassLoader().loadClass(TIGER_LISTENER);
+            tiger = (LifecycleListener) clazz.newInstance();
+        } catch (Exception e) {
+            ; // Swallow any class not found or instantiation exception
+        }
+
+        // Return the calculated result
+        tigerInitialized = true;
+        return tiger;
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractApplicationBeanTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractApplicationBeanTestCase.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractApplicationBeanTestCase.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractApplicationBeanTestCase.java Tue May  9 02:39:17 2006
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import javax.servlet.ServletContextAttributeListener;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.view.faces.LifecycleListener;
+
+/**
+ * <p>Test case for <code>org.apache.shale.view.AbstractApplicationBean</code>.</p>
+ */
+public class AbstractApplicationBeanTestCase extends AbstractJsfTestCase {
+    
+    
+    // ------------------------------------------------------------ Constructors
+
+
+    // Construct a new instance of this test case.
+    public AbstractApplicationBeanTestCase(String name) {
+        super(name);
+    }
+
+
+    // ---------------------------------------------------- Overall Test Methods
+
+
+    // Set up instance variables required by this test case.
+    public void setUp() {
+
+        super.setUp();
+        listener = new ApplicationAttributeListener();
+        servletContext.addAttributeListener(listener);
+        servletContext.addAttributeListener(new LifecycleListener());
+
+    }
+
+
+    // Return the tests included in this test case.
+    public static Test suite() {
+
+        return (new TestSuite(AbstractApplicationBeanTestCase.class));
+
+    }
+
+
+    // Tear down instance variables required by this test case.
+    public void tearDown() {
+
+        listener = null;
+        ApplicationAttributeListener.clear();
+        ConcreteApplicationBean.clear();
+        super.tearDown();
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    ServletContextAttributeListener listener = null;
+
+
+    // ------------------------------------------------------------ Test Methods
+
+
+
+    // Test a prisine instance
+    public void testPristine() {
+
+        assertEquals("", ApplicationAttributeListener.record());
+
+    }
+
+
+    // Test processing an attribute
+    public void testProcess() {
+
+        assertEquals("", ApplicationAttributeListener.record());
+        ConcreteApplicationBean bean = new ConcreteApplicationBean();
+        assertEquals("", ConcreteApplicationBean.record());
+
+        servletContext.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteApplicationBean)//",
+                     ApplicationAttributeListener.record());
+        assertEquals("init()//",
+                     ConcreteApplicationBean.record());
+
+        servletContext.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteApplicationBean)//" +
+                     "attributeReplaced(bean,ConcreteApplicationBean)//",
+                     ApplicationAttributeListener.record());
+        assertEquals("init()//destroy()//init()//",
+                     ConcreteApplicationBean.record());
+
+        servletContext.removeAttribute("bean");
+        assertEquals("attributeAdded(bean,ConcreteApplicationBean)//" +
+                     "attributeReplaced(bean,ConcreteApplicationBean)//" +
+                     "attributeRemoved(bean,ConcreteApplicationBean)//",
+                     ApplicationAttributeListener.record());
+        assertEquals("init()//destroy()//init()//destroy()//",
+                     ConcreteApplicationBean.record());
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractRequestBeanTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractRequestBeanTestCase.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractRequestBeanTestCase.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractRequestBeanTestCase.java Tue May  9 02:39:17 2006
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import javax.servlet.ServletRequestAttributeListener;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.view.faces.LifecycleListener;
+
+/**
+ * <p>Test case for <code>org.apache.shale.view.AbstractRequestBean</code>.</p>
+ */
+public class AbstractRequestBeanTestCase extends AbstractJsfTestCase {
+    
+    
+    // ------------------------------------------------------------ Constructors
+
+
+    // Construct a new instance of this test case.
+    public AbstractRequestBeanTestCase(String name) {
+        super(name);
+    }
+
+
+    // ---------------------------------------------------- Overall Test Methods
+
+
+    // Set up instance variables required by this test case.
+    public void setUp() {
+
+        super.setUp();
+        listener = new RequestAttributeListener();
+        request.addAttributeListener(listener);
+        request.addAttributeListener(new LifecycleListener());
+
+    }
+
+
+    // Return the tests included in this test case.
+    public static Test suite() {
+
+        return (new TestSuite(AbstractRequestBeanTestCase.class));
+
+    }
+
+
+    // Tear down instance variables required by this test case.
+    public void tearDown() {
+
+        listener = null;
+        RequestAttributeListener.clear();
+        ConcreteRequestBean.clear();
+        super.tearDown();
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    ServletRequestAttributeListener listener = null;
+
+
+    // ------------------------------------------------------------ Test Methods
+
+
+
+    // Test a prisine instance
+    public void testPristine() {
+
+        assertEquals("", RequestAttributeListener.record());
+
+    }
+
+
+    // Test processing an attribute
+    public void testProcess() {
+
+        assertEquals("", RequestAttributeListener.record());
+        ConcreteRequestBean bean = new ConcreteRequestBean();
+        assertEquals("", ConcreteRequestBean.record());
+
+        request.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteRequestBean)//",
+                     RequestAttributeListener.record());
+        assertEquals("init()//",
+                     ConcreteRequestBean.record());
+
+        request.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteRequestBean)//" +
+                     "attributeReplaced(bean,ConcreteRequestBean)//",
+                     RequestAttributeListener.record());
+        assertEquals("init()//destroy()//init()//",
+                     ConcreteRequestBean.record());
+
+        request.removeAttribute("bean");
+        assertEquals("attributeAdded(bean,ConcreteRequestBean)//" +
+                     "attributeReplaced(bean,ConcreteRequestBean)//" +
+                     "attributeRemoved(bean,ConcreteRequestBean)//",
+                     RequestAttributeListener.record());
+        assertEquals("init()//destroy()//init()//destroy()//",
+                     ConcreteRequestBean.record());
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractSessionBeanTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractSessionBeanTestCase.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractSessionBeanTestCase.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/AbstractSessionBeanTestCase.java Tue May  9 02:39:17 2006
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.view.faces.LifecycleListener;
+
+/**
+ * <p>Test case for <code>org.apache.shale.view.AbstractSessionBean</code>.</p>
+ */
+public class AbstractSessionBeanTestCase extends AbstractJsfTestCase {
+    
+    
+    // ------------------------------------------------------------ Constructors
+
+
+    // Construct a new instance of this test case.
+    public AbstractSessionBeanTestCase(String name) {
+        super(name);
+    }
+
+
+    // ---------------------------------------------------- Overall Test Methods
+
+
+    // Set up instance variables required by this test case.
+    public void setUp() {
+
+        super.setUp();
+        listener = new SessionAttributeListener();
+        session.addAttributeListener(listener);
+        session.addAttributeListener(new LifecycleListener());
+
+    }
+
+
+    // Return the tests included in this test case.
+    public static Test suite() {
+
+        return (new TestSuite(AbstractSessionBeanTestCase.class));
+
+    }
+
+
+    // Tear down instance variables required by this test case.
+    public void tearDown() {
+
+        listener = null;
+        SessionAttributeListener.clear();
+        ConcreteSessionBean.clear();
+        super.tearDown();
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    SessionAttributeListener listener = null;
+
+
+    // ------------------------------------------------------------ Test Methods
+
+
+
+    // Test a prisine instance
+    public void testPristine() {
+
+        assertEquals("", SessionAttributeListener.record());
+
+    }
+
+
+    // Test processing an attribute
+    public void testProcess() {
+
+        assertEquals("", SessionAttributeListener.record());
+        ConcreteSessionBean bean = new ConcreteSessionBean();
+        assertEquals("", ConcreteSessionBean.record());
+
+        session.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteSessionBean)//",
+                     SessionAttributeListener.record());
+        assertEquals("init()//",
+                     ConcreteSessionBean.record());
+
+        session.setAttribute("bean", bean);
+        assertEquals("attributeAdded(bean,ConcreteSessionBean)//" +
+                     "attributeReplaced(bean,ConcreteSessionBean)//",
+                     SessionAttributeListener.record());
+        assertEquals("init()//destroy()//init()//",
+                     ConcreteSessionBean.record());
+
+        session.removeAttribute("bean");
+        assertEquals("attributeAdded(bean,ConcreteSessionBean)//" +
+                     "attributeReplaced(bean,ConcreteSessionBean)//" +
+                     "attributeRemoved(bean,ConcreteSessionBean)//",
+                     SessionAttributeListener.record());
+        assertEquals("init()//destroy()//init()//destroy()//",
+                     ConcreteSessionBean.record());
+
+    }
+
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/ApplicationAttributeListener.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/ApplicationAttributeListener.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/ApplicationAttributeListener.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/ApplicationAttributeListener.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import javax.servlet.ServletContextAttributeEvent;
+import javax.servlet.ServletContextAttributeListener;
+
+/**
+ *
+ * @author craigmcc
+ */
+public class ApplicationAttributeListener implements ServletContextAttributeListener {
+    
+
+    // -------------------------------------------------------- Listener Methods
+
+
+    public void attributeAdded(ServletContextAttributeEvent event) {
+        record("attributeAdded(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeRemoved(ServletContextAttributeEvent event) {
+        record("attributeRemoved(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeReplaced(ServletContextAttributeEvent event) {
+        record("attributeReplaced(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteApplicationBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteApplicationBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteApplicationBean.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteApplicationBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+/**
+ * <p>Concrete implementation of {@link AbstractApplicationBean}.</p>
+ */
+public class ConcreteApplicationBean extends AbstractApplicationBean {
+    
+    /** Creates a new instance of ConcreteApplicationBean */
+    public ConcreteApplicationBean() {
+    }
+    
+
+    // ---------------------------------------------------------- Public Methods
+
+
+    public void init() {
+        record("init()");
+    }
+
+
+    public void destroy() {
+        record("destroy()");
+    }
+
+
+    public String toString() {
+        return "ConcreteApplicationBean";
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteRequestBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteRequestBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteRequestBean.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteRequestBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+/**
+ * <p>Concrete implementation of {@link AbstractRequestBean}.</p>
+ */
+public class ConcreteRequestBean extends AbstractRequestBean {
+    
+    /** Creates a new instance of ConcreteRequestBean */
+    public ConcreteRequestBean() {
+    }
+    
+
+    // ---------------------------------------------------------- Public Methods
+
+
+    public void init() {
+        record("init()");
+    }
+
+
+    public void destroy() {
+        record("destroy()");
+    }
+
+
+    public String toString() {
+        return "ConcreteRequestBean";
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteSessionBean.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteSessionBean.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteSessionBean.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/ConcreteSessionBean.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+/**
+ * <p>Concrete implementation of {@link AbstractSessionBean}.</p>
+ */
+public class ConcreteSessionBean extends AbstractSessionBean {
+    
+    /** Creates a new instance of ConcreteSessionBean */
+    public ConcreteSessionBean() {
+    }
+    
+
+    // ---------------------------------------------------------- Public Methods
+
+
+    public void init() {
+        record("init()");
+    }
+
+
+    public void destroy() {
+        record("destroy()");
+    }
+
+
+    public String toString() {
+        return "ConcreteSessionBean";
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/RequestAttributeListener.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/RequestAttributeListener.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/RequestAttributeListener.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/RequestAttributeListener.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import javax.servlet.ServletRequestAttributeEvent;
+import javax.servlet.ServletRequestAttributeListener;
+
+/**
+ *
+ * @author craigmcc
+ */
+public class RequestAttributeListener implements ServletRequestAttributeListener {
+    
+
+    // -------------------------------------------------------- Listener Methods
+
+
+    public void attributeAdded(ServletRequestAttributeEvent event) {
+        record("attributeAdded(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeRemoved(ServletRequestAttributeEvent event) {
+        record("attributeRemoved(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeReplaced(ServletRequestAttributeEvent event) {
+        record("attributeReplaced(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}

Added: struts/shale/trunk/core-library/src/test/org/apache/shale/view/SessionAttributeListener.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/core-library/src/test/org/apache/shale/view/SessionAttributeListener.java?rev=405360&view=auto
==============================================================================
--- struts/shale/trunk/core-library/src/test/org/apache/shale/view/SessionAttributeListener.java (added)
+++ struts/shale/trunk/core-library/src/test/org/apache/shale/view/SessionAttributeListener.java Tue May  9 02:39:17 2006
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ * 
+ * Licensed 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.shale.view;
+
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+
+/**
+ *
+ * @author craigmcc
+ */
+public class SessionAttributeListener implements HttpSessionAttributeListener {
+    
+
+    // -------------------------------------------------------- Listener Methods
+
+
+    public void attributeAdded(HttpSessionBindingEvent event) {
+        record("attributeAdded(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeRemoved(HttpSessionBindingEvent event) {
+        record("attributeRemoved(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    public void attributeReplaced(HttpSessionBindingEvent event) {
+        record("attributeReplaced(" + event.getName() + "," + event.getValue() + ")");
+    }
+
+
+    // --------------------------------------------------------- Support Methods
+
+
+    private static String record = "";
+
+
+    public static void clear() {
+        record = "";
+    }
+
+
+    public static String record() {
+        return record;
+    }
+
+
+    private static void record(String message) {
+        record += message + "//";
+    }
+
+}



Mime
View raw message