Index: nbproject/project.xml =================================================================== --- nbproject/project.xml (revision 8854) +++ nbproject/project.xml (working copy) @@ -18,6 +18,10 @@ UTF-8 + + /Users/edburns/Documents/chaff/netbeans-hack-links/jsf-api-test + + java jsf-ri/build/generate @@ -47,6 +51,12 @@ jsf-ri/test UTF-8 + + + java + /Users/edburns/Documents/chaff/netbeans-hack-links/jsf-api-test + UTF-8 + @@ -88,6 +98,10 @@ jsf-ri/test + + + /Users/edburns/Documents/chaff/netbeans-hack-links/jsf-api-test + build.xml @@ -109,7 +123,8 @@ jsf-ri/test jsf-api/build/generate jsf-ri/build/generate - dependencies/jars/jsp-api-2.1.jar:dependencies/jars/jstl-1.2.jar:dependencies/jars/validation-api-1.0.0.GA.jar:dependencies/jars/servlet-api-3.0.20100224.jar:dependencies/jars/groovy-all-1.6.9.jar:dependencies/jars/junit-3.8.1.jar:lib/jsf-extensions-test-time.jar:lib/cactus-1.7.1-javaee5.jar:dependencies/jars/cdi-api-1.0-SP1.jar:dependencies/jars/javax.inject-1.0-PFD-1.jar:${container.home}/modules/el-impl.jar:${container.home}/modules/bean-validator.jar:${container.home}/modules/javax.servlet.jsp.jar:${container.home}/modules/javax.servlet.jar + /Users/edburns/Documents/chaff/netbeans-hack-links/jsf-api-test + jsf-api/build/classes:dependencies/jars/jsp-api-2.1.jar:dependencies/jars/jstl-1.2.jar:dependencies/jars/validation-api-1.0.0.GA.jar:dependencies/jars/servlet-api-3.0.20100224.jar:dependencies/jars/groovy-all-1.6.9.jar:dependencies/jars/junit-3.8.1.jar:lib/jsf-extensions-test-time.jar:lib/cactus-1.7.1-javaee5.jar:dependencies/jars/cdi-api-1.0-SP1.jar:dependencies/jars/javax.inject-1.0-PFD-1.jar:/Users/edburns/Documents/JavaEE/runtimes/glassfish-3.1-mojarra-shared/glassfish3/glassfish/modules/el-impl.jar:/Users/edburns/Documents/JavaEE/runtimes/glassfish-3.1-mojarra-shared/glassfish3/glassfish/modules/bean-validator.jar:/Users/edburns/Documents/JavaEE/runtimes/glassfish-3.1-mojarra-shared/glassfish3/glassfish/modules/javax.servlet.jsp.jar:/Users/edburns/Documents/JavaEE/runtimes/glassfish-3.1-mojarra-shared/glassfish3/glassfish/modules/javax.servlet.jar 1.5 Index: jsf-api/src/test/java/javax/faces/component/NamingContainerTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/component/NamingContainerTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/component/NamingContainerTestCase.java (working copy) @@ -58,6 +58,7 @@ import java.util.HashMap; import java.util.Map; import javax.faces.FactoryFinder; +import javax.faces.TestUtil; import javax.faces.application.ApplicationFactory; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; @@ -104,7 +105,7 @@ // Set up instance variables required by this test case. - public void setUp() { + public void setUp() throws Exception { // Set up Servlet API Objects servletContext = new MockServletContext(); @@ -117,6 +118,8 @@ request.setAttribute("reqScopeName", "reqScopeValue"); response = new MockHttpServletResponse(); + TestUtil.injectServletContextIntoFactoryFinder(servletContext); + // Set up Faces API Objects FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, "com.sun.faces.mock.MockApplicationFactory"); @@ -148,7 +151,6 @@ Map map = new HashMap(); externalContext.setRequestParameterMap(map); - } @@ -163,9 +165,21 @@ // Tear down instance variables required by this test case. - public void tearDown() { + public void tearDown() throws Exception { + FactoryFinder.releaseFactories(); + TestUtil.injectServletContextIntoFactoryFinder(null); + facesContext.release(); root = null; + application = null; + config = null; + externalContext = null; + facesContext = null; + lifecycle = null; + request = null; + response = null; + servletContext = null; + session = null; } Index: jsf-api/src/test/java/javax/faces/component/UIViewRootTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/component/UIViewRootTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/component/UIViewRootTestCase.java (working copy) @@ -65,6 +65,7 @@ import javax.el.ValueExpression; import javax.el.MethodExpression; +import javax.faces.TestUtil; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; @@ -117,7 +118,7 @@ } }; - public void setUp() { + public void setUp() throws Exception { FactoryFinder.releaseFactories(); super.setUp(); for (int i = 0, len = FACTORIES.length; i < len; i++) { @@ -126,6 +127,7 @@ FactoryFinder.releaseFactories(); int len, i = 0; + TestUtil.injectServletContextIntoFactoryFinder(servletContext); // simulate the "faces implementation specific" part for (i = 0, len = FACTORIES.length; i < len; i++) { @@ -152,7 +154,10 @@ /** * Tear down instance variables required by this test case. */ - public void tearDown() { + public void tearDown() throws Exception { + FactoryFinder.releaseFactories(); + TestUtil.injectServletContextIntoFactoryFinder(null); + facesContext.release(); component = null; @@ -812,25 +817,6 @@ } - // These overrides are necessary because our normal setup - // calls releaseFactories, which makes it impossible to get clientIds. - - public void testInvokeOnComponentPositive() throws Exception { - super.setUp(); - super.testInvokeOnComponentPositive(); - } - - public void testInvokeOnComponentNegative() throws Exception { - super.setUp(); - super.testInvokeOnComponentNegative(); - } - - public void testInvokeOnComponentWithPrependId() throws Exception { - super.setUp(); - super.testInvokeOnComponentWithPrependId(); - } - - @Override public void testChildrenListAfterAddViewPublish() { Index: jsf-api/src/test/java/javax/faces/component/UIComponentBaseTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/component/UIComponentBaseTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/component/UIComponentBaseTestCase.java (working copy) @@ -88,7 +88,7 @@ // Set up instance variables required by this test case. - public void setUp() { + public void setUp() throws Exception { // Set up the component under test super.setUp(); @@ -104,7 +104,7 @@ // Tear down instance variables required by ths test case - public void tearDown() { + public void tearDown() throws Exception { externalContext.setRequestParameterMap(null); super.tearDown(); Index: jsf-api/src/test/java/javax/faces/component/UIComponentTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/component/UIComponentTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/component/UIComponentTestCase.java (working copy) @@ -60,6 +60,7 @@ import javax.faces.validator.ValidatorException; import java.io.Serializable; import java.util.*; +import javax.faces.TestUtil; /** @@ -144,7 +145,7 @@ // Set up instance variables required by this test case. - public void setUp() { + public void setUp() throws Exception { expectedAttributes = new String[0]; expectedFamily = "Test"; @@ -163,7 +164,9 @@ request = new MockHttpServletRequest(session); request.setAttribute("reqScopeName", "reqScopeValue"); response = new MockHttpServletResponse(); + TestUtil.injectServletContextIntoFactoryFinder(servletContext); + // Set up Faces API Objects FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, "com.sun.faces.mock.MockApplicationFactory"); @@ -207,7 +210,10 @@ // Tear down instance variables required by this test case. - public void tearDown() { + public void tearDown() throws Exception { + FactoryFinder.releaseFactories(); + TestUtil.injectServletContextIntoFactoryFinder(null); + facesContext.release(); component = null; expectedAttributes = null; Index: jsf-api/src/test/java/javax/faces/validator/ValidatorTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/validator/ValidatorTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/validator/ValidatorTestCase.java (working copy) @@ -41,15 +41,8 @@ package javax.faces.validator; -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; import javax.faces.FactoryFinder; -import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; -import javax.faces.context.FacesContext; -import javax.faces.el.ValueBinding; -import javax.faces.event.FacesEvent; import com.sun.faces.mock.MockApplication; import com.sun.faces.mock.MockExternalContext; import com.sun.faces.mock.MockFacesContext; @@ -58,14 +51,11 @@ import com.sun.faces.mock.MockHttpSession; import com.sun.faces.mock.MockLifecycle; import com.sun.faces.mock.MockRenderKit; -import com.sun.faces.mock.MockRenderKitFactory; import com.sun.faces.mock.MockServletConfig; import com.sun.faces.mock.MockServletContext; -import com.sun.faces.mock.MockValueBinding; import javax.faces.TestUtil; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; -import javax.faces.validator.Validator; import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; @@ -123,6 +113,7 @@ request = new MockHttpServletRequest(session); request.setAttribute("reqScopeName", "reqScopeValue"); response = new MockHttpServletResponse(); + TestUtil.injectServletContextIntoFactoryFinder(servletContext); // Set up Faces API Objects FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, @@ -165,6 +156,10 @@ public void tearDown() throws Exception { super.tearDown(); + FactoryFinder.releaseFactories(); + TestUtil.injectServletContextIntoFactoryFinder(null); + facesContext.release(); + application = null; config = null; externalContext = null; Index: jsf-api/src/test/java/javax/faces/FactoryFinderTestCase.java =================================================================== --- jsf-api/src/test/java/javax/faces/FactoryFinderTestCase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/FactoryFinderTestCase.java (working copy) @@ -41,10 +41,8 @@ package javax.faces; -import java.io.IOException; -import java.io.File; -import java.util.Iterator; -import java.util.List; +import com.sun.faces.mock.MockServletContext; +import javax.servlet.ServletContext; import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; @@ -96,8 +94,11 @@ for (int i = 0, len = FACTORIES.length; i < len; i++) { System.getProperties().remove(FACTORIES[i][0]); } + ServletContext sc = new MockServletContext(); + TestUtil.injectServletContextIntoFactoryFinder(sc); } + // Return the tests included in this test case. public static Test suite() { Index: jsf-api/src/test/java/javax/faces/FactoryFinderTestCase2.java =================================================================== --- jsf-api/src/test/java/javax/faces/FactoryFinderTestCase2.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/FactoryFinderTestCase2.java (working copy) @@ -41,10 +41,8 @@ package javax.faces; -import java.io.IOException; -import java.io.File; -import java.util.Iterator; -import java.util.List; +import com.sun.faces.mock.MockServletContext; +import javax.servlet.ServletContext; import junit.framework.TestCase; import junit.framework.Test; import junit.framework.TestSuite; @@ -77,9 +75,10 @@ for (int i = 0, len = FactoryFinderTestCase.FACTORIES.length; i < len; i++) { System.getProperties().remove(FactoryFinderTestCase.FACTORIES[i][0]); } + ServletContext sc = new MockServletContext(); + TestUtil.injectServletContextIntoFactoryFinder(sc); } - // Return the tests included in this test case. public static Test suite() { return (new TestSuite(FactoryFinderTestCase2.class)); Index: jsf-api/src/test/java/javax/faces/TestUtil.java =================================================================== --- jsf-api/src/test/java/javax/faces/TestUtil.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/TestUtil.java (working copy) @@ -45,10 +45,12 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; +import java.lang.reflect.Field; import java.util.Iterator; import javax.faces.component.UIComponent; import javax.faces.component.ValueHolder; import javax.faces.model.SelectItem; +import javax.servlet.ServletContext; public class TestUtil extends Object { @@ -206,6 +208,14 @@ curDepth--; } + public static void injectServletContextIntoFactoryFinder(ServletContext sc) throws Exception { + Field servletContextStoreField; + ThreadLocal servletContextStore; + servletContextStoreField = FactoryFinder.class.getDeclaredField("servletContextStore"); + servletContextStoreField.setAccessible(true); + servletContextStore = (ThreadLocal) servletContextStoreField.get(null); + servletContextStore.set(sc); + } } Index: jsf-api/src/test/java/javax/faces/webapp/TagTestCaseBase.java =================================================================== --- jsf-api/src/test/java/javax/faces/webapp/TagTestCaseBase.java (revision 8854) +++ jsf-api/src/test/java/javax/faces/webapp/TagTestCaseBase.java (working copy) @@ -41,29 +41,14 @@ package javax.faces.webapp; -import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; import javax.faces.FactoryFinder; -import javax.faces.application.Application; import javax.faces.application.ApplicationFactory; -import javax.faces.component.NamingContainer; -import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; -import javax.faces.context.FacesContext; -import javax.faces.event.FacesEvent; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; -import javax.faces.validator.Validator; -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import junit.framework.TestCase; -import junit.framework.Test; -import junit.framework.TestSuite; import com.sun.faces.mock.MockApplication; import com.sun.faces.mock.MockExternalContext; @@ -71,14 +56,13 @@ import com.sun.faces.mock.MockHttpServletRequest; import com.sun.faces.mock.MockHttpServletResponse; import com.sun.faces.mock.MockHttpSession; -import com.sun.faces.mock.MockJspWriter; import com.sun.faces.mock.MockLifecycle; import com.sun.faces.mock.MockPageContext; import com.sun.faces.mock.MockRenderKit; -import com.sun.faces.mock.MockRenderKitFactory; import com.sun.faces.mock.MockServlet; import com.sun.faces.mock.MockServletConfig; import com.sun.faces.mock.MockServletContext; +import javax.faces.TestUtil; /** @@ -141,6 +125,7 @@ pageContext = new MockPageContext(); pageContext.initialize(servlet, request, response, null, true, 1024, true); + TestUtil.injectServletContextIntoFactoryFinder(servletContext); // Set up Faces API Objects FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, @@ -175,6 +160,9 @@ * Tear down instance variables required by this test case. */ public void tearDown() throws Exception { + FactoryFinder.releaseFactories(); + TestUtil.injectServletContextIntoFactoryFinder(null); + facesContext.release(); application = null; config = null; Index: jsf-api/src/main/java/javax/faces/FactoryFinder.java =================================================================== --- jsf-api/src/main/java/javax/faces/FactoryFinder.java (revision 8854) +++ jsf-api/src/main/java/javax/faces/FactoryFinder.java (working copy) @@ -67,6 +67,9 @@ import java.lang.reflect.Constructor; import java.net.URL; import java.net.URLConnection; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; +import javax.servlet.ServletContext; /** @@ -231,6 +234,11 @@ // ------------------------------------------------------- Static Variables + private static ThreadLocal servletContextStore = new ThreadLocal() { + @Override + protected ServletContext initialValue() { return (null); } + }; + private static final FactoryManagerCache FACTORIES_CACHE = new FactoryManagerCache(); @@ -311,9 +319,10 @@ // Identify the web application class loader ClassLoader classLoader = getClassLoader(); + Object context = FactoryFinder.getContext(); FactoryManager manager = - FACTORIES_CACHE.getApplicationFactoryManager(classLoader); + FACTORIES_CACHE.getApplicationFactoryManager(context); return manager.getFactory(classLoader, factoryName); } @@ -341,11 +350,10 @@ validateFactoryName(factoryName); - // Identify the web application class loader - ClassLoader classLoader = getClassLoader(); + Object context = FactoryFinder.getContext(); FactoryManager manager = - FACTORIES_CACHE.getApplicationFactoryManager(classLoader); + FACTORIES_CACHE.getApplicationFactoryManager(context); manager.addFactory(factoryName, implName); } @@ -363,17 +371,31 @@ */ public static void releaseFactories() throws FacesException { - // Identify the web application class loader - ClassLoader cl = getClassLoader(); + Object context = FactoryFinder.getContext(); - FACTORIES_CACHE.removeApplicationFactoryManager(cl); + if (null != context) { + FACTORIES_CACHE.removeApplicationFactoryManager(context); + } else { + FACTORIES_CACHE.removeAllFactoryManagers(); + } } // -------------------------------------------------------- Private Methods + private static Object getContext() { + Object context = null; + FacesContext facesContext = FacesContext.getCurrentInstance(); + if (null != facesContext) { + context = facesContext.getExternalContext().getContext(); + } else { + context = servletContextStore.get(); + } + return context; + } + /** *

