Author: matzew Date: Sun Jan 13 14:30:00 2008 New Revision: 611661 URL: http://svn.apache.org/viewvc?rev=611661&view=rev Log: SHALE-482 - simple lifecycle added; needs testing...
Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ApplyRequestValuesExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/DefaultRestoreViewSupport.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/InvokeApplicationExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycle.java - copied, changed from r610605, shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycleFactory.java - copied, changed from r610605, shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycleFactory.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseListenerManager.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ProcessValidationsExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RenderResponseExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewExecutor.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewSupport.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/UpdateModelValuesExecutor.java Removed: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycleFactory.java Modified: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/base/AbstractJsfTestCase.java shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/jmock/AbstractJmockJsfTestCase.java Modified: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/base/AbstractJsfTestCase.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/base/AbstractJsfTestCase.java?rev=611661&r1=611660&r2=611661&view=diff ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/base/AbstractJsfTestCase.java (original) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/base/AbstractJsfTestCase.java Sun Jan 13 14:30:00 2008 @@ -35,11 +35,11 @@ import org.apache.shale.test.mock.MockHttpServletRequest; import org.apache.shale.test.mock.MockHttpServletResponse; import org.apache.shale.test.mock.MockHttpSession; -import org.apache.shale.test.mock.MockLifecycle; -import org.apache.shale.test.mock.MockLifecycleFactory; import org.apache.shale.test.mock.MockRenderKit; import org.apache.shale.test.mock.MockServletConfig; import org.apache.shale.test.mock.MockServletContext; +import org.apache.shale.test.mock.lifecycle.MockLifecycle; +import org.apache.shale.test.mock.lifecycle.MockLifecycleFactory; /** * <p>Abstract JUnit test case base class, which sets up the JavaServer Faces @@ -116,7 +116,7 @@ FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, "org.apache.shale.test.mock.MockFacesContextFactory"); FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, - "org.apache.shale.test.mock.MockLifecycleFactory"); + "org.apache.shale.test.mock.lifecycle.MockLifecycleFactory"); FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, "org.apache.shale.test.mock.MockRenderKitFactory"); Modified: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/jmock/AbstractJmockJsfTestCase.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/jmock/AbstractJmockJsfTestCase.java?rev=611661&r1=611660&r2=611661&view=diff ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/jmock/AbstractJmockJsfTestCase.java (original) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/jmock/AbstractJmockJsfTestCase.java Sun Jan 13 14:30:00 2008 @@ -33,11 +33,11 @@ import org.apache.shale.test.mock.MockHttpServletRequest; import org.apache.shale.test.mock.MockHttpServletResponse; import org.apache.shale.test.mock.MockHttpSession; -import org.apache.shale.test.mock.MockLifecycle; -import org.apache.shale.test.mock.MockLifecycleFactory; import org.apache.shale.test.mock.MockRenderKit; import org.apache.shale.test.mock.MockServletConfig; import org.apache.shale.test.mock.MockServletContext; +import org.apache.shale.test.mock.lifecycle.MockLifecycle; +import org.apache.shale.test.mock.lifecycle.MockLifecycleFactory; import org.jmock.cglib.MockObjectTestCase; /** @@ -109,7 +109,7 @@ FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, "org.apache.shale.test.mock.MockFacesContextFactory"); FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, - "org.apache.shale.test.mock.MockLifecycleFactory"); + "org.apache.shale.test.mock.lifecycle.MockLifecycleFactory"); FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, "org.apache.shale.test.mock.MockRenderKitFactory"); Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ApplyRequestValuesExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ApplyRequestValuesExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ApplyRequestValuesExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ApplyRequestValuesExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +/** + * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2 + * @author Nikolay Petrov + * + * Apply request values phase (JSF Spec 2.2.2) + */ +class ApplyRequestValuesExecutor implements PhaseExecutor { + public boolean execute(FacesContext facesContext) { + + System.out.println("\n\n\n\n\n ApplyRequestValuesExecutor \n\n\n\n\n"); + + facesContext.getViewRoot().processDecodes(facesContext); + return false; + } + + public PhaseId getPhase() { + return PhaseId.APPLY_REQUEST_VALUES; + } +} Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/DefaultRestoreViewSupport.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/DefaultRestoreViewSupport.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/DefaultRestoreViewSupport.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/DefaultRestoreViewSupport.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import java.util.Iterator; +import java.util.Map; + +import javax.el.ValueExpression; +import javax.faces.FacesException; +import javax.faces.component.UIComponent; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author Mathias Broekelmann (latest modification by $Author: mbr $) + * @version $Revision: 517403 $ $Date: 2007-03-12 22:17:00 +0100 (Mo, 12 Mrz 2007) $ + */ +public class DefaultRestoreViewSupport implements RestoreViewSupport +{ + private static final String JAVAX_SERVLET_INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path"; + + private static final String JAVAX_SERVLET_INCLUDE_PATH_INFO = "javax.servlet.include.path_info"; + + private final Log log = LogFactory.getLog(DefaultRestoreViewSupport.class); + + public void processComponentBinding(FacesContext facesContext, UIComponent component) + { + ValueExpression binding = component.getValueExpression("binding"); + if (binding != null) + { + binding.setValue(facesContext.getELContext(), component); + } + + for (Iterator iter = component.getFacetsAndChildren(); iter.hasNext();) + { + processComponentBinding(facesContext, (UIComponent) iter.next()); + } + } + + public String calculateViewId(FacesContext facesContext) + { + //Assert.notNull(facesContext); + ExternalContext externalContext = facesContext.getExternalContext(); + Map requestMap = externalContext.getRequestMap(); + + String viewId = (String) requestMap.get(JAVAX_SERVLET_INCLUDE_PATH_INFO); + boolean traceEnabled = log.isTraceEnabled(); + if (viewId != null) + { + if (traceEnabled) + { + log.trace("Calculated viewId '" + viewId + "' from request param '" + JAVAX_SERVLET_INCLUDE_PATH_INFO + + "'"); + } + } + else + { + viewId = externalContext.getRequestPathInfo(); + if (viewId != null && traceEnabled) + { + log.trace("Calculated viewId '" + viewId + "' from request path info"); + } + } + + if (viewId == null) + { + viewId = (String) requestMap.get(JAVAX_SERVLET_INCLUDE_SERVLET_PATH); + if (viewId != null && traceEnabled) + { + log.trace("Calculated viewId '" + viewId + "' from request param '" + + JAVAX_SERVLET_INCLUDE_SERVLET_PATH + "'"); + } + } + + if (viewId == null) + { + viewId = externalContext.getRequestServletPath(); + if (viewId != null && traceEnabled) + { + log.trace("Calculated viewId '" + viewId + "' from request servlet path"); + } + } + + if (viewId == null) + { + throw new FacesException("Could not determine view id."); + } + + return viewId; + } + + public boolean isPostback(FacesContext facesContext) + { + return true; + } +} Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/InvokeApplicationExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/InvokeApplicationExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/InvokeApplicationExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/InvokeApplicationExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +/** + * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2 + * @author Nikolay Petrov + * + * Invoke application phase (JSF Spec 2.2.5) + */ +class InvokeApplicationExecutor implements PhaseExecutor { + public boolean execute(FacesContext facesContext) { + facesContext.getViewRoot().processApplication(facesContext); + return false; + } + + public PhaseId getPhase() { + return PhaseId.INVOKE_APPLICATION; + } +} \ No newline at end of file Copied: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycle.java (from r610605, shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java) URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycle.java?p2=shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycle.java&p1=shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java&r1=610605&r2=611661&rev=611661&view=diff ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycle.java (original) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycle.java Sun Jan 13 14:30:00 2008 @@ -15,12 +15,13 @@ * limitations under the License. */ -package org.apache.shale.test.mock; +package org.apache.shale.test.mock.lifecycle; import java.util.ArrayList; import java.util.List; import javax.faces.FacesException; import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.faces.lifecycle.Lifecycle; @@ -42,8 +43,22 @@ /** * <p>List of event listeners for this instance.</p> */ - private List listeners = new ArrayList(); + private List phaseListenerList = new ArrayList(); + private PhaseExecutor[] lifecycleExecutors; + private PhaseExecutor renderExecutor; + + public MockLifecycle() + { + lifecycleExecutors = new PhaseExecutor[] { + new RestoreViewExecutor(), + new ApplyRequestValuesExecutor(), + new ProcessValidationsExecutor(), + new UpdateModelValuesExecutor(), + new InvokeApplicationExecutor() + }; + renderExecutor = new RenderResponseExecutor(); + } // ------------------------------------------------------- Lifecycle Methods @@ -51,7 +66,7 @@ /** [EMAIL PROTECTED] */ public void addPhaseListener(PhaseListener listener) { - listeners.add(listener); + phaseListenerList.add(listener); } @@ -59,15 +74,51 @@ /** [EMAIL PROTECTED] */ public void execute(FacesContext context) throws FacesException { - throw new UnsupportedOperationException(); + PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, context, getPhaseListeners()); + for(int executorIndex = 0;executorIndex < lifecycleExecutors.length;executorIndex++) { + if(executePhase(context, lifecycleExecutors[executorIndex], phaseListenerMgr)) { + return; + } + } + } + + private boolean executePhase(FacesContext facesContext, PhaseExecutor executor, + PhaseListenerManager phaseListenerMgr) throws FacesException { + boolean skipFurtherProcessing = false; + + try { + phaseListenerMgr.informPhaseListenersBefore(executor.getPhase()); + + if(isResponseComplete(facesContext, executor.getPhase(), true)) { + // have to return right away + return true; + } + if(shouldRenderResponse(facesContext, executor.getPhase(), true)) { + skipFurtherProcessing = true; + } + + if(executor.execute(facesContext)) { + return true; + } + } finally { + phaseListenerMgr.informPhaseListenersAfter(executor.getPhase()); + } + + + if (isResponseComplete(facesContext, executor.getPhase(), false) + || shouldRenderResponse(facesContext, executor.getPhase(), false)) { + // since this phase is completed we don't need to return right away even if the response is completed + skipFurtherProcessing = true; + } + return skipFurtherProcessing; } /** [EMAIL PROTECTED] */ public PhaseListener[] getPhaseListeners() { - return (PhaseListener[]) listeners.toArray(new PhaseListener[listeners.size()]); + return (PhaseListener[]) phaseListenerList.toArray(new PhaseListener[phaseListenerList.size()]); } @@ -75,7 +126,7 @@ /** [EMAIL PROTECTED] */ public void removePhaseListener(PhaseListener listener) { - listeners.remove(listener); + phaseListenerList.remove(listener); } @@ -83,9 +134,41 @@ /** [EMAIL PROTECTED] */ public void render(FacesContext context) throws FacesException { - throw new UnsupportedOperationException(); + // if the response is complete we should not be invoking the phase listeners + if(isResponseComplete(context, renderExecutor.getPhase(), true)) { + return; + } + + PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, context, getPhaseListeners()); + + try { + phaseListenerMgr.informPhaseListenersBefore(renderExecutor.getPhase()); + // also possible that one of the listeners completed the response + if(isResponseComplete(context, renderExecutor.getPhase(), true)) { + return; + } + + renderExecutor.execute(context); + } finally { + phaseListenerMgr.informPhaseListenersAfter(renderExecutor.getPhase()); + } } + + private boolean isResponseComplete(FacesContext facesContext, PhaseId phase, boolean before) { + boolean flag = false; + if (facesContext.getResponseComplete()) { + flag = true; + } + return flag; + } + private boolean shouldRenderResponse(FacesContext facesContext, PhaseId phase, boolean before) { + boolean flag = false; + if (facesContext.getRenderResponse()) { + flag = true; + } + return flag; + } } Copied: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycleFactory.java (from r610605, shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycleFactory.java) URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycleFactory.java?p2=shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycleFactory.java&p1=shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycleFactory.java&r1=610605&r2=611661&rev=611661&view=diff ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/MockLifecycleFactory.java (original) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/MockLifecycleFactory.java Sun Jan 13 14:30:00 2008 @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.shale.test.mock; +package org.apache.shale.test.mock.lifecycle; import java.util.HashMap; import java.util.Iterator; Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + + +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +/** + * Implements the PhaseExecutor for a lifecycle + * + * @author Nikolay Petrov + * + */ +interface PhaseExecutor { + + /** + * Executes a phase of the JavaServer(tm) Faces lifecycle, like UpdateModelValues. + * The <code>execute</code> method is called by the lifecylce implementation's private + * <code>executePhase</code>. + * @param facesContext The <code>FacesContext</code> for the current request we are processing + * @return <code>true</code> if execution should be stopped + */ + boolean execute(FacesContext facesContext); + + /** + * Returns the <code>PhaseId</code> for which the implemented executor is invoked + * @return + */ + PhaseId getPhase(); +} \ No newline at end of file Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseListenerManager.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseListenerManager.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseListenerManager.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/PhaseListenerManager.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import java.util.HashMap; +import java.util.Map; +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseEvent; +import javax.faces.event.PhaseId; +import javax.faces.event.PhaseListener; +import javax.faces.lifecycle.Lifecycle; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * This class encapsulates the logic used to call PhaseListeners. It was + * needed because of issue 9 of the JSF 1.2 spec. See section 11.3 for more + * details. + * + * @author Stan Silvert + */ +class PhaseListenerManager { + + private static final Log log = LogFactory.getLog(PhaseListenerManager.class); + + private Lifecycle lifecycle; + private FacesContext facesContext; + private PhaseListener[] phaseListeners; + + // Tracks success in the beforePhase. Listeners that throw an exception + // in beforePhase or were never called because a previous listener threw + // an exception should not have its afterPhase called + //private Map<PhaseId, boolean[]> listenerSuccessMap = new HashMap<PhaseId, boolean[]>(); + private Map listenerSuccessMap = new HashMap(); + + /** Creates a new instance of PhaseListenerManager */ + PhaseListenerManager(Lifecycle lifecycle, FacesContext facesContext, PhaseListener[] phaseListeners) { + this.lifecycle = lifecycle; + this.facesContext = facesContext; + this.phaseListeners = phaseListeners; + } + + private boolean isListenerForThisPhase(PhaseListener phaseListener, PhaseId phaseId) { + int listenerPhaseId = phaseListener.getPhaseId().getOrdinal(); + return (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() || + listenerPhaseId == phaseId.getOrdinal()); + } + + void informPhaseListenersBefore(PhaseId phaseId) { + boolean[] beforePhaseSuccess = new boolean[phaseListeners.length]; + listenerSuccessMap.put(phaseId, beforePhaseSuccess); + + for (int i = 0; i < phaseListeners.length; i++) { + PhaseListener phaseListener = phaseListeners[i]; + if (isListenerForThisPhase(phaseListener, phaseId)) { + try { + phaseListener.beforePhase(new PhaseEvent(facesContext, phaseId, lifecycle)); + beforePhaseSuccess[i] = true; + } catch (Exception e) { + beforePhaseSuccess[i] = false; // redundant - for clarity + log.error("Exception in PhaseListener " + phaseId.toString() + " beforePhase.", e); + return; + } + } + } + } + + void informPhaseListenersAfter(PhaseId phaseId) { + //boolean[] beforePhaseSuccess = listenerSuccessMap.get(phaseId); + boolean[] beforePhaseSuccess = (boolean[]) listenerSuccessMap.get(phaseId); + + for (int i = phaseListeners.length - 1; i >= 0; i--) { + PhaseListener phaseListener = phaseListeners[i]; + if (isListenerForThisPhase(phaseListener, phaseId) + && beforePhaseSuccess[i]) { + try { + phaseListener.afterPhase(new PhaseEvent(facesContext, phaseId, lifecycle)); + } catch (Exception e) { + log.error("Exception in PhaseListener " + phaseId.toString() + " afterPhase", e); + } + } + } + + } +} \ No newline at end of file Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ProcessValidationsExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ProcessValidationsExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ProcessValidationsExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/ProcessValidationsExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +/** + * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2 + * @author Nikolay Petrov + * + * Process validations phase (JSF Spec 2.2.3) + */ +class ProcessValidationsExecutor implements PhaseExecutor { + public boolean execute(FacesContext facesContext) { + facesContext.getViewRoot().processValidators(facesContext); + return false; + } + + public PhaseId getPhase() { + return PhaseId.PROCESS_VALIDATIONS; + } +} \ No newline at end of file Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RenderResponseExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RenderResponseExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RenderResponseExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RenderResponseExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import java.io.IOException; + +import javax.faces.FacesException; +import javax.faces.application.Application; +import javax.faces.application.ViewHandler; +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +/** + * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2 + * @author Nikolay Petrov + * + * render response phase (JSF Spec 2.2.6) + */ +class RenderResponseExecutor implements PhaseExecutor { + public boolean execute(FacesContext facesContext) { + Application application = facesContext.getApplication(); + ViewHandler viewHandler = application.getViewHandler(); + + try { + viewHandler.renderView(facesContext, facesContext.getViewRoot()); + } catch (IOException e) { + throw new FacesException(e.getMessage(), e); + } + return false; + } + + public PhaseId getPhase() { + return PhaseId.RENDER_RESPONSE; + } +} \ No newline at end of file Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.FacesException; +import javax.faces.application.Application; +import javax.faces.application.ViewExpiredException; +import javax.faces.application.ViewHandler; +import javax.faces.component.UIViewRoot; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Implements the Restore View Phase (JSF Spec 2.2.1) + * + * @author Nikolay Petrov + * @author Bruno Aranda (JSF 1.2) + * @version $Revision: 517403 $ $Date: 2007-03-12 22:17:00 +0100 (Mo, 12 Mrz 2007) $ + * + */ +class RestoreViewExecutor implements PhaseExecutor +{ + + private static final Log log = LogFactory.getLog(RestoreViewExecutor.class); + private RestoreViewSupport _restoreViewSupport; + + public boolean execute(FacesContext facesContext) + { + if (facesContext == null) + { + throw new FacesException("FacesContext is null"); + } + + // init the View + Application application = facesContext.getApplication(); + ViewHandler viewHandler = application.getViewHandler(); + viewHandler.initView(facesContext); + + UIViewRoot viewRoot = facesContext.getViewRoot(); + + RestoreViewSupport restoreViewSupport = getRestoreViewSupport(); + + if (viewRoot != null) + { + if (log.isTraceEnabled()) + log.trace("View already exists in the FacesContext"); + + viewRoot.setLocale(facesContext.getExternalContext().getRequestLocale()); + restoreViewSupport.processComponentBinding(facesContext, viewRoot); + return false; + } + + String viewId = restoreViewSupport.calculateViewId(facesContext); + + // Determine if this request is a postback or initial request + if (restoreViewSupport.isPostback(facesContext)) + { + if (log.isTraceEnabled()) + log.trace("Request is a postback"); + + viewRoot = viewHandler.restoreView(facesContext, viewId); + if (viewRoot == null) + { + throw new ViewExpiredException("The expected view was not returned " + "for the view identifier: " + + viewId, viewId); + } + restoreViewSupport.processComponentBinding(facesContext, viewRoot); + } + else + { + if (log.isTraceEnabled()) + log.trace("Request is not a postback. New UIViewRoot will be created"); + + viewRoot = viewHandler.createView(facesContext, viewId); + facesContext.renderResponse(); + } + + facesContext.setViewRoot(viewRoot); + + return false; + } + + protected RestoreViewSupport getRestoreViewSupport() + { + if (_restoreViewSupport == null) + { + _restoreViewSupport = new DefaultRestoreViewSupport(); + } + return _restoreViewSupport; + } + + /** + * @param restoreViewSupport + * the restoreViewSupport to set + */ + public void setRestoreViewSupport(RestoreViewSupport restoreViewSupport) + { + _restoreViewSupport = restoreViewSupport; + } + + public PhaseId getPhase() + { + return PhaseId.RESTORE_VIEW; + } + + /** + * TODO place that stuff into the default view handler implementation. + */ + private static String deriveViewId(FacesContext facesContext) + { + ExternalContext externalContext = facesContext.getExternalContext(); + +// if (PortletUtil.isPortletRequest(facesContext)) +// { +// PortletRequest request = (PortletRequest) externalContext.getRequest(); +// return request.getParameter(MyFacesGenericPortlet.VIEW_ID); +// } +// + String viewId = externalContext.getRequestPathInfo(); // getPathInfo + if (viewId == null) + { + // No extra path info found, so it is propably extension mapping + viewId = externalContext.getRequestServletPath(); // getServletPath +// DebugUtils.assertError(viewId != null, log, +// "RequestServletPath is null, cannot determine viewId of current page."); + if (viewId == null) + return null; + + // TODO: JSF Spec 2.2.1 - what do they mean by "if the default + // ViewHandler implementation is used..." ? + String defaultSuffix = externalContext.getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME); + String suffix = defaultSuffix != null ? defaultSuffix : ViewHandler.DEFAULT_SUFFIX; +// DebugUtils.assertError(suffix.charAt(0) == '.', log, "Default suffix must start with a dot!"); + + int dot = viewId.lastIndexOf('.'); + if (dot == -1) + { + log.error("Assumed extension mapping, but there is no extension in " + viewId); + viewId = null; + } + else + { + viewId = viewId.substring(0, dot) + suffix; + } + } + + return viewId; + } +} Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewSupport.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewSupport.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewSupport.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/RestoreViewSupport.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.FacesException; +import javax.faces.component.UIComponent; +import javax.faces.context.ExternalContext; +import javax.faces.context.FacesContext; + +/** + * Support class for restore view phase + * + * @author Mathias Broekelmann (latest modification by $Author: mbr $) + * @version $Revision: 517403 $ $Date: 2007-03-12 22:17:00 +0100 (Mo, 12 Mrz 2007) $ + */ +public interface RestoreViewSupport +{ + /** + * <p> + * Calculates the view id from the given faces context by the following algorithm + * </p> + * <ul> + * <li>lookup the viewid from the request attribute "javax.servlet.include.path_info" + * <li>if null lookup the value for viewid by [EMAIL PROTECTED] ExternalContext#getRequestPathInfo()} + * <li>if null lookup the value for viewid from the request attribute "javax.servlet.include.servlet_path" + * <li>if null lookup the value for viewid by [EMAIL PROTECTED] ExternalContext#getRequestServletPath()} + * <li>if null throw a [EMAIL PROTECTED] FacesException} + * </ul> + */ + String calculateViewId(FacesContext facesContext); + + /** + * Processes the component tree. For each component (including the given one) in the tree determine if a value + * expression for the attribute "binding" is defined. If the expression is not null set the component instance to + * the value of this expression + * + * @param facesContext + * @param component + * the root component + */ + void processComponentBinding(FacesContext facesContext, UIComponent component); + + /** + * <p> + * Determine if the current request is a post back by the following algorithm. + * </p> + * <p> + * Find the render-kit-id for the current request by calling calculateRenderKitId() on the Applicationâs + * ViewHandler. Get that RenderKitâs ResponseStateManager and call its isPostback() method, passing the given + * FacesContext. + * </p> + * + * @param facesContext + * @return + */ + boolean isPostback(FacesContext facesContext); +} \ No newline at end of file Added: shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/UpdateModelValuesExecutor.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/UpdateModelValuesExecutor.java?rev=611661&view=auto ============================================================================== --- shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/UpdateModelValuesExecutor.java (added) +++ shale/framework/trunk/shale-test/src/main/java/org/apache/shale/test/mock/lifecycle/UpdateModelValuesExecutor.java Sun Jan 13 14:30:00 2008 @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shale.test.mock.lifecycle; + +import javax.faces.context.FacesContext; +import javax.faces.event.PhaseId; + + +/** + * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2 + * @author Nikolay Petrov + * + * Update model values phase (JSF Spec 2.2.4) + */ +class UpdateModelValuesExecutor implements PhaseExecutor { + public boolean execute(FacesContext facesContext) { + facesContext.getViewRoot().processUpdates(facesContext); + return false; + } + + public PhaseId getPhase() { + return PhaseId.UPDATE_MODEL_VALUES; + } +} \ No newline at end of file