From 52018b64c5e9249820a065bb9da0b24adc05e4f2 Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Mon, 26 Nov 2007 19:45:14 +0000 Subject: [PATCH] SWF-418 - Restore JSF 1.1 compatability --- .../.settings/org.eclipse.jdt.core.prefs | 6 +- spring-faces/project.properties | 4 +- .../src/main/java/META-INF/faces-config.xml | 17 +- .../CompositeFlowPropertyResolver.java | 27 + .../CompositeFlowVariableResolver.java | 27 + .../ELDelegatingPropertyResolver.java | 89 +++ .../ELDelegatingVariableResolver.java | 28 + .../faces/expression/SimpleELContext.java | 27 + .../faces/ui/AjaxViewRoot.java | 245 +++++++++ .../faces/ui/DelegatingViewRoot.java | 506 ++++++++++++++++++ .../springframework/faces/ui/DojoAdvisor.java | 14 +- .../faces/ui/DojoAdvisorRenderer.java | 2 +- .../faces/ui/DojoClientCurrencyValidator.java | 6 +- .../springframework/faces/ui/ExtAdvisor.java | 18 +- .../ui/resource/RenderResourceAction.java | 4 +- .../faces/webflow/FlowFacesContext.java | 71 ++- .../faces/webflow/FlowViewHandler.java | 8 - .../faces/webflow/FlowViewStateManager.java | 164 +++--- .../faces/webflow/JsfUtils.java | 11 + .../faces/webflow/JsfViewFactory.java | 7 +- .../faces/webflow/TreeStructureManager.java | 13 +- .../ui/resource/FlowResourceHelperTests.java | 26 +- .../resource/RenderResourceActionTests.java | 26 +- .../webflow/FlowActionListenerTests.java | 10 +- .../faces/webflow/FlowFacesContextTests.java | 34 +- .../webflow/JsfFinalResponseActionTests.java | 7 +- .../faces/webflow/JsfViewFactoryTests.java | 8 +- .../faces/webflow/JsfViewTests.java | 9 +- 28 files changed, 1190 insertions(+), 224 deletions(-) create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowPropertyResolver.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowVariableResolver.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingPropertyResolver.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingVariableResolver.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/SimpleELContext.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/ui/DelegatingViewRoot.java diff --git a/spring-faces/.settings/org.eclipse.jdt.core.prefs b/spring-faces/.settings/org.eclipse.jdt.core.prefs index 32388fa4..26021078 100644 --- a/spring-faces/.settings/org.eclipse.jdt.core.prefs +++ b/spring-faces/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,4 @@ -#Tue Sep 25 14:10:50 EDT 2007 +#Tue Nov 20 08:06:17 EST 2007 eclipse.preferences.version=1 org.eclipse.jdt.core.codeComplete.argumentPrefixes= org.eclipse.jdt.core.codeComplete.argumentSuffixes= @@ -9,7 +9,7 @@ org.eclipse.jdt.core.codeComplete.localSuffixes= org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate @@ -79,7 +79,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=di org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.source=1.4 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 diff --git a/spring-faces/project.properties b/spring-faces/project.properties index 0aadb2b5..c2b7cb1c 100644 --- a/spring-faces/project.properties +++ b/spring-faces/project.properties @@ -7,5 +7,5 @@ project.base.version=2.0-m3-SNAPSHOT #project.version=${project.base.version} #ivy.status=release -javac.source=1.5 -javac.target=1.5 +javac.source=1.4 +javac.target=1.4 diff --git a/spring-faces/src/main/java/META-INF/faces-config.xml b/spring-faces/src/main/java/META-INF/faces-config.xml index 01e750a7..4d8b3951 100644 --- a/spring-faces/src/main/java/META-INF/faces-config.xml +++ b/spring-faces/src/main/java/META-INF/faces-config.xml @@ -1,17 +1,22 @@ - + + + org.springframework.faces.webflow.FlowActionListener - org.springframework.webflow.core.expression.el.RequestContextELResolver - org.springframework.webflow.core.expression.el.ScopeSearchingELResolver + org.springframework.faces.expression.CompositeFlowVariableResolver + org.springframework.faces.expression.CompositeFlowPropertyResolver org.springframework.faces.webflow.FlowViewStateManager org.springframework.faces.webflow.FlowViewHandler + + org.springframework.faces.support.RequestLoggingPhaseListener + + spring.faces.DojoClientTextValidator org.springframework.faces.ui.DojoClientTextValidator diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowPropertyResolver.java b/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowPropertyResolver.java new file mode 100644 index 00000000..1106d0b7 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowPropertyResolver.java @@ -0,0 +1,27 @@ +package org.springframework.faces.expression; + +import javax.el.CompositeELResolver; +import javax.faces.el.PropertyResolver; + +import org.springframework.webflow.core.expression.el.RequestContextELResolver; +import org.springframework.webflow.core.expression.el.ScopeSearchingELResolver; + +/** + * Assembles {@link RequestContextELResolver} and {@link ScopeSearchingELResolver} into a composite that may be used + * with JSF 1.1 and higher for property resolution. + * + * @author Jeremy Grelle + */ +public class CompositeFlowPropertyResolver extends ELDelegatingPropertyResolver { + + private static final CompositeELResolver composite = new CompositeELResolver(); + + static { + composite.add(new RequestContextELResolver()); + composite.add(new ScopeSearchingELResolver()); + } + + public CompositeFlowPropertyResolver(PropertyResolver nextResolver) { + super(nextResolver, composite); + } +} diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowVariableResolver.java b/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowVariableResolver.java new file mode 100644 index 00000000..377e3f9e --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/CompositeFlowVariableResolver.java @@ -0,0 +1,27 @@ +package org.springframework.faces.expression; + +import javax.el.CompositeELResolver; +import javax.faces.el.VariableResolver; + +import org.springframework.webflow.core.expression.el.RequestContextELResolver; +import org.springframework.webflow.core.expression.el.ScopeSearchingELResolver; + +/** + * Assembles {@link RequestContextELResolver} and {@link ScopeSearchingELResolver} into a composite that may be used + * with JSF 1.1 and higher for variable resolution. + * + * @author Jeremy Grelle + */ +public class CompositeFlowVariableResolver extends ELDelegatingVariableResolver { + + private static final CompositeELResolver composite = new CompositeELResolver(); + + static { + composite.add(new RequestContextELResolver()); + composite.add(new ScopeSearchingELResolver()); + } + + public CompositeFlowVariableResolver(VariableResolver nextResolver) { + super(nextResolver, composite); + } +} diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingPropertyResolver.java b/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingPropertyResolver.java new file mode 100644 index 00000000..01a549b7 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingPropertyResolver.java @@ -0,0 +1,89 @@ +package org.springframework.faces.expression; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.faces.el.EvaluationException; +import javax.faces.el.PropertyNotFoundException; +import javax.faces.el.PropertyResolver; + +public abstract class ELDelegatingPropertyResolver extends PropertyResolver { + + private PropertyResolver nextResolver; + + private ELContext elContext; + + public ELDelegatingPropertyResolver(PropertyResolver nextResolver, ELResolver delegate) { + this.nextResolver = nextResolver; + this.elContext = new SimpleELContext(delegate); + } + + public Class getType(Object base, int index) throws EvaluationException, PropertyNotFoundException { + Class type = elContext.getELResolver().getType(elContext, base, new Integer(index)); + if (elContext.isPropertyResolved()) { + return type; + } else { + return nextResolver.getType(base, index); + } + } + + public Class getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException { + Class type = elContext.getELResolver().getType(elContext, base, property); + if (elContext.isPropertyResolved()) { + return type; + } else { + return nextResolver.getType(base, property); + } + } + + public Object getValue(Object base, int index) throws EvaluationException, PropertyNotFoundException { + Object value = elContext.getELResolver().getValue(elContext, base, new Integer(index)); + if (elContext.isPropertyResolved()) { + return value; + } else { + return nextResolver.getValue(base, index); + } + } + + public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException { + Object value = elContext.getELResolver().getValue(elContext, base, property); + if (elContext.isPropertyResolved()) { + return value; + } else { + return nextResolver.getValue(base, property); + } + } + + public boolean isReadOnly(Object base, int index) throws EvaluationException, PropertyNotFoundException { + boolean readOnly = elContext.getELResolver().isReadOnly(elContext, base, new Integer(index)); + if (elContext.isPropertyResolved()) { + return readOnly; + } else { + return nextResolver.isReadOnly(base, index); + } + } + + public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException { + boolean readOnly = elContext.getELResolver().isReadOnly(elContext, base, property); + if (elContext.isPropertyResolved()) { + return readOnly; + } else { + return nextResolver.isReadOnly(base, property); + } + } + + public void setValue(Object base, int index, Object value) throws EvaluationException, PropertyNotFoundException { + elContext.getELResolver().setValue(elContext, base, new Integer(index), value); + if (!elContext.isPropertyResolved()) { + nextResolver.setValue(base, index, value); + } + } + + public void setValue(Object base, Object property, Object value) throws EvaluationException, + PropertyNotFoundException { + elContext.getELResolver().setValue(elContext, base, property, value); + if (!elContext.isPropertyResolved()) { + nextResolver.setValue(base, property, value); + } + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingVariableResolver.java b/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingVariableResolver.java new file mode 100644 index 00000000..9984f0b1 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/ELDelegatingVariableResolver.java @@ -0,0 +1,28 @@ +package org.springframework.faces.expression; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.faces.context.FacesContext; +import javax.faces.el.EvaluationException; +import javax.faces.el.VariableResolver; + +public abstract class ELDelegatingVariableResolver extends VariableResolver { + + private VariableResolver nextResolver; + + private ELContext elContext; + + public ELDelegatingVariableResolver(VariableResolver nextResolver, ELResolver delegate) { + this.nextResolver = nextResolver; + this.elContext = new SimpleELContext(delegate); + } + + public Object resolveVariable(FacesContext facesContext, String name) throws EvaluationException { + Object result = elContext.getELResolver().getValue(elContext, null, name); + if (elContext.isPropertyResolved()) { + return result; + } else { + return nextResolver.resolveVariable(facesContext, name); + } + } +} diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/SimpleELContext.java b/spring-faces/src/main/java/org/springframework/faces/expression/SimpleELContext.java new file mode 100644 index 00000000..e5737dd9 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/SimpleELContext.java @@ -0,0 +1,27 @@ +package org.springframework.faces.expression; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.el.FunctionMapper; +import javax.el.VariableMapper; + +class SimpleELContext extends ELContext { + + private ELResolver resolver; + + public SimpleELContext(ELResolver resolver) { + this.resolver = resolver; + } + + public ELResolver getELResolver() { + return resolver; + } + + public FunctionMapper getFunctionMapper() { + return null; + } + + public VariableMapper getVariableMapper() { + return null; + } +} diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java new file mode 100644 index 00000000..537cc956 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/ui/AjaxViewRoot.java @@ -0,0 +1,245 @@ +package org.springframework.faces.ui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import javax.faces.component.ContextCallback; +import javax.faces.component.UIComponent; +import javax.faces.component.UIForm; +import javax.faces.component.UIViewRoot; +import javax.faces.context.FacesContext; +import javax.faces.context.ResponseWriter; +import javax.faces.event.AbortProcessingException; +import javax.faces.event.FacesEvent; +import javax.faces.event.PhaseId; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Customizes the behavior of an existing UIViewRoot with Ajax-aware processing. + * + * @author Jeremy Grelle + */ +public class AjaxViewRoot extends DelegatingViewRoot { + + public static final String AJAX_SOURCE_PARAM = "ajaxSource"; + + public static final String PROCESS_IDS_PARAM = "processIds"; + + public static final String RENDER_IDS_PARAM = "renderIds"; + + protected static final String FORM_RENDERED = "formRendered"; + + private List events = new ArrayList(); + + private String[] processIds; + + private String[] renderIds; + + public AjaxViewRoot(UIViewRoot original) { + super(original); + swapChildren(original, this); + setId(original.getId() + "_ajax"); + } + + private void swapChildren(UIViewRoot source, UIViewRoot target) { + target.getChildren().addAll(source.getChildren()); + Iterator i = target.getChildren().iterator(); + while (i.hasNext()) { + UIComponent child = (UIComponent) i.next(); + child.setParent(this); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#encodeAll(javax.faces.context.FacesContext) + */ + public void encodeAll(FacesContext context) throws IOException { + processRequestParams(context); + for (int i = 0; i < renderIds.length; i++) { + String renderId = renderIds[i]; + ContextCallback callback = new ContextCallback() { + public void invokeContextCallback(FacesContext context, UIComponent target) { + try { + target.encodeAll(context); + if (target instanceof UIForm) { + context.getViewRoot().getAttributes().put(FORM_RENDERED, FORM_RENDERED); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + invokeOnComponent(context, renderId, callback); + } + swapChildren(this, getOriginalViewRoot()); + context.setViewRoot(getOriginalViewRoot()); + if (!getAttributes().containsKey(FORM_RENDERED)) { + context.getApplication().getViewHandler().writeState(context); + writeFormURL(context); + } + + broadCastEvents(context, PhaseId.APPLY_REQUEST_VALUES); + } + + /** + * + * @param context + */ + private void writeFormURL(FacesContext context) { + ResponseWriter writer = context.getResponseWriter(); + try { + writer.startElement("div", null); + writer.writeAttribute("id", "flowExecutionUrl", null); + writer.writeText(context.getApplication().getViewHandler().getActionURL(context, getViewId()), null); + writer.endElement("div"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#processApplication(javax.faces.context.FacesContext) + */ + public void processApplication(FacesContext context) { + broadCastEvents(context, PhaseId.INVOKE_APPLICATION); + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#processDecodes(javax.faces.context.FacesContext) + */ + public void processDecodes(FacesContext context) { + processRequestParams(context); + for (int i = 0; i < processIds.length; i++) { + String processId = processIds[i]; + ContextCallback callback = new ContextCallback() { + public void invokeContextCallback(FacesContext context, UIComponent target) { + target.processDecodes(context); + } + }; + invokeOnComponent(context, processId, callback); + } + broadCastEvents(context, PhaseId.APPLY_REQUEST_VALUES); + } + + private void processRequestParams(FacesContext context) { + + String processIdsParam = (String) context.getExternalContext().getRequestParameterMap().get(PROCESS_IDS_PARAM); + processIds = StringUtils.delimitedListToStringArray(processIdsParam, ",", " "); + processIds = removeNestedChildren(context, processIds); + + String renderIdsParam = (String) context.getExternalContext().getRequestParameterMap().get(RENDER_IDS_PARAM); + renderIds = StringUtils.delimitedListToStringArray(renderIdsParam, ",", " "); + renderIds = removeNestedChildren(context, renderIds); + } + + private String[] removeNestedChildren(FacesContext context, String[] ids) { + List idList = Arrays.asList(ids); + List trimmedIds = new ArrayList(idList); + for (ListIterator i = trimmedIds.listIterator(); i.hasNext();) { + String id = (String) i.next(); + UIComponent component = findComponent(id); + Assert.notNull(component, "Component with id " + id + " does not exist."); + while (!(component.getParent() instanceof UIViewRoot)) { + component = component.getParent(); + if (trimmedIds.contains(component.getClientId(context))) { + i.remove(); + } + } + } + return (String[]) trimmedIds.toArray(new String[trimmedIds.size()]); + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#processUpdates(javax.faces.context.FacesContext) + */ + public void processUpdates(FacesContext context) { + for (int i = 0; i < processIds.length; i++) { + String processId = processIds[i]; + ContextCallback callback = new ContextCallback() { + public void invokeContextCallback(FacesContext context, UIComponent target) { + target.processUpdates(context); + } + }; + invokeOnComponent(context, processId, callback); + } + broadCastEvents(context, PhaseId.UPDATE_MODEL_VALUES); + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#processValidators(javax.faces.context.FacesContext) + */ + public void processValidators(FacesContext context) { + for (int i = 0; i < processIds.length; i++) { + String processId = processIds[i]; + ContextCallback callback = new ContextCallback() { + public void invokeContextCallback(FacesContext context, UIComponent target) { + target.processValidators(context); + } + }; + invokeOnComponent(context, processId, callback); + } + broadCastEvents(context, PhaseId.PROCESS_VALIDATIONS); + } + + /* + * (non-Javadoc) + * @see org.springframework.faces.webflow.DelegatingViewRoot#queueEvent(javax.faces.event.FacesEvent) + */ + public void queueEvent(FacesEvent event) { + Assert.notNull(event, "Cannot queue a null event."); + events.add(event); + } + + private void broadCastEvents(FacesContext context, PhaseId phaseId) { + + List processedEvents = new ArrayList(); + + if (events.size() == 0) + return; + + boolean abort = false; + + int phaseIdOrdinal = phaseId.getOrdinal(); + Iterator i = events.iterator(); + while (i.hasNext()) { + FacesEvent event = (FacesEvent) i.next(); + int ordinal = event.getPhaseId().getOrdinal(); + if (ordinal == PhaseId.ANY_PHASE.getOrdinal() || ordinal == phaseIdOrdinal) { + UIComponent source = event.getComponent(); + try { + processedEvents.add(event); + source.broadcast(event); + } catch (AbortProcessingException e) { + abort = true; + break; + } + } + } + + if (abort) { + events.clear(); + } else { + events.removeAll(processedEvents); + } + } + + protected String[] getProcessIds() { + return processIds; + } + + protected String[] getRenderIds() { + return renderIds; + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DelegatingViewRoot.java b/spring-faces/src/main/java/org/springframework/faces/ui/DelegatingViewRoot.java new file mode 100644 index 00000000..c646db9b --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/ui/DelegatingViewRoot.java @@ -0,0 +1,506 @@ +package org.springframework.faces.ui; + +import java.io.IOException; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import javax.el.MethodExpression; +import javax.el.ValueExpression; +import javax.faces.FacesException; +import javax.faces.component.ContextCallback; +import javax.faces.component.UIComponent; +import javax.faces.component.UIViewRoot; +import javax.faces.context.FacesContext; +import javax.faces.el.ValueBinding; +import javax.faces.event.AbortProcessingException; +import javax.faces.event.FacesEvent; +import javax.faces.event.PhaseListener; + +/** + * Base class for wrapping an existing UIViewRoot to customize its behavior. + * + * @author Jeremy Grelle + */ +public abstract class DelegatingViewRoot extends UIViewRoot { + + private UIViewRoot original; + + public DelegatingViewRoot(UIViewRoot original) { + this.original = original; + } + + protected UIViewRoot getOriginalViewRoot() { + return original; + } + + /** + * @param phaseListener + * @see javax.faces.component.UIViewRoot#addPhaseListener(javax.faces.event.PhaseListener) + */ + public void addPhaseListener(PhaseListener phaseListener) { + original.addPhaseListener(phaseListener); + } + + /** + * @param event + * @throws AbortProcessingException + * @see javax.faces.component.UIComponentBase#broadcast(javax.faces.event.FacesEvent) + */ + public void broadcast(FacesEvent event) throws AbortProcessingException { + original.broadcast(event); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#createUniqueId() + */ + public String createUniqueId() { + return original.createUniqueId(); + } + + /** + * @param context + * @see javax.faces.component.UIComponentBase#decode(javax.faces.context.FacesContext) + */ + public void decode(FacesContext context) { + original.decode(context); + } + + /** + * @param context + * @throws IOException + * @see javax.faces.component.UIComponent#encodeAll(javax.faces.context.FacesContext) + */ + public void encodeAll(FacesContext context) throws IOException { + original.encodeAll(context); + } + + /** + * @param context + * @throws IOException + * @see javax.faces.component.UIViewRoot#encodeBegin(javax.faces.context.FacesContext) + */ + public void encodeBegin(FacesContext context) throws IOException { + original.encodeBegin(context); + } + + /** + * @param context + * @throws IOException + * @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext) + */ + public void encodeChildren(FacesContext context) throws IOException { + original.encodeChildren(context); + } + + /** + * @param context + * @throws IOException + * @see javax.faces.component.UIViewRoot#encodeEnd(javax.faces.context.FacesContext) + */ + public void encodeEnd(FacesContext context) throws IOException { + original.encodeEnd(context); + } + + /** + * @param expr + * @return + * @see javax.faces.component.UIComponentBase#findComponent(java.lang.String) + */ + public UIComponent findComponent(String expr) { + return original.findComponent(expr); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getAfterPhaseListener() + */ + public MethodExpression getAfterPhaseListener() { + return original.getAfterPhaseListener(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getAttributes() + */ + public Map getAttributes() { + return original.getAttributes(); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getBeforePhaseListener() + */ + public MethodExpression getBeforePhaseListener() { + return original.getBeforePhaseListener(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getChildCount() + */ + public int getChildCount() { + return original.getChildCount(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getChildren() + */ + public List getChildren() { + return original.getChildren(); + } + + /** + * @param context + * @return + * @see javax.faces.component.UIComponentBase#getClientId(javax.faces.context.FacesContext) + */ + public String getClientId(FacesContext context) { + return original.getClientId(context); + } + + /** + * @param ctx + * @return + * @see javax.faces.component.UIComponent#getContainerClientId(javax.faces.context.FacesContext) + */ + public String getContainerClientId(FacesContext ctx) { + return original.getContainerClientId(ctx); + } + + /** + * @param name + * @return + * @see javax.faces.component.UIComponentBase#getFacet(java.lang.String) + */ + public UIComponent getFacet(String name) { + return original.getFacet(name); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getFacetCount() + */ + public int getFacetCount() { + return original.getFacetCount(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getFacets() + */ + public Map getFacets() { + return original.getFacets(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getFacetsAndChildren() + */ + public Iterator getFacetsAndChildren() { + return original.getFacetsAndChildren(); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getFamily() + */ + public String getFamily() { + return original.getFamily(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getId() + */ + public String getId() { + return original.getId(); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getLocale() + */ + public Locale getLocale() { + return original.getLocale(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getParent() + */ + public UIComponent getParent() { + return original.getParent(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getRendererType() + */ + public String getRendererType() { + return original.getRendererType(); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getRenderKitId() + */ + public String getRenderKitId() { + return original.getRenderKitId(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#getRendersChildren() + */ + public boolean getRendersChildren() { + return original.getRendersChildren(); + } + + /** + * @param name + * @return + * @deprecated + * @see javax.faces.component.UIComponentBase#getValueBinding(java.lang.String) + */ + public ValueBinding getValueBinding(String name) { + return original.getValueBinding(name); + } + + /** + * @param name + * @return + * @see javax.faces.component.UIComponent#getValueExpression(java.lang.String) + */ + public ValueExpression getValueExpression(String name) { + return original.getValueExpression(name); + } + + /** + * @return + * @see javax.faces.component.UIViewRoot#getViewId() + */ + public String getViewId() { + return original.getViewId(); + } + + /** + * @param context + * @param clientId + * @param callback + * @return + * @throws FacesException + * @see javax.faces.component.UIComponentBase#invokeOnComponent(javax.faces.context.FacesContext, java.lang.String, + * javax.faces.component.ContextCallback) + */ + public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback) + throws FacesException { + return original.invokeOnComponent(context, clientId, callback); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#isRendered() + */ + public boolean isRendered() { + return original.isRendered(); + } + + /** + * @return + * @see javax.faces.component.UIComponentBase#isTransient() + */ + public boolean isTransient() { + return original.isTransient(); + } + + /** + * @param context + * @see javax.faces.component.UIViewRoot#processApplication(javax.faces.context.FacesContext) + */ + public void processApplication(FacesContext context) { + original.processApplication(context); + } + + /** + * @param context + * @see javax.faces.component.UIViewRoot#processDecodes(javax.faces.context.FacesContext) + */ + public void processDecodes(FacesContext context) { + original.processDecodes(context); + } + + /** + * @param context + * @param state + * @see javax.faces.component.UIComponentBase#processRestoreState(javax.faces.context.FacesContext, + * java.lang.Object) + */ + public void processRestoreState(FacesContext context, Object state) { + original.processRestoreState(context, state); + } + + /** + * @param context + * @return + * @see javax.faces.component.UIComponentBase#processSaveState(javax.faces.context.FacesContext) + */ + public Object processSaveState(FacesContext context) { + return original.processSaveState(context); + } + + /** + * @param context + * @see javax.faces.component.UIViewRoot#processUpdates(javax.faces.context.FacesContext) + */ + public void processUpdates(FacesContext context) { + original.processUpdates(context); + } + + /** + * @param context + * @see javax.faces.component.UIViewRoot#processValidators(javax.faces.context.FacesContext) + */ + public void processValidators(FacesContext context) { + original.processValidators(context); + } + + /** + * @param event + * @see javax.faces.component.UIViewRoot#queueEvent(javax.faces.event.FacesEvent) + */ + public void queueEvent(FacesEvent event) { + original.queueEvent(event); + } + + /** + * @param phaseListener + * @see javax.faces.component.UIViewRoot#removePhaseListener(javax.faces.event.PhaseListener) + */ + public void removePhaseListener(PhaseListener phaseListener) { + original.removePhaseListener(phaseListener); + } + + /** + * @param facesContext + * @param state + * @see javax.faces.component.UIViewRoot#restoreState(javax.faces.context.FacesContext, java.lang.Object) + */ + public void restoreState(FacesContext facesContext, Object state) { + original.restoreState(facesContext, state); + } + + /** + * @param facesContext + * @return + * @see javax.faces.component.UIViewRoot#saveState(javax.faces.context.FacesContext) + */ + public Object saveState(FacesContext facesContext) { + return original.saveState(facesContext); + } + + /** + * @param afterPhaseListener + * @see javax.faces.component.UIViewRoot#setAfterPhaseListener(javax.el.MethodExpression) + */ + public void setAfterPhaseListener(MethodExpression afterPhaseListener) { + original.setAfterPhaseListener(afterPhaseListener); + } + + /** + * @param beforePhaseListener + * @see javax.faces.component.UIViewRoot#setBeforePhaseListener(javax.el.MethodExpression) + */ + public void setBeforePhaseListener(MethodExpression beforePhaseListener) { + original.setBeforePhaseListener(beforePhaseListener); + } + + /** + * @param id + * @see javax.faces.component.UIComponentBase#setId(java.lang.String) + */ + public void setId(String id) { + original.setId(id); + } + + /** + * @param locale + * @see javax.faces.component.UIViewRoot#setLocale(java.util.Locale) + */ + public void setLocale(Locale locale) { + original.setLocale(locale); + } + + /** + * @param parent + * @see javax.faces.component.UIComponentBase#setParent(javax.faces.component.UIComponent) + */ + public void setParent(UIComponent parent) { + original.setParent(parent); + } + + /** + * @param rendered + * @see javax.faces.component.UIComponentBase#setRendered(boolean) + */ + public void setRendered(boolean rendered) { + original.setRendered(rendered); + } + + /** + * @param rendererType + * @see javax.faces.component.UIComponentBase#setRendererType(java.lang.String) + */ + public void setRendererType(String rendererType) { + if (original != null) { + original.setRendererType(rendererType); + } + } + + /** + * @param renderKitId + * @see javax.faces.component.UIViewRoot#setRenderKitId(java.lang.String) + */ + public void setRenderKitId(String renderKitId) { + original.setRenderKitId(renderKitId); + } + + /** + * @param transientFlag + * @see javax.faces.component.UIComponentBase#setTransient(boolean) + */ + public void setTransient(boolean transientFlag) { + original.setTransient(transientFlag); + } + + /** + * @param name + * @param binding + * @deprecated + * @see javax.faces.component.UIComponentBase#setValueBinding(java.lang.String, javax.faces.el.ValueBinding) + */ + public void setValueBinding(String name, ValueBinding binding) { + original.setValueBinding(name, binding); + } + + /** + * @param name + * @param expression + * @see javax.faces.component.UIComponent#setValueExpression(java.lang.String, javax.el.ValueExpression) + */ + public void setValueExpression(String name, ValueExpression expression) { + original.setValueExpression(name, expression); + } + + /** + * @param viewId + * @see javax.faces.component.UIViewRoot#setViewId(java.lang.String) + */ + public void setViewId(String viewId) { + original.setViewId(viewId); + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisor.java b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisor.java index ef887a5b..efb9f532 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisor.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisor.java @@ -15,9 +15,9 @@ */ package org.springframework.faces.ui; -import javax.el.ValueExpression; import javax.faces.component.UIComponentBase; import javax.faces.context.FacesContext; +import javax.faces.el.ValueBinding; public abstract class DojoAdvisor extends UIComponentBase { @@ -46,8 +46,8 @@ public abstract class DojoAdvisor extends UIComponentBase { if (disabled != null) { return disabled; } - ValueExpression exp = getValueExpression("disabled"); - return exp != null ? (Boolean) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("disabled"); + return exp != null ? (Boolean) exp.getValue(getFacesContext()) : null; } public void setDisabled(Boolean disabled) { @@ -82,8 +82,8 @@ public abstract class DojoAdvisor extends UIComponentBase { if (promptMessage != null) { return promptMessage; } - ValueExpression exp = getValueExpression("promptMessage"); - return exp != null ? (String) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("promptMessage"); + return exp != null ? (String) exp.getValue(getFacesContext()) : null; } public void setPromptMessage(String promptMessage) { @@ -94,8 +94,8 @@ public abstract class DojoAdvisor extends UIComponentBase { if (invalidMessage != null) { return invalidMessage; } - ValueExpression exp = getValueExpression("invalidMessage"); - return exp != null ? (String) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("invalidMessage"); + return exp != null ? (String) exp.getValue(getFacesContext()) : null; } public void setInvalidMessage(String invalidMessage) { diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java index 28a171b4..925e5392 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/DojoAdvisorRenderer.java @@ -40,7 +40,7 @@ public class DojoAdvisorRenderer extends DojoRenderer { if (component.getChildCount() == 0) throw new FacesException("A Spring Faces advisor expects to have at least one child component."); - UIComponent advisedChild = component.getChildren().get(0); + UIComponent advisedChild = (UIComponent) component.getChildren().get(0); resourceHelper.renderDojoInclude(context, ((DojoAdvisor) component).getDojoComponentType()); diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/DojoClientCurrencyValidator.java b/spring-faces/src/main/java/org/springframework/faces/ui/DojoClientCurrencyValidator.java index 1a86e0d7..4860b484 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/DojoClientCurrencyValidator.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/DojoClientCurrencyValidator.java @@ -15,8 +15,8 @@ */ package org.springframework.faces.ui; -import javax.el.ValueExpression; import javax.faces.context.FacesContext; +import javax.faces.el.ValueBinding; public class DojoClientCurrencyValidator extends DojoAdvisor { @@ -38,8 +38,8 @@ public class DojoClientCurrencyValidator extends DojoAdvisor { if (currency != null) { return currency; } - ValueExpression exp = getValueExpression("currency"); - return exp != null ? (String) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("currency"); + return exp != null ? (String) exp.getValue(getFacesContext()) : null; } public void setCurrency(String currency) { diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/ExtAdvisor.java b/spring-faces/src/main/java/org/springframework/faces/ui/ExtAdvisor.java index 65638422..089fc689 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/ExtAdvisor.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/ExtAdvisor.java @@ -15,8 +15,8 @@ */ package org.springframework.faces.ui; -import javax.el.ValueExpression; import javax.faces.context.FacesContext; +import javax.faces.el.ValueBinding; public abstract class ExtAdvisor extends ExtJsComponent { @@ -123,8 +123,8 @@ public abstract class ExtAdvisor extends ExtJsComponent { if (disabled != null) { return disabled; } - ValueExpression exp = getValueExpression("disabled"); - return exp != null ? (Boolean) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("disabled"); + return exp != null ? (Boolean) exp.getValue(getFacesContext()) : null; } public void setDisabled(Boolean disabled) { @@ -167,8 +167,8 @@ public abstract class ExtAdvisor extends ExtJsComponent { if (invalidText != null) { return invalidText; } - ValueExpression exp = getValueExpression("invalidText"); - return exp != null ? (String) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("invalidText"); + return exp != null ? (String) exp.getValue(getFacesContext()) : null; } public void setInvalidText(String invalidText) { @@ -179,8 +179,8 @@ public abstract class ExtAdvisor extends ExtJsComponent { if (msgClass != null) { return msgClass; } - ValueExpression exp = getValueExpression("msgClass"); - return exp != null ? (String) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("msgClass"); + return exp != null ? (String) exp.getValue(getFacesContext()) : null; } public void setMsgClass(String msgClass) { @@ -199,8 +199,8 @@ public abstract class ExtAdvisor extends ExtJsComponent { if (readOnly != null) { return readOnly; } - ValueExpression exp = getValueExpression("readOnly"); - return exp != null ? (Boolean) exp.getValue(getFacesContext().getELContext()) : null; + ValueBinding exp = getValueBinding("readOnly"); + return exp != null ? (Boolean) exp.getValue(getFacesContext()) : null; } public void setReadOnly(Boolean readOnly) { diff --git a/spring-faces/src/main/java/org/springframework/faces/ui/resource/RenderResourceAction.java b/spring-faces/src/main/java/org/springframework/faces/ui/resource/RenderResourceAction.java index 4277496b..beb24cbb 100644 --- a/spring-faces/src/main/java/org/springframework/faces/ui/resource/RenderResourceAction.java +++ b/spring-faces/src/main/java/org/springframework/faces/ui/resource/RenderResourceAction.java @@ -33,7 +33,7 @@ public class RenderResourceAction implements Action { private static final String HTTP_CACHE_CONTROL_HEADER = "Cache-Control"; - private Map defaultMimeTypes = new HashMap(); + private Map defaultMimeTypes = new HashMap(); { defaultMimeTypes.put(".css", "text/css"); defaultMimeTypes.put(".gif", "image/gif"); @@ -76,7 +76,7 @@ public class RenderResourceAction implements Action { String mimeType = servletContext.getMimeType(jarResourcePath); if (mimeType == null) { String extension = jarResourcePath.substring(jarResourcePath.lastIndexOf('.')); - mimeType = defaultMimeTypes.get(extension); + mimeType = (String) defaultMimeTypes.get(extension); } response.setContentType(mimeType); diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java index a7392da7..616341e9 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContext.java @@ -15,6 +15,7 @@ */ package org.springframework.faces.webflow; +import java.lang.reflect.Method; import java.util.Iterator; import javax.el.ELContext; @@ -32,6 +33,7 @@ import org.springframework.binding.message.MessageResolver; import org.springframework.binding.message.Messages; import org.springframework.binding.message.Severity; import org.springframework.context.MessageSource; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.webflow.execution.RequestContext; @@ -44,7 +46,17 @@ import org.springframework.webflow.execution.RequestContext; public class FlowFacesContext extends FacesContext { /** - * The Web Flow request context. + * The key for storing the responseComplete flag + */ + static final String RESPONSE_COMPLETE_KEY = "responseComplete"; + + /** + * The key for storing the renderResponse flag + */ + static final String RENDER_RESPONSE_KEY = "renderResponse"; + + /** + * The key for storing the renderResponse flag */ private RequestContext context; @@ -68,12 +80,18 @@ public class FlowFacesContext extends FacesContext { if (StringUtils.hasText(message.getSummary())) { msgText.append(message.getSummary()); } + + String source = null; + if (StringUtils.hasText(clientId)) { + source = clientId; + } + if (message.getSeverity() == FacesMessage.SEVERITY_INFO) { - messageResolver = Messages.text(msgText.toString(), Severity.INFO); + messageResolver = Messages.text(source, msgText.toString(), Severity.INFO); } else if (message.getSeverity() == FacesMessage.SEVERITY_WARN) { - messageResolver = Messages.text(msgText.toString(), Severity.WARNING); + messageResolver = Messages.text(source, msgText.toString(), Severity.WARNING); } else { - messageResolver = Messages.text(msgText.toString(), Severity.ERROR); + messageResolver = Messages.text(source, msgText.toString(), Severity.ERROR); } context.getMessageContext().addMessage(messageResolver); } @@ -81,7 +99,7 @@ public class FlowFacesContext extends FacesContext { /** * Returns an Iterator for all component clientId's for which messages have been added. */ - public Iterator getClientIdsWithMessages() { + public Iterator getClientIdsWithMessages() { return new ClientIdIterator(); } @@ -94,9 +112,9 @@ public class FlowFacesContext extends FacesContext { return null; } FacesMessage.Severity max = FacesMessage.SEVERITY_INFO; - Iterator i = getMessages(); + Iterator i = getMessages(); while (i.hasNext()) { - FacesMessage message = i.next(); + FacesMessage message = (FacesMessage) i.next(); if (message.getSeverity().getOrdinal() > max.getOrdinal()) { max = message.getSeverity(); } @@ -109,7 +127,7 @@ public class FlowFacesContext extends FacesContext { /** * Returns an Iterator for all Messages in the current MessageContext that does translation to FacesMessages. */ - public Iterator getMessages() { + public Iterator getMessages() { return new FacesMessageIterator(); } @@ -117,24 +135,32 @@ public class FlowFacesContext extends FacesContext { * Returns an Iterator for all Messages with the given clientId in the current MessageContext that does translation * to FacesMessages. */ - public Iterator getMessages(String clientId) { + public Iterator getMessages(String clientId) { return new FacesMessageIterator(clientId); } public boolean getRenderResponse() { - return delegate.getRenderResponse(); + Boolean renderResponse = context.getFlashScope().getBoolean(RENDER_RESPONSE_KEY); + if (renderResponse == null) { + return false; + } + return renderResponse.booleanValue(); } public boolean getResponseComplete() { - return delegate.getResponseComplete(); + Boolean responseComplete = context.getFlashScope().getBoolean(RESPONSE_COMPLETE_KEY); + if (responseComplete == null) { + return false; + } + return responseComplete.booleanValue(); } public void renderResponse() { - delegate.renderResponse(); + context.getFlashScope().put(RENDER_RESPONSE_KEY, Boolean.TRUE); } public void responseComplete() { - delegate.responseComplete(); + context.getFlashScope().put(RESPONSE_COMPLETE_KEY, Boolean.TRUE); } // ------------------ Pass-through delegate methods ----------------------// @@ -144,7 +170,16 @@ public class FlowFacesContext extends FacesContext { } public ELContext getELContext() { - return delegate.getELContext(); + Method delegateMethod = ClassUtils.getMethodIfAvailable(delegate.getClass(), "getELContext", null); + if (delegateMethod != null) { + try { + return (ELContext) delegateMethod.invoke(delegate, null); + } catch (Exception e) { + return null; + } + } else { + return null; + } } public ExternalContext getExternalContext() { @@ -188,7 +223,7 @@ public class FlowFacesContext extends FacesContext { return delegate; } - private class FacesMessageIterator implements Iterator { + private class FacesMessageIterator implements Iterator { private Message[] messages; @@ -206,7 +241,7 @@ public class FlowFacesContext extends FacesContext { return messages.length > currentIndex + 1; } - public FacesMessage next() { + public Object next() { currentIndex++; Message nextMessage = messages[currentIndex]; FacesMessage facesMessage; @@ -229,7 +264,7 @@ public class FlowFacesContext extends FacesContext { } - private class ClientIdIterator implements Iterator { + private class ClientIdIterator implements Iterator { private Message[] messages; @@ -250,7 +285,7 @@ public class FlowFacesContext extends FacesContext { return false; } - public String next() { + public Object next() { Message next = messages[++currentIndex]; while (next.getSource() == null || "".equals(next.getSource())) { next = messages[++currentIndex]; diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java index 53f4833f..8bdb451c 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewHandler.java @@ -44,10 +44,6 @@ public class FlowViewHandler extends ViewHandler { } // ------------------- Pass-through delegate methods ------------------// - public String calculateCharacterEncoding(FacesContext context) { - return delegate.calculateCharacterEncoding(context); - } - public Locale calculateLocale(FacesContext context) { return delegate.calculateLocale(context); } @@ -64,10 +60,6 @@ public class FlowViewHandler extends ViewHandler { return delegate.getResourceURL(context, path); } - public void initView(FacesContext context) throws FacesException { - delegate.initView(context); - } - public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException { delegate.renderView(context, viewToRender); } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewStateManager.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewStateManager.java index ab3f7a45..22deb231 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewStateManager.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowViewStateManager.java @@ -2,8 +2,6 @@ package org.springframework.faces.webflow; import java.io.IOException; import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; import javax.faces.application.StateManager; import javax.faces.component.UIViewRoot; @@ -18,132 +16,108 @@ public class FlowViewStateManager extends StateManager { private static final Log logger = LogFactory.getLog(FlowViewStateManager.class); - private static final String VIEW_MAP = "org.springframework.webflow.viewMap"; + private static final String SERIALIZED_VIEW_STATE = "org.springframework.webflow.viewState"; - public boolean isSavingStateInClient(FacesContext context) { - return false; - } + private static final String ACTIVE_VIEW_ROOT = "org.springframework.webflow.viewRoot"; - // required to implement for 1.1 view handlers - unfortunately, facelets is one of these... - public javax.faces.application.StateManager.SerializedView saveSerializedView(FacesContext context) { - SerializedView view = (SerializedView) saveView(context); - return new javax.faces.application.StateManager.SerializedView(view.treeStructure, view.componentState); - } - - public Object saveView(FacesContext context) { - RequestContext requestContext = RequestContextHolder.getRequestContext(); - SerializedViewMap viewMap = (SerializedViewMap) requestContext.getFlowScope().get(VIEW_MAP); - if (viewMap == null) { - viewMap = new SerializedViewMap(); - requestContext.getFlowScope().put(VIEW_MAP, viewMap); + protected Object getComponentStateToSave(FacesContext context) { + UIViewRoot viewRoot = context.getViewRoot(); + if (viewRoot.isTransient()) { + return null; + } else { + return viewRoot.processSaveState(context); } - if (logger.isDebugEnabled()) { - logger.debug("Saving view root '" + context.getViewRoot().getViewId() + "' in flow scope"); - } - return viewMap.putSerializedView(context); } - public UIViewRoot restoreView(FacesContext context, String viewId, String renderKitId) { + protected Object getTreeStructureToSave(FacesContext context) { + UIViewRoot viewRoot = context.getViewRoot(); + if (viewRoot.isTransient()) { + return null; + } else { + return new TreeStructureManager().buildTreeStructureToSave(viewRoot); + } + } + + protected void restoreComponentState(FacesContext context, UIViewRoot viewRoot, String renderKitId) { RequestContext requestContext = RequestContextHolder.getRequestContext(); - SerializedViewMap viewMap = (SerializedViewMap) requestContext.getFlowScope().get(VIEW_MAP); - if (viewMap == null) { - logger.debug("No view map in flow scope; no views have been saved yet..."); + SerializedView view = (SerializedView) requestContext.getFlowScope().get(SERIALIZED_VIEW_STATE); + viewRoot.processRestoreState(context, view.componentState); + logger.debug("UIViewRoot component state restored"); + } + + protected UIViewRoot restoreTreeStructure(FacesContext context, String viewId, String renderKitId) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + SerializedView view = (SerializedView) requestContext.getFlowScope().get(SERIALIZED_VIEW_STATE); + if (view == null || !view.viewId.equals(viewId)) { + logger.debug("No matching view in flow scope;"); return null; } if (logger.isDebugEnabled()) { logger.debug("Restoring view root with id '" + viewId + "' from flow scope"); } - return viewMap.getDeserializedView(viewId, context); + if (view.treeStructure == null) { + logger.debug("Tree structure is null indicating transient UIViewRoot; returning null"); + return null; + } + UIViewRoot viewRoot = new TreeStructureManager().restoreTreeStructure(view.treeStructure); + logger.debug("UIViewRoot structure restored."); + return viewRoot; } - public void writeState(FacesContext context, Object state) throws IOException { + public void writeState(FacesContext context, javax.faces.application.StateManager.SerializedView state) + throws IOException { // nothing to do, as saving state to client always returns false } - private static class SerializedViewMap implements Serializable { - private static final Log logger = LogFactory.getLog(SerializedViewMap.class); + public boolean isSavingStateInClient(FacesContext context) { + return false; + } - private Map views; + /** + * JSF 1.1 version of state saving + */ + public javax.faces.application.StateManager.SerializedView saveSerializedView(FacesContext context) { + SerializedView view = (SerializedView) saveView(context); + return new javax.faces.application.StateManager.SerializedView(view.treeStructure, view.componentState); + } - public SerializedViewMap() { - views = new HashMap(); + /** + * JSF 1.2 version of state saving + */ + public Object saveView(FacesContext context) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + if (logger.isDebugEnabled()) { + logger.debug("Saving view root '" + context.getViewRoot().getViewId() + "' in flow scope"); } + SerializedView view = new SerializedView(context.getViewRoot().getViewId(), getTreeStructureToSave(context), + getComponentStateToSave(context)); + requestContext.getFlowScope().put(SERIALIZED_VIEW_STATE, view); + return view; + } - public void put(String viewId, SerializedView view) { - views.put(viewId, view); - } + public UIViewRoot restoreView(FacesContext context, String viewId, String renderKitId) { - public SerializedView get(String viewId) { - return views.get(viewId); - } - - public Object putSerializedView(FacesContext context) { - SerializedView view = SerializedView.create(context); - if (logger.isDebugEnabled()) { - logger.debug("Indexing serialized view under key '" + context.getViewRoot().getViewId() + "'"); - } - put(context.getViewRoot().getViewId(), view); - return view; - } - - public UIViewRoot getDeserializedView(String viewId, FacesContext context) { - SerializedView view = get(viewId); - if (view == null) { - if (logger.isDebugEnabled()) { - logger.debug("No serialized view found under key '" + viewId + "; returning null"); - } - return null; - } - return view.deserialize(context); + UIViewRoot viewRoot = restoreTreeStructure(context, viewId, renderKitId); + if (viewRoot != null) { + restoreComponentState(context, viewRoot, renderKitId); } + return viewRoot; } private static class SerializedView implements Serializable { private static final Log logger = LogFactory.getLog(SerializedView.class); - private Serializable treeStructure; + private Object treeStructure; private Object componentState; - private SerializedView(Serializable treeStructure, Object componentState) { + private String viewId; + + public SerializedView(String viewId, Object treeStructure, Object componentState) { + this.viewId = viewId; this.treeStructure = treeStructure; this.componentState = componentState; } - - public UIViewRoot deserialize(FacesContext context) { - if (treeStructure == null) { - logger.debug("Tree structure is null indicating transient UIViewRoot; returning null"); - return null; - } - UIViewRoot viewRoot = new TreeStructureManager().restoreTreeStructure(treeStructure); - logger.debug("UIViewRoot structure restored"); - viewRoot.processRestoreState(context, componentState); - logger.debug("UIViewRoot component state restored"); - logger.debug("Returning restored UIViewRoot"); - return viewRoot; - } - - public static SerializedView create(FacesContext context) { - return new SerializedView(getTreeStructure(context), getComponentState(context)); - } - - private static Serializable getTreeStructure(FacesContext context) { - UIViewRoot viewRoot = context.getViewRoot(); - if (viewRoot.isTransient()) { - return null; - } else { - return new TreeStructureManager().buildTreeStructureToSave(viewRoot); - } - } - - private static Object getComponentState(FacesContext context) { - UIViewRoot viewRoot = context.getViewRoot(); - if (viewRoot.isTransient()) { - return null; - } else { - return viewRoot.processSaveState(context); - } - } } } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfUtils.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfUtils.java index aa511d62..2b2dcbb8 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfUtils.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfUtils.java @@ -21,6 +21,8 @@ import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.faces.lifecycle.Lifecycle; +import org.springframework.webflow.execution.RequestContextHolder; + /** * Common support for the JSF integration with Spring Web Flow. * @@ -47,4 +49,13 @@ class JsfUtils { } } } + + public static boolean isAsynchronousFlowRequest() { + if (RequestContextHolder.getRequestContext() != null + && RequestContextHolder.getRequestContext().getRequestParameters().contains("ajaxSource")) { + return true; + } else { + return false; + } + } } diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java index d194fdad..41a4b983 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfViewFactory.java @@ -17,13 +17,13 @@ package org.springframework.faces.webflow; import java.util.Iterator; -import javax.el.ValueExpression; import javax.faces.FactoryFinder; import javax.faces.application.ViewHandler; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.FacesContextFactory; +import javax.faces.el.ValueBinding; import javax.faces.event.PhaseId; import javax.faces.lifecycle.Lifecycle; @@ -96,6 +96,7 @@ public class JsfViewFactory implements ViewFactory { logger.debug("Creating view root for '" + viewName + "'"); } view = createJsfView(viewHandler.createView(facesContext, viewName), lifecycle, context); + facesContext.setViewRoot(view.getViewRoot()); restored = false; } } @@ -146,9 +147,9 @@ public class JsfViewFactory implements ViewFactory { } private void processComponentBinding(FacesContext context, UIComponent component) { - ValueExpression binding = component.getValueExpression("binding"); + ValueBinding binding = component.getValueBinding("binding"); if (binding != null) { - binding.setValue(context.getELContext(), component); + binding.setValue(context, component); } Iterator i = component.getChildren().iterator(); diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/TreeStructureManager.java b/spring-faces/src/main/java/org/springframework/faces/webflow/TreeStructureManager.java index 699abd34..da4f572f 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/TreeStructureManager.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/TreeStructureManager.java @@ -41,7 +41,7 @@ class TreeStructureManager { // children if (component.getChildCount() > 0) { List childList = component.getChildren(); - List structChildList = new ArrayList(); + List structChildList = new ArrayList(); for (int i = 0, len = childList.size(); i < len; i++) { UIComponent child = (UIComponent) childList.get(i); if (!child.isTransient()) { @@ -49,14 +49,15 @@ class TreeStructureManager { structChildList.add(structChild); } } - TreeStructComponent[] childArray = structChildList.toArray(new TreeStructComponent[structChildList.size()]); + TreeStructComponent[] childArray = (TreeStructComponent[]) structChildList + .toArray(new TreeStructComponent[structChildList.size()]); structComp.setChildren(childArray); } // facets - Map facetMap = component.getFacets(); + Map facetMap = component.getFacets(); if (!facetMap.isEmpty()) { - List structFacetList = new ArrayList(); + List structFacetList = new ArrayList(); for (Iterator it = facetMap.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); UIComponent child = (UIComponent) entry.getValue(); @@ -90,7 +91,7 @@ class TreeStructureManager { // children TreeStructComponent[] childArray = treeStructComp.getChildren(); if (childArray != null) { - List childList = component.getChildren(); + List childList = component.getChildren(); for (int i = 0, len = childArray.length; i < len; i++) { UIComponent child = internalRestoreTreeStructure(childArray[i]); childList.add(child); @@ -100,7 +101,7 @@ class TreeStructureManager { // facets Object[] facetArray = treeStructComp.getFacets(); if (facetArray != null) { - Map facetMap = component.getFacets(); + Map facetMap = component.getFacets(); for (int i = 0, len = facetArray.length; i < len; i++) { Object[] tuple = (Object[]) facetArray[i]; String facetName = (String) tuple[0]; diff --git a/spring-faces/src/test/java/org/springframework/faces/ui/resource/FlowResourceHelperTests.java b/spring-faces/src/test/java/org/springframework/faces/ui/resource/FlowResourceHelperTests.java index 5633fe2b..692f4ada 100644 --- a/spring-faces/src/test/java/org/springframework/faces/ui/resource/FlowResourceHelperTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/ui/resource/FlowResourceHelperTests.java @@ -1,9 +1,6 @@ package org.springframework.faces.ui.resource; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; +import org.easymock.EasyMock; import java.io.IOException; import java.io.StringWriter; @@ -11,7 +8,6 @@ import java.io.StringWriter; import junit.framework.TestCase; import org.apache.shale.test.mock.MockResponseWriter; -import org.easymock.EasyMock; import org.springframework.faces.webflow.JSFMockHelper; import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.context.FlowDefinitionRequestInfo; @@ -21,8 +17,8 @@ import org.springframework.webflow.execution.RequestContextHolder; public class FlowResourceHelperTests extends TestCase { - RequestContext requestContext = createMock(RequestContext.class); - ExternalContext externalContext = createMock(ExternalContext.class); + RequestContext requestContext = (RequestContext) EasyMock.createMock(RequestContext.class); + ExternalContext externalContext = (ExternalContext) EasyMock.createMock(ExternalContext.class); FlowResourceHelper resourceHelper = new FlowResourceHelper(); StringWriter writer = new StringWriter(); @@ -32,7 +28,7 @@ public class FlowResourceHelperTests extends TestCase { protected void setUp() throws Exception { jsf.setUp(); jsf.facesContext().setResponseWriter(new MockResponseWriter(writer, "text/html", "UTF-8")); - expect(requestContext.getExternalContext()).andStubReturn(externalContext); + EasyMock.expect(requestContext.getExternalContext()).andStubReturn(externalContext); RequestContextHolder.setRequestContext(requestContext); } @@ -48,14 +44,15 @@ public class FlowResourceHelperTests extends TestCase { FlowDefinitionRequestInfo expectedRequest = new FlowDefinitionRequestInfo("resources", new RequestPath( scriptPath), null, null); - expect(externalContext.buildFlowDefinitionUrl(requestInfoMatches(expectedRequest))).andReturn(expectedUrl); + EasyMock.expect(externalContext.buildFlowDefinitionUrl(requestInfoMatches(expectedRequest))).andReturn( + expectedUrl); - replay(new Object[] { requestContext, externalContext }); + EasyMock.replay(new Object[] { requestContext, externalContext }); resourceHelper.renderScriptLink(jsf.facesContext(), scriptPath); resourceHelper.renderScriptLink(jsf.facesContext(), scriptPath); - verify(new Object[] { externalContext }); + EasyMock.verify(new Object[] { externalContext }); String expectedOutput = "