Identify and return the class loader that is associated with the * calling web application.

@@ -680,17 +702,17 @@ */ private static final class FactoryManagerCache { - private ConcurrentMap> applicationMap = - new ConcurrentHashMap>(); + private ConcurrentMap> applicationMap = + new ConcurrentHashMap>(); // ------------------------------------------------------ Public Methods - private FactoryManager getApplicationFactoryManager(ClassLoader cl) { + private FactoryManager getApplicationFactoryManager(Object context) { while (true) { - Future factories = applicationMap.get(cl); + Future factories = applicationMap.get(context); if (factories == null) { Callable callable = new Callable() { @@ -702,7 +724,7 @@ FutureTask ft = new FutureTask(callable); - factories = applicationMap.putIfAbsent(cl, ft); + factories = applicationMap.putIfAbsent(context, ft); if (factories == null) { factories = ft; ft.run(); @@ -717,14 +739,14 @@ ce.toString(), ce); } - applicationMap.remove(cl); + applicationMap.remove(context); } catch (InterruptedException ie) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log(Level.FINEST, ie.toString(), ie); } - applicationMap.remove(cl); + applicationMap.remove(context); } catch (ExecutionException ee) { throw new FacesException(ee); } @@ -734,12 +756,16 @@ } - public void removeApplicationFactoryManager(ClassLoader cl) { + public void removeApplicationFactoryManager(Object context) { - applicationMap.remove(cl); + applicationMap.remove(context); } + public void removeAllFactoryManagers() { + applicationMap.clear(); + } + } // END FactoryCache Index: jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java =================================================================== --- jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java (revision 8854) +++ jsf-api/src/main/java/javax/faces/webapp/FacesServlet.java (working copy) @@ -42,6 +42,7 @@ import java.io.IOException; +import java.lang.reflect.Field; import java.util.ResourceBundle; import java.util.logging.Level; import java.util.logging.Logger; @@ -55,6 +56,7 @@ import javax.faces.lifecycle.LifecycleFactory; import javax.servlet.Servlet; import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -247,9 +249,14 @@ // Save our ServletConfig instance this.servletConfig = servletConfig; + ServletContext sc = null; // Acquire our FacesContextFactory instance try { + if (null == FacesContext.getCurrentInstance()) { + sc = servletConfig.getServletContext(); + injectServletContextIntoFactoryFinder(sc); + } facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory (FactoryFinder.FACES_CONTEXT_FACTORY); @@ -285,11 +292,38 @@ } else { throw new ServletException(e.getMessage(), rootCause); } + } finally { + if (null != sc) { + injectServletContextIntoFactoryFinder(null); + } } } + private void injectServletContextIntoFactoryFinder(ServletContext sc) { + Field servletContextStoreField; + ThreadLocal servletContextStore; + try { + servletContextStoreField = FactoryFinder.class.getDeclaredField("servletContextStore"); + servletContextStoreField.setAccessible(true); + servletContextStore = (ThreadLocal) servletContextStoreField.get(null); + servletContextStore.set(sc); + } catch (NoSuchFieldException nsfe) { + if (LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, "Unable to find private field named 'servletContextStore' in javax.faces.FactoryFinder."); + } + } catch (Exception e) { + if (LOGGER.isLoggable(Level.SEVERE)) { + LOGGER.log(Level.SEVERE, e.toString(), e); + } + servletContextStoreField = null; + } + + + } + + /** *

Process an incoming request, and create the * corresponding response according to the following Index: jsf-api/build.xml =================================================================== --- jsf-api/build.xml (revision 8854) +++ jsf-api/build.xml (working copy) @@ -878,7 +878,7 @@ logging.config.file="${api.test.results.dir}/test-logging.properties"> + includes="javax/faces/component/UIViewRootTestCase.class"/> Index: jsf-ri/systest/src/com/sun/faces/htmlunit/SimpleTesterTestCase.java =================================================================== --- jsf-ri/systest/src/com/sun/faces/htmlunit/SimpleTesterTestCase.java (revision 8854) +++ jsf-ri/systest/src/com/sun/faces/htmlunit/SimpleTesterTestCase.java (working copy) @@ -90,6 +90,7 @@ private void doRegexp(String text) throws Exception { if (null != regexp && 0 < regexp.length()) { + System.out.println("text: " + text + "regexp: " + regexp); assertTrue(text.matches(regexp)); } Index: jsf-ri/systest/build-tests.xml =================================================================== --- jsf-ri/systest/build-tests.xml (revision 8854) +++ jsf-ri/systest/build-tests.xml (working copy) @@ -1108,10 +1108,10 @@ regexp="(?s).*/renderkit01.jsp PASSED.*"/> + regexp="(?s).*/renderkit02.jsp\\s*PASSED.*"/> + regexp="(?s).*This\s*IS\s*A\s*SIMPLE\s*LABEL\s*FROM\s*THE\s*CUSTOM\s*RENDERER.*/renderkit03.jsp\s*PASSED.*"/> Index: jsf-ri/systest/build.xml =================================================================== --- jsf-ri/systest/build.xml (revision 8854) +++ jsf-ri/systest/build.xml (working copy) @@ -224,7 +224,7 @@ - + Index: jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/SimplePhaseListener.java =================================================================== --- jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/SimplePhaseListener.java (revision 8854) +++ jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/SimplePhaseListener.java (working copy) @@ -43,6 +43,7 @@ import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; +import java.util.Map; public class SimplePhaseListener implements PhaseListener { @@ -57,8 +58,12 @@ public void beforePhase(PhaseEvent event) { - event.getFacesContext().getExternalContext().getRequestMap().put("beforePhase", - "beforePhase"); + Map requestMap = + event.getFacesContext().getExternalContext().getRequestMap(); + String message = requestMap.containsKey("beforePhase") ? + requestMap.get("beforePhase").toString() : ""; + requestMap.put("beforePhase", + message + " beforePhase"); event.getFacesContext().getExternalContext().getRequestMap().put("lifecycleImpl", event.getSource()); } Index: jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/ReplaceLifecycleTestCase.java =================================================================== --- jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/ReplaceLifecycleTestCase.java (revision 8854) +++ jsf-ri/systest-per-webapp/replace-lifecycle/src/java/com/sun/faces/systest/ReplaceLifecycleTestCase.java (working copy) @@ -128,7 +128,10 @@ public void testReplaceLifecycle() throws Exception { HtmlPage page = getPage("/faces/test.jsp"); - assertTrue(-1 != page.asText().indexOf("beforePhase")); + String pageText = page.asText(); + assertTrue(-1 != pageText.indexOf("beforePhase")); + // Ensure the phaseListener is only called once. + assertTrue(!pageText.matches("(?s).*beforePhase.*beforePhase.*")); } Index: build.xml =================================================================== --- build.xml (revision 8854) +++ build.xml (working copy) @@ -400,6 +400,8 @@ + + Index: lib/jsf-extensions-test-time.jar =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream