Coverage Report - javax.faces.FactoryFinder
 
Classes in this File Line Coverage Branch Coverage Complexity
FactoryFinder
55%
155/279
48%
42/86
6.55
FactoryFinder$1
0%
0/2
N/A
6.55
FactoryFinder$2
0%
0/2
N/A
6.55
 
 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 javax.faces;
 20  
 
 21  
 import javax.faces.application.ApplicationFactory;
 22  
 import javax.faces.component.visit.VisitContextFactory;
 23  
 import javax.faces.context.ExceptionHandlerFactory;
 24  
 import javax.faces.context.ExternalContextFactory;
 25  
 import javax.faces.context.FacesContext;
 26  
 import javax.faces.context.FacesContextFactory;
 27  
 import javax.faces.context.FlashFactory;
 28  
 import javax.faces.context.PartialViewContextFactory;
 29  
 import javax.faces.flow.FlowHandlerFactory;
 30  
 import javax.faces.lifecycle.ClientWindowFactory;
 31  
 import javax.faces.lifecycle.LifecycleFactory;
 32  
 import javax.faces.render.RenderKitFactory;
 33  
 import javax.faces.view.ViewDeclarationLanguageFactory;
 34  
 import javax.faces.view.facelets.FaceletCacheFactory;
 35  
 import javax.faces.view.facelets.TagHandlerDelegateFactory;
 36  
 import java.lang.reflect.Constructor;
 37  
 import java.lang.reflect.InvocationTargetException;
 38  
 import java.lang.reflect.Method;
 39  
 import java.security.AccessController;
 40  
 import java.util.ArrayList;
 41  
 import java.util.HashMap;
 42  
 import java.util.HashSet;
 43  
 import java.util.Iterator;
 44  
 import java.util.List;
 45  
 import java.util.Map;
 46  
 import java.util.Set;
 47  
 import java.util.concurrent.CopyOnWriteArrayList;
 48  
 import java.util.logging.Level;
 49  
 import java.util.logging.Logger;
 50  
 
 51  
 /**
 52  
  * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
 53  
  */
 54  
 public final class FactoryFinder
 55  
 {
 56  
     public static final String APPLICATION_FACTORY = "javax.faces.application.ApplicationFactory";
 57  
     public static final String EXCEPTION_HANDLER_FACTORY = "javax.faces.context.ExceptionHandlerFactory";
 58  
     public static final String EXTERNAL_CONTEXT_FACTORY = "javax.faces.context.ExternalContextFactory";
 59  
     public static final String FACES_CONTEXT_FACTORY = "javax.faces.context.FacesContextFactory";
 60  
     public static final String LIFECYCLE_FACTORY = "javax.faces.lifecycle.LifecycleFactory";
 61  
     public static final String PARTIAL_VIEW_CONTEXT_FACTORY = "javax.faces.context.PartialViewContextFactory";
 62  
     public static final String RENDER_KIT_FACTORY = "javax.faces.render.RenderKitFactory";
 63  
     public static final String TAG_HANDLER_DELEGATE_FACTORY = "javax.faces.view.facelets.TagHandlerDelegateFactory";
 64  
     public static final String VIEW_DECLARATION_LANGUAGE_FACTORY = "javax.faces.view.ViewDeclarationLanguageFactory";
 65  
     public static final String VISIT_CONTEXT_FACTORY = "javax.faces.component.visit.VisitContextFactory";
 66  
     public static final String FACELET_CACHE_FACTORY = "javax.faces.view.facelets.FaceletCacheFactory";
 67  
     public static final String FLASH_FACTORY = "javax.faces.context.FlashFactory";
 68  
     public static final String FLOW_HANDLER_FACTORY = "javax.faces.flow.FlowHandlerFactory";
 69  
     public static final String CLIENT_WINDOW_FACTORY = "javax.faces.lifecycle.ClientWindowFactory";
 70  
 
 71  
     /**
 72  
      * used as a monitor for itself and _factories. Maps in this map are used as monitors for themselves and the
 73  
      * corresponding maps in _factories.
 74  
      */
 75  2
     private static Map<ClassLoader, Map<String, List<String>>> registeredFactoryNames
 76  
             = new HashMap<ClassLoader, Map<String, List<String>>>();
 77  
 
 78  
     /**
 79  
      * Maps from classLoader to another map, the container (i.e. Tomcat) will create a class loader for each web app
 80  
      * that it controls (typically anyway) and that class loader is used as the key.
 81  
      * 
 82  
      * The secondary map maps the factory name (i.e. FactoryFinder.APPLICATION_FACTORY) to actual instances that are
 83  
      * created via getFactory. The instances will be of the class specified in the setFactory method for the factory
 84  
      * name, i.e. FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, MyFactory.class).
 85  
      */
 86  2
     private static Map<ClassLoader, Map<String, Object>> factories
 87  
             = new HashMap<ClassLoader, Map<String, Object>>();
 88  
 
 89  2
     private static final Set<String> VALID_FACTORY_NAMES = new HashSet<String>();
 90  2
     private static final Map<String, Class<?>> ABSTRACT_FACTORY_CLASSES = new HashMap<String, Class<?>>();
 91  
     private static final ClassLoader MYFACES_CLASSLOADER;
 92  
     
 93  
     private static final String INJECTION_PROVIDER_INSTANCE = "oam.spi.INJECTION_PROVIDER_KEY";
 94  
     private static final String INJECTED_BEAN_STORAGE_KEY = "org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";
 95  
     private static final String BEAN_ENTRY_CLASS_NAME = "org.apache.myfaces.cdi.dependent.BeanEntry";
 96  
 
 97  2
     private static final Logger LOGGER = Logger.getLogger(FactoryFinder.class.getName());
 98  
 
 99  
     static
 100  
     {
 101  2
         VALID_FACTORY_NAMES.add(APPLICATION_FACTORY);
 102  2
         VALID_FACTORY_NAMES.add(EXCEPTION_HANDLER_FACTORY);
 103  2
         VALID_FACTORY_NAMES.add(EXTERNAL_CONTEXT_FACTORY);
 104  2
         VALID_FACTORY_NAMES.add(FACES_CONTEXT_FACTORY);
 105  2
         VALID_FACTORY_NAMES.add(LIFECYCLE_FACTORY);
 106  2
         VALID_FACTORY_NAMES.add(PARTIAL_VIEW_CONTEXT_FACTORY);
 107  2
         VALID_FACTORY_NAMES.add(RENDER_KIT_FACTORY);
 108  2
         VALID_FACTORY_NAMES.add(TAG_HANDLER_DELEGATE_FACTORY);
 109  2
         VALID_FACTORY_NAMES.add(VIEW_DECLARATION_LANGUAGE_FACTORY);
 110  2
         VALID_FACTORY_NAMES.add(VISIT_CONTEXT_FACTORY);
 111  2
         VALID_FACTORY_NAMES.add(FACELET_CACHE_FACTORY);
 112  2
         VALID_FACTORY_NAMES.add(FLASH_FACTORY);
 113  2
         VALID_FACTORY_NAMES.add(FLOW_HANDLER_FACTORY);
 114  2
         VALID_FACTORY_NAMES.add(CLIENT_WINDOW_FACTORY);
 115  
         
 116  2
         ABSTRACT_FACTORY_CLASSES.put(APPLICATION_FACTORY, ApplicationFactory.class);
 117  2
         ABSTRACT_FACTORY_CLASSES.put(EXCEPTION_HANDLER_FACTORY, ExceptionHandlerFactory.class);
 118  2
         ABSTRACT_FACTORY_CLASSES.put(EXTERNAL_CONTEXT_FACTORY, ExternalContextFactory.class);
 119  2
         ABSTRACT_FACTORY_CLASSES.put(FACES_CONTEXT_FACTORY, FacesContextFactory.class);
 120  2
         ABSTRACT_FACTORY_CLASSES.put(LIFECYCLE_FACTORY, LifecycleFactory.class);
 121  2
         ABSTRACT_FACTORY_CLASSES.put(PARTIAL_VIEW_CONTEXT_FACTORY, PartialViewContextFactory.class);
 122  2
         ABSTRACT_FACTORY_CLASSES.put(RENDER_KIT_FACTORY, RenderKitFactory.class);
 123  2
         ABSTRACT_FACTORY_CLASSES.put(TAG_HANDLER_DELEGATE_FACTORY, TagHandlerDelegateFactory.class);
 124  2
         ABSTRACT_FACTORY_CLASSES.put(VIEW_DECLARATION_LANGUAGE_FACTORY, ViewDeclarationLanguageFactory.class);
 125  2
         ABSTRACT_FACTORY_CLASSES.put(VISIT_CONTEXT_FACTORY, VisitContextFactory.class);
 126  2
         ABSTRACT_FACTORY_CLASSES.put(FACELET_CACHE_FACTORY, FaceletCacheFactory.class);
 127  2
         ABSTRACT_FACTORY_CLASSES.put(FLASH_FACTORY, FlashFactory.class);
 128  2
         ABSTRACT_FACTORY_CLASSES.put(FLOW_HANDLER_FACTORY, FlowHandlerFactory.class);
 129  2
         ABSTRACT_FACTORY_CLASSES.put(CLIENT_WINDOW_FACTORY, ClientWindowFactory.class);
 130  
         try
 131  
         {
 132  
             ClassLoader classLoader;
 133  2
             if (System.getSecurityManager() != null)
 134  
             {
 135  0
                 classLoader = (ClassLoader) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction()
 136  0
                 {
 137  
                     public Object run()
 138  
                     {
 139  0
                         return FactoryFinder.class.getClassLoader();
 140  
                     }
 141  
                 });
 142  
             }
 143  
             else
 144  
             {
 145  2
                 classLoader = FactoryFinder.class.getClassLoader();
 146  
             }
 147  
 
 148  2
             if (classLoader == null)
 149  
             {
 150  0
                 throw new FacesException("jsf api class loader cannot be identified", null);
 151  
             }
 152  2
             MYFACES_CLASSLOADER = classLoader;
 153  
         }
 154  0
         catch (Exception e)
 155  
         {
 156  0
             throw new FacesException("jsf api class loader cannot be identified", e);
 157  2
         }
 158  
     }
 159  
 
 160  
     // ~ Start FactoryFinderProvider Support
 161  
     
 162  
     private static Object factoryFinderProviderFactoryInstance;
 163  
     
 164  2
     private static volatile boolean initialized = false;
 165  
     
 166  
     private static void initializeFactoryFinderProviderFactory()
 167  
     {
 168  7440
         if (!initialized)
 169  
         {
 170  2
             factoryFinderProviderFactoryInstance = _FactoryFinderProviderFactory.getInstance();
 171  2
             initialized = true;
 172  
         }
 173  7440
     }
 174  
 
 175  
     // ~ End FactoryFinderProvider Support
 176  
 
 177  
     // avoid instantiation
 178  
     FactoryFinder()
 179  0
     {
 180  0
     }
 181  
 
 182  
     /**
 183  
      * <p>
 184  
      * Create (if necessary) and return a per-web-application instance of the appropriate implementation class for the
 185  
      * specified JavaServer Faces factory class, based on the discovery algorithm described in the class description.
 186  
      * </p>
 187  
      * 
 188  
      * <p>
 189  
      * The standard factories and wrappers in JSF all implement the interface {@link FacesWrapper}. If the returned
 190  
      * <code>Object</code> is an implementation of one of the standard factories, it must be legal to cast it to an
 191  
      * instance of <code>FacesWrapper</code> and call {@link FacesWrapper#getWrapped()} on the instance.
 192  
      * </p>
 193  
      * 
 194  
      * @param factoryName
 195  
      *            Fully qualified name of the JavaServer Faces factory for which an implementation instance is requested
 196  
      * 
 197  
      * @return A per-web-application instance of the appropriate implementation class for the specified JavaServer Faces
 198  
      *         factory class
 199  
      * 
 200  
      * @throws FacesException
 201  
      *             if the web application class loader cannot be identified
 202  
      * @throws FacesException
 203  
      *             if an instance of the configured factory implementation class cannot be loaded
 204  
      * @throws FacesException
 205  
      *             if an instance of the configured factory implementation class cannot be instantiated
 206  
      * @throws IllegalArgumentException
 207  
      *             if <code>factoryname</code> does not identify a standard JavaServer Faces factory name
 208  
      * @throws IllegalStateException
 209  
      *             if there is no configured factory implementation class for the specified factory name
 210  
      * @throws NullPointerException
 211  
      *             if <code>factoryname</code> is null
 212  
      */
 213  
     public static Object getFactory(String factoryName) throws FacesException
 214  
     {
 215  2364
         if (factoryName == null)
 216  
         {
 217  0
             throw new NullPointerException("factoryName may not be null");
 218  
         }
 219  
         
 220  2364
         initializeFactoryFinderProviderFactory();
 221  
         
 222  2364
         if (factoryFinderProviderFactoryInstance == null)
 223  
         {
 224  
             // Do the typical stuff
 225  2364
             return _getFactory(factoryName);
 226  
         }
 227  
         else
 228  
         {
 229  
             try
 230  
             {
 231  
                 //Obtain the FactoryFinderProvider instance for this context.
 232  0
                 Object ffp = _FactoryFinderProviderFactory
 233  
                         .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
 234  
                         .invoke(factoryFinderProviderFactoryInstance, null);
 235  
                 
 236  
                 //Call getFactory method and pass the params
 237  0
                 return _FactoryFinderProviderFactory
 238  
                         .FACTORY_FINDER_PROVIDER_GET_FACTORY_METHOD.invoke(ffp, factoryName);
 239  
             }
 240  0
             catch (InvocationTargetException e)
 241  
             {
 242  0
                 Throwable targetException = e.getCause();
 243  0
                 if (targetException instanceof NullPointerException)
 244  
                 {
 245  0
                     throw (NullPointerException) targetException;
 246  
                 }
 247  0
                 else if (targetException instanceof FacesException)
 248  
                 {
 249  0
                     throw (FacesException) targetException;
 250  
                 }
 251  0
                 else if (targetException instanceof IllegalArgumentException)
 252  
                 {
 253  0
                     throw (IllegalArgumentException) targetException;
 254  
                 }
 255  0
                 else if (targetException instanceof IllegalStateException)
 256  
                 {
 257  0
                     throw (IllegalStateException) targetException;
 258  
                 }
 259  0
                 else if (targetException == null)
 260  
                 {
 261  0
                     throw new FacesException(e);
 262  
                 }
 263  
                 else
 264  
                 {
 265  0
                     throw new FacesException(targetException);
 266  
                 }
 267  
             }
 268  0
             catch (Exception e)
 269  
             {
 270  
                 //No Op
 271  0
                 throw new FacesException(e);
 272  
             }
 273  
         }
 274  
     }
 275  
 
 276  
     private static Object _getFactory(String factoryName) throws FacesException
 277  
     {
 278  2364
         ClassLoader classLoader = getClassLoader();
 279  
 
 280  
         // This code must be synchronized because this could cause a problem when
 281  
         // using update feature each time of myfaces (org.apache.myfaces.CONFIG_REFRESH_PERIOD)
 282  
         // In this moment, a concurrency problem could happen
 283  2364
         Map<String, List<String>> factoryClassNames = null;
 284  2364
         Map<String, Object> factoryMap = null;
 285  
 
 286  2364
         synchronized (registeredFactoryNames)
 287  
         {
 288  2364
             factoryClassNames = registeredFactoryNames.get(classLoader);
 289  
 
 290  2364
             if (factoryClassNames == null)
 291  
             {
 292  2
                 String message
 293  
                         = "No Factories configured for this Application. This happens if the faces-initialization "
 294  
                         + "does not work at all - make sure that you properly include all configuration "
 295  
                         + "settings necessary for a basic faces application "
 296  
                         + "and that all the necessary libs are included. Also check the logging output of your "
 297  
                         + "web application and your container for any exceptions!"
 298  
                         + "\nIf you did that and find nothing, the mistake might be due to the fact "
 299  
                         + "that you use some special web-containers which "
 300  
                         + "do not support registering context-listeners via TLD files and "
 301  
                         + "a context listener is not setup in your web.xml.\n"
 302  
                         + "A typical config looks like this;\n<listener>\n"
 303  
                         + "  <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>\n"
 304  
                         + "</listener>\n";
 305  2
                 throw new IllegalStateException(message);
 306  
             }
 307  
 
 308  2362
             if (!factoryClassNames.containsKey(factoryName))
 309  
             {
 310  2
                 throw new IllegalArgumentException("no factory " + factoryName + " configured for this application.");
 311  
             }
 312  
 
 313  2360
             factoryMap = factories.get(classLoader);
 314  
 
 315  2360
             if (factoryMap == null)
 316  
             {
 317  526
                 factoryMap = new HashMap<String, Object>();
 318  526
                 factories.put(classLoader, factoryMap);
 319  
             }
 320  2360
         }
 321  
 
 322  
         List beanEntryStorage;
 323  
 
 324  2360
         synchronized (factoryClassNames)
 325  
         {
 326  2360
             beanEntryStorage = (List)factoryMap.get(INJECTED_BEAN_STORAGE_KEY);
 327  
 
 328  2360
             if (beanEntryStorage == null)
 329  
             {
 330  526
                 beanEntryStorage = new CopyOnWriteArrayList();
 331  526
                 factoryMap.put(INJECTED_BEAN_STORAGE_KEY, beanEntryStorage);
 332  
             }
 333  2360
         }
 334  
 
 335  
         List<String> classNames;
 336  
         Object factory;
 337  
         Object injectionProvider;
 338  2360
         synchronized (factoryClassNames)
 339  
         {
 340  2360
             factory = factoryMap.get(factoryName);
 341  2360
             if (factory != null)
 342  
             {
 343  272
                 return factory;
 344  
             }
 345  
 
 346  2088
             classNames = factoryClassNames.get(factoryName);
 347  
             
 348  2088
             injectionProvider = factoryMap.get(INJECTION_PROVIDER_INSTANCE);
 349  2088
         }
 350  
 
 351  2088
         if (injectionProvider == null)
 352  
         {
 353  2088
             injectionProvider = getInjectionProvider();
 354  2088
             synchronized (factoryClassNames)
 355  
             {
 356  2088
                 factoryMap.put(INJECTION_PROVIDER_INSTANCE, injectionProvider);
 357  2088
             }
 358  
         }
 359  
 
 360  
         // release lock while calling out
 361  2088
         factory = newFactoryInstance(ABSTRACT_FACTORY_CLASSES.get(factoryName), 
 362  
             classNames.iterator(), classLoader, injectionProvider, beanEntryStorage);
 363  
 
 364  2088
         synchronized (factoryClassNames)
 365  
         {
 366  
             // check if someone else already installed the factory
 367  2088
             if (factoryMap.get(factoryName) == null)
 368  
             {
 369  2088
                 factoryMap.put(factoryName, factory);
 370  
             }
 371  2088
         }
 372  
 
 373  2088
         return factory;
 374  
     }
 375  
     
 376  
     private static Object getInjectionProvider()
 377  
     {
 378  
         try
 379  
         {
 380  
             // Remember the first call in a webapp over FactoryFinder.getFactory(...) comes in the 
 381  
             // initialization block, so there is a startup FacesContext active and
 382  
             // also a valid startup ExternalContext. Note after that, we need to cache
 383  
             // the injection provider for the classloader, because in a normal
 384  
             // request there is no active FacesContext in the moment and this call will
 385  
             // surely fail.
 386  2088
             FacesContext facesContext = FacesContext.getCurrentInstance();
 387  2088
             if (facesContext != null)
 388  
             {
 389  1054
                 Object injectionProviderFactory =
 390  
                     _FactoryFinderProviderFactory.INJECTION_PROVIDER_FACTORY_GET_INSTANCE_METHOD
 391  
                         .invoke(_FactoryFinderProviderFactory.INJECTION_PROVIDER_CLASS);
 392  0
                 Object injectionProvider = 
 393  
                     _FactoryFinderProviderFactory.INJECTION_PROVIDER_FACTORY_GET_INJECTION_PROVIDER_METHOD
 394  
                         .invoke(injectionProviderFactory, facesContext.getExternalContext());
 395  0
                 return injectionProvider;
 396  
             }
 397  
         }
 398  1054
         catch (Exception e)
 399  
         {
 400  1034
         }
 401  2088
         return null;
 402  
     }
 403  
     
 404  
     private static void injectAndPostConstruct(Object injectionProvider, Object instance, List injectedBeanStorage)
 405  
     {
 406  2088
         if (injectionProvider != null)
 407  
         {
 408  
             try
 409  
             {
 410  0
                 Object creationMetaData = _FactoryFinderProviderFactory.INJECTION_PROVIDER_INJECT_METHOD.invoke(
 411  
                     injectionProvider, instance);
 412  
 
 413  0
                 addBeanEntry(instance, creationMetaData, injectedBeanStorage);
 414  
 
 415  0
                 _FactoryFinderProviderFactory.INJECTION_PROVIDER_POST_CONSTRUCT_METHOD.invoke(
 416  
                     injectionProvider, instance, creationMetaData);
 417  
             }
 418  0
             catch (Exception ex)
 419  
             {
 420  0
                 throw new FacesException(ex);
 421  0
             }
 422  
         }
 423  2088
     }
 424  
     
 425  
     private static void preDestroy(Object injectionProvider, Object beanEntry)
 426  
     {
 427  0
         if (injectionProvider != null)
 428  
         {
 429  
             try
 430  
             {
 431  0
                 _FactoryFinderProviderFactory.INJECTION_PROVIDER_PRE_DESTROY_METHOD.invoke(
 432  
                     injectionProvider, getInstance(beanEntry), getCreationMetaData(beanEntry));
 433  
             }
 434  0
             catch (Exception ex)
 435  
             {
 436  0
                 throw new FacesException(ex);
 437  0
             }
 438  
         }
 439  0
     }
 440  
 
 441  
     private static Object getInstance(Object beanEntry)
 442  
     {
 443  
         try
 444  
         {
 445  0
             Method getterMethod = getMethod(beanEntry, "getInstance");
 446  0
             return getterMethod.invoke(beanEntry);
 447  
         }
 448  0
         catch (Exception e)
 449  
         {
 450  0
             throw new IllegalStateException(e);
 451  
         }
 452  
     }
 453  
 
 454  
     private static Object getCreationMetaData(Object beanEntry)
 455  
     {
 456  
         try
 457  
         {
 458  0
             Method getterMethod = getMethod(beanEntry, "getCreationMetaData");
 459  0
             return getterMethod.invoke(beanEntry);
 460  
         }
 461  0
         catch (Exception e)
 462  
         {
 463  0
             throw new IllegalStateException(e);
 464  
         }
 465  
     }
 466  
 
 467  
     private static Method getMethod(Object beanEntry, String methodName) throws NoSuchMethodException
 468  
     {
 469  0
         return beanEntry.getClass().getDeclaredMethod(methodName);
 470  
     }
 471  
 
 472  
     private static void addBeanEntry(Object instance, Object creationMetaData, List injectedBeanStorage)
 473  
     {
 474  
         try
 475  
         {
 476  0
             Class<?> beanEntryClass = _FactoryFinderProviderFactory.classForName(BEAN_ENTRY_CLASS_NAME);
 477  0
             Constructor beanEntryConstructor = beanEntryClass.getDeclaredConstructor(Object.class, Object.class);
 478  
 
 479  0
             Object result = beanEntryConstructor.newInstance(instance, creationMetaData);
 480  0
             injectedBeanStorage.add(result);
 481  
         }
 482  0
         catch (Exception e)
 483  
         {
 484  0
             throw new RuntimeException(e);
 485  0
         }
 486  0
     }
 487  
 
 488  
     private static Object newFactoryInstance(Class<?> interfaceClass, Iterator<String> classNamesIterator,
 489  
                                              ClassLoader classLoader, Object injectionProvider,
 490  
                                              List injectedBeanStorage)
 491  
     {
 492  
         try
 493  
         {
 494  2088
             Object current = null;
 495  
             
 496  4176
             while (classNamesIterator.hasNext())
 497  
             {
 498  2088
                 String implClassName = classNamesIterator.next();
 499  2088
                 Class<?> implClass = null;
 500  
                 try
 501  
                 {
 502  2088
                     implClass = classLoader.loadClass(implClassName);
 503  
                 }
 504  0
                 catch (ClassNotFoundException e)
 505  
                 {
 506  0
                     implClass = MYFACES_CLASSLOADER.loadClass(implClassName);
 507  2088
                 }
 508  
 
 509  
                 // check, if class is of expected interface type
 510  2088
                 if (!interfaceClass.isAssignableFrom(implClass))
 511  
                 {
 512  0
                     throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
 513  
                 }
 514  
 
 515  2088
                 if (current == null)
 516  
                 {
 517  
                     // nothing to decorate
 518  2088
                     current = implClass.newInstance();
 519  2088
                     injectAndPostConstruct(injectionProvider, current, injectedBeanStorage);
 520  
                 }
 521  
                 else
 522  
                 {
 523  
                     // let's check if class supports the decorator pattern
 524  
                     try
 525  
                     {
 526  0
                         Constructor<?> delegationConstructor = implClass.getConstructor(new Class[] { interfaceClass });
 527  
                         // impl class supports decorator pattern,
 528  
                         try
 529  
                         {
 530  
                             // create new decorator wrapping current
 531  0
                             current = delegationConstructor.newInstance(new Object[] { current });
 532  0
                             injectAndPostConstruct(injectionProvider, current, injectedBeanStorage);
 533  
                         }
 534  0
                         catch (InstantiationException e)
 535  
                         {
 536  0
                             throw new FacesException(e);
 537  
                         }
 538  0
                         catch (IllegalAccessException e)
 539  
                         {
 540  0
                             throw new FacesException(e);
 541  
                         }
 542  0
                         catch (InvocationTargetException e)
 543  
                         {
 544  0
                             throw new FacesException(e);
 545  0
                         }
 546  
                     }
 547  0
                     catch (NoSuchMethodException e)
 548  
                     {
 549  
                         // no decorator pattern support
 550  0
                         current = implClass.newInstance();
 551  0
                         injectAndPostConstruct(injectionProvider, current, injectedBeanStorage);
 552  0
                     }
 553  
                 }
 554  2088
             }
 555  
 
 556  2088
             return current;
 557  
         }
 558  0
         catch (ClassNotFoundException e)
 559  
         {
 560  0
             throw new FacesException(e);
 561  
         }
 562  0
         catch (InstantiationException e)
 563  
         {
 564  0
             throw new FacesException(e);
 565  
         }
 566  0
         catch (IllegalAccessException e)
 567  
         {
 568  0
             throw new FacesException(e);
 569  
         }
 570  
     }
 571  
 
 572  
     public static void setFactory(String factoryName, String implName)
 573  
     {
 574  4000
         if (factoryName == null)
 575  
         {
 576  0
             throw new NullPointerException("factoryName may not be null");
 577  
         }
 578  
         
 579  4000
         initializeFactoryFinderProviderFactory();
 580  
         
 581  4000
         if (factoryFinderProviderFactoryInstance == null)
 582  
         {
 583  
             // Do the typical stuff
 584  4000
             _setFactory(factoryName, implName);
 585  
         }
 586  
         else
 587  
         {
 588  
             try
 589  
             {
 590  
                 //Obtain the FactoryFinderProvider instance for this context.
 591  0
                 Object ffp = _FactoryFinderProviderFactory
 592  
                         .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
 593  
                         .invoke(factoryFinderProviderFactoryInstance, null);
 594  
                 
 595  
                 //Call getFactory method and pass the params
 596  0
                 _FactoryFinderProviderFactory
 597  
                         .FACTORY_FINDER_PROVIDER_SET_FACTORY_METHOD.invoke(ffp, factoryName, implName);
 598  
             }
 599  0
             catch (InvocationTargetException e)
 600  
             {
 601  0
                 Throwable targetException = e.getCause();
 602  0
                 if (targetException instanceof NullPointerException)
 603  
                 {
 604  0
                     throw (NullPointerException) targetException;
 605  
                 }
 606  0
                 else if (targetException instanceof FacesException)
 607  
                 {
 608  0
                     throw (FacesException) targetException;
 609  
                 }
 610  0
                 else if (targetException instanceof IllegalArgumentException)
 611  
                 {
 612  0
                     throw (IllegalArgumentException) targetException;
 613  
                 }
 614  0
                 else if (targetException == null)
 615  
                 {
 616  0
                     throw new FacesException(e);
 617  
                 }
 618  
                 else
 619  
                 {
 620  0
                     throw new FacesException(targetException);
 621  
                 }
 622  
             }
 623  0
             catch (Exception e)
 624  
             {
 625  
                 //No Op
 626  0
                 throw new FacesException(e);
 627  0
             }
 628  
             
 629  
         }
 630  3998
     }
 631  
 
 632  
     private static void _setFactory(String factoryName, String implName)
 633  
     {
 634  4000
         checkFactoryName(factoryName);
 635  
 
 636  3998
         ClassLoader classLoader = getClassLoader();
 637  3998
         Map<String, List<String>> factoryClassNames = null;
 638  3998
         synchronized (registeredFactoryNames)
 639  
         {
 640  3998
             Map<String, Object> factories = FactoryFinder.factories.get(classLoader);
 641  
 
 642  3998
             if (factories != null && factories.containsKey(factoryName))
 643  
             {
 644  
                 // Javadoc says ... This method has no effect if getFactory() has already been
 645  
                 // called looking for a factory for this factoryName.
 646  12
                 return;
 647  
             }
 648  
 
 649  3986
             factoryClassNames = registeredFactoryNames.get(classLoader);
 650  
 
 651  3986
             if (factoryClassNames == null)
 652  
             {
 653  532
                 factoryClassNames = new HashMap<String, List<String>>();
 654  532
                 registeredFactoryNames.put(classLoader, factoryClassNames);
 655  
             }
 656  3986
         }
 657  
 
 658  3986
         synchronized (factoryClassNames)
 659  
         {
 660  3986
             List<String> classNameList = factoryClassNames.get(factoryName);
 661  
 
 662  3986
             if (classNameList == null)
 663  
             {
 664  3984
                 classNameList = new ArrayList<String>();
 665  3984
                 factoryClassNames.put(factoryName, classNameList);
 666  
             }
 667  
 
 668  3986
             classNameList.add(implName);
 669  3986
         }
 670  3986
     }
 671  
 
 672  
     public static void releaseFactories() throws FacesException
 673  
     {
 674  1076
         initializeFactoryFinderProviderFactory();
 675  
         
 676  1076
         if (factoryFinderProviderFactoryInstance == null)
 677  
         {
 678  
             // Do the typical stuff
 679  1076
             _releaseFactories();
 680  
         }
 681  
         else
 682  
         {
 683  
             try
 684  
             {
 685  
                 //Obtain the FactoryFinderProvider instance for this context.
 686  0
                 Object ffp = _FactoryFinderProviderFactory
 687  
                         .FACTORY_FINDER_PROVIDER_FACTORY_GET_FACTORY_FINDER_METHOD
 688  
                         .invoke(factoryFinderProviderFactoryInstance, null);
 689  
                 
 690  
                 //Call getFactory method and pass the params
 691  0
                 _FactoryFinderProviderFactory.FACTORY_FINDER_PROVIDER_RELEASE_FACTORIES_METHOD.invoke(ffp, null);
 692  
             }
 693  0
             catch (InvocationTargetException e)
 694  
             {
 695  0
                 Throwable targetException = e.getCause();
 696  0
                 if (targetException instanceof FacesException)
 697  
                 {
 698  0
                     throw (FacesException) targetException;
 699  
                 }
 700  0
                 else if (targetException == null)
 701  
                 {
 702  0
                     throw new FacesException(e);
 703  
                 }
 704  
                 else
 705  
                 {
 706  0
                     throw new FacesException(targetException);
 707  
                 }
 708  
             }
 709  0
             catch (Exception e)
 710  
             {
 711  
                 //No Op
 712  0
                 throw new FacesException(e);
 713  0
             }
 714  
             
 715  
         }
 716  1076
     }
 717  
 
 718  
     private static void _releaseFactories() throws FacesException
 719  
     {
 720  1076
         ClassLoader classLoader = getClassLoader();
 721  
 
 722  
         Map<String, Object> factoryMap;
 723  
         // This code must be synchronized
 724  1076
         synchronized (registeredFactoryNames)
 725  
         {
 726  1076
             factoryMap = factories.remove(classLoader);
 727  
 
 728  
             // _registeredFactoryNames has as value type Map<String,List> and this must
 729  
             // be cleaned before release (for gc).
 730  1076
             Map<String, List<String>> factoryClassNames = registeredFactoryNames.get(classLoader);
 731  1076
             if (factoryClassNames != null)
 732  
             {
 733  532
                 factoryClassNames.clear();
 734  
             }
 735  
 
 736  1076
             registeredFactoryNames.remove(classLoader);
 737  1076
         }
 738  
 
 739  1076
         if (factoryMap != null)
 740  
         {
 741  526
             Object injectionProvider = factoryMap.remove(INJECTION_PROVIDER_INSTANCE);
 742  526
             if (injectionProvider != null)
 743  
             {
 744  0
                 List injectedBeanStorage = (List)factoryMap.get(INJECTED_BEAN_STORAGE_KEY);
 745  
 
 746  0
                 FacesException firstException = null;
 747  0
                 for (Object entry : injectedBeanStorage)
 748  
                 {
 749  
                     try
 750  
                     {
 751  0
                         preDestroy(injectionProvider, entry);
 752  
                     }
 753  0
                     catch (FacesException e)
 754  
                     {
 755  0
                         LOGGER.log(Level.SEVERE, "#preDestroy failed", e);
 756  
 
 757  0
                         if (firstException == null)
 758  
                         {
 759  0
                             firstException = e; //all preDestroy callbacks need to get invoked
 760  
                         }
 761  0
                     }
 762  0
                 }
 763  0
                 injectedBeanStorage.clear();
 764  
 
 765  0
                 if (firstException != null)
 766  
                 {
 767  0
                     throw firstException;
 768  
                 }
 769  
             }
 770  
         }
 771  1076
     }
 772  
 
 773  
     private static void checkFactoryName(String factoryName)
 774  
     {
 775  4000
         if (!VALID_FACTORY_NAMES.contains(factoryName))
 776  
         {
 777  2
             throw new IllegalArgumentException("factoryName '" + factoryName + "'");
 778  
         }
 779  3998
     }
 780  
 
 781  
     private static ClassLoader getClassLoader()
 782  
     {
 783  
         try
 784  
         {
 785  7438
             ClassLoader classLoader = null;
 786  7438
             if (System.getSecurityManager() != null)
 787  
             {
 788  0
                 classLoader = (ClassLoader) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction()
 789  0
                 {
 790  
                     public Object run()
 791  
                     {
 792  0
                         return Thread.currentThread().getContextClassLoader();
 793  
                     }
 794  
                 });
 795  
             }
 796  
             else
 797  
             {
 798  7438
                 classLoader = Thread.currentThread().getContextClassLoader();
 799  
             }
 800  
             
 801  7438
             if (classLoader == null)
 802  
             {
 803  0
                 throw new FacesException("web application class loader cannot be identified", null);
 804  
             }
 805  7438
             return classLoader;
 806  
         }
 807  0
         catch (Exception e)
 808  
         {
 809  0
             throw new FacesException("web application class loader cannot be identified", e);
 810  
         }
 811  
     }
 812  
 }