/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2014 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.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 javax.faces.component; import com.sun.faces.mock.MockRenderKit; import java.lang.reflect.Field; import java.util.List; import java.util.Locale; import java.io.IOException; import javax.faces.FactoryFinder; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseListener; import javax.faces.context.FacesContext; import javax.faces.event.PhaseId; import junit.framework.Test; import junit.framework.TestSuite; import javax.el.ValueExpression; import javax.el.MethodExpression; import javax.faces.render.RenderKit; import javax.faces.render.RenderKitFactory; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; /** * <p> * Test case for the <strong>javax.faces.UIViewRoot</strong> * concrete class.</p> */ public class UIViewRootTestCase extends UIComponentBaseTestCase { // ------------------------------------------------------------ Constructors /** * Construct a new instance of this test case. * * @param name Name of the test case */ public UIViewRootTestCase(String name) { super(name); } // ---------------------------------------------------- Overall Test Methods /** * Return the tests included in this test suite. * * @return */ public static Test suite() { return (new TestSuite(UIViewRootTestCase.class)); } public static String FACTORIES[][] = { {FactoryFinder.APPLICATION_FACTORY, "com.sun.faces.mock.MockApplicationFactory" }, {FactoryFinder.FACES_CONTEXT_FACTORY, "com.sun.faces.mock.MockFacesContextFactory" }, {FactoryFinder.LIFECYCLE_FACTORY, "com.sun.faces.mock.MockLifecycleFactory" }, {FactoryFinder.RENDER_KIT_FACTORY, "com.sun.faces.mock.MockRenderKitFactory" } }; @Override public void setUp() throws Exception { FactoryFinder.releaseFactories(); super.setUp(); for (int i = 0, len = FACTORIES.length; i < len; i++) { System.getProperties().remove(FACTORIES[i][0]); } FactoryFinder.releaseFactories(); int len, i = 0; // simulate the "faces implementation specific" part for (i = 0, len = FACTORIES.length; i < len; i++) { FactoryFinder.setFactory(FACTORIES[i][0], FACTORIES[i][1]); } UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); root.setViewId("/viewId"); facesContext.setViewRoot(root); RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); RenderKit renderKit = new MockRenderKit(); try { renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, renderKit); } catch (IllegalArgumentException e) { } } /** * Tear down instance variables required by this test case. * * @throws java.lang.Exception */ @Override public void tearDown() throws Exception { component = null; super.tearDown(); } // ------------------------------------------------- Individual Test Methods public void testAddGetComponentResources() { application.addComponent("javax.faces.ComponentResourceContainer", Container.class.getName()); UIViewRoot root = new UIViewRoot(); UIOutput resource = new UIOutput(); // no target argument should result in target being head root.addComponentResource(facesContext, resource); List<UIComponent> components = root.getComponentResources(facesContext, "head"); assertNotNull(components); assertTrue(components.size() == 1); assertTrue(components.get(0) == resource); UIOutput resource2 = new UIOutput(); root.addComponentResource(facesContext, resource2); assertTrue(components.size() == 2); assertTrue(components.get(1) == resource2); root.addComponentResource(facesContext, resource2, "form"); components = root.getComponentResources(facesContext, "form"); assertTrue(components.size() == 1); root.addComponentResource(facesContext, resource2, "body"); components = root.getComponentResources(facesContext, "body"); assertTrue(components.size() == 1); // the default implementation masks the facet name values // of head and form to ensure there are no collisions with valid // facets by the name. Calling UIViewRoot.getFacet("head") or // get("form") will return null. assertNull(root.getFacet("head")); assertNull(root.getFacet("form")); assertNull(root.getFacet("body")); assertNotNull(root.getFacet("javax_faces_location_HEAD")); assertNotNull(root.getFacet("javax_faces_location_FORM")); assertNotNull(root.getFacet("javax_faces_location_BODY")); // custom locations will also be masked root.addComponentResource(facesContext, resource2, "gt"); assertNotNull(root.getFacet("javax_faces_location_gt")); components = root.getComponentResources(facesContext, "gt"); assertTrue(components.size() == 1); } // Test AbortProcessingException support public void testAbortProcessingException() { // Register three listeners, with the second one set to abort UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); root.addFacesListener(new ListenerTestImpl("a", false)); root.addFacesListener(new ListenerTestImpl("b", true)); root.addFacesListener(new ListenerTestImpl("c", false)); // Queue two event and check the results ListenerTestImpl.trace(null); EventTestImpl event1 = new EventTestImpl(root, "1"); event1.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event1); EventTestImpl event2 = new EventTestImpl(root, "2"); event2.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event2); root.processDecodes(facesContext); assertEquals("/a/1/b/1/a/2/b/2", ListenerTestImpl.trace()); } // Test event queuing and dequeuing during broadcasting public void testEventBroadcasting() { // Register a listener that will conditionally queue a new event UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); root.addFacesListener(new ListenerTestImpl("t", "2", "4")); ListenerTestImpl.trace(null); // Queue some events, including the trigger one EventTestImpl event = new EventTestImpl(root, "1"); event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event); event = new EventTestImpl(root, "2"); event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event); event = new EventTestImpl(root, "3"); event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event); // Simulate the Apply Request Values phase root.processDecodes(facesContext); // Validate the results (expect 4th event to also be queued) String expected = "/t/1/t/2/t/3/t/4"; assertEquals(expected, ListenerTestImpl.trace()); } // Test event queuing and broadcasting public void testEventQueuing() { // Check for correct ifecycle management processing of event broadcast checkEventQueueing(PhaseId.APPLY_REQUEST_VALUES); checkEventQueueing(PhaseId.PROCESS_VALIDATIONS); checkEventQueueing(PhaseId.UPDATE_MODEL_VALUES); checkEventQueueing(PhaseId.INVOKE_APPLICATION); checkEventQueueing(PhaseId.ANY_PHASE); } public void testLocaleFromVB() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); ValueExpression expression = application.getExpressionFactory().createValueExpression(facesContext.getELContext(), "#{locale}", Object.class); request.setAttribute("locale", Locale.CHINESE); assertEquals(Locale.getDefault(), root.getLocale()); root.setValueExpression("locale", expression); assertEquals(Locale.CHINESE, root.getLocale()); // test locale from String request.setAttribute("locale", "en"); assertEquals(new Locale("en"), root.getLocale()); request.setAttribute("locale", "en_IE"); assertEquals(new Locale("en", "IE"), root.getLocale()); request.setAttribute("locale", "en_IE_EURO"); assertEquals(new Locale("en", "IE", "EURO"), root.getLocale()); root.setLocale(Locale.CANADA_FRENCH); assertEquals(Locale.CANADA_FRENCH, root.getLocale()); } public void testUninitializedInstance() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); assertEquals(javax.faces.render.RenderKitFactory.HTML_BASIC_RENDER_KIT, root.getRenderKitId()); assertEquals(Locale.getDefault(), root.getLocale()); } public void testPhaseMethExpression() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseMethodExpression(root, false); } public void testPhaseMethExpressionSkipping() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseMethodExpression(root, true); } public void testPhaseListener() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseListener(root, false); } public void testPhaseListenerSkipping() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseListener(root, true); } public void testPhaseMethodExpressionAndListener() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseMethodExpressionAndListener(root, false); } public void testPhaseMethodExpressionAndListenerSkipping() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); doTestPhaseMethodExpressionAndListener(root, true); } public void testPhaseMethExpressionState() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); Object state = root.saveState(facesContext); root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); root.restoreState(facesContext, state); doTestPhaseMethodExpression(root, false); } public void testPhaseListenerState() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); Object state = root.saveState(facesContext); root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); root.restoreState(facesContext, state); doTestPhaseListener(root, false); } public void testPhaseMethodExpressionAndListenerState() throws Exception { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); Object state = root.saveState(facesContext); root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); root.restoreState(facesContext, state); doTestPhaseMethodExpressionAndListener(root, false); } public void testPhaseListenerExceptions() throws Exception { PhaseId[] ids = { PhaseId.APPLY_REQUEST_VALUES, PhaseId.PROCESS_VALIDATIONS, PhaseId.UPDATE_MODEL_VALUES, PhaseId.INVOKE_APPLICATION, PhaseId.RENDER_RESPONSE}; Class[] args = new Class[]{PhaseEvent.class}; MethodExpression beforeExpression = facesContext.getApplication() .getExpressionFactory() .createMethodExpression(facesContext.getELContext(), "#{bean.beforePhase}", null, args); MethodExpression afterExpression = facesContext.getApplication() .getExpressionFactory() .createMethodExpression(facesContext.getELContext(), "#{bean.afterPhase}", null, args); for (PhaseId id : ids) { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); PhaseListenerBean bean = new PhaseListenerBean(id, true, false); PhaseListenerBean pl1 = new PhaseListenerBean(id); PhaseListenerBean pl2 = new PhaseListenerBean(id); facesContext.getExternalContext().getRequestMap().put("bean", bean); root.setBeforePhaseListener(beforeExpression); root.setAfterPhaseListener(afterExpression); root.addPhaseListener(pl1); root.addPhaseListener(pl2); // validate behavior callRightLifecycleMethodGivenPhaseId(root, id); assertTrue(bean.isBeforePhaseCalled()); assertTrue(!bean.isAfterPhaseCalled()); assertTrue(!pl1.isBeforePhaseCalled()); assertTrue(!pl1.isAfterPhaseCalled()); assertTrue(!pl2.isBeforePhaseCalled()); assertTrue(!pl2.isAfterPhaseCalled()); // ensure PLs are invoked properly in the case of exceptions root = facesContext.getApplication().getViewHandler().createView(facesContext, null); bean = new PhaseListenerBean(id); pl1 = new PhaseListenerBean(id, true, false); pl2 = new PhaseListenerBean(id); facesContext.getExternalContext().getRequestMap().put("bean", bean); root.setBeforePhaseListener(beforeExpression); root.setAfterPhaseListener(afterExpression); root.addPhaseListener(pl1); root.addPhaseListener(pl2); // validate behavior callRightLifecycleMethodGivenPhaseId(root, id); assertTrue(bean.isBeforePhaseCalled()); assertTrue(bean.isAfterPhaseCalled()); assertTrue(pl1.isBeforePhaseCalled()); assertTrue(!pl1.isAfterPhaseCalled()); assertTrue(!pl2.isBeforePhaseCalled()); assertTrue(!pl2.isAfterPhaseCalled()); } } public void doTestPhaseMethodExpression(UIViewRoot root, boolean skipping) throws Exception { PhaseSkipTestComponent comp = null; if (skipping) { comp = new PhaseSkipTestComponent(); root.getChildren().add(comp); facesContext.responseComplete(); } doTestPhaseMethodExpressionWithPhaseId(root, PhaseId.APPLY_REQUEST_VALUES); if (skipping) { assertTrue(!comp.isDecodeCalled()); } doTestPhaseMethodExpressionWithPhaseId(root, PhaseId.PROCESS_VALIDATIONS); if (skipping) { assertTrue(!comp.isProcessValidatorsCalled()); } doTestPhaseMethodExpressionWithPhaseId(root, PhaseId.UPDATE_MODEL_VALUES); if (skipping) { assertTrue(!comp.isProcessUpdatesCalled()); } doTestPhaseMethodExpressionWithPhaseId(root, PhaseId.INVOKE_APPLICATION); doTestPhaseMethodExpressionWithPhaseId(root, PhaseId.RENDER_RESPONSE); if (skipping) { assertTrue(!comp.isEncodeBeginCalled()); } } public void doTestPhaseMethodExpressionWithPhaseId(UIViewRoot root, PhaseId phaseId) throws Exception { PhaseListenerBean phaseListenerBean = new PhaseListenerBean(phaseId); facesContext.getExternalContext().getRequestMap().put("bean", phaseListenerBean); Class[] args = new Class[]{PhaseEvent.class}; MethodExpression beforeExpression = facesContext.getApplication().getExpressionFactory().createMethodExpression(facesContext.getELContext(), "#{bean.beforePhase}", null, args), afterExpression = facesContext.getApplication().getExpressionFactory().createMethodExpression(facesContext.getELContext(), "#{bean.afterPhase}", null, args); root.setBeforePhaseListener(beforeExpression); root.setAfterPhaseListener(afterExpression); callRightLifecycleMethodGivenPhaseId(root, phaseId); assertTrue(phaseListenerBean.isBeforePhaseCalled()); assertTrue(phaseListenerBean.isAfterPhaseCalled()); } public void doTestPhaseListener(UIViewRoot root, boolean skipping) throws Exception { PhaseSkipTestComponent comp = null; if (skipping) { comp = new PhaseSkipTestComponent(); root.getChildren().add(comp); facesContext.responseComplete(); } doTestPhaseListenerWithPhaseId(root, PhaseId.APPLY_REQUEST_VALUES); if (skipping) { assertTrue(!comp.isDecodeCalled()); } doTestPhaseListenerWithPhaseId(root, PhaseId.PROCESS_VALIDATIONS); if (skipping) { assertTrue(!comp.isProcessValidatorsCalled()); } doTestPhaseListenerWithPhaseId(root, PhaseId.UPDATE_MODEL_VALUES); if (skipping) { assertTrue(!comp.isProcessUpdatesCalled()); } doTestPhaseListenerWithPhaseId(root, PhaseId.INVOKE_APPLICATION); doTestPhaseListenerWithPhaseId(root, PhaseId.RENDER_RESPONSE); if (skipping) { assertTrue(!comp.isEncodeBeginCalled()); } } public void doTestPhaseListenerWithPhaseId(UIViewRoot root, PhaseId phaseId) throws Exception { PhaseListenerBean phaseListener = new PhaseListenerBean(phaseId); root.addPhaseListener(phaseListener); callRightLifecycleMethodGivenPhaseId(root, phaseId); assertTrue(phaseListener.isBeforePhaseCalled()); assertTrue(phaseListener.isAfterPhaseCalled()); } public void doTestPhaseMethodExpressionAndListener(UIViewRoot root, boolean skipping) throws Exception { PhaseSkipTestComponent comp = null; if (skipping) { comp = new PhaseSkipTestComponent(); root.getChildren().add(comp); facesContext.responseComplete(); } doTestPhaseMethodExpressionAndListenerWithPhaseId(root, PhaseId.APPLY_REQUEST_VALUES); if (skipping) { assertTrue(!comp.isDecodeCalled()); } doTestPhaseMethodExpressionAndListenerWithPhaseId(root, PhaseId.PROCESS_VALIDATIONS); if (skipping) { assertTrue(!comp.isProcessValidatorsCalled()); } doTestPhaseMethodExpressionAndListenerWithPhaseId(root, PhaseId.UPDATE_MODEL_VALUES); if (skipping) { assertTrue(!comp.isProcessUpdatesCalled()); } doTestPhaseMethodExpressionAndListenerWithPhaseId(root, PhaseId.INVOKE_APPLICATION); doTestPhaseMethodExpressionAndListenerWithPhaseId(root, PhaseId.RENDER_RESPONSE); if (skipping) { assertTrue(!comp.isEncodeBeginCalled()); } } public void doTestPhaseMethodExpressionAndListenerWithPhaseId(UIViewRoot root, PhaseId phaseId) throws Exception { PhaseListenerBean phaseListener = new PhaseListenerBean(phaseId); PhaseListenerBean phaseListenerBean = new PhaseListenerBean(phaseId); facesContext.getExternalContext().getRequestMap().put("bean", phaseListenerBean); Class[] args = new Class[]{PhaseEvent.class}; MethodExpression beforeExpression = facesContext.getApplication().getExpressionFactory().createMethodExpression(facesContext.getELContext(), "#{bean.beforePhase}", null, args), afterExpression = facesContext.getApplication().getExpressionFactory().createMethodExpression(facesContext.getELContext(), "#{bean.afterPhase}", null, args); root.setBeforePhaseListener(beforeExpression); root.setAfterPhaseListener(afterExpression); root.addPhaseListener(phaseListener); callRightLifecycleMethodGivenPhaseId(root, phaseId); assertTrue(phaseListenerBean.isBeforePhaseCalled()); assertTrue(phaseListenerBean.isAfterPhaseCalled()); assertTrue(phaseListener.isBeforePhaseCalled()); assertTrue(phaseListener.isAfterPhaseCalled()); } private void checkEventQueuesSizes(List<List> events, int applyEventsSize, int valEventsSize, int updateEventsSize, int appEventsSize) { List applyEvents = events.get(PhaseId.APPLY_REQUEST_VALUES.getOrdinal()); assertEquals("Apply-Request-Values Event Count", applyEventsSize, applyEvents.size()); List valEvents = events.get(PhaseId.PROCESS_VALIDATIONS.getOrdinal()); assertEquals("Process-Validations Event Count", valEventsSize, valEvents.size()); List updateEvents = events.get(PhaseId.UPDATE_MODEL_VALUES.getOrdinal()); assertEquals("Update-Model Event Count", updateEventsSize, updateEvents.size()); List appEvents = events.get(PhaseId.INVOKE_APPLICATION.getOrdinal()); assertEquals("Invoke-Application Event Count", appEventsSize, appEvents.size()); } // Test Events List Clearing public void testEventsListClear() { UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); EventTestImpl event1, event2, event3, event4 = null; event1 = new EventTestImpl(root, "1"); event1.setPhaseId(PhaseId.APPLY_REQUEST_VALUES); root.queueEvent(event1); event2 = new EventTestImpl(root, "2"); event2.setPhaseId(PhaseId.PROCESS_VALIDATIONS); root.queueEvent(event2); event3 = new EventTestImpl(root, "3"); event3.setPhaseId(PhaseId.UPDATE_MODEL_VALUES); root.queueEvent(event3); event4 = new EventTestImpl(root, "4"); event4.setPhaseId(PhaseId.INVOKE_APPLICATION); root.queueEvent(event4); final Field fields[] = UIViewRoot.class.getDeclaredFields(); Field field = null; List<List> events = null; for (int i = 0; i < fields.length; ++i) { if ("events".equals(fields[i].getName())) { field = fields[i]; field.setAccessible(true); try { events = TypedCollections.dynamicallyCastList((List) field.get(root), List.class); } catch (Exception e) { assertTrue(false); } break; } } // CASE: renderReponse not set; responseComplete not set; // check for existence of events before processDecodes checkEventQueuesSizes(events, 1, 1, 1, 1); root.processDecodes(facesContext); // there should be no events checkEventQueuesSizes(events, 0, 1, 1, 1); // requeue apply request event root.queueEvent(event1); // CASE: renderReponse set; // check for existence of events before processValidators checkEventQueuesSizes(events, 1, 1, 1, 1); facesContext.renderResponse(); root.processValidators(facesContext); // there should be no events checkEventQueuesSizes(events, 0, 0, 0, 0); // reset FacesContext facesContext.setRenderResponse(false); facesContext.setResponseComplete(false); // requeue all events root.queueEvent(event1); root.queueEvent(event2); root.queueEvent(event3); root.queueEvent(event4); try { events = TypedCollections.dynamicallyCastList((List) field.get(root), List.class); } catch (Exception e) { assertTrue(false); } // CASE: response set; // check for existence of events before processValidators checkEventQueuesSizes(events, 1, 1, 1, 1); facesContext.renderResponse(); root.processValidators(facesContext); // there should be no events checkEventQueuesSizes(events, 0, 0, 0, 0); // reset FacesContext facesContext.setRenderResponse(false); facesContext.setResponseComplete(false); // requeue all events root.queueEvent(event1); root.queueEvent(event2); root.queueEvent(event3); root.queueEvent(event4); try { events = TypedCollections.dynamicallyCastList((List) field.get(root), List.class); } catch (Exception e) { assertTrue(false); } // CASE: response complete; // check for existence of events before processUpdates checkEventQueuesSizes(events, 1, 1, 1, 1); facesContext.responseComplete(); root.processUpdates(facesContext); // there should be no events checkEventQueuesSizes(events, 0, 0, 0, 0); // reset FacesContext facesContext.setRenderResponse(false); facesContext.setResponseComplete(false); // requeue all events root.queueEvent(event1); root.queueEvent(event2); root.queueEvent(event3); root.queueEvent(event4); try { events = TypedCollections.dynamicallyCastList((List) field.get(root), List.class); } catch (Exception e) { assertTrue(false); } // CASE: response complete; // check for existence of events before processApplication checkEventQueuesSizes(events, 1, 1, 1, 1); facesContext.responseComplete(); root.processApplication(facesContext); // there should be no events checkEventQueuesSizes(events, 0, 0, 0, 0); //finally, get the internal events list one more time //to make sure it is null try { events = TypedCollections.dynamicallyCastList((List) field.get(root), List.class); } catch (Exception e) { assertTrue(false); } assertNull("events", events); } private void callRightLifecycleMethodGivenPhaseId(UIViewRoot root, PhaseId phaseId) throws Exception { if (phaseId.getOrdinal() == PhaseId.APPLY_REQUEST_VALUES.getOrdinal()) { root.processDecodes(facesContext); } else if (phaseId.getOrdinal() == PhaseId.PROCESS_VALIDATIONS.getOrdinal()) { root.processValidators(facesContext); } else if (phaseId.getOrdinal() == PhaseId.UPDATE_MODEL_VALUES.getOrdinal()) { root.processUpdates(facesContext); } else if (phaseId.getOrdinal() == PhaseId.INVOKE_APPLICATION.getOrdinal()) { root.processApplication(facesContext); } else if (phaseId.getOrdinal() == PhaseId.RENDER_RESPONSE.getOrdinal()) { root.encodeBegin(facesContext); root.encodeEnd(facesContext); } } // --------------------------------------------------------- Support Methods private void checkEventQueueing(PhaseId phaseId) { // NOTE: Current semantics for ANY_PHASE listeners is that // the event should be delivered exactly once, so the existence // of such a listener does not cause the event to remain queued. // Therefore, the expected string is the same as for any // phase-specific listener, and it should get matched after // Apply Request Values processing since that is first phase // for which events are fired // Register an event listener for the specified phase id UIViewRoot root = facesContext.getApplication().getViewHandler().createView(facesContext, null); facesContext.setViewRoot(root); EventTestImpl event = null; ListenerTestImpl listener = new ListenerTestImpl("t"); root.addFacesListener(listener); // Queue some events to be processed event = new EventTestImpl(root, "1"); event.setPhaseId(phaseId); root.queueEvent(event); event = new EventTestImpl(root, "2"); event.setPhaseId(phaseId); root.queueEvent(event); String expected = "/t/1/t/2"; // Fire off the relevant lifecycle methods and check expected results ListenerTestImpl.trace(null); assertEquals("", ListenerTestImpl.trace()); root.processDecodes(facesContext); if (PhaseId.APPLY_REQUEST_VALUES.equals(phaseId) || PhaseId.ANY_PHASE.equals(phaseId)) { assertEquals(expected, ListenerTestImpl.trace()); } else { assertEquals("", ListenerTestImpl.trace()); } root.processValidators(facesContext); if (PhaseId.PROCESS_VALIDATIONS.equals(phaseId) || PhaseId.APPLY_REQUEST_VALUES.equals(phaseId) || PhaseId.APPLY_REQUEST_VALUES.equals(phaseId) || PhaseId.ANY_PHASE.equals(phaseId)) { assertEquals(expected, ListenerTestImpl.trace()); } else { assertEquals("", ListenerTestImpl.trace()); } root.processUpdates(facesContext); if (PhaseId.UPDATE_MODEL_VALUES.equals(phaseId) || PhaseId.PROCESS_VALIDATIONS.equals(phaseId) || PhaseId.APPLY_REQUEST_VALUES.equals(phaseId) || PhaseId.ANY_PHASE.equals(phaseId)) { assertEquals(expected, ListenerTestImpl.trace()); } else { assertEquals("", ListenerTestImpl.trace()); } root.processApplication(facesContext); assertEquals(expected, ListenerTestImpl.trace()); } // These overrides are necessary because our normal setup // calls releaseFactories, which makes it impossible to get clientIds. @Override public void testInvokeOnComponentPositive() throws Exception { super.setUp(); super.testInvokeOnComponentPositive(); } @Override public void testInvokeOnComponentNegative() throws Exception { super.setUp(); super.testInvokeOnComponentNegative(); } @Override public void testInvokeOnComponentWithPrependId() throws Exception { super.setUp(); super.testInvokeOnComponentWithPrependId(); } @Override public void testChildrenListAfterAddViewPublish() { // overridding to do nothing. UIViewRoot is a special cases // and there should always only be on UIViewRoot in a tree } @Override public void testFacetMapAfterAddViewPublish() { // overridding to do nothing. UIViewRoot is a special cases // and there should always only be on UIViewRoot in a tree } // Check that the properties on the specified components are equal @Override protected void checkProperties(UIComponent comp1, UIComponent comp2) { super.checkProperties(comp1, comp2); UIViewRoot vr1 = (UIViewRoot) comp1; UIViewRoot vr2 = (UIViewRoot) comp2; assertEquals(vr2.getRenderKitId(), vr2.getRenderKitId()); assertEquals(vr1.getViewId(), vr2.getViewId()); assertEquals(vr1.getLocale(), vr2.getLocale()); } // Create a pristine component of the type to be used in state holder tests @Override protected UIComponent createComponent() { UIComponent component = new UIViewRoot(); component.setRendererType(null); return (component); } // Populate a pristine component to be used in state holder tests @Override protected void populateComponent(UIComponent component) { super.populateComponent(component); UIViewRoot vr = (UIViewRoot) component; vr.setRenderKitId("foo"); vr.setViewId("bar"); vr.setLocale(new Locale("fr", "FR")); } public static class PhaseListenerBean extends Object implements PhaseListener { private boolean beforePhaseCalled = false; private boolean afterPhaseCalled = false; private PhaseId phaseId = null; private boolean exceptionBefore; private boolean exceptionAfter; public PhaseListenerBean(PhaseId phaseId) { this.phaseId = phaseId; } public PhaseListenerBean(PhaseId phaseId, boolean exceptionBefore, boolean exceptionAfter) { this(phaseId); this.exceptionBefore = exceptionBefore; this.exceptionAfter = exceptionAfter; } public boolean isBeforePhaseCalled() { return beforePhaseCalled; } public boolean isAfterPhaseCalled() { return afterPhaseCalled; } @Override public void beforePhase(PhaseEvent e) { beforePhaseCalled = true; if (exceptionBefore) { throw new RuntimeException(); } } @Override public void afterPhase(PhaseEvent e) { afterPhaseCalled = true; if (exceptionAfter) { throw new RuntimeException(); } } @Override public PhaseId getPhaseId() { return phaseId; } } public static class PhaseSkipTestComponent extends UIInput { private boolean decodeCalled = false; @Override public void decode(FacesContext context) { decodeCalled = true; } public boolean isDecodeCalled() { return decodeCalled; } private boolean encodeBeginCalled = false; @Override public void encodeBegin(FacesContext context) throws IOException { encodeBeginCalled = true; } public boolean isEncodeBeginCalled() { return encodeBeginCalled; } private boolean processValidatorsCalled = false; @Override public void processValidators(FacesContext context) { processValidatorsCalled = true; } public boolean isProcessValidatorsCalled() { return processValidatorsCalled; } private boolean processUpdatesCalled = false; @Override public void processUpdates(FacesContext context) { processUpdatesCalled = true; } public boolean isProcessUpdatesCalled() { return processUpdatesCalled; } } public static class Container extends UIPanel { @Override public void encodeAll(FacesContext context) throws IOException { } } }