Index: jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java =================================================================== --- jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java (revision 8821) +++ jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java (working copy) @@ -196,7 +196,13 @@ */ private ServletConfig servletConfig = null; + /** + * From JAVASERVERFACES-1914. If true, the FacesContext instance + * left over from startup time has been released. + */ + private boolean initFacesContextReleased = false; + /** *

Release all resources acquired at startup time.

*/ @@ -379,7 +385,15 @@ sendError(HttpServletResponse.SC_NOT_FOUND); return; } - } + } + + if (!initFacesContextReleased) { + FacesContext initFacesContext = FacesContext.getCurrentInstance(); + if (null != initFacesContext) { + initFacesContext.release(); + } + initFacesContextReleased = true; + } // Acquire the FacesContext instance for this request FacesContext context = facesContextFactory.getFacesContext Index: jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java =================================================================== --- jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (revision 8821) +++ jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (working copy) @@ -470,7 +470,6 @@ ServletContext servletContext = (ServletContext) ctx.getExternalContext().getContext(); FactoryFinder.releaseFactories(); servletContext.removeAttribute("com.sun.faces.ApplicationAssociate"); - servletContext.removeAttribute("com.sun.faces.application.ApplicationImpl"); ConfigManager config = ConfigManager.getInstance(); DocumentBuilderFactory factory = DbfFactory.getFactory(); Index: jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java =================================================================== --- jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java (revision 8821) +++ jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java (working copy) @@ -133,7 +133,6 @@ import com.sun.faces.cactus.ServletFacesTestCase; import com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter; import com.sun.faces.application.ApplicationAssociate; -import com.sun.faces.application.ApplicationImpl; import junit.framework.Test; import junit.framework.TestSuite; @@ -255,7 +254,6 @@ ServletContext ctx = (ServletContext) getFacesContext().getExternalContext().getContext(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); - ApplicationImpl.clearInstance(getFacesContext().getExternalContext()); ctx.removeAttribute("com.sun.faces.config.WebConfiguration"); ServletContextWrapper w = new ServletContextWrapper(ctx); ServletContextEvent sce = new ServletContextEvent(w); @@ -299,7 +297,6 @@ ServletContext ctx = (ServletContext) getFacesContext().getExternalContext().getContext(); ApplicationAssociate.clearInstance(getFacesContext().getExternalContext()); - ApplicationImpl.clearInstance(getFacesContext().getExternalContext()); ctx.removeAttribute("com.sun.faces.config.WebConfiguration"); ServletContextWrapper w = new ServletContextWrapper(ctx); ServletContextEvent sce = new ServletContextEvent(w); Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java (working copy) @@ -138,8 +138,7 @@ // Flag indicating that a response has been rendered. private boolean responseRendered = false; - public static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + - "ApplicationAssociate"; + private static final String ASSOCIATE_KEY = ApplicationAssociate.class.getName(); private static ThreadLocal instance = new ThreadLocal() { @@ -188,8 +187,11 @@ private NamedEventManager namedEventManager; + private ServletContextSensitiveSingletonStore appStore; + public ApplicationAssociate(ApplicationImpl appImpl) { app = appImpl; + appStore = new ServletContextSensitiveSingletonStore(ASSOCIATE_KEY); propertyEditorHelper = new PropertyEditorHelper(appImpl); @@ -200,12 +202,11 @@ MessageUtils.APPLICATION_ASSOCIATE_CTOR_WRONG_CALLSTACK_ID)); } ExternalContext externalContext = ctx.getExternalContext(); - if (null != externalContext.getApplicationMap().get(ASSOCIATE_KEY)) { - throw new IllegalStateException( - MessageUtils.getExceptionMessageString( - MessageUtils.APPLICATION_ASSOCIATE_EXISTS_ID)); + Object existingAssociate = appStore.getReferenceToSingleton(); + if (null != existingAssociate) { + throw new IllegalStateException("ApplicationAssociate already exists for this webapp."); } - externalContext.getApplicationMap().put(ASSOCIATE_KEY, this); + appStore.putSingletonReference(this); //noinspection CollectionWithoutInitialCapacity navigationMap = new ConcurrentHashMap>(); injectionProvider = (InjectionProvider) ctx.getAttributes().get(ConfigManager.INJECTION_PROVIDER_KEY); @@ -243,16 +244,18 @@ if (externalContext == null) { return null; } - Map applicationMap = externalContext.getApplicationMap(); - return ((ApplicationAssociate) - applicationMap.get(ASSOCIATE_KEY)); + ApplicationAssociate result = ((ApplicationAssociate) + ServletContextSensitiveSingletonStore.getReferenceToSingleton(externalContext, ASSOCIATE_KEY)); + return result; } public static ApplicationAssociate getInstance(ServletContext context) { if (context == null) { return null; } - return (ApplicationAssociate) context.getAttribute(ASSOCIATE_KEY); + ApplicationAssociate result = (ApplicationAssociate) + ServletContextSensitiveSingletonStore.getReferenceToSingleton(context, ASSOCIATE_KEY); + return result; } public static void setCurrentInstance(ApplicationAssociate associate) { @@ -322,24 +325,25 @@ public static void clearInstance(ExternalContext externalContext) { - Map applicationMap = externalContext.getApplicationMap(); - ApplicationAssociate me = (ApplicationAssociate) applicationMap.get(ASSOCIATE_KEY); + ApplicationAssociate me = (ApplicationAssociate) + ServletContextSensitiveSingletonStore.getReferenceToSingleton(externalContext, ASSOCIATE_KEY); if (null != me) { if (null != me.resourceBundles) { me.resourceBundles.clear(); } } - applicationMap.remove(ASSOCIATE_KEY); + ServletContextSensitiveSingletonStore.removeSingletonReference(externalContext, ASSOCIATE_KEY); } public static void clearInstance(ServletContext sc) { - ApplicationAssociate me = (ApplicationAssociate) sc.getAttribute(ASSOCIATE_KEY); + ApplicationAssociate me = (ApplicationAssociate) + ServletContextSensitiveSingletonStore.getReferenceToSingleton(sc, ASSOCIATE_KEY); if (null != me) { if (null != me.resourceBundles) { me.resourceBundles.clear(); } } - sc.removeAttribute(ASSOCIATE_KEY); + ServletContextSensitiveSingletonStore.removeSingletonReference(sc, ASSOCIATE_KEY); } Index: jsf-ri/src/main/java/com/sun/faces/application/WebappLifecycleListener.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/WebappLifecycleListener.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/application/WebappLifecycleListener.java (working copy) @@ -65,7 +65,9 @@ import com.sun.faces.io.FastStringWriter; import com.sun.faces.mgbean.BeanManager; import com.sun.faces.util.FacesLogger; +import java.util.Collections; import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.event.ExceptionQueuedEvent; @@ -73,6 +75,7 @@ import javax.faces.event.SystemEvent; import javax.faces.event.PreDestroyViewMapEvent; import javax.faces.event.ViewMapListener; +import javax.servlet.ServletContextListener; /** *

