http://java.net/jira/browse/GLASSFISH-11984 SECTION: Modified Files ---------------------------- M jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java remove attr Application from servletContext M jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java clear Application from the externalcontext M jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java M jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java removed the application field. It should not be saved since we need one per servletcontext. M jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java M jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java make sure the delegate is not saved as a field of this class. Call getDelegate() instead of delegate. getDelegate() makes sure its not null using reflection. M jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java SECTION: Diffs ---------------------------- Index: jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java =================================================================== --- jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (revision 8766) +++ jsf-ri/test/com/sun/faces/renderkit/TestRenderKit.java (working copy) @@ -470,6 +470,7 @@ 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 8766) +++ jsf-ri/test/com/sun/faces/config/ConfigureListenerTestCase.java (working copy) @@ -133,6 +133,7 @@ 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; @@ -254,6 +255,7 @@ 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); @@ -297,6 +299,7 @@ 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 8766) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.java (working copy) @@ -138,7 +138,7 @@ // Flag indicating that a response has been rendered. private boolean responseRendered = false; - private static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + + public static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + "ApplicationAssociate"; private static ThreadLocal instance = Index: jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (revision 8766) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationFactoryImpl.java (working copy) @@ -49,6 +49,7 @@ import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; +import javax.faces.context.FacesContext; /** *

ApplicationFactory is a factory object that creates @@ -66,31 +67,12 @@ // Log instance for this class private static final Logger logger = FacesLogger.APPLICATION.getLogger(); - // - // Protected Constants - // - // - // Class Variables - // - - // Attribute Instance Variables - - private volatile Application application; - - // Relationship Instance Variables - - // - // Constructors and Initializers - // - - /* * Constructor */ public ApplicationFactoryImpl() { super(); - application = null; if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "Created ApplicationFactory "); } @@ -102,7 +84,8 @@ * for this web application.

*/ public Application getApplication() { - + Application application = + (Application)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(ApplicationImpl.class.getName()); if (application == null) { application = new ApplicationImpl(); if (logger.isLoggable(Level.FINE)) { @@ -113,7 +96,7 @@ return application; } - + /** *

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

@@ -127,10 +110,14 @@ throw new NullPointerException(message); } - this.application = application; + 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()); + } 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/ApplicationImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (revision 8766) +++ jsf-ri/src/main/java/com/sun/faces/application/ApplicationImpl.java (working copy) @@ -40,6 +40,7 @@ package com.sun.faces.application; +import javax.servlet.ServletContext; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.Constructor; @@ -76,6 +77,7 @@ 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; @@ -234,7 +236,23 @@ } } + /** + * 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 8766) +++ jsf-ri/src/main/java/com/sun/faces/application/InjectionApplicationFactory.java (working copy) @@ -41,10 +41,15 @@ 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; @@ -53,6 +58,9 @@ 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} @@ -63,40 +71,84 @@ public class InjectionApplicationFactory extends ApplicationFactory implements FacesWrapper { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); - - private ApplicationFactory delegate; - private Application defaultApplication; - private Field defaultApplicationField; - private volatile Application application; - - + private static final String APPLICATION_FACTORY = RIConstants.FACES_PREFIX + "APPLICATION_FACTORY"; + private static String APPLICATION_FACTORY_CLASS = RIConstants.FACES_PREFIX + "APPLICATION_FACTORY_CLASS"; + // ------------------------------------------------------------ Constructors public InjectionApplicationFactory(ApplicationFactory delegate) { Util.notNull("applicationFactory", delegate); - this.delegate = delegate; + APPLICATION_FACTORY_CLASS = delegate.getClass().getName(); + FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().put(APPLICATION_FACTORY, delegate); } // ----------------------------------------- Methods from ApplicationFactory + private ApplicationFactory getDelegate() { + 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 static void clearInstance(ExternalContext + externalContext) { + Map applicationMap = externalContext.getApplicationMap(); + + applicationMap.remove(APPLICATION_FACTORY); + } + public Application getApplication() { - + + Application application = getDelegate().getApplication(); if (application == null) { - application = delegate.getApplication(); - if (application == null) { - // No i18n here + // No i18n here String message = MessageFormat .format("Delegate ApplicationContextFactory, {0}, returned null when calling getApplication().", - delegate.getClass().getName()); - throw new IllegalStateException(message); - } - injectDefaultApplication(); + getDelegate().getClass().getName()); + throw new IllegalStateException(message); } + + injectDefaultApplication(application); + return application; } @@ -104,10 +156,9 @@ public synchronized void setApplication(Application application) { - this.application = application; - delegate.setApplication(application); - injectDefaultApplication(); - + getDelegate().setApplication(application); + injectDefaultApplication(application); + } @@ -117,7 +168,7 @@ @Override public ApplicationFactory getWrapped() { - return delegate; + return getDelegate(); } @@ -125,25 +176,19 @@ // --------------------------------------------------------- Private Methods - private void injectDefaultApplication() { + private void injectDefaultApplication(Application application) { + Application defaultApplication; + Field defaultApplicationField; + FacesContext ctx = FacesContext.getCurrentInstance(); + String attrName = ApplicationImpl.class.getName(); + defaultApplication = (Application) ctx.getExternalContext().getApplicationMap().get(attrName); - if (defaultApplication == null) { - FacesContext ctx = FacesContext.getCurrentInstance(); - String attrName = ApplicationImpl.class.getName(); - defaultApplication = (Application) ctx.getExternalContext() - .getApplicationMap().get(attrName); - ctx.getExternalContext().getApplicationMap() - .remove(attrName); - } if (defaultApplication != null) { try { - if (defaultApplicationField == null) { - defaultApplicationField = - Application.class - .getDeclaredField("defaultApplication"); - defaultApplicationField.setAccessible(true); - } + defaultApplicationField = + Application.class.getDeclaredField("defaultApplication"); + defaultApplicationField.setAccessible(true); defaultApplicationField.set(application, defaultApplication); } catch (NoSuchFieldException nsfe) { Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (revision 8766) +++ jsf-ri/src/main/java/com/sun/faces/config/ConfigureListener.java (working copy) @@ -223,7 +223,9 @@ Verifier.setCurrentInstance(new Verifier()); } initScripting(); + configManager.initialize(context); + if (shouldInitConfigMonitoring()) { initConfigMonitoring(context); } @@ -342,8 +344,10 @@ e); } } finally { - ApplicationAssociate.clearInstance(context); + ApplicationAssociate.clearInstance(initContext.getExternalContext()); 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) {