Coverage Report - org.apache.myfaces.webapp.StartupServletContextListener
 
Classes in this File Line Coverage Branch Coverage Complexity
StartupServletContextListener
0%
0/133
0%
0/44
2.75
 
 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 org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 22  
 import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
 23  
 import org.apache.myfaces.shared.util.ClassUtils;
 24  
 
 25  
 import javax.faces.FactoryFinder;
 26  
 import javax.faces.context.ExternalContext;
 27  
 import javax.faces.context.FacesContext;
 28  
 
 29  
 import javax.servlet.ServletContext;
 30  
 import javax.servlet.ServletContextAttributeEvent;
 31  
 import javax.servlet.ServletContextAttributeListener;
 32  
 import javax.servlet.ServletContextEvent;
 33  
 import javax.servlet.ServletContextListener;
 34  
 import javax.servlet.ServletRequestAttributeEvent;
 35  
 import javax.servlet.ServletRequestAttributeListener;
 36  
 import javax.servlet.ServletRequestEvent;
 37  
 import javax.servlet.ServletRequestListener;
 38  
 import javax.servlet.http.HttpSessionAttributeListener;
 39  
 import javax.servlet.http.HttpSessionBindingEvent;
 40  
 import javax.servlet.http.HttpSessionEvent;
 41  
 import javax.servlet.http.HttpSessionListener;
 42  
 import java.lang.reflect.InvocationTargetException;
 43  
 import java.lang.reflect.Method;
 44  
 
 45  
 import java.util.ArrayList;
 46  
 import java.util.Iterator;
 47  
 import java.util.LinkedList;
 48  
 import java.util.List;
 49  
 import java.util.Map;
 50  
 import java.util.logging.Level;
 51  
 import java.util.logging.Logger;
 52  
 
 53  
 /**
 54  
  * Initialise the MyFaces system.
 55  
  * <p/>
 56  
  * This context listener is registered by the JSP TLD file for the standard JSF "f" components. Normally, servlet
 57  
  * containers will automatically load and process .tld files at startup time, and therefore register and run this class
 58  
  * automatically.
 59  
  * <p/>
 60  
  * Some very old servlet containers do not do this correctly, so in those cases this listener may be registered manually
 61  
  * in web.xml. Registering it twice (ie in both .tld and web.xml) will result in a harmless warning message being
 62  
  * generated. Very old versions of MyFaces Core do not register the listener in the .tld file, so those also need a
 63  
  * manual entry in web.xml. However all versions since at least 1.1.2 have this entry in the tld.
 64  
  * <p/>
 65  
  * This listener also delegates all session, request and context events to ManagedBeanDestroyer.
 66  
  * Because of that we only need to register one listener in the tld.
 67  
  *
 68  
  * @author Manfred Geiler (latest modification by $Author$)
 69  
  * @version $Revision$ $Date$
 70  
  */
 71  0
 public class StartupServletContextListener implements ServletContextListener,
 72  
         HttpSessionAttributeListener, HttpSessionListener,
 73  
         ServletRequestListener, ServletRequestAttributeListener,
 74  
         ServletContextAttributeListener
 75  
 {
 76  
     static final String FACES_INIT_DONE = "org.apache.myfaces.webapp.StartupServletContextListener.FACES_INIT_DONE";
 77  
 
 78  
     /**
 79  
      * comma delimited list of plugin classes which can be hooked into myfaces
 80  
      */
 81  
     @JSFWebConfigParam(since = "2.0")
 82  
     static final String FACES_INIT_PLUGINS = "org.apache.myfaces.FACES_INIT_PLUGINS";
 83  
 
 84  
     private static final byte FACES_INIT_PHASE_PREINIT = 0;
 85  
     private static final byte FACES_INIT_PHASE_POSTINIT = 1;
 86  
     private static final byte FACES_INIT_PHASE_PREDESTROY = 2;
 87  
     private static final byte FACES_INIT_PHASE_POSTDESTROY = 3;
 88  
 
 89  
     //private static final Log log = LogFactory.getLog(StartupServletContextListener.class);
 90  0
     private static final Logger log = Logger.getLogger(StartupServletContextListener.class.getName());
 91  
 
 92  
     private FacesInitializer _facesInitializer;
 93  
     private ServletContext _servletContext;
 94  0
     private ManagedBeanDestroyerListener _detroyerListener = new ManagedBeanDestroyerListener();
 95  
 
 96  
     public void contextInitialized(ServletContextEvent event)
 97  
     {
 98  0
         if (_servletContext != null)
 99  
         {
 100  0
             throw new IllegalStateException("context is already initialized");
 101  
         }
 102  0
         _servletContext = event.getServletContext();
 103  
 
 104  0
         Boolean b = (Boolean) _servletContext.getAttribute(FACES_INIT_DONE);
 105  0
         if (b == null || b.booleanValue() == false)
 106  
         {
 107  0
             long start = System.currentTimeMillis();
 108  
 
 109  0
             if (_facesInitializer == null)
 110  
             {
 111  0
                 _facesInitializer = FacesInitializerFactory.getFacesInitializer(_servletContext);
 112  
             }
 113  
 
 114  
             // Create startup FacesContext before initializing
 115  0
             FacesContext facesContext = _facesInitializer.initStartupFacesContext(_servletContext);
 116  
 
 117  
             // publish the ManagedBeanDestroyerListener instance in the application map
 118  0
             _publishManagedBeanDestroyerListener(facesContext);
 119  
 
 120  0
             dispatchInitializationEvent(event, FACES_INIT_PHASE_PREINIT);
 121  0
             _facesInitializer.initFaces(_servletContext);
 122  0
             dispatchInitializationEvent(event, FACES_INIT_PHASE_POSTINIT);
 123  0
             _servletContext.setAttribute(FACES_INIT_DONE, Boolean.TRUE);
 124  
 
 125  
             // call contextInitialized on ManagedBeanDestroyerListener
 126  0
             _detroyerListener.contextInitialized(event);
 127  
 
 128  
             //Destroy startup FacesContext
 129  0
             _facesInitializer.destroyStartupFacesContext(facesContext);
 130  
 
 131  0
             log.log(Level.INFO, "MyFaces Core has started, it took ["
 132  
                     + (System.currentTimeMillis() - start)
 133  
                     + "] ms.");
 134  0
         }
 135  
         else
 136  
         {
 137  0
             log.info("MyFaces already initialized");
 138  
         }
 139  0
     }
 140  
 
 141  
     /**
 142  
      * Publishes the ManagedBeanDestroyerListener instance in the application map.
 143  
      * This allows the FacesConfigurator to access the instance and to set the
 144  
      * correct ManagedBeanDestroyer instance on it.
 145  
      *
 146  
      * @param facesContext
 147  
      */
 148  
     private void _publishManagedBeanDestroyerListener(FacesContext facesContext)
 149  
     {
 150  0
         ExternalContext externalContext = facesContext.getExternalContext();
 151  0
         Map<String, Object> applicationMap = externalContext.getApplicationMap();
 152  
 
 153  0
         applicationMap.put(ManagedBeanDestroyerListener.APPLICATION_MAP_KEY, _detroyerListener);
 154  0
     }
 155  
 
 156  
     public void contextDestroyed(ServletContextEvent event)
 157  
     {
 158  0
         if (_facesInitializer != null && _servletContext != null)
 159  
         {
 160  
             // Create startup FacesContext before start undeploy
 161  0
             FacesContext facesContext = _facesInitializer.initShutdownFacesContext(_servletContext);
 162  
 
 163  0
             dispatchInitializationEvent(event, FACES_INIT_PHASE_PREDESTROY);
 164  
             // call contextDestroyed on ManagedBeanDestroyerListener to destroy the attributes
 165  0
             _detroyerListener.contextDestroyed(event);
 166  
 
 167  0
             _facesInitializer.destroyFaces(_servletContext);
 168  
 
 169  0
             LifecycleProviderFactory.getLifecycleProviderFactory().release();
 170  
 
 171  
             // Destroy startup FacesContext, but note we do before publish postdestroy event on
 172  
             // plugins and before release factories.
 173  0
             if (facesContext != null)
 174  
             {
 175  0
                 _facesInitializer.destroyShutdownFacesContext(facesContext);
 176  
             }
 177  
 
 178  0
             FactoryFinder.releaseFactories();
 179  
 
 180  
             //DiscoverSingleton.release(); //clears EnvironmentCache and prevents leaking classloader references
 181  0
             dispatchInitializationEvent(event, FACES_INIT_PHASE_POSTDESTROY);
 182  
         }
 183  
 
 184  0
         _servletContext = null;
 185  0
     }
 186  
 
 187  
     /**
 188  
      * configure the faces initializer
 189  
      *
 190  
      * @param facesInitializer
 191  
      */
 192  
     public void setFacesInitializer(FacesInitializer facesInitializer) // TODO who uses this method?
 193  
     {
 194  0
         if (_facesInitializer != null && _facesInitializer != facesInitializer && _servletContext != null)
 195  
         {
 196  0
             _facesInitializer.destroyFaces(_servletContext);
 197  
         }
 198  0
         _facesInitializer = facesInitializer;
 199  0
         if (_servletContext != null)
 200  
         {
 201  0
             facesInitializer.initFaces(_servletContext);
 202  
         }
 203  0
     }
 204  
 
 205  
     /**
 206  
      * loads the faces init plugins per reflection and Service loader
 207  
      * in a jdk6 environment
 208  
      *
 209  
      * @return false in case of a failed attempt or no listeners found
 210  
      *         which then will cause the jdk5 context.xml code to trigger
 211  
      */
 212  
     private boolean loadFacesInitPluginsJDK6()
 213  
     {
 214  0
         String[] pluginEntries = null;
 215  
         try
 216  
         {
 217  0
             Class serviceLoader = ClassUtils.getContextClassLoader().loadClass("java.util.ServiceLoader");
 218  0
             Method m = serviceLoader.getDeclaredMethod("load", Class.class, ClassLoader.class);
 219  0
             Object loader = m.invoke(serviceLoader, StartupListener.class, ClassUtils.getContextClassLoader());
 220  0
             m = loader.getClass().getDeclaredMethod("iterator");
 221  0
             Iterator<StartupListener> it = (Iterator<StartupListener>) m.invoke(loader);
 222  0
             List<StartupListener> listeners = new LinkedList<StartupListener>();
 223  0
             if (!it.hasNext())
 224  
             {
 225  0
                 return false;
 226  
             }
 227  0
             while (it.hasNext())
 228  
             {
 229  0
                 listeners.add(it.next());
 230  
             }
 231  
             //StartupListener[] listeners1 = listeners.toArray(new StartupListener[listeners.size()]);
 232  0
             _servletContext.setAttribute(FACES_INIT_PLUGINS, listeners);
 233  0
             return true;
 234  
         }
 235  0
         catch (ClassNotFoundException e)
 236  
         {
 237  
 
 238  
         }
 239  0
         catch (NoSuchMethodException e)
 240  
         {
 241  0
             log.log(Level.SEVERE, e.getMessage(), e);
 242  
         }
 243  0
         catch (InvocationTargetException e)
 244  
         {
 245  0
             log.log(Level.SEVERE, e.getMessage(), e);
 246  
         }
 247  0
         catch (IllegalAccessException e)
 248  
         {
 249  0
             log.log(Level.SEVERE, e.getMessage(), e);
 250  0
         }
 251  0
         return false;
 252  
     }
 253  
 
 254  
     /**
 255  
      * loads the faces init plugins per reflection and Service loader
 256  
      * in a jdk6 environment
 257  
      */
 258  
     private void loadFacesInitPluginsJDK5()
 259  
     {
 260  
 
 261  0
         String plugins = (String) _servletContext.getInitParameter(FACES_INIT_PLUGINS);
 262  0
         if (plugins == null)
 263  
         {
 264  0
             return;
 265  
         }
 266  0
         log.info("MyFaces Plugins found");
 267  0
         String[] pluginEntries = plugins.split(",");
 268  0
         List<StartupListener> listeners = new ArrayList<StartupListener>(pluginEntries.length);
 269  0
         for (String pluginEntry : pluginEntries)
 270  
         {
 271  
             try
 272  
             {
 273  0
                 Class pluginClass = null;
 274  0
                 pluginClass = ClassUtils.getContextClassLoader().loadClass(pluginEntry);
 275  0
                 if (pluginClass == null)
 276  
                 {
 277  0
                     pluginClass = this.getClass().getClassLoader().loadClass(pluginEntry);
 278  
                 }
 279  0
                 listeners.add((StartupListener) pluginClass.newInstance());
 280  
             }
 281  0
             catch (ClassNotFoundException e)
 282  
             {
 283  0
                 log.log(Level.SEVERE, e.getMessage(), e);
 284  
             }
 285  0
             catch (InstantiationException e)
 286  
             {
 287  0
                 log.log(Level.SEVERE, e.getMessage(), e);
 288  
             }
 289  0
             catch (IllegalAccessException e)
 290  
             {
 291  0
                 log.log(Level.SEVERE, e.getMessage(), e);
 292  0
             }
 293  
         }
 294  
         // StartupListener[] listeners1 = listeners.toArray(new StartupListener[listeners.size()]);
 295  0
         _servletContext.setAttribute(FACES_INIT_PLUGINS, listeners);
 296  
 
 297  0
     }
 298  
 
 299  
     /**
 300  
      * the central initialisation event dispatcher which calls
 301  
      * our listeners
 302  
      *
 303  
      * @param event
 304  
      * @param operation
 305  
      */
 306  
     private void dispatchInitializationEvent(ServletContextEvent event, int operation)
 307  
     {
 308  
 
 309  0
         if (operation == FACES_INIT_PHASE_PREINIT)
 310  
         {
 311  0
             if (!loadFacesInitPluginsJDK6())
 312  
             {
 313  0
                 loadFacesInitPluginsJDK5();
 314  
             }
 315  
         }
 316  
 
 317  0
         List<StartupListener> pluginEntries = (List<StartupListener>) _servletContext.getAttribute(FACES_INIT_PLUGINS);
 318  0
         if (pluginEntries == null)
 319  
         {
 320  0
             return;
 321  
         }
 322  
 
 323  
         //now we process the plugins
 324  0
         for (StartupListener initializer : pluginEntries)
 325  
         {
 326  0
             log.info("Processing plugin");
 327  
 
 328  
             //for now the initializers have to be stateless to
 329  
             //so that we do not have to enforce that the initializer
 330  
             //must be serializable
 331  0
             switch (operation)
 332  
             {
 333  
                 case FACES_INIT_PHASE_PREINIT:
 334  0
                     initializer.preInit(event);
 335  0
                     break;
 336  
                 case FACES_INIT_PHASE_POSTINIT:
 337  0
                     initializer.postInit(event);
 338  0
                     break;
 339  
                 case FACES_INIT_PHASE_PREDESTROY:
 340  0
                     initializer.preDestroy(event);
 341  0
                     break;
 342  
                 default:
 343  0
                     initializer.postDestroy(event);
 344  
                     break;
 345  
             }
 346  0
         }
 347  0
         log.info("Processing MyFaces plugins done");
 348  0
     }
 349  
 
 350  
     /* the following methods are needed to serve ManagedBeanDestroyerListener */
 351  
     /* Session related methods ***********************************************/
 352  
 
 353  
     public void attributeAdded(HttpSessionBindingEvent event)
 354  
     {
 355  0
         _detroyerListener.attributeAdded(event);
 356  0
     }
 357  
 
 358  
     public void attributeRemoved(HttpSessionBindingEvent event)
 359  
     {
 360  0
         _detroyerListener.attributeRemoved(event);
 361  0
     }
 362  
 
 363  
     public void attributeReplaced(HttpSessionBindingEvent event)
 364  
     {
 365  0
         _detroyerListener.attributeReplaced(event);
 366  0
     }
 367  
 
 368  
     public void sessionCreated(HttpSessionEvent event)
 369  
     {
 370  0
         _detroyerListener.sessionCreated(event);
 371  0
     }
 372  
 
 373  
     public void sessionDestroyed(HttpSessionEvent event)
 374  
     {
 375  0
         _detroyerListener.sessionDestroyed(event);
 376  0
     }
 377  
 
 378  
     /* Context related methods ***********************************************/
 379  
 
 380  
     public void attributeAdded(ServletContextAttributeEvent event)
 381  
     {
 382  0
         _detroyerListener.attributeAdded(event);
 383  0
     }
 384  
 
 385  
     public void attributeRemoved(ServletContextAttributeEvent event)
 386  
     {
 387  0
         _detroyerListener.attributeRemoved(event);
 388  0
     }
 389  
 
 390  
     public void attributeReplaced(ServletContextAttributeEvent event)
 391  
     {
 392  0
         _detroyerListener.attributeReplaced(event);
 393  0
     }
 394  
 
 395  
     /* Request related methods ***********************************************/
 396  
 
 397  
     public void attributeAdded(ServletRequestAttributeEvent event)
 398  
     {
 399  0
         _detroyerListener.attributeAdded(event);
 400  0
     }
 401  
 
 402  
     public void attributeRemoved(ServletRequestAttributeEvent event)
 403  
     {
 404  0
         _detroyerListener.attributeRemoved(event);
 405  0
     }
 406  
 
 407  
     public void attributeReplaced(ServletRequestAttributeEvent event)
 408  
     {
 409  0
         _detroyerListener.attributeReplaced(event);
 410  0
     }
 411  
 
 412  
     public void requestInitialized(ServletRequestEvent event)
 413  
     {
 414  0
         _detroyerListener.requestInitialized(event);
 415  0
     }
 416  
 
 417  
     public void requestDestroyed(ServletRequestEvent event)
 418  
     {
 419  0
         _detroyerListener.requestDestroyed(event);
 420  0
     }
 421  
 
 422  
 }