Central location for web application lifecycle events.

@@ -85,11 +88,14 @@ // Log instance for this class private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); + private static final String KEY = WebappLifecycleListener.class.getName(); + private ServletContext servletContext; private ApplicationAssociate applicationAssociate; private List activeSessions; + private List additionalListeners; + private ServletContextSensitiveSingletonStore appStore; - // ------------------------------------------------------------ Constructors @@ -98,10 +104,23 @@ public WebappLifecycleListener(ServletContext servletContext) { this.servletContext = servletContext; + additionalListeners = new CopyOnWriteArrayList(); + appStore = new ServletContextSensitiveSingletonStore(KEY); + appStore.putSingletonReference(this); + } + static WebappLifecycleListener getInstance(ServletContext sc) { + WebappLifecycleListener result = (WebappLifecycleListener) + ServletContextSensitiveSingletonStore.getReferenceToSingleton(sc, KEY); + + return result; } + List getAdditionalListeners() { + return additionalListeners; + } + // ---------------------------------------------------------- Public Methods /** @@ -369,6 +388,9 @@ servletContext.getAttribute(beanName), ELUtils.Scope.APPLICATION); } + for (ServletContextListener cur : getAdditionalListeners()) { + cur.contextDestroyed(event); + } this.applicationAssociate = null; } Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (working copy) @@ -46,6 +46,7 @@ import java.util.logging.Logger; import java.util.logging.Level; import java.text.MessageFormat; +import java.util.Map; import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; @@ -68,6 +69,10 @@ // Log instance for this class private static final Logger logger = FacesLogger.APPLICATION.getLogger(); + private static final String APPLICATION_KEY = ApplicationFactoryImpl.class.getName(); + + private ServletContextSensitiveSingletonStore appStore; + /* * Constructor */ @@ -76,27 +81,34 @@ if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Created ApplicationFactory "); } + appStore = new ServletContextSensitiveSingletonStore(APPLICATION_KEY); + } + Class getApplicationInstanceClass() { + return ApplicationImpl.class; + } + /** *

