Coverage Report - org.apache.myfaces.webapp.ManagedBeanDestroyerListener
 
Classes in this File Line Coverage Branch Coverage Complexity
ManagedBeanDestroyerListener
0%
0/65
0%
0/28
1.941
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.webapp;
 20  
 
 21  
 import java.util.Enumeration;
 22  
 import javax.faces.context.ExceptionHandler;
 23  
 import javax.faces.context.ExternalContext;
 24  
 import javax.faces.context.FacesContext;
 25  
 
 26  
 import javax.servlet.ServletContext;
 27  
 import javax.servlet.ServletContextAttributeEvent;
 28  
 import javax.servlet.ServletContextAttributeListener;
 29  
 import javax.servlet.ServletContextEvent;
 30  
 import javax.servlet.ServletContextListener;
 31  
 import javax.servlet.ServletRequest;
 32  
 import javax.servlet.ServletRequestAttributeEvent;
 33  
 import javax.servlet.ServletRequestAttributeListener;
 34  
 import javax.servlet.ServletRequestEvent;
 35  
 import javax.servlet.ServletRequestListener;
 36  
 import javax.servlet.http.HttpSessionAttributeListener;
 37  
 import javax.servlet.http.HttpSessionBindingEvent;
 38  
 import javax.servlet.http.HttpSessionEvent;
 39  
 import javax.servlet.http.HttpSessionListener;
 40  
 
 41  
 import org.apache.myfaces.config.ManagedBeanDestroyer;
 42  
 import org.apache.myfaces.context.ReleaseableExternalContext;
 43  
 import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
 44  
 import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
 45  
 import org.apache.myfaces.shared.context.ExceptionHandlerImpl;
 46  
 import org.apache.myfaces.spi.ViewScopeProvider;
 47  
 
 48  
 /**
 49  
  * Listens to
 50  
  *   - removing, replacing of attributes in context, session and request
 51  
  *   - destroying of context, session and request
 52  
  * for the ManagedBeanDestroyer to assure right destruction of managed beans in those scopes.
 53  
  * 
 54  
  * This listener is not registered in a tld or web.xml, but will be called by StartupServletContextListener.
 55  
  * 
 56  
  * @author Jakob Korherr (latest modification by $Author$)
 57  
  * @version $Revision$ $Date$
 58  
  * @since 2.0
 59  
  */
 60  0
 public class ManagedBeanDestroyerListener implements 
 61  
         HttpSessionAttributeListener, HttpSessionListener,
 62  
         ServletContextListener, ServletContextAttributeListener,
 63  
         ServletRequestListener, ServletRequestAttributeListener
 64  
 {
 65  
 
 66  
     /**
 67  
      * The instance of the ManagedBeanDestroyerListener created by
 68  
      * StartupServletContextListener is stored under this key in the
 69  
      * ApplicationMap.
 70  
      */
 71  
     public static final String APPLICATION_MAP_KEY = "org.apache.myfaces.ManagedBeanDestroyerListener";
 72  
 
 73  0
     private ManagedBeanDestroyer _destroyer = null;
 74  
     
 75  0
     private ViewScopeProvider _viewScopeHandler = null;
 76  
 
 77  
     /**
 78  
      * Sets the ManagedBeanDestroyer instance to use.
 79  
      *  
 80  
      * @param destroyer
 81  
      */
 82  
     public void setManagedBeanDestroyer(ManagedBeanDestroyer destroyer)
 83  
     {
 84  0
         _destroyer = destroyer;
 85  0
     }
 86  
     
 87  
     public void setViewScopeHandler(ViewScopeProvider listener)
 88  
     {
 89  0
         _viewScopeHandler = listener;
 90  0
     }
 91  
 
 92  
     /* Session related methods ***********************************************/
 93  
     
 94  
     public void attributeAdded(HttpSessionBindingEvent event)
 95  
     {
 96  
         // noop
 97  0
     }
 98  
 
 99  
     public void attributeRemoved(HttpSessionBindingEvent event)
 100  
     {
 101  0
         if (_destroyer != null)
 102  
         {
 103  0
             _destroyer.destroy(event.getName(), event.getValue());
 104  
         }
 105  0
     }
 106  
 
 107  
     public void attributeReplaced(HttpSessionBindingEvent event)
 108  
     {
 109  0
         if (_destroyer != null)
 110  
         {
 111  0
             _destroyer.destroy(event.getName(), event.getValue());
 112  
         }
 113  0
     }
 114  
 
 115  
     public void sessionCreated(HttpSessionEvent event)
 116  
     {
 117  
         // noop
 118  0
     }
 119  
 
 120  
     @SuppressWarnings("unchecked")
 121  
     public void sessionDestroyed(HttpSessionEvent event)
 122  
     {
 123  
         // MYFACES-3040 @PreDestroy Has Called 2 times
 124  
         // attributeRemoved receives the event too, so it does not 
 125  
         // have sense to handle it here. Unfortunately, it is not possible to 
 126  
         // handle it first and then on attributeRemoved, so the best bet is
 127  
         // let the code in just one place.
 128  
         /*
 129  
         if (_destroyer != null)
 130  
         {
 131  
             HttpSession session = event.getSession();
 132  
             Enumeration<String> attributes = session.getAttributeNames();
 133  
             if (!attributes.hasMoreElements())
 134  
             {
 135  
                 // nothing to do
 136  
                 return;
 137  
             }
 138  
 
 139  
             while (attributes.hasMoreElements())
 140  
             {
 141  
                 String name = attributes.nextElement();
 142  
                 Object value = session.getAttribute(name);
 143  
                 _destroyer.destroy(name, value);
 144  
             }
 145  
         }*/
 146  
         
 147  
         // If we don't propagate this event, CDI will do for us but outside JSF control
 148  
         // so when @PreDestroy methods are called there will not be an active FacesContext.
 149  
         // The trick here is ensure clean the affected scopes to avoid duplicates.
 150  
         // Remember cdi session scope is different from jsf session scope, because in
 151  
         // jsf case the beans are stored under a session attribute, so it has the problem
 152  
         // with attributeRemoved, but on cdi a wrapper is used instead, avoiding the problem.
 153  0
         if (_viewScopeHandler != null)
 154  
         {
 155  0
             FacesContext facesContext = FacesContext.getCurrentInstance();
 156  0
             if (facesContext != null)
 157  
             {
 158  0
                 _viewScopeHandler.onSessionDestroyed();
 159  
             }
 160  
             else
 161  
             {
 162  
                 // In case no FacesContext is available, we are on session invalidation
 163  
                 // through timeout. In that case, create a dummy FacesContext for this one
 164  
                 // like the one used in startup or shutdown and invoke the destroy method.
 165  
                 try
 166  
                 {
 167  0
                     ServletContext servletContext = event.getSession().getServletContext();
 168  0
                     ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, false);
 169  0
                     ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
 170  0
                     facesContext = new StartupFacesContextImpl(externalContext, 
 171  
                             (ReleaseableExternalContext) externalContext, exceptionHandler, false);
 172  0
                     _viewScopeHandler.onSessionDestroyed();
 173  
                 }
 174  
                 finally
 175  
                 {
 176  0
                     facesContext.release();
 177  0
                 }
 178  
             }
 179  
         }
 180  0
     }
 181  
     
 182  
     /* Context related methods ***********************************************/
 183  
     
 184  
     public void attributeAdded(ServletContextAttributeEvent event)
 185  
     {
 186  
         // noop
 187  0
     }
 188  
 
 189  
     public void attributeRemoved(ServletContextAttributeEvent event)
 190  
     {
 191  0
         if (_destroyer != null)
 192  
         {
 193  0
             _destroyer.destroy(event.getName(), event.getValue());
 194  
         }
 195  0
     }
 196  
 
 197  
     public void attributeReplaced(ServletContextAttributeEvent event)
 198  
     {
 199  0
         if (_destroyer != null)
 200  
         {
 201  0
             _destroyer.destroy(event.getName(), event.getValue());
 202  
         }
 203  0
     }
 204  
 
 205  
     public void contextInitialized(ServletContextEvent event)
 206  
     {
 207  
         // noop
 208  0
     }
 209  
     
 210  
     @SuppressWarnings("unchecked")
 211  
     public void contextDestroyed(ServletContextEvent event)
 212  
     {
 213  0
         if (_destroyer != null)
 214  
         {
 215  0
             ServletContext ctx = event.getServletContext();
 216  0
             Enumeration<String> attributes = ctx.getAttributeNames();
 217  0
             if (!attributes.hasMoreElements())
 218  
             {
 219  
                 // nothing to do
 220  0
                 return;
 221  
             }
 222  
 
 223  0
             while (attributes.hasMoreElements())
 224  
             {
 225  0
                 String name = attributes.nextElement();
 226  0
                 Object value = ctx.getAttribute(name);
 227  0
                 _destroyer.destroy(name, value);
 228  0
             }
 229  
         }
 230  0
     }
 231  
     
 232  
     /* Request related methods ***********************************************/
 233  
     
 234  
     public void attributeAdded(ServletRequestAttributeEvent event)
 235  
     {
 236  
         // noop
 237  0
     }
 238  
 
 239  
     public void attributeRemoved(ServletRequestAttributeEvent event)
 240  
     {
 241  0
         if (_destroyer != null)
 242  
         {
 243  0
             _destroyer.destroy(event.getName(), event.getValue());
 244  
         }
 245  0
     }
 246  
 
 247  
     public void attributeReplaced(ServletRequestAttributeEvent event)
 248  
     {
 249  0
         if (_destroyer != null)
 250  
         {
 251  0
             _destroyer.destroy(event.getName(), event.getValue());
 252  
         }
 253  0
     }
 254  
 
 255  
     public void requestInitialized(ServletRequestEvent event)
 256  
     {
 257  
         // noop
 258  0
     }
 259  
     
 260  
     @SuppressWarnings("unchecked")
 261  
     public void requestDestroyed(ServletRequestEvent event)
 262  
     {
 263  0
         if (_destroyer != null)
 264  
         {
 265  0
             ServletRequest request = event.getServletRequest();
 266  0
             Enumeration<String> attributes = request.getAttributeNames();
 267  0
             if (!attributes.hasMoreElements())
 268  
             {
 269  
                 // nothing to do
 270  0
                 return;
 271  
             }
 272  
             
 273  0
             while (attributes.hasMoreElements())
 274  
             {
 275  0
                 String name = attributes.nextElement();
 276  0
                 Object value = request.getAttribute(name);
 277  0
                 _destroyer.destroy(name, value);
 278  0
             }
 279  
         }
 280  0
     }
 281  
 
 282  
 }