Create (if needed) and return an {@link Application} instance * for this web application.

*/ public Application getApplication() { - Application application = - (Application)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(ApplicationImpl.class.getName()); + Application application = appStore.getReferenceToSingleton(); + if (application == null) { application = new ApplicationImpl(); if (logger.isLoggable(Level.FINE)) { logger.fine(MessageFormat.format("Created Application instance ''{0}''", application)); } + appStore.putSingletonReference(application); } return application; } - + /** *

Replace the {@link Application} instance that will be * returned for this web application.

@@ -109,15 +121,14 @@ (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "application"); throw new NullPointerException(message); } + Map appMap = + FacesContext.getCurrentInstance().getExternalContext().getApplicationMap(); - FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(ApplicationImpl.class.getName(), application); - if (application instanceof ApplicationImpl) { - FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(ApplicationAssociate.ASSOCIATE_KEY, - ((com.sun.faces.application.ApplicationImpl) application).getApplicationAssociate()); - } + appStore.removeSingletonReference(); + appStore.putSingletonReference(application); if (logger.isLoggable(Level.FINE)) { - logger.fine(MessageFormat.format("set Application Instance to ''{0}''", - application.getClass().getName())); + logger.fine(MessageFormat.format("set Application Instance to ''{0}''", + application.getClass().getName())); } } } Index: jsf-ri/src/main/java/com/sun/faces/application/ServletContextSensitiveSingletonStore.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ServletContextSensitiveSingletonStore.java (revision 0) +++ jsf-ri/src/main/java/com/sun/faces/application/ServletContextSensitiveSingletonStore.java (revision 0) @@ -0,0 +1,159 @@ + +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.faces.application; + +import java.util.Collections; +import java.util.Map; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + + +/* + * This class is responsible for storing an instance of Application + * in a ServletContext instance such that the instance is a singleton + * within that ServletContext instance. + * + */ +@WebListener +class ServletContextSensitiveSingletonStore implements ServletContextListener { + + private final String key; + private Map appMap; + + private static final String KEY_BASE = + ServletContextSensitiveSingletonStore.class.getName(); + + public ServletContextSensitiveSingletonStore(String singletonKey) { + FacesContext facesContext = FacesContext.getCurrentInstance(); + ExternalContext extContext = facesContext.getExternalContext(); + if (null != facesContext) { + appMap = extContext.getApplicationMap(); + } else { + assert(false); + appMap = Collections.emptyMap(); + } + Object context = extContext.getContext(); + if (context instanceof ServletContext) { + ServletContext sc = (ServletContext) context; + WebappLifecycleListener listener = WebappLifecycleListener.getInstance(sc); + if (null != listener) { + listener.getAdditionalListeners().add(this); + } + } + + String keyForKey = KEY_BASE + singletonKey; + String candidateKey = (String) appMap.get(keyForKey); + // Is this the first time that this kind of singleton has been created + // for this ServletContext instance or any wrapped instance? + if (null == candidateKey) { + // if so, create the key... + this.key = singletonKey + context.hashCode(); + appMap.put(keyForKey, this.key); + } else { + this.key = candidateKey; + } + + } + + static Object getReferenceToSingleton(ExternalContext extContext, String key) { + Object result = null; + Map map = extContext.getApplicationMap(); + Object context = extContext.getContext(); + String keyVal = key + context.hashCode(); + result = map.get(keyVal); + + return result; + } + + static Object getReferenceToSingleton(ServletContext context, String key) { + Object result = null; + String keyVal = key + context.hashCode(); + result = context.getAttribute(keyVal); + + return result; + } + + S getReferenceToSingleton() { + S result = (S) appMap.get(key); + + return result; + } + + S removeSingletonReference() { + S result = (S) appMap.remove(key); + return result; + } + + static Object removeSingletonReference(ExternalContext extContext, String key) { + Object result = null; + Map map = extContext.getApplicationMap(); + Object context = extContext.getContext(); + String keyVal = key + context.hashCode(); + result = map.remove(keyVal); + + return result; + } + + static void removeSingletonReference(ServletContext context, String key) { + String keyVal = key + context.hashCode(); + context.removeAttribute(keyVal); + } + + + void putSingletonReference(S instance) { + appMap.put(key, instance); + } + + public void contextDestroyed(ServletContextEvent sce) { + removeSingletonReference(); + } + + public void contextInitialized(ServletContextEvent sce) { + } + + + +} Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (working copy) @@ -40,7 +40,6 @@ package com.sun.faces.application; -import javax.servlet.ServletContext; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.Constructor; @@ -77,7 +76,6 @@ import javax.faces.component.UIViewRoot; import javax.faces.component.behavior.Behavior; import javax.faces.context.FacesContext; -import javax.faces.context.ExternalContext; import javax.faces.convert.Converter; import javax.faces.convert.DateTimeConverter; import javax.faces.el.MethodBinding; @@ -223,8 +221,6 @@ elResolvers = new CompositeELResolver(); FacesContext ctx = FacesContext.getCurrentInstance(); - ctx.getExternalContext().getApplicationMap().put(this.getClass().getName(), - this); WebConfiguration webConfig = WebConfiguration.getInstance(ctx.getExternalContext()); passDefaultTimeZone = webConfig.isOptionEnabled(DateTimeConverterUsesSystemTimezone); registerPropertyEditors = webConfig.isOptionEnabled(RegisterConverterPropertyEditors); @@ -236,23 +232,7 @@ } } - /** - * method to return the ApplicationAssociate instance - * @return associate - */ - public ApplicationAssociate getApplicationAssociate() { - return associate; - } - public static void clearInstance(ServletContext sc) { - sc.removeAttribute(ApplicationImpl.class.getName()); - } - - public static void clearInstance(ExternalContext sc) { - sc.getApplicationMap().remove(ApplicationImpl.class.getName()); - } - - /** * @see javax.faces.application.Application#publishEvent(FacesContext, Class, Object) */ Index: jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java (working copy) @@ -41,26 +41,17 @@ package com.sun.faces.application; import java.lang.reflect.Field; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.ClassLoader; import java.util.logging.Level; import java.util.logging.Logger; import java.text.MessageFormat; -import java.util.Map; - import javax.faces.application.ApplicationFactory; import javax.faces.application.Application; -import javax.faces.context.FacesContext; import com.sun.faces.util.FacesLogger; import com.sun.faces.util.Util; import javax.faces.FacesWrapper; -import com.sun.faces.RIConstants; -import javax.faces.context.ExternalContext; - /** * This {@link javax.faces.application.ApplicationFactory} is responsible for injecting the * default {@link Application} instance into the top-level {@link Application} @@ -71,88 +62,51 @@ public class InjectionApplicationFactory extends ApplicationFactory implements FacesWrapper { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); - private static final String APPLICATION_FACTORY = RIConstants.FACES_PREFIX + "APPLICATION_FACTORY"; - private static String APPLICATION_FACTORY_CLASS = RIConstants.FACES_PREFIX + "APPLICATION_FACTORY_CLASS"; - + + private static final String APPLICATION_KEY = InjectionApplicationFactory.class.getName(); + private static final String DEFAULT_APPLICATION_KEY = + InjectionApplicationFactory.class.getPackage().getName() + ".DefaultApplication"; + + private ApplicationFactory delegate; + private Field defaultApplicationField; + // Store the Application instance we create + private ServletContextSensitiveSingletonStore appStore; + // Store the Application instance that is the default application instance + private ServletContextSensitiveSingletonStore defaultApplicationAppStore; + // ------------------------------------------------------------ Constructors public InjectionApplicationFactory(ApplicationFactory delegate) { Util.notNull("applicationFactory", delegate); - APPLICATION_FACTORY_CLASS = delegate.getClass().getName(); - FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(APPLICATION_FACTORY, delegate); + this.delegate = delegate; + appStore = new ServletContextSensitiveSingletonStore(APPLICATION_KEY); + defaultApplicationAppStore = + new ServletContextSensitiveSingletonStore(DEFAULT_APPLICATION_KEY); } // ----------------------------------------- Methods from ApplicationFactory - private ApplicationFactory getDelegate() { - //delegate is retrieved from externalContext's applicationMap - //if null, make use of the variable APPLICATION_FACTORY_CLASS to - //reflectively create a new delegate. - ApplicationFactory delegate = (ApplicationFactory)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(APPLICATION_FACTORY); - if (delegate == null) { - //this code gets executed when there are multiple virtual servers - //the assumption is that the delegate class has public constructors - String className = APPLICATION_FACTORY_CLASS; - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - try { - Class cl = loader.loadClass(className); - Constructor constructor = cl.getConstructor(new Class[] {ApplicationFactory.class}); - if (constructor != null) { - Object arglist[] = new Object[1]; - arglist[0] = new ApplicationFactoryImpl(); - delegate = (ApplicationFactory) constructor.newInstance(arglist); - } else { - //llok for default constructor - constructor = cl.getConstructor(new Class[] {}); - delegate = (ApplicationFactory) constructor.newInstance(); - } - - FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(APPLICATION_FACTORY, delegate); - } catch (ClassNotFoundException ce) { - String message = "ClassNotFoundException occurred : " + ce.getMessage(); - throw new IllegalStateException(message); - } catch (InstantiationException ie) { - String message = "InstantiationException occurred : " + ie.getMessage(); - throw new IllegalStateException(message); - } catch (InvocationTargetException le) { - String message = "InvocationTargetException occurred : " + le.getMessage(); - throw new IllegalStateException(message); - } catch (IllegalAccessException e) { - String message = "IllegalAccessException occurred : " + e.getMessage(); - throw new IllegalStateException(message); - } catch (NoSuchMethodException se) { - String message = "IllegalAccessException occurred : " + se.getMessage(); - throw new IllegalStateException(message); - } - } - return delegate; - } + public Application getApplication() { - public static void clearInstance(ExternalContext - externalContext) { - Map applicationMap = externalContext.getApplicationMap(); + Application application = appStore.getReferenceToSingleton(); - applicationMap.remove(APPLICATION_FACTORY); - } - - public Application getApplication() { - - Application application = getDelegate().getApplication(); if (application == null) { - // No i18n here + application = delegate.getApplication(); + appStore.putSingletonReference(application); + if (application == null) { + // No i18n here String message = MessageFormat .format("Delegate ApplicationContextFactory, {0}, returned null when calling getApplication().", - getDelegate().getClass().getName()); - throw new IllegalStateException(message); + delegate.getClass().getName()); + throw new IllegalStateException(message); + } + injectDefaultApplication(application); } - - injectDefaultApplication(application); - return application; } @@ -160,9 +114,10 @@ public synchronized void setApplication(Application application) { - getDelegate().setApplication(application); + delegate.setApplication(application); + appStore.putSingletonReference(application); injectDefaultApplication(application); - + } @@ -172,7 +127,7 @@ @Override public ApplicationFactory getWrapped() { - return getDelegate(); + return delegate; } @@ -180,20 +135,28 @@ // --------------------------------------------------------- Private Methods - private void injectDefaultApplication(Application application) { + private void injectDefaultApplication(Application toInject) { + if (!isInjectionNecessary(toInject)) { + return; + } - Application defaultApplication; - Field defaultApplicationField; - FacesContext ctx = FacesContext.getCurrentInstance(); - String attrName = ApplicationImpl.class.getName(); - defaultApplication = (Application) ctx.getExternalContext().getApplicationMap().get(attrName); + Application defaultApplication = defaultApplicationAppStore.getReferenceToSingleton(); + if (defaultApplication == null) { + ApplicationFactory defaultAppFactory = new ApplicationFactoryImpl(); + defaultApplication = defaultAppFactory.getApplication(); + defaultApplicationAppStore.putSingletonReference(toInject); + defaultAppFactory = null; + } if (defaultApplication != null) { try { - defaultApplicationField = - Application.class.getDeclaredField("defaultApplication"); - defaultApplicationField.setAccessible(true); - defaultApplicationField.set(application, defaultApplication); + if (defaultApplicationField == null) { + defaultApplicationField = + Application.class + .getDeclaredField("defaultApplication"); + defaultApplicationField.setAccessible(true); + } + defaultApplicationField.set(toInject, defaultApplication); } catch (NoSuchFieldException nsfe) { if (LOGGER.isLoggable(Level.FINE)) { @@ -207,4 +170,16 @@ } } + private boolean isInjectionNecessary(Application toInject) { + boolean result = false; + ApplicationFactoryImpl defaultFactory; + if (delegate instanceof ApplicationFactoryImpl) { + defaultFactory = (ApplicationFactoryImpl)delegate; + } else { + defaultFactory = new ApplicationFactoryImpl(); + } + result = !defaultFactory.getApplicationInstanceClass().equals(toInject.getClass()); + return result; + } + } Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (revision 8821) +++ jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (working copy) @@ -151,8 +151,8 @@ if (timer != null) { timer.startTiming(); } + InitFacesContext initContext = new InitFacesContext(context); - if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format( @@ -198,7 +198,6 @@ // bootstrap of faces required webAppListener = new WebappLifecycleListener(context); webAppListener.contextInitialized(sce); - InitFacesContext initContext = new InitFacesContext(context); ReflectionUtils.initCache(Thread.currentThread().getContextClassLoader()); Throwable caughtThrowable = null; @@ -223,9 +222,7 @@ Verifier.setCurrentInstance(new Verifier()); } initScripting(); - configManager.initialize(context); - if (shouldInitConfigMonitoring()) { initConfigMonitoring(context); } @@ -282,7 +279,6 @@ } finally { Verifier.setCurrentInstance(null); - initContext.release(); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "jsf.config.listener.version.complete"); @@ -344,10 +340,8 @@ e); } } finally { - ApplicationAssociate.clearInstance(initContext.getExternalContext()); + ApplicationAssociate.clearInstance(context); ApplicationAssociate.setCurrentInstance(null); - com.sun.faces.application.ApplicationImpl.clearInstance(initContext.getExternalContext()); - com.sun.faces.application.InjectionApplicationFactory.clearInstance(initContext.getExternalContext()); // Release the initialization mark on this web application ConfigManager.getInstance().destory(context); if (initContext != null) { Index: jsf-ri/build-tests.xml =================================================================== --- jsf-ri/build-tests.xml (revision 8821) +++ jsf-ri/build-tests.xml (working copy) @@ -544,7 +544,8 @@ - + + - + + + + + + + + - Index: jsf-ri/build.xml =================================================================== --- jsf-ri/build.xml (revision 8821) +++ jsf-ri/build.xml (working copy) @@ -674,10 +674,11 @@ - +