Upgrade spring-faces to JSF 2 as a minimum requirement

* Rework all state handling, removed FlowSerializedView class and save
state as opaque object
* Use FacesWrapper classes instead of custom delegates
* Deprecate isAtLeastJSFXXX() methods and removed all internal use
* Remove all Jsf2XXX versions of classes
* Refactor all calls to deprecated JSF methods
* Removed older VariableResolver and PropertyResolver classes
* Deprecate Jsf2FlowResourceResolver and log warning if used
* Create new FlowELResolver to replace removed VariableResolvers and
PropertyResolvers
* Update faces-config.xml to use newer xsd
* Significantly rework FlowFacesContext to remove the message delegate
and generally improve the code
* Added "provided" dependency to MyFaces and fixed partial state saving
on MyFaces
* Fixed FlowResourceResolver to delegate to both MyFaces or Mojarra
depending on availability
* Add JsfUtils.findFactory method and rework existing code to replace
FactoryFinder calls and casts
* Refactor JsfViewFactory to improve code readability
* Rename FlowViewStateManager and FlowViewResponseStateManager to
FlowStateManager and FlowResponseStateManager
* Ensure ResponseContextHolder is reset after each test
* Update JSF portlet support to function with JSF 2.0

Issue: SWF-1536, SWF-1540, SWF-1550
This commit is contained in:
Phillip Webb
2012-06-07 16:23:37 -07:00
committed by Rossen Stoyanchev
parent 7e03970fbf
commit 706490c4dc
119 changed files with 3338 additions and 4071 deletions

View File

@@ -224,6 +224,7 @@ project('spring-faces') {
compile("com.sun.facelets:jsf-facelets:1.1.14", optional)
compile("com.sun.faces:jsf-api:2.1.7", provided)
compile("com.sun.faces:jsf-impl:2.1.7", provided)
compile("org.apache.myfaces.core:myfaces-impl:2.1.7", provided)
testCompile("log4j:log4j:$log4jVersion") { dep ->
optional dep

View File

@@ -1,119 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.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;
/**
* A JSF 1.1 {@link PropertyResolver} that delegates to a wrapped Unified EL resolver chain for property resolution.
*
* @author Jeremy Grelle
* @deprecated Upgrade to JSF 2.0
*/
@Deprecated
public abstract class ELDelegatingPropertyResolver extends PropertyResolver {
private PropertyResolver nextResolver;
private ELResolver delegate;
public ELDelegatingPropertyResolver(PropertyResolver nextResolver, ELResolver delegate) {
this.nextResolver = nextResolver;
this.delegate = delegate;
}
public Class<?> getType(Object base, int index) throws EvaluationException, PropertyNotFoundException {
ELContext elContext = new SimpleELContext(delegate);
Class<?> type = elContext.getELResolver().getType(elContext, base, index);
if (elContext.isPropertyResolved()) {
return type;
} else {
return nextResolver.getType(base, index);
}
}
public Class<?> getType(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
ELContext elContext = new SimpleELContext(delegate);
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 {
ELContext elContext = new SimpleELContext(delegate);
Object value = elContext.getELResolver().getValue(elContext, base, index);
if (elContext.isPropertyResolved()) {
return value;
} else {
return nextResolver.getValue(base, index);
}
}
public Object getValue(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
ELContext elContext = new SimpleELContext(delegate);
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 {
ELContext elContext = new SimpleELContext(delegate);
boolean readOnly = elContext.getELResolver().isReadOnly(elContext, base, index);
if (elContext.isPropertyResolved()) {
return readOnly;
} else {
return nextResolver.isReadOnly(base, index);
}
}
public boolean isReadOnly(Object base, Object property) throws EvaluationException, PropertyNotFoundException {
ELContext elContext = new SimpleELContext(delegate);
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 elContext = new SimpleELContext(delegate);
elContext.getELResolver().setValue(elContext, base, index, value);
if (!elContext.isPropertyResolved()) {
nextResolver.setValue(base, index, value);
}
}
public void setValue(Object base, Object property, Object value) throws EvaluationException,
PropertyNotFoundException {
ELContext elContext = new SimpleELContext(delegate);
elContext.getELResolver().setValue(elContext, base, property, value);
if (!elContext.isPropertyResolved()) {
nextResolver.setValue(base, property, value);
}
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.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;
/**
* A JSF 1.1 {@link VariableResolver} that delegates to a wrapped Unified EL resolver chain for variable resolution.
*
* @author Jeremy Grelle
* @deprecated Upgrade to JSF 2.0
*/
@Deprecated
public abstract class ELDelegatingVariableResolver extends VariableResolver {
private VariableResolver nextResolver;
private ELResolver delegate;
public ELDelegatingVariableResolver(VariableResolver nextResolver, ELResolver delegate) {
this.nextResolver = nextResolver;
this.delegate = delegate;
}
public Object resolveVariable(FacesContext facesContext, String name) throws EvaluationException {
ELContext elContext = new SimpleELContext(delegate);
Object result = elContext.getELResolver().getValue(elContext, null, name);
if (elContext.isPropertyResolved()) {
return result;
} else {
return nextResolver.resolveVariable(facesContext, name);
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed 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.springframework.faces.expression;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.FunctionMapper;
import javax.el.VariableMapper;
/**
* A minimal {@link ELContext} implementation.
*
* @author Jeremy Grelle
*/
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;
}
}

View File

@@ -1,5 +0,0 @@
<html>
<body>
<p>Support for adapting Unified EL resolvers to the JSF 1.1 API.</p>
</body>
</html>

View File

@@ -41,26 +41,26 @@ public class ManySelectionTrackingListDataModel<T> extends SerializableListDataM
}
public List<T> getSelections() {
return selections;
return this.selections;
}
public boolean isCurrentRowSelected() {
return selections.contains(getRowData());
return this.selections.contains(getRowData());
}
public void selectAll() {
selections.clear();
selections.addAll(getWrappedData());
this.selections.clear();
this.selections.addAll(getWrappedData());
}
public void setCurrentRowSelected(boolean rowSelected) {
if (!isRowAvailable()) {
return;
}
if (rowSelected && !selections.contains(getRowData())) {
selections.add(getRowData());
if (rowSelected && !this.selections.contains(getRowData())) {
this.selections.add(getRowData());
} else if (!rowSelected) {
selections.remove(getRowData());
this.selections.remove(getRowData());
}
}
@@ -70,8 +70,8 @@ public class ManySelectionTrackingListDataModel<T> extends SerializableListDataM
public void select(T rowData) {
Assert.isTrue((getWrappedData()).contains(rowData), "The object to select is not contained in this DataModel.");
if (!selections.contains(rowData)) {
selections.add(rowData);
if (!this.selections.contains(rowData)) {
this.selections.add(rowData);
}
}

View File

@@ -43,17 +43,17 @@ public class OneSelectionTrackingListDataModel<T> extends SerializableListDataMo
}
public List<T> getSelections() {
return selections;
return this.selections;
}
public boolean isCurrentRowSelected() {
return selections.contains(getRowData());
return this.selections.contains(getRowData());
}
public void select(T rowData) {
Assert.isTrue((getWrappedData()).contains(rowData), "The object to select is not contained in this DataModel.");
selections.clear();
selections.add(rowData);
this.selections.clear();
this.selections.add(rowData);
}
public void selectAll() {
@@ -68,10 +68,10 @@ public class OneSelectionTrackingListDataModel<T> extends SerializableListDataMo
}
if (!rowSelected) {
selections.remove(getRowData());
} else if (rowSelected && !selections.contains(getRowData())) {
selections.clear();
selections.add(getRowData());
this.selections.remove(getRowData());
} else if (rowSelected && !this.selections.contains(getRowData())) {
this.selections.clear();
this.selections.add(getRowData());
}
}
@@ -81,8 +81,8 @@ public class OneSelectionTrackingListDataModel<T> extends SerializableListDataMo
}
public Object getSelectedRow() {
if (selections.size() == 1) {
return selections.get(0);
if (this.selections.size() == 1) {
return this.selections.get(0);
} else {
return null;
}

View File

@@ -44,7 +44,7 @@ public class SelectionTrackingActionListener implements ActionListener {
private static final Log logger = LogFactory.getLog(FlowActionListener.class);
private ActionListener delegate;
private final ActionListener delegate;
public SelectionTrackingActionListener(ActionListener delegate) {
this.delegate = delegate;
@@ -52,7 +52,7 @@ public class SelectionTrackingActionListener implements ActionListener {
public void processAction(ActionEvent event) throws AbortProcessingException {
trackSelection(event.getComponent());
delegate.processAction(event);
this.delegate.processAction(event);
}
private void trackSelection(UIComponent component) {

View File

@@ -52,36 +52,36 @@ public class SerializableListDataModel<T> extends DataModel<T> implements Serial
}
public int getRowCount() {
return data.size();
return this.data.size();
}
public T getRowData() {
Assert.isTrue(isRowAvailable(), getClass()
+ " is in an illegal state - no row is available at the current index.");
return data.get(rowIndex);
return this.data.get(this.rowIndex);
}
public int getRowIndex() {
return rowIndex;
return this.rowIndex;
}
public List<T> getWrappedData() {
return data;
return this.data;
}
public boolean isRowAvailable() {
return rowIndex >= 0 && rowIndex < data.size();
return this.rowIndex >= 0 && this.rowIndex < this.data.size();
}
public void setRowIndex(int newRowIndex) {
if (newRowIndex < -1) {
throw new IllegalArgumentException("Illegal row index for " + getClass() + ": " + newRowIndex);
}
int oldRowIndex = rowIndex;
rowIndex = newRowIndex;
if (data != null && oldRowIndex != rowIndex) {
int oldRowIndex = this.rowIndex;
this.rowIndex = newRowIndex;
if (this.data != null && oldRowIndex != this.rowIndex) {
Object row = isRowAvailable() ? getRowData() : null;
DataModelEvent event = new DataModelEvent(this, rowIndex, row);
DataModelEvent event = new DataModelEvent(this, this.rowIndex, row);
DataModelListener[] listeners = getDataModelListeners();
for (DataModelListener listener : listeners) {
listener.rowSelected(event);
@@ -101,7 +101,7 @@ public class SerializableListDataModel<T> extends DataModel<T> implements Serial
}
public String toString() {
return data.toString();
return this.data.toString();
}
}

View File

@@ -15,12 +15,10 @@
*/
package org.springframework.faces.mvc;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf12;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isPortletRequest;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
@@ -48,7 +46,7 @@ public class JsfView extends AbstractUrlBasedView {
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
facesLifecycle = createFacesLifecycle();
this.facesLifecycle = createFacesLifecycle();
}
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
@@ -59,11 +57,11 @@ public class JsfView extends AbstractUrlBasedView {
populateRequestMap(facesContext, model);
JsfUtils.notifyBeforeListeners(PhaseId.RESTORE_VIEW, facesLifecycle, facesContext);
JsfUtils.notifyBeforeListeners(PhaseId.RESTORE_VIEW, this.facesLifecycle, facesContext);
ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
if (isAtLeastJsf12() && (!isPortletRequest(facesContext))) {
if (!isPortletRequest(facesContext)) {
viewHandler.initView(facesContext);
}
@@ -74,15 +72,15 @@ public class JsfView extends AbstractUrlBasedView {
facesContext.setViewRoot(viewRoot);
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, facesLifecycle, facesContext);
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, this.facesLifecycle, facesContext);
facesContext.setViewRoot(viewRoot);
facesContext.renderResponse();
try {
logger.debug("Asking faces lifecycle to render");
facesLifecycle.render(facesContext);
this.logger.debug("Asking faces lifecycle to render");
this.facesLifecycle.render(facesContext);
} finally {
logger.debug("View rendering complete");
this.logger.debug("View rendering complete");
facesContextHelper.releaseIfNecessary();
}
}
@@ -96,8 +94,7 @@ public class JsfView extends AbstractUrlBasedView {
}
private Lifecycle createFacesLifecycle() {
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
LifecycleFactory lifecycleFactory = JsfUtils.findFactory(LifecycleFactory.class);
return lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,18 +47,18 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
* <p>
* A base class for an &lt;authorize&gt; tag used to make Spring Security based authorization decisions.
* </p>
*
*
* <p>
* This class is independent of tag rendering technology (JSP, Facelets). It treats tag attributes as simple strings
* (with the notable exception of the "access" attribute, which is always expected to contain a Spring EL expression).
* Therefore subclasses are expected to extract tag attribute values from the specific rendering technology, evaluate
* them as expressions if necessary, and use the result to set the String-based attributes of this class.
* </p>
*
*
* @author Francois Beausoleil
* @author Luke Taylor
* @author Rossen Stoyanchev
*
*
* @since 2.2.0
*/
public abstract class AbstractAuthorizeTag {
@@ -97,9 +97,9 @@ public abstract class AbstractAuthorizeTag {
* <li>ifAllGranted, ifAnyGranted, ifNotGranted</li>
* </ul>
* The above combinations are mutually exclusive and evaluated in the given order.
*
*
* @return the result of the authorization decision
*
*
* @throws IOException
*/
public boolean authorize() throws IOException {
@@ -122,7 +122,7 @@ public abstract class AbstractAuthorizeTag {
/**
* Make an authorization decision by considering ifAllGranted, ifAnyGranted, and ifNotGranted. All 3 or any
* combination can be provided. All provided attributes must evaluate to true.
*
*
* @return the result of the authorization decision
*/
public boolean authorizeUsingGrantedAuthorities() {
@@ -162,9 +162,9 @@ public abstract class AbstractAuthorizeTag {
/**
* Make an authorization decision based on a Spring EL expression. See the "Expression-Based Access Control" chapter
* in Spring Security for details on what expressions can be used.
*
*
* @return the result of the authorization decision
*
*
* @throws IOException
*/
public boolean authorizeUsingAccessExpression() throws IOException {
@@ -197,9 +197,9 @@ public abstract class AbstractAuthorizeTag {
/**
* Make an authorization decision based on the URL and HTTP method attributes. True is returned if the user is
* allowed to access the given URL as defined.
*
*
* @return the result of the authorization decision
*
*
* @throws IOException
*/
public boolean authorizeUsingUrlCheck() throws IOException {
@@ -209,7 +209,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getAccess() {
return access;
return this.access;
}
public void setAccess(String access) {
@@ -217,7 +217,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getUrl() {
return url;
return this.url;
}
public void setUrl(String url) {
@@ -225,7 +225,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getMethod() {
return method;
return this.method;
}
public void setMethod(String method) {
@@ -233,7 +233,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getIfAllGranted() {
return ifAllGranted;
return this.ifAllGranted;
}
public void setIfAllGranted(String ifAllGranted) {
@@ -241,7 +241,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getIfAnyGranted() {
return ifAnyGranted;
return this.ifAnyGranted;
}
public void setIfAnyGranted(String ifAnyGranted) {
@@ -249,7 +249,7 @@ public abstract class AbstractAuthorizeTag {
}
public String getIfNotGranted() {
return ifNotGranted;
return this.ifNotGranted;
}
public void setIfNotGranted(String ifNotGranted) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
* <li>ifAllGranted, ifAnyGranted, ifNotGranted</li>
* </ul>
* The var attribute can be used to store the result of the authorization decision for later use in the view.
*
*
* @author Rossen Stoyanchev
* @since 2.2.0
* @see FaceletsAuthorizeTag
@@ -71,8 +71,8 @@ public class FaceletsAuthorizeTagHandler extends TagHandler {
return;
}
FaceletsAuthorizeTag authorizeTag = new FaceletsAuthorizeTag(faceletContext, access, url, method, ifAllGranted,
ifAnyGranted, ifNotGranted);
FaceletsAuthorizeTag authorizeTag = new FaceletsAuthorizeTag(faceletContext, this.access, this.url, this.method, this.ifAllGranted,
this.ifAnyGranted, this.ifNotGranted);
boolean isAuthorized = authorizeTag.authorize();
@@ -81,7 +81,7 @@ public class FaceletsAuthorizeTagHandler extends TagHandler {
}
if (this.var != null) {
faceletContext.setAttribute(var.getValue(faceletContext), Boolean.valueOf(isAuthorized));
faceletContext.setAttribute(this.var.getValue(faceletContext), Boolean.valueOf(isAuthorized));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ import com.sun.facelets.tag.TagHandler;
* <li>ifAllGranted, ifAnyGranted, ifNotGranted</li>
* </ul>
* The var attribute can be used to store the result of the authorization decision for later use in the view.
*
*
* @author Rossen Stoyanchev
* @since 2.2.0
* @see Jsf12FaceletsAuthorizeTag
@@ -72,8 +72,8 @@ public class Jsf12FaceletsAuthorizeTagHandler extends TagHandler {
return;
}
Jsf12FaceletsAuthorizeTag authorizeTag = new Jsf12FaceletsAuthorizeTag(faceletContext, access, url, method,
ifAllGranted, ifAnyGranted, ifNotGranted);
Jsf12FaceletsAuthorizeTag authorizeTag = new Jsf12FaceletsAuthorizeTag(faceletContext, this.access, this.url, this.method,
this.ifAllGranted, this.ifAnyGranted, this.ifNotGranted);
boolean isAuthorized = authorizeTag.authorize();
@@ -82,7 +82,7 @@ public class Jsf12FaceletsAuthorizeTagHandler extends TagHandler {
}
if (this.var != null) {
faceletContext.setAttribute(var.getValue(faceletContext), Boolean.valueOf(isAuthorized));
faceletContext.setAttribute(this.var.getValue(faceletContext), Boolean.valueOf(isAuthorized));
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.support;
import javax.faces.FacesException;
import javax.faces.FacesWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
/**
* Provides a simple implementation of {@link Lifecycle} that can be subclassed by developers wishing to provide
* specialized behavior to an existing {@link Lifecycle instance} . The default implementation of all methods is to call
* through to the wrapped {@link Lifecycle}.
*
* @author Phillip Webb
*
* @since 2.4
*/
public abstract class LifecycleWrapper extends Lifecycle implements FacesWrapper<Lifecycle> {
public abstract Lifecycle getWrapped();
public void addPhaseListener(PhaseListener listener) {
getWrapped().addPhaseListener(listener);
}
public void execute(FacesContext context) throws FacesException {
getWrapped().execute(context);
}
public PhaseListener[] getPhaseListeners() {
return getWrapped().getPhaseListeners();
}
public void removePhaseListener(PhaseListener listener) {
getWrapped().removePhaseListener(listener);
}
public void render(FacesContext context) throws FacesException {
getWrapped().render(context);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,12 +26,13 @@ import org.apache.commons.logging.LogFactory;
* {@link PhaseListener} that logs the execution of the individual phases of the JSF lifecycle. Useful during JSF
* application development in order to detect unreported JSF errors that cause the lifecycle to short-circuit. Turn
* logging level to DEBUG to see its output.
*
*
* @author Jeremy Grelle
*/
@SuppressWarnings("serial")
public class RequestLoggingPhaseListener implements PhaseListener {
private Log logger = LogFactory.getLog(RequestLoggingPhaseListener.class);
private static final Log logger = LogFactory.getLog(RequestLoggingPhaseListener.class);
public void afterPhase(PhaseEvent event) {
// no-op

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed 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.springframework.faces.support;
import java.io.IOException;
import javax.faces.FacesWrapper;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.context.FacesContext;
import javax.faces.render.ResponseStateManager;
/**
* Provides a simple implementation of {@link ResponseStateManager} that can be subclassed by developers wishing to
* provide specialized behavior to an existing {@link ResponseStateManager instance} . The default implementation of all
* methods is to call through to the wrapped {@link ResponseStateManager}.
*
* @author Phillip Webb
*
* @since 2.4
*/
@SuppressWarnings("deprecation")
public abstract class ResponseStateManagerWrapper extends ResponseStateManager implements
FacesWrapper<ResponseStateManager> {
public abstract ResponseStateManager getWrapped();
@Override
public void writeState(FacesContext context, Object state) throws IOException {
getWrapped().writeState(context, state);
}
@Override
@Deprecated
public void writeState(FacesContext context, SerializedView state) throws IOException {
getWrapped().writeState(context, state);
}
@Override
public Object getState(FacesContext context, String viewId) {
return getWrapped().getState(context, viewId);
}
@Override
@Deprecated
public Object getTreeStructureToRestore(FacesContext context, String viewId) {
return getWrapped().getTreeStructureToRestore(context, viewId);
}
@Override
@Deprecated
public Object getComponentStateToRestore(FacesContext context) {
return getWrapped().getComponentStateToRestore(context);
}
@Override
public boolean isPostback(FacesContext context) {
return getWrapped().isPostback(context);
}
@Override
public String getViewState(FacesContext context, Object state) {
return getWrapped().getViewState(context, state);
}
}

View File

@@ -60,7 +60,7 @@ public class AjaxViewRoot extends DelegatingViewRoot {
protected static final String PROCESS_ALL = "*";
private List<FacesEvent> events = new ArrayList<FacesEvent>();
private final List<FacesEvent> events = new ArrayList<FacesEvent>();
private String[] processIds;
@@ -72,7 +72,7 @@ public class AjaxViewRoot extends DelegatingViewRoot {
public AjaxViewRoot(UIViewRoot original) {
super(original);
renderIdsExpr = FacesContext.getCurrentInstance().getApplication().createValueBinding(RENDER_IDS_EXPRESSION);
this.renderIdsExpr = FacesContext.getCurrentInstance().getApplication().createValueBinding(RENDER_IDS_EXPRESSION);
if (!StringUtils.hasText(original.getId())) {
original.setId(createUniqueId());
}
@@ -87,7 +87,7 @@ public class AjaxViewRoot extends DelegatingViewRoot {
public void queueEvent(FacesEvent event) {
Assert.notNull(event, "Cannot queue a null event.");
events.add(event);
this.events.add(event);
}
public void encodeAll(FacesContext context) throws IOException {
@@ -162,30 +162,30 @@ public class AjaxViewRoot extends DelegatingViewRoot {
// subclassing hooks
protected String[] getProcessIds() {
if (processIds == null) {
if (this.processIds == null) {
FacesContext context = FacesContext.getCurrentInstance();
String processIdsParam = context.getExternalContext().getRequestParameterMap().get(PROCESS_IDS_PARAM);
if (StringUtils.hasText(processIdsParam) && processIdsParam.indexOf(PROCESS_ALL) != -1) {
processIds = new String[] { getOriginalViewRoot().getClientId(context) };
this.processIds = new String[] { getOriginalViewRoot().getClientId(context) };
} else {
processIds = StringUtils.delimitedListToStringArray(processIdsParam, ",", " ");
processIds = removeNestedChildren(context, processIds);
this.processIds = StringUtils.delimitedListToStringArray(processIdsParam, ",", " ");
this.processIds = removeNestedChildren(context, this.processIds);
}
}
return processIds;
return this.processIds;
}
protected String[] getRenderIds() {
if (renderIds == null) {
if (this.renderIds == null) {
FacesContext context = FacesContext.getCurrentInstance();
renderIds = (String[]) renderIdsExpr.getValue(context);
if (renderIds == null || renderIds.length == 0) {
renderIds = getProcessIds();
this.renderIds = (String[]) this.renderIdsExpr.getValue(context);
if (this.renderIds == null || this.renderIds.length == 0) {
this.renderIds = getProcessIds();
} else {
renderIds = removeNestedChildren(context, renderIds);
this.renderIds = removeNestedChildren(context, this.renderIds);
}
}
return renderIds;
return this.renderIds;
}
// internal helpers
@@ -260,12 +260,12 @@ public class AjaxViewRoot extends DelegatingViewRoot {
private void broadCastEvents(FacesContext context, PhaseId phaseId) {
List<FacesEvent> processedEvents = new ArrayList<FacesEvent>();
if (events.size() == 0) {
if (this.events.size() == 0) {
return;
}
boolean abort = false;
int phaseIdOrdinal = phaseId.getOrdinal();
for (FacesEvent event : events) {
for (FacesEvent event : this.events) {
int ordinal = event.getPhaseId().getOrdinal();
if (ordinal == PhaseId.ANY_PHASE.getOrdinal() || ordinal == phaseIdOrdinal) {
UIComponent source = event.getComponent();
@@ -279,9 +279,9 @@ public class AjaxViewRoot extends DelegatingViewRoot {
}
}
if (abort) {
events.clear();
this.events.clear();
} else {
events.removeAll(processedEvents);
this.events.removeAll(processedEvents);
}
}

View File

@@ -34,14 +34,14 @@ public abstract class BaseComponentRenderer extends BaseHtmlTagRenderer {
private Map<String, RenderAttributeCallback> attributeCallbacks;
private RenderAttributeCallback idCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback idCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
writer.writeAttribute(attribute, component.getClientId(context), property);
}
};
private RenderAttributeCallback disabledCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback disabledCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
if (Boolean.TRUE.equals(attributeValue)) {
@@ -51,12 +51,12 @@ public abstract class BaseComponentRenderer extends BaseHtmlTagRenderer {
};
protected Map<String, RenderAttributeCallback> getAttributeCallbacks(UIComponent component) {
if (attributeCallbacks == null) {
attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
attributeCallbacks.put("id", idCallback);
attributeCallbacks.put("name", idCallback);
attributeCallbacks.put("disabled", disabledCallback);
if (this.attributeCallbacks == null) {
this.attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
this.attributeCallbacks.put("id", this.idCallback);
this.attributeCallbacks.put("name", this.idCallback);
this.attributeCallbacks.put("disabled", this.disabledCallback);
}
return attributeCallbacks;
return this.attributeCallbacks;
}
}

View File

@@ -45,7 +45,7 @@ abstract class BaseHtmlTagRenderer extends Renderer {
* Default {@link RenderAttributeCallback} that just renders the tag attribute as a pass-through value if the value
* is not null.
*/
private RenderAttributeCallback defaultRenderAttributeCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback defaultRenderAttributeCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
if (attributeValue != null) {
@@ -79,7 +79,7 @@ abstract class BaseHtmlTagRenderer extends Renderer {
}
Object attributeValue = component.getAttributes().get(property);
RenderAttributeCallback callback = defaultRenderAttributeCallback;
RenderAttributeCallback callback = this.defaultRenderAttributeCallback;
if (getAttributeCallbacks(null).containsKey(attribute)) {
callback = getAttributeCallbacks(component).get(attribute);
}

View File

@@ -32,14 +32,14 @@ import org.springframework.faces.webflow.JsfUtils;
*/
public abstract class BaseSpringJavascriptComponentRenderer extends BaseComponentRenderer {
private String springJsResourceUri = "/spring/Spring.js";
private final String springJsResourceUri = "/spring/Spring.js";
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
super.encodeBegin(context, component);
if (!JsfUtils.isAsynchronousFlowRequest()) {
ResourceHelper.renderScriptLink(context, springJsResourceUri);
ResourceHelper.renderScriptLink(context, this.springJsResourceUri);
}
}
}

View File

@@ -26,12 +26,12 @@ import org.springframework.faces.webflow.JsfUtils;
public abstract class BaseSpringJavascriptDecorationRenderer extends Renderer {
private String springJsResourceUri = "/spring/Spring.js";
private final String springJsResourceUri = "/spring/Spring.js";
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
if (!JsfUtils.isAsynchronousFlowRequest()) {
ResourceHelper.renderScriptLink(context, springJsResourceUri);
ResourceHelper.renderScriptLink(context, this.springJsResourceUri);
}
}

View File

@@ -40,14 +40,14 @@ import javax.faces.event.PhaseListener;
*/
public abstract class DelegatingViewRoot extends UIViewRoot {
private UIViewRoot original;
private final UIViewRoot original;
public DelegatingViewRoot(UIViewRoot original) {
this.original = original;
}
public UIViewRoot getOriginalViewRoot() {
return original;
return this.original;
}
/**
@@ -55,7 +55,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#addPhaseListener(javax.faces.event.PhaseListener)
*/
public void addPhaseListener(PhaseListener phaseListener) {
original.addPhaseListener(phaseListener);
this.original.addPhaseListener(phaseListener);
}
/**
@@ -64,14 +64,14 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#broadcast(javax.faces.event.FacesEvent)
*/
public void broadcast(FacesEvent event) throws AbortProcessingException {
original.broadcast(event);
this.original.broadcast(event);
}
/**
* @see javax.faces.component.UIViewRoot#createUniqueId()
*/
public String createUniqueId() {
return (original != null) ? original.createUniqueId() : null;
return (this.original != null) ? this.original.createUniqueId() : null;
}
/**
@@ -79,7 +79,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#decode(javax.faces.context.FacesContext)
*/
public void decode(FacesContext context) {
original.decode(context);
this.original.decode(context);
}
/**
@@ -88,7 +88,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponent#encodeAll(javax.faces.context.FacesContext)
*/
public void encodeAll(FacesContext context) throws IOException {
original.encodeAll(context);
this.original.encodeAll(context);
}
/**
@@ -97,7 +97,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#encodeBegin(javax.faces.context.FacesContext)
*/
public void encodeBegin(FacesContext context) throws IOException {
original.encodeBegin(context);
this.original.encodeBegin(context);
}
/**
@@ -106,7 +106,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#encodeChildren(javax.faces.context.FacesContext)
*/
public void encodeChildren(FacesContext context) throws IOException {
original.encodeChildren(context);
this.original.encodeChildren(context);
}
/**
@@ -115,7 +115,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#encodeEnd(javax.faces.context.FacesContext)
*/
public void encodeEnd(FacesContext context) throws IOException {
original.encodeEnd(context);
this.original.encodeEnd(context);
}
/**
@@ -123,42 +123,42 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#findComponent(java.lang.String)
*/
public UIComponent findComponent(String expr) {
return original.findComponent(expr);
return this.original.findComponent(expr);
}
/**
* @see javax.faces.component.UIViewRoot#getAfterPhaseListener()
*/
public MethodExpression getAfterPhaseListener() {
return original.getAfterPhaseListener();
return this.original.getAfterPhaseListener();
}
/**
* @see javax.faces.component.UIComponentBase#getAttributes()
*/
public Map<String, Object> getAttributes() {
return original.getAttributes();
return this.original.getAttributes();
}
/**
* @see javax.faces.component.UIViewRoot#getBeforePhaseListener()
*/
public MethodExpression getBeforePhaseListener() {
return original.getBeforePhaseListener();
return this.original.getBeforePhaseListener();
}
/**
* @see javax.faces.component.UIComponentBase#getChildCount()
*/
public int getChildCount() {
return original.getChildCount();
return this.original.getChildCount();
}
/**
* @see javax.faces.component.UIComponentBase#getChildren()
*/
public List<UIComponent> getChildren() {
return original.getChildren();
return this.original.getChildren();
}
/**
@@ -166,7 +166,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#getClientId(javax.faces.context.FacesContext)
*/
public String getClientId(FacesContext context) {
return original.getClientId(context);
return this.original.getClientId(context);
}
/**
@@ -174,7 +174,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponent#getContainerClientId(javax.faces.context.FacesContext)
*/
public String getContainerClientId(FacesContext ctx) {
return original.getContainerClientId(ctx);
return this.original.getContainerClientId(ctx);
}
/**
@@ -182,77 +182,77 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#getFacet(java.lang.String)
*/
public UIComponent getFacet(String name) {
return original.getFacet(name);
return this.original.getFacet(name);
}
/**
* @see javax.faces.component.UIComponentBase#getFacetCount()
*/
public int getFacetCount() {
return original.getFacetCount();
return this.original.getFacetCount();
}
/**
* @see javax.faces.component.UIComponentBase#getFacets()
*/
public Map<String, UIComponent> getFacets() {
return original.getFacets();
return this.original.getFacets();
}
/**
* @see javax.faces.component.UIComponentBase#getFacetsAndChildren()
*/
public Iterator<UIComponent> getFacetsAndChildren() {
return original.getFacetsAndChildren();
return this.original.getFacetsAndChildren();
}
/**
* @see javax.faces.component.UIViewRoot#getFamily()
*/
public String getFamily() {
return original.getFamily();
return this.original.getFamily();
}
/**
* @see javax.faces.component.UIComponentBase#getId()
*/
public String getId() {
return original.getId();
return this.original.getId();
}
/**
* @see javax.faces.component.UIViewRoot#getLocale()
*/
public Locale getLocale() {
return original.getLocale();
return this.original.getLocale();
}
/**
* @see javax.faces.component.UIComponentBase#getParent()
*/
public UIComponent getParent() {
return original.getParent();
return this.original.getParent();
}
/**
* @see javax.faces.component.UIComponentBase#getRendererType()
*/
public String getRendererType() {
return original.getRendererType();
return this.original.getRendererType();
}
/**
* @see javax.faces.component.UIViewRoot#getRenderKitId()
*/
public String getRenderKitId() {
return original.getRenderKitId();
return this.original.getRenderKitId();
}
/**
* @see javax.faces.component.UIComponentBase#getRendersChildren()
*/
public boolean getRendersChildren() {
return original.getRendersChildren();
return this.original.getRendersChildren();
}
/**
@@ -261,7 +261,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#getValueBinding(java.lang.String)
*/
public ValueBinding getValueBinding(String name) {
return original.getValueBinding(name);
return this.original.getValueBinding(name);
}
/**
@@ -269,14 +269,14 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponent#getValueExpression(java.lang.String)
*/
public ValueExpression getValueExpression(String name) {
return original.getValueExpression(name);
return this.original.getValueExpression(name);
}
/**
* @see javax.faces.component.UIViewRoot#getViewId()
*/
public String getViewId() {
return original.getViewId();
return this.original.getViewId();
}
/**
@@ -289,28 +289,28 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
*/
public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
throws FacesException {
return original.invokeOnComponent(context, clientId, callback);
return this.original.invokeOnComponent(context, clientId, callback);
}
/**
* @see javax.faces.component.UIComponentBase#isRendered()
*/
public boolean isRendered() {
return original.isRendered();
return this.original.isRendered();
}
/**
* @see javax.faces.component.UIComponentBase#isTransient()
*/
public boolean isTransient() {
return original.isTransient();
return this.original.isTransient();
}
/**
* @see javax.faces.component.UIViewRoot#processApplication(javax.faces.context.FacesContext)
*/
public void processApplication(FacesContext context) {
original.processApplication(context);
this.original.processApplication(context);
}
/**
@@ -318,7 +318,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#processDecodes(javax.faces.context.FacesContext)
*/
public void processDecodes(FacesContext context) {
original.processDecodes(context);
this.original.processDecodes(context);
}
/**
@@ -328,7 +328,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* java.lang.Object)
*/
public void processRestoreState(FacesContext context, Object state) {
original.processRestoreState(context, state);
this.original.processRestoreState(context, state);
}
/**
@@ -336,7 +336,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#processSaveState(javax.faces.context.FacesContext)
*/
public Object processSaveState(FacesContext context) {
return original.processSaveState(context);
return this.original.processSaveState(context);
}
/**
@@ -344,7 +344,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#processUpdates(javax.faces.context.FacesContext)
*/
public void processUpdates(FacesContext context) {
original.processUpdates(context);
this.original.processUpdates(context);
}
/**
@@ -352,7 +352,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#processValidators(javax.faces.context.FacesContext)
*/
public void processValidators(FacesContext context) {
original.processValidators(context);
this.original.processValidators(context);
}
/**
@@ -360,7 +360,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#queueEvent(javax.faces.event.FacesEvent)
*/
public void queueEvent(FacesEvent event) {
original.queueEvent(event);
this.original.queueEvent(event);
}
/**
@@ -368,7 +368,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#removePhaseListener(javax.faces.event.PhaseListener)
*/
public void removePhaseListener(PhaseListener phaseListener) {
original.removePhaseListener(phaseListener);
this.original.removePhaseListener(phaseListener);
}
/**
@@ -377,7 +377,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#restoreState(javax.faces.context.FacesContext, java.lang.Object)
*/
public void restoreState(FacesContext facesContext, Object state) {
original.restoreState(facesContext, state);
this.original.restoreState(facesContext, state);
}
/**
@@ -385,7 +385,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#saveState(javax.faces.context.FacesContext)
*/
public Object saveState(FacesContext facesContext) {
return original.saveState(facesContext);
return this.original.saveState(facesContext);
}
/**
@@ -393,7 +393,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#setAfterPhaseListener(javax.el.MethodExpression)
*/
public void setAfterPhaseListener(MethodExpression afterPhaseListener) {
original.setAfterPhaseListener(afterPhaseListener);
this.original.setAfterPhaseListener(afterPhaseListener);
}
/**
@@ -401,7 +401,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#setBeforePhaseListener(javax.el.MethodExpression)
*/
public void setBeforePhaseListener(MethodExpression beforePhaseListener) {
original.setBeforePhaseListener(beforePhaseListener);
this.original.setBeforePhaseListener(beforePhaseListener);
}
/**
@@ -410,8 +410,8 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
*/
public void setId(String id) {
// Test for null to deal with JSF setId on constructor
if (original != null) {
original.setId(id);
if (this.original != null) {
this.original.setId(id);
}
}
@@ -420,7 +420,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#setLocale(java.util.Locale)
*/
public void setLocale(Locale locale) {
original.setLocale(locale);
this.original.setLocale(locale);
}
/**
@@ -428,7 +428,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#setParent(javax.faces.component.UIComponent)
*/
public void setParent(UIComponent parent) {
original.setParent(parent);
this.original.setParent(parent);
}
/**
@@ -436,7 +436,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#setRendered(boolean)
*/
public void setRendered(boolean rendered) {
original.setRendered(rendered);
this.original.setRendered(rendered);
}
/**
@@ -444,8 +444,8 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#setRendererType(java.lang.String)
*/
public void setRendererType(String rendererType) {
if (original != null) {
original.setRendererType(rendererType);
if (this.original != null) {
this.original.setRendererType(rendererType);
}
}
@@ -454,7 +454,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#setRenderKitId(java.lang.String)
*/
public void setRenderKitId(String renderKitId) {
original.setRenderKitId(renderKitId);
this.original.setRenderKitId(renderKitId);
}
/**
@@ -462,7 +462,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#setTransient(boolean)
*/
public void setTransient(boolean transientFlag) {
original.setTransient(transientFlag);
this.original.setTransient(transientFlag);
}
/**
@@ -472,7 +472,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponentBase#setValueBinding(java.lang.String, javax.faces.el.ValueBinding)
*/
public void setValueBinding(String name, ValueBinding binding) {
original.setValueBinding(name, binding);
this.original.setValueBinding(name, binding);
}
/**
@@ -481,7 +481,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIComponent#setValueExpression(java.lang.String, javax.el.ValueExpression)
*/
public void setValueExpression(String name, ValueExpression expression) {
original.setValueExpression(name, expression);
this.original.setValueExpression(name, expression);
}
/**
@@ -489,7 +489,7 @@ public abstract class DelegatingViewRoot extends UIViewRoot {
* @see javax.faces.component.UIViewRoot#setViewId(java.lang.String)
*/
public void setViewId(String viewId) {
original.setViewId(viewId);
this.original.setViewId(viewId);
}
}

View File

@@ -42,8 +42,8 @@ public class DojoClientCurrencyValidator extends DojoWidget {
private String currency;
public String getCurrency() {
if (currency != null) {
return currency;
if (this.currency != null) {
return this.currency;
}
ValueBinding exp = getValueBinding("currency");
return exp != null ? (String) exp.getValue(getFacesContext()) : null;

View File

@@ -51,7 +51,7 @@ public class DojoClientDateValidator extends DojoWidget {
if (child.getConverter() instanceof DateTimeConverter) {
return ((DateTimeConverter) child.getConverter()).getPattern();
}
return datePattern;
return this.datePattern;
}
public void setDatePattern(String datePattern) {

View File

@@ -56,8 +56,8 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
private Boolean uppercase;
public Boolean getDisabled() {
if (disabled != null) {
return disabled;
if (this.disabled != null) {
return this.disabled;
}
ValueBinding exp = getValueBinding("disabled");
return exp != null ? (Boolean) exp.getValue(getFacesContext()) : null;
@@ -68,7 +68,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Boolean getIntermediateChanges() {
return intermediateChanges;
return this.intermediateChanges;
}
public void setIntermediateChanges(Boolean intermediateChanges) {
@@ -76,7 +76,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Integer getTabIndex() {
return tabIndex;
return this.tabIndex;
}
public void setTabIndex(Integer tabIndex) {
@@ -84,7 +84,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Boolean getRequired() {
return required;
return this.required;
}
public void setRequired(Boolean required) {
@@ -92,8 +92,8 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public String getPromptMessage() {
if (promptMessage != null) {
return promptMessage;
if (this.promptMessage != null) {
return this.promptMessage;
}
ValueBinding exp = getValueBinding("promptMessage");
return exp != null ? (String) exp.getValue(getFacesContext()) : null;
@@ -104,8 +104,8 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public String getInvalidMessage() {
if (invalidMessage != null) {
return invalidMessage;
if (this.invalidMessage != null) {
return this.invalidMessage;
}
ValueBinding exp = getValueBinding("invalidMessage");
return exp != null ? (String) exp.getValue(getFacesContext()) : null;
@@ -116,7 +116,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public String getConstraints() {
return constraints;
return this.constraints;
}
public void setConstraints(String constraints) {
@@ -124,7 +124,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public String getRegExp() {
return regExp;
return this.regExp;
}
public void setRegExp(String regExp) {
@@ -132,7 +132,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public String getRegExpGen() {
return regExpGen;
return this.regExpGen;
}
public void setRegExpGen(String regExpGen) {
@@ -140,7 +140,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Boolean getLowercase() {
return lowercase;
return this.lowercase;
}
public void setLowercase(Boolean lowercase) {
@@ -148,7 +148,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Boolean getUppercase() {
return uppercase;
return this.uppercase;
}
public void setUppercase(Boolean uppercase) {
@@ -156,7 +156,7 @@ public abstract class DojoWidget extends SpringJavascriptElementDecoration {
}
public Boolean getPropercase() {
return propercase;
return this.propercase;
}
public void setPropercase(Boolean propercase) {

View File

@@ -55,7 +55,7 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoComponentRenderer
private Map<String, RenderAttributeCallback> attributeCallbacks;
private RenderAttributeCallback onclickCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback onclickCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
@@ -93,12 +93,12 @@ public class ProgressiveCommandButtonRenderer extends BaseDojoComponentRenderer
};
protected Map<String, RenderAttributeCallback> getAttributeCallbacks(UIComponent component) {
if (attributeCallbacks == null) {
attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
attributeCallbacks.putAll(super.getAttributeCallbacks(component));
attributeCallbacks.put("onclick", onclickCallback);
if (this.attributeCallbacks == null) {
this.attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
this.attributeCallbacks.putAll(super.getAttributeCallbacks(component));
this.attributeCallbacks.put("onclick", this.onclickCallback);
}
return attributeCallbacks;
return this.attributeCallbacks;
}
/**

View File

@@ -69,14 +69,14 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
private Map<String, RenderAttributeCallback> attributeCallbacks;
private RenderAttributeCallback hrefCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback hrefCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
writer.writeAttribute(attribute, "#", property);
}
};
private RenderAttributeCallback classCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback classCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
String classToAdd = "progressiveLink";
@@ -89,7 +89,7 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
}
};
private RenderAttributeCallback noOpCallback = new RenderAttributeCallback() {
private final RenderAttributeCallback noOpCallback = new RenderAttributeCallback() {
public void doRender(FacesContext context, ResponseWriter writer, UIComponent component, String attribute,
Object attributeValue, String property) throws IOException {
@@ -194,14 +194,14 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
}
protected Map<String, RenderAttributeCallback> getAttributeCallbacks(UIComponent component) {
if (attributeCallbacks == null) {
attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
attributeCallbacks.putAll(super.getAttributeCallbacks(component));
attributeCallbacks.put("href", hrefCallback);
attributeCallbacks.put("class", classCallback);
attributeCallbacks.put("type", noOpCallback);
if (this.attributeCallbacks == null) {
this.attributeCallbacks = new HashMap<String, RenderAttributeCallback>();
this.attributeCallbacks.putAll(super.getAttributeCallbacks(component));
this.attributeCallbacks.put("href", this.hrefCallback);
this.attributeCallbacks.put("class", this.classCallback);
this.attributeCallbacks.put("type", this.noOpCallback);
}
return attributeCallbacks;
return this.attributeCallbacks;
}
protected String getOnClickNoAjax(FacesContext context, UIComponent component) {
@@ -241,81 +241,81 @@ public class ProgressiveCommandLinkRenderer extends ProgressiveCommandButtonRend
private class DoubleQuoteEscapingWriter extends ResponseWriter {
private ResponseWriter original;
private final ResponseWriter original;
private ResponseWriter clonedWriter;
private final ResponseWriter clonedWriter;
private StringWriter buffer = new StringWriter();
private final StringWriter buffer = new StringWriter();
public DoubleQuoteEscapingWriter(ResponseWriter original) {
this.original = original;
this.clonedWriter = original.cloneWithWriter(buffer);
this.clonedWriter = original.cloneWithWriter(this.buffer);
}
public String escapeResult() {
String result = buffer.toString();
String result = this.buffer.toString();
result = result.replaceAll("\\\"", "\\\\\"");
return result;
}
public ResponseWriter cloneWithWriter(Writer arg0) {
return clonedWriter.cloneWithWriter(arg0);
return this.clonedWriter.cloneWithWriter(arg0);
}
public void endDocument() throws IOException {
clonedWriter.endDocument();
this.clonedWriter.endDocument();
}
public void endElement(String arg0) throws IOException {
clonedWriter.endElement(arg0);
this.clonedWriter.endElement(arg0);
}
public void flush() throws IOException {
clonedWriter.flush();
this.clonedWriter.flush();
}
public String getCharacterEncoding() {
return clonedWriter.getCharacterEncoding();
return this.clonedWriter.getCharacterEncoding();
}
public String getContentType() {
return clonedWriter.getContentType();
return this.clonedWriter.getContentType();
}
public void startDocument() throws IOException {
clonedWriter.startDocument();
this.clonedWriter.startDocument();
}
public void startElement(String arg0, UIComponent arg1) throws IOException {
clonedWriter.startElement(arg0, arg1);
this.clonedWriter.startElement(arg0, arg1);
}
public void writeAttribute(String arg0, Object arg1, String arg2) throws IOException {
clonedWriter.writeAttribute(arg0, arg1, arg2);
this.clonedWriter.writeAttribute(arg0, arg1, arg2);
}
public void writeComment(Object arg0) throws IOException {
clonedWriter.writeComment(arg0);
this.clonedWriter.writeComment(arg0);
}
public void writeText(char[] arg0, int arg1, int arg2) throws IOException {
clonedWriter.writeText(arg0, arg1, arg2);
this.clonedWriter.writeText(arg0, arg1, arg2);
}
public void writeText(Object arg0, String arg1) throws IOException {
clonedWriter.writeText(arg0, arg1);
this.clonedWriter.writeText(arg0, arg1);
}
public void writeURIAttribute(String arg0, Object arg1, String arg2) throws IOException {
clonedWriter.writeURIAttribute(arg0, arg1, arg2);
this.clonedWriter.writeURIAttribute(arg0, arg1, arg2);
}
public void close() throws IOException {
clonedWriter.close();
this.clonedWriter.close();
}
public void write(char[] cbuf, int off, int len) throws IOException {
clonedWriter.write(cbuf, off, len);
this.clonedWriter.write(cbuf, off, len);
}
}

View File

@@ -41,7 +41,7 @@ public class ProgressiveUICommand extends UICommand {
private Boolean ajaxEnabled = true;
public String getType() {
return type;
return this.type;
}
public void setType(String type) {
@@ -49,8 +49,8 @@ public class ProgressiveUICommand extends UICommand {
}
public Boolean getDisabled() {
if (disabled != null) {
return disabled;
if (this.disabled != null) {
return this.disabled;
}
ValueBinding vb = getValueBinding("disabled");
return vb != null ? (Boolean) vb.getValue(getFacesContext()) : false;
@@ -61,7 +61,7 @@ public class ProgressiveUICommand extends UICommand {
}
public Boolean getAjaxEnabled() {
return ajaxEnabled;
return this.ajaxEnabled;
}
public void setAjaxEnabled(Boolean ajaxEnabled) {
@@ -84,18 +84,18 @@ public class ProgressiveUICommand extends UICommand {
public Object saveState(FacesContext context) {
Object[] values = new Object[4];
values[0] = super.saveState(context);
values[1] = type;
values[2] = disabled;
values[3] = ajaxEnabled;
values[1] = this.type;
values[2] = this.disabled;
values[3] = this.ajaxEnabled;
return values;
}
public void restoreState(FacesContext context, Object state) {
Object values[] = (Object[]) state;
super.restoreState(context, values[0]);
type = (String) values[1];
disabled = (Boolean) values[2];
ajaxEnabled = (Boolean) values[3];
this.type = (String) values[1];
this.disabled = (Boolean) values[2];
this.ajaxEnabled = (Boolean) values[3];
}
}

View File

@@ -1,208 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Principal;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.faces.context.ExternalContext;
class ExternalContextWrapper extends ExternalContext {
protected ExternalContext delegate;
public ExternalContextWrapper(ExternalContext delegate) {
this.delegate = delegate;
}
public void dispatch(String path) throws IOException {
delegate.dispatch(path);
}
public String encodeActionURL(String url) {
return delegate.encodeActionURL(url);
}
public String encodeNamespace(String name) {
return delegate.encodeNamespace(name);
}
public String encodeResourceURL(String url) {
return delegate.encodeResourceURL(url);
}
public Map<String, Object> getApplicationMap() {
return delegate.getApplicationMap();
}
public String getAuthType() {
return delegate.getAuthType();
}
public Object getContext() {
return delegate.getContext();
}
public String getInitParameter(String name) {
return delegate.getInitParameter(name);
}
@SuppressWarnings("rawtypes")
public Map getInitParameterMap() {
return delegate.getInitParameterMap();
}
public String getRemoteUser() {
return delegate.getRemoteUser();
}
public Object getRequest() {
return delegate.getRequest();
}
public String getRequestCharacterEncoding() {
return delegate.getRequestCharacterEncoding();
}
public String getRequestContentType() {
return delegate.getRequestContentType();
}
public String getRequestContextPath() {
return delegate.getRequestContextPath();
}
public Map<String, Object> getRequestCookieMap() {
return delegate.getRequestCookieMap();
}
public Map<String, String> getRequestHeaderMap() {
return delegate.getRequestHeaderMap();
}
public Map<String, String[]> getRequestHeaderValuesMap() {
return delegate.getRequestHeaderValuesMap();
}
public Locale getRequestLocale() {
return delegate.getRequestLocale();
}
public Iterator<Locale> getRequestLocales() {
return delegate.getRequestLocales();
}
public Map<String, Object> getRequestMap() {
return delegate.getRequestMap();
}
public Map<String, String> getRequestParameterMap() {
return delegate.getRequestParameterMap();
}
public Iterator<String> getRequestParameterNames() {
return delegate.getRequestParameterNames();
}
public Map<String, String[]> getRequestParameterValuesMap() {
return delegate.getRequestParameterValuesMap();
}
public String getRequestPathInfo() {
return delegate.getRequestPathInfo();
}
public String getRequestServletPath() {
return delegate.getRequestServletPath();
}
public URL getResource(String path) throws MalformedURLException {
return delegate.getResource(path);
}
public InputStream getResourceAsStream(String path) {
return delegate.getResourceAsStream(path);
}
public Set<String> getResourcePaths(String path) {
return delegate.getResourcePaths(path);
}
public Object getResponse() {
return delegate.getResponse();
}
public String getResponseCharacterEncoding() {
return delegate.getResponseCharacterEncoding();
}
public String getResponseContentType() {
return delegate.getResponseContentType();
}
public Object getSession(boolean create) {
return delegate.getSession(create);
}
public Map<String, Object> getSessionMap() {
return delegate.getSessionMap();
}
public Principal getUserPrincipal() {
return delegate.getUserPrincipal();
}
public boolean isUserInRole(String role) {
return delegate.isUserInRole(role);
}
public void log(String message, Throwable exception) {
delegate.log(message, exception);
}
public void log(String message) {
delegate.log(message);
}
public void redirect(String url) throws IOException {
delegate.redirect(url);
}
public void setRequest(Object request) {
delegate.setRequest(request);
}
public void setRequestCharacterEncoding(String encoding) throws UnsupportedEncodingException {
delegate.setRequestCharacterEncoding(encoding);
}
public void setResponse(Object response) {
delegate.setResponse(response);
}
public void setResponseCharacterEncoding(String encoding) {
delegate.setResponseCharacterEncoding(encoding);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,46 +13,79 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.faces.lifecycle.Lifecycle;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import org.springframework.faces.webflow.context.portlet.PortletFacesContextImpl;
/**
* <p>
* Provides helper methods for getting a FacesContext that is suitable for use outside of Web Flow. Inside a running
* Flow session {@link FlowFacesContext} is typically used instead.
* <p>
*
*
* @author Rossen Stoyanchev
* @author Phillip Webb
*
* @since 2.2.0
*/
public class FacesContextHelper {
private boolean release = false;
public FacesContext getFacesContext(ServletContext servletContext, HttpServletRequest request,
HttpServletResponse response) {
/**
* Returns a faces context that can be used outside of Web Flow. The context must be {@link #releaseIfNecessary()
* released} after use.
*
* @param context the native context
* @param request the native request
* @param response the native response
* @return a {@link FacesContext} instance.
* @see #release
*/
public FacesContext getFacesContext(Object context, Object request, Object response) {
FacesContext facesContext = null;
if (FacesContext.getCurrentInstance() != null) {
facesContext = FacesContext.getCurrentInstance();
} else {
FacesContextFactory factory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = factory.getFacesContext(servletContext, request, response, FlowLifecycle.newInstance());
release = true;
facesContext = newDefaultInstance(context, request, response, FlowLifecycle.newInstance());
this.release = true;
}
return facesContext;
}
/**
* Release any previously {@link #getFacesContext obtained} {@link FacesContext} if necessary.
*
* @see #getFacesContext(Object, Object, Object)
*/
public void releaseIfNecessary() {
if (release) {
FacesContext.getCurrentInstance().release();
}
}
/**
* Factory method that can be used to create a new default {@link FacesContext} instance for the running
* (Portlet/Servlet) environment.
*
* @param context the native context
* @param request the native request
* @param response the native response
* @param lifecycle the JSF lifecycle
* @return a new {@link FacesContext} instance
*/
public static FacesContext newDefaultInstance(Object context, Object request, Object response, Lifecycle lifecycle) {
if (JsfRuntimeInformation.isPortletContext(context)) {
return new PortletFacesContextImpl((PortletContext) context, (PortletRequest) request, (PortletResponse) response);
}
FacesContextFactory facesContextFactory = JsfUtils.findFactory(FacesContextFactory.class);
return facesContextFactory.getFacesContext(context, request, response, lifecycle);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,9 +21,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
/**
* <p>
* A Spring EL {@link ExpressionParser} for use with JSF. Adds JSF specific Spring EL PropertyAccessors.
* </p>
*
* @author Rossen Stoyanchev
* @since 2.1

View File

@@ -19,7 +19,7 @@ import java.util.ArrayList;
import java.util.List;
import javax.faces.application.NavigationHandler;
import javax.faces.component.ActionSource;
import javax.faces.component.ActionSource2;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
@@ -40,15 +40,11 @@ import org.springframework.webflow.validation.WebFlowMessageCodesResolver;
/**
* The default {@link ActionListener} implementation to be used with Web Flow.
*
* <p>
* This implementation bypasses the JSF {@link NavigationHandler} mechanism to instead let the event be handled directly
* by Web Flow.
* </p>
*
* <p>
* Web Flow's model-level validation will be invoked here after an event has been detected if the event is not an
* immediate event.
* </p>
*
* @author Jeremy Grelle
*/
@@ -58,9 +54,9 @@ public class FlowActionListener implements ActionListener {
private static final String MESSAGES_ID = "messages";
private ActionListener delegate;
private final ActionListener delegate;
private MessageCodesResolver messageCodesResolver = new WebFlowMessageCodesResolver();
private final MessageCodesResolver messageCodesResolver = new WebFlowMessageCodesResolver();
public FlowActionListener(ActionListener delegate) {
this.delegate = delegate;
@@ -68,17 +64,17 @@ public class FlowActionListener implements ActionListener {
public void processAction(ActionEvent actionEvent) throws AbortProcessingException {
if (!JsfUtils.isFlowRequest()) {
delegate.processAction(actionEvent);
this.delegate.processAction(actionEvent);
return;
}
FacesContext context = FacesContext.getCurrentInstance();
ActionSource source = (ActionSource) actionEvent.getSource();
ActionSource2 source = (ActionSource2) actionEvent.getSource();
String eventId = null;
if (source.getAction() != null) {
if (source.getActionExpression() != null) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking action " + source.getAction());
logger.debug("Invoking action " + source.getActionExpression());
}
eventId = (String) source.getAction().invoke(context, null);
eventId = (String) source.getActionExpression().invoke(context.getELContext(), null);
}
if (StringUtils.hasText(eventId)) {
if (logger.isDebugEnabled()) {
@@ -156,6 +152,6 @@ public class FlowActionListener implements ActionListener {
private void validate(RequestContext requestContext, Object model, String eventId) {
new ValidationHelper(model, requestContext, eventId, getModelExpression(requestContext).getExpressionString(),
null, messageCodesResolver, null).validate();
null, this.messageCodesResolver, null).validate();
}
}

View File

@@ -15,93 +15,70 @@
*/
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf20;
import java.util.Collection;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.el.ELContextListener;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ApplicationWrapper;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.el.MethodBinding;
import javax.faces.el.PropertyResolver;
import javax.faces.el.ReferenceSyntaxException;
import javax.faces.el.ValueBinding;
import javax.faces.el.VariableResolver;
import javax.faces.event.ActionListener;
import javax.faces.validator.Validator;
import org.springframework.util.Assert;
/**
* Wraps an {@link Application} instance in order to ensure Web Flow specific implementations of {@link ViewHandler} and
* {@link StateManager} are inserted at the front of the processing chain in JSF 1.2 and JSF 2.0 environments. This is
* done by intercepting the corresponding setters. All other methods are simple delegation methods.
* {@link StateManager} are inserted at the front of the processing chain in JSF environments. This is done by
* intercepting the corresponding setters. All other methods are simple delegation methods.
*
* @author Rossen Stoyanchev
*
* @see Jsf2FlowApplication
* @author Phillip Webb
*/
public class FlowApplication extends Application {
public class FlowApplication extends ApplicationWrapper {
private Application delegate;
private final Application wrapped;
/**
* Class constructor that accepts a delegate Application instance. If the delegate has default instantiation logic
* for its StateManager and ViewHandler instances, those will be wrapped with {@link FlowViewStateManager} and a
* for its StateManager and ViewHandler instances, those will be wrapped with {@link FlowStateManager} and a
* {@link FlowViewHandler} instance.
*
* @param delegate the Application instance to delegate to.
* @param wrapped the wrapped Application instance.
*/
public FlowApplication(Application delegate) {
Assert.notNull(delegate, "The delegate Application instance must not be null!");
this.delegate = delegate;
public FlowApplication(Application wrapped) {
Assert.notNull(wrapped, "The wrapped Application instance must not be null!");
this.wrapped = wrapped;
ViewHandler handler = this.delegate.getViewHandler();
ViewHandler handler = this.wrapped.getViewHandler();
if (shouldWrap(handler)) {
wrapAndSetViewHandler(handler);
}
StateManager manager = this.delegate.getStateManager();
StateManager manager = this.wrapped.getStateManager();
if (shouldWrap(manager)) {
wrapAndSetStateManager(manager);
}
}
/**
* @return the wrapped Application instance
*/
public Application getDelegate() {
return delegate;
}
public ELContextListener[] getELContextListeners() {
return getDelegate().getELContextListeners();
public Application getWrapped() {
return this.wrapped;
}
/**
* Inserts {@link FlowViewStateManager} in front of the given StateManager (if not already done).
* Inserts {@link FlowStateManager} in front of the given StateManager (if not already done).
*/
public void setStateManager(StateManager manager) {
if (shouldWrap(manager)) {
wrapAndSetStateManager(manager);
} else {
delegate.setStateManager(manager);
super.setStateManager(manager);
}
}
private boolean shouldWrap(StateManager manager) {
return (manager != null) && (!(manager instanceof FlowStateManager));
}
private void wrapAndSetStateManager(StateManager target) {
super.setStateManager(new FlowStateManager(target));
}
/**
* Inserts a {@link FlowViewHandler} in front of the given ViewHandler (if not already done).
*/
@@ -109,200 +86,20 @@ public class FlowApplication extends Application {
if (shouldWrap(handler)) {
wrapAndSetViewHandler(handler);
} else {
delegate.setViewHandler(handler);
super.setViewHandler(handler);
}
}
// ------------------- JSF 1.2 pass-through delegate methods ------------------//
public void addComponent(String componentType, String componentClass) {
delegate.addComponent(componentType, componentClass);
}
public void addConverter(String converterId, String converterClass) {
delegate.addConverter(converterId, converterClass);
}
public void addConverter(Class<?> targetClass, String converterClass) {
delegate.addConverter(targetClass, converterClass);
}
public void addELContextListener(ELContextListener listener) {
getDelegate().addELContextListener(listener);
}
public void addELResolver(ELResolver resolver) {
getDelegate().addELResolver(resolver);
}
public void addValidator(String validatorId, String validatorClass) {
delegate.addValidator(validatorId, validatorClass);
}
public UIComponent createComponent(String componentType) throws FacesException {
return delegate.createComponent(componentType);
}
public UIComponent createComponent(ValueBinding componentBinding, FacesContext context, String componentType)
throws FacesException {
return delegate.createComponent(componentBinding, context, componentType);
}
public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType)
throws FacesException {
return getDelegate().createComponent(componentExpression, context, componentType);
}
public Converter createConverter(String converterId) {
return delegate.createConverter(converterId);
}
public Converter createConverter(Class<?> targetClass) {
return delegate.createConverter(targetClass);
}
public MethodBinding createMethodBinding(String ref, Class<?>... params) throws ReferenceSyntaxException {
return delegate.createMethodBinding(ref, params);
}
public Validator createValidator(String validatorId) throws FacesException {
return delegate.createValidator(validatorId);
}
public ValueBinding createValueBinding(String ref) throws ReferenceSyntaxException {
return delegate.createValueBinding(ref);
}
public <T> T evaluateExpressionGet(FacesContext context, String expression, Class<? extends T> expectedType)
throws ELException {
return getDelegate().evaluateExpressionGet(context, expression, expectedType);
}
public ActionListener getActionListener() {
return delegate.getActionListener();
}
public Iterator<String> getComponentTypes() {
return delegate.getComponentTypes();
}
public Iterator<String> getConverterIds() {
return delegate.getConverterIds();
}
public Iterator<Class<?>> getConverterTypes() {
return delegate.getConverterTypes();
}
public Locale getDefaultLocale() {
return delegate.getDefaultLocale();
}
public String getDefaultRenderKitId() {
return delegate.getDefaultRenderKitId();
}
public ELResolver getELResolver() {
return getDelegate().getELResolver();
}
public ExpressionFactory getExpressionFactory() {
return getDelegate().getExpressionFactory();
}
public String getMessageBundle() {
return delegate.getMessageBundle();
}
public NavigationHandler getNavigationHandler() {
return delegate.getNavigationHandler();
}
public PropertyResolver getPropertyResolver() {
return delegate.getPropertyResolver();
}
public ResourceBundle getResourceBundle(FacesContext ctx, String name) {
return getDelegate().getResourceBundle(ctx, name);
}
public StateManager getStateManager() {
return delegate.getStateManager();
}
public Iterator<Locale> getSupportedLocales() {
return delegate.getSupportedLocales();
}
public Iterator<String> getValidatorIds() {
return delegate.getValidatorIds();
}
public VariableResolver getVariableResolver() {
return delegate.getVariableResolver();
}
public ViewHandler getViewHandler() {
return delegate.getViewHandler();
}
public void removeELContextListener(ELContextListener listener) {
getDelegate().removeELContextListener(listener);
}
public void setActionListener(ActionListener listener) {
delegate.setActionListener(listener);
}
public void setDefaultLocale(Locale locale) {
delegate.setDefaultLocale(locale);
}
public void setDefaultRenderKitId(String renderKitId) {
delegate.setDefaultRenderKitId(renderKitId);
}
public void setMessageBundle(String bundle) {
delegate.setMessageBundle(bundle);
}
public void setNavigationHandler(NavigationHandler handler) {
delegate.setNavigationHandler(handler);
}
public void setPropertyResolver(PropertyResolver resolver) {
delegate.setPropertyResolver(resolver);
}
public void setSupportedLocales(Collection<Locale> locales) {
delegate.setSupportedLocales(locales);
}
public void setVariableResolver(VariableResolver resolver) {
delegate.setVariableResolver(resolver);
}
// ------------------- Private helper methods ------------------//
private boolean shouldWrap(ViewHandler delegateViewHandler) {
return (delegateViewHandler != null) && (!(delegateViewHandler instanceof FlowViewHandler));
}
private boolean wrapAndSetViewHandler(ViewHandler target) {
if ((target != null) && (!(target instanceof FlowViewHandler))) {
ViewHandler handler = (isAtLeastJsf20()) ? new Jsf2FlowViewHandler(target) : new FlowViewHandler(target);
delegate.setViewHandler(handler);
ViewHandler handler = new FlowViewHandler(target);
super.setViewHandler(handler);
return true;
}
return false;
}
private boolean shouldWrap(StateManager manager) {
return (manager != null) && (!(manager instanceof FlowViewStateManager));
}
private void wrapAndSetStateManager(StateManager target) {
delegate.setStateManager(new FlowViewStateManager(target));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf20;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
@@ -29,32 +27,30 @@ import org.springframework.util.Assert;
* @see FlowApplication
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class FlowApplicationFactory extends ApplicationFactory {
private ApplicationFactory delegate;
private final ApplicationFactory wrapped;
public FlowApplicationFactory(ApplicationFactory delegate) {
Assert.notNull(delegate, "The delegate ApplicationFactory instance must not be null!");
this.delegate = delegate;
public FlowApplicationFactory(ApplicationFactory wrapped) {
Assert.notNull(wrapped, "The wrapped ApplicationFactory instance must not be null!");
this.wrapped = wrapped;
}
public Application getApplication() {
Application delegateApplication = delegate.getApplication();
if (delegateApplication != null && (!(delegateApplication instanceof FlowApplication))) {
Application flowApplication = (isAtLeastJsf20()) ? new Jsf2FlowApplication(delegateApplication)
: new FlowApplication(delegateApplication);
setApplication(flowApplication);
Application application = this.wrapped.getApplication();
if (application != null && (!(application instanceof FlowApplication))) {
setApplication(new FlowApplication(application));
}
return delegate.getApplication();
return this.wrapped.getApplication();
}
public void setApplication(Application application) {
delegate.setApplication(application);
this.wrapped.setApplication(application);
}
public ApplicationFactory getWrapped() {
return delegate;
return this.wrapped;
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.el.CompositeELResolver;
import javax.el.ELContext;
import javax.el.ELResolver;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.el.SpringBeanELResolver;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.expression.el.MapAdaptableELResolver;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.expression.el.FlowResourceELResolver;
import org.springframework.webflow.expression.el.ImplicitFlowVariableELResolver;
import org.springframework.webflow.expression.el.RequestContextELResolver;
import org.springframework.webflow.expression.el.ScopeSearchingELResolver;
/**
* Custom {@link ELResolver} for resolving web flow specific expressions.
*
* @author Jeremy Grelle
* @author Phillip Webb
*
* @since 2.4
*/
public class FlowELResolver extends CompositeELResolver {
public FlowELResolver() {
add(new RequestContextELResolver());
add(new ImplicitFlowVariableELResolver());
add(new FlowResourceELResolver());
add(new ScopeSearchingELResolver());
add(new MapAdaptableELResolver());
add(new BeanELResolver());
}
private static class BeanELResolver extends SpringBeanELResolver {
private static final BeanFactory EMPTY_BEAN_FACTORY = new StaticListableBeanFactory();
protected BeanFactory getBeanFactory(ELContext elContext) {
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (requestContext == null) {
return EMPTY_BEAN_FACTORY;
}
BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext();
return beanFactory != null ? beanFactory : EMPTY_BEAN_FACTORY;
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.IOException;
import javax.faces.context.ExternalContext;
import javax.faces.context.ExternalContextWrapper;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.webflow.execution.RequestContext;
/**
* Custom {@link ExternalContext} implementation that supports custom response objects other than
* {@link HttpServletResponse}.
*
* @author Jeremy Grelle
* @author Phillip Webb
* @author Rossen Stoyanchev
*
* @since 2.4
*/
public class FlowExternalContext extends ExternalContextWrapper {
Log logger = LogFactory.getLog(FlowExternalContext.class);
private static final String CUSTOM_RESPONSE = FlowExternalContext.class.getName() + ".customResponse";
private final ExternalContext wrapped;
private final RequestContext context;
public FlowExternalContext(RequestContext context, ExternalContext wrapped) {
this.context = context;
this.wrapped = wrapped;
}
public ExternalContext getWrapped() {
return this.wrapped;
}
public Object getResponse() {
if (this.context.getRequestScope().contains(CUSTOM_RESPONSE)) {
return this.context.getRequestScope().get(CUSTOM_RESPONSE);
}
return super.getResponse();
}
public void setResponse(Object response) {
this.context.getRequestScope().put(CUSTOM_RESPONSE, response);
super.setResponse(response);
}
public void responseSendError(int statusCode, String message) throws IOException {
this.logger.debug("Sending error HTTP status code " + statusCode + " with message '" + message + "'");
super.responseSendError(statusCode, message);
}
}

View File

@@ -15,28 +15,37 @@
*/
package org.springframework.faces.webflow;
import java.lang.reflect.Method;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.el.ELContext;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.context.ResponseStream;
import javax.faces.context.ResponseWriter;
import javax.faces.context.FacesContextWrapper;
import javax.faces.context.PartialViewContext;
import javax.faces.context.PartialViewContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.render.RenderKit;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import org.springframework.binding.message.Message;
import org.springframework.binding.message.MessageCriteria;
import org.springframework.binding.message.MessageResolver;
import org.springframework.binding.message.Severity;
import org.springframework.context.MessageSource;
import org.springframework.faces.webflow.context.portlet.PortletFacesContextImpl;
import org.springframework.util.ClassUtils;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.webflow.execution.RequestContext;
/**
@@ -45,82 +54,127 @@ import org.springframework.webflow.execution.RequestContext;
* {@code renderResponse} flag in flash scope so that the execution of the JSF {@link Lifecycle} may span multiple
* requests in the case of the POST+REDIRECT+GET pattern being enabled.
*
* @see FlowExternalContext
*
* @author Jeremy Grelle
* @author Phillip Webb
* @author Rossen Stoyanchev
*/
public class FlowFacesContext extends FacesContext {
public class FlowFacesContext extends FacesContextWrapper {
/**
* The key for storing the renderResponse flag
*/
static final String RENDER_RESPONSE_KEY = "flowRenderResponse";
/**
* The key for storing the renderResponse flag
*/
private RequestContext context;
private FlowFacesContextMessageDelegate messageDelegate;
private ExternalContext externalContext;
/**
* The base FacesContext delegate
*/
private FacesContext delegate;
public static FlowFacesContext newInstance(RequestContext context, Lifecycle lifecycle) {
FacesContext defaultFacesContext = null;
if (JsfRuntimeInformation.isPortletRequest(context)) {
defaultFacesContext = new PortletFacesContextImpl((PortletContext) context.getExternalContext()
.getNativeContext(), (PortletRequest) context.getExternalContext().getNativeRequest(),
(PortletResponse) context.getExternalContext().getNativeResponse());
} else {
FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
defaultFacesContext = facesContextFactory.getFacesContext(context.getExternalContext().getNativeContext(),
context.getExternalContext().getNativeRequest(), context.getExternalContext().getNativeResponse(),
lifecycle);
}
return (JsfRuntimeInformation.isAtLeastJsf20()) ? new Jsf2FlowFacesContext(context, defaultFacesContext)
: new FlowFacesContext(context, defaultFacesContext);
private static final Map<Severity, FacesMessage.Severity> SPRING_SEVERITY_TO_FACES;
static {
SPRING_SEVERITY_TO_FACES = new HashMap<Severity, FacesMessage.Severity>();
SPRING_SEVERITY_TO_FACES.put(Severity.INFO, FacesMessage.SEVERITY_INFO);
SPRING_SEVERITY_TO_FACES.put(Severity.WARNING, FacesMessage.SEVERITY_WARN);
SPRING_SEVERITY_TO_FACES.put(Severity.ERROR, FacesMessage.SEVERITY_ERROR);
SPRING_SEVERITY_TO_FACES.put(Severity.FATAL, FacesMessage.SEVERITY_FATAL);
}
public FlowFacesContext(RequestContext context, FacesContext delegate) {
private static final Map<FacesMessage.Severity, Severity> FACES_SEVERITY_TO_SPRING;
static {
FACES_SEVERITY_TO_SPRING = new HashMap<FacesMessage.Severity, Severity>();
for (Map.Entry<Severity, FacesMessage.Severity> entry : SPRING_SEVERITY_TO_FACES.entrySet()) {
FACES_SEVERITY_TO_SPRING.put(entry.getValue(), entry.getKey());
}
}
private final FacesContext wrapped;
private final RequestContext context;
private final ExternalContext externalContext;
private final PartialViewContext partialViewContext;
public FlowFacesContext(RequestContext context, FacesContext wrapped) {
this.context = context;
this.delegate = delegate;
this.messageDelegate = new FlowFacesContextMessageDelegate(context);
this.externalContext = new FlowExternalContext(delegate.getExternalContext());
this.wrapped = wrapped;
this.externalContext = new FlowExternalContext(context, wrapped.getExternalContext());
PartialViewContextFactory factory = JsfUtils.findFactory(PartialViewContextFactory.class);
PartialViewContext partialViewContextDelegate = factory.getPartialViewContext(this);
this.partialViewContext = new FlowPartialViewContext(partialViewContextDelegate);
setCurrentInstance(this);
}
public FacesContext getWrapped() {
return this.wrapped;
}
public void release() {
super.release();
setCurrentInstance(null);
}
public ExternalContext getExternalContext() {
return this.externalContext;
}
public PartialViewContext getPartialViewContext() {
return this.partialViewContext;
}
public ELContext getELContext() {
ELContext elContext = super.getELContext();
// Ensure that our wrapper is used over the stock FacesContextImpl
elContext.putContext(FacesContext.class, this);
return elContext;
}
public boolean getRenderResponse() {
Boolean renderResponse = this.context.getFlashScope().getBoolean(RENDER_RESPONSE_KEY);
return (renderResponse == null ? false : renderResponse);
}
public boolean getResponseComplete() {
return this.context.getExternalContext().isResponseComplete();
}
public void renderResponse() {
// stored in flash scope to survive a redirect when transitioning from one view to another
this.context.getFlashScope().put(RENDER_RESPONSE_KEY, true);
}
public void responseComplete() {
this.context.getExternalContext().recordResponseComplete();
}
public boolean isValidationFailed() {
if (this.context.getMessageContext().hasErrorMessages()) {
return true;
} else {
return super.isValidationFailed();
}
}
/**
* Translates a FacesMessage to a Spring Web Flow message and adds it to the current MessageContext
*/
public void addMessage(String clientId, FacesMessage message) {
messageDelegate.addToFlowMessageContext(clientId, message);
FacesMessageSource source = new FacesMessageSource(clientId);
FlowFacesMessage flowFacesMessage = new FlowFacesMessage(source, message);
this.context.getMessageContext().addMessage(flowFacesMessage);
}
/**
* Returns an Iterator for all component clientId's for which messages have been added.
*/
public Iterator<String> getClientIdsWithMessages() {
return messageDelegate.getClientIdsWithMessages();
}
public ELContext getELContext() {
Method delegateMethod = ClassUtils.getMethodIfAvailable(delegate.getClass(), "getELContext");
if (delegateMethod != null) {
try {
ELContext context = (ELContext) delegateMethod.invoke(delegate);
context.putContext(FacesContext.class, this);
return context;
} catch (Exception e) {
return null;
Set<String> clientIds = new LinkedHashSet<String>();
for (Message message : this.context.getMessageContext().getAllMessages()) {
Object source = message.getSource();
if (source != null && source instanceof String) {
clientIds.add((String) source);
} else if (message.getSource() instanceof FacesMessageSource) {
clientIds.add(((FacesMessageSource) source).getClientId());
}
} else {
return null;
}
return Collections.unmodifiableSet(clientIds).iterator();
}
/**
@@ -128,14 +182,36 @@ public class FlowFacesContext extends FacesContext {
* associated with any specific UIComponent. If no such messages have been queued, return null.
*/
public FacesMessage.Severity getMaximumSeverity() {
return messageDelegate.getMaximumSeverity();
if (this.context.getMessageContext().getAllMessages().length == 0) {
return null;
}
FacesMessage.Severity max = FacesMessage.SEVERITY_INFO;
Iterator<FacesMessage> messages = getMessages();
while (messages.hasNext()) {
FacesMessage message = messages.next();
if (message.getSeverity().getOrdinal() > max.getOrdinal()) {
max = message.getSeverity();
}
if (max.getOrdinal() == FacesMessage.SEVERITY_FATAL.getOrdinal()) {
break;
}
}
return max;
}
/**
* Returns an Iterator for all Messages in the current MessageContext that does translation to FacesMessages.
*/
public Iterator<FacesMessage> getMessages() {
return messageDelegate.getMessages();
return getMessageList().iterator();
}
/**
* Returns a List for all Messages in the current MessageContext that does translation to FacesMessages.
*/
public List<FacesMessage> getMessageList() {
Message[] messages = this.context.getMessageContext().getAllMessages();
return asFacesMessages(messages);
}
/**
@@ -143,100 +219,189 @@ public class FlowFacesContext extends FacesContext {
* to FacesMessages.
*/
public Iterator<FacesMessage> getMessages(String clientId) {
return messageDelegate.getMessages(clientId);
return getMessageList(clientId).iterator();
}
public boolean getRenderResponse() {
Boolean renderResponse = context.getFlashScope().getBoolean(RENDER_RESPONSE_KEY);
return (renderResponse == null ? false : renderResponse);
}
public boolean getResponseComplete() {
return context.getExternalContext().isResponseComplete();
}
public void renderResponse() {
// stored in flash scope to survive a redirect when transitioning from one view to another
context.getFlashScope().put(RENDER_RESPONSE_KEY, true);
}
public void responseComplete() {
context.getExternalContext().recordResponseComplete();
}
// ------------------ Pass-through delegate methods ----------------------//
public Application getApplication() {
return delegate.getApplication();
}
public ExternalContext getExternalContext() {
return externalContext;
}
public RenderKit getRenderKit() {
return delegate.getRenderKit();
}
public ResponseStream getResponseStream() {
return delegate.getResponseStream();
}
public ResponseWriter getResponseWriter() {
return delegate.getResponseWriter();
}
public UIViewRoot getViewRoot() {
return delegate.getViewRoot();
}
public void release() {
delegate.release();
setCurrentInstance(null);
}
public void setResponseStream(ResponseStream responseStream) {
delegate.setResponseStream(responseStream);
}
public void setResponseWriter(ResponseWriter responseWriter) {
delegate.setResponseWriter(responseWriter);
}
public void setViewRoot(UIViewRoot root) {
delegate.setViewRoot(root);
}
protected FacesContext getDelegate() {
return delegate;
}
protected FlowFacesContextMessageDelegate getMessageDelegate() {
return messageDelegate;
}
protected class FlowExternalContext extends ExternalContextWrapper {
private static final String CUSTOM_RESPONSE = "customResponse";
public FlowExternalContext(ExternalContext delegate) {
super(delegate);
}
public Object getResponse() {
if (context.getRequestScope().contains(CUSTOM_RESPONSE)) {
return context.getRequestScope().get(CUSTOM_RESPONSE);
/**
* Returns a List for all Messages with the given clientId in the current MessageContext that does translation to
* FacesMessages.
*/
public List<FacesMessage> getMessageList(final String clientId) {
final FacesMessageSource source = new FacesMessageSource(clientId);
Message[] messages = this.context.getMessageContext().getMessagesByCriteria(new MessageCriteria() {
public boolean test(Message message) {
return ObjectUtils.nullSafeEquals(message.getSource(), source)
|| ObjectUtils.nullSafeEquals(message.getSource(), clientId);
}
return delegate.getResponse();
});
return asFacesMessages(messages);
}
private List<FacesMessage> asFacesMessages(Message[] messages) {
if (messages == null || messages.length == 0) {
return Collections.emptyList();
}
List<FacesMessage> facesMessages = new ArrayList<FacesMessage>();
for (Message message : messages) {
facesMessages.add(asFacesMessage(message));
}
return Collections.unmodifiableList(facesMessages);
}
private FacesMessage asFacesMessage(Message message) {
if (message instanceof FlowFacesMessage) {
return ((FlowFacesMessage) message).getFacesMessage();
}
FacesMessage.Severity severity = SPRING_SEVERITY_TO_FACES.get(message.getSeverity());
if (severity == null) {
severity = FacesMessage.SEVERITY_INFO;
}
return new FacesMessage(severity, message.getText(), null);
}
public static FlowFacesContext newInstance(RequestContext context, Lifecycle lifecycle) {
FacesContext defaultFacesContext = newDefaultInstance(context, lifecycle);
return new FlowFacesContext(context, defaultFacesContext);
}
private static FacesContext newDefaultInstance(RequestContext context, Lifecycle lifecycle) {
Object nativeContext = context.getExternalContext().getNativeContext();
Object nativeRequest = context.getExternalContext().getNativeRequest();
Object nativeResponse = context.getExternalContext().getNativeResponse();
return FacesContextHelper.newDefaultInstance(nativeContext, nativeRequest, nativeResponse, lifecycle);
}
/**
* Adapter class to convert a {@link FacesMessage} to a Spring {@link Message}. This adapter is required to allow
* <tt>FacesMessages</tt> to be registered with Spring whilst still retaining their mutable nature. It is not
* uncommon for <tt>FacesMessages</tt> to be changed after they have been added to a <tt>FacesContext</tt>, for
* example, from a <tt>PhaseListener</tt>.
* <p>
* NOTE: Only {@link javax.faces.application.FacesMessage} instances are directly adapted, any subclasses will be
* converted to the standard FacesMessage implementation. This is to protect against bugs such as SWF-1073.
*
* For convenience this class also implements the {@link MessageResolver} interface.
*/
protected static class FlowFacesMessage extends Message implements MessageResolver {
private transient FacesMessage facesMessage;
public FlowFacesMessage(FacesMessageSource source, FacesMessage message) {
super(source, null, null);
this.facesMessage = asStandardFacesMessageInstance(message);
}
/**
* Store the native response object to be used for the duration of the Faces Request
* Use standard faces message as required to protect against bugs such as SWF-1073.
*
* @param message {@link javax.faces.application.FacesMessage} or subclass.
* @return {@link javax.faces.application.FacesMessage} instance
*/
public void setResponse(Object response) {
context.getRequestScope().put(CUSTOM_RESPONSE, response);
delegate.setResponse(response);
private FacesMessage asStandardFacesMessageInstance(FacesMessage message) {
if (FacesMessage.class.equals(message.getClass())) {
return message;
}
return new FacesMessage(message.getSeverity(), message.getSummary(), message.getDetail());
}
// Custom serialization to work around myfaces bug MYFACES-1347
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(this.facesMessage.getSummary());
oos.writeObject(this.facesMessage.getDetail());
oos.writeInt(this.facesMessage.getSeverity().getOrdinal());
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
String summary = (String) ois.readObject();
String detail = (String) ois.readObject();
int severityOrdinal = ois.readInt();
FacesMessage.Severity severity = FacesMessage.SEVERITY_INFO;
for (Iterator<?> iterator = FacesMessage.VALUES.iterator(); iterator.hasNext();) {
FacesMessage.Severity value = (FacesMessage.Severity) iterator.next();
if (value.getOrdinal() == severityOrdinal) {
severity = value;
}
}
this.facesMessage = new FacesMessage(severity, summary, detail);
}
public String getText() {
StringBuilder text = new StringBuilder();
if (StringUtils.hasLength(this.facesMessage.getSummary())) {
text.append(this.facesMessage.getSummary());
}
if (StringUtils.hasLength(this.facesMessage.getDetail())) {
text.append(text.length() == 0 ? "" : " : ");
text.append(this.facesMessage.getDetail());
}
return text.toString();
}
public Severity getSeverity() {
Severity severity = null;
if (this.facesMessage.getSeverity() != null) {
severity = FACES_SEVERITY_TO_SPRING.get(this.facesMessage.getSeverity());
}
return (severity == null ? Severity.INFO : severity);
}
public String toString() {
ToStringCreator rtn = new ToStringCreator(this);
rtn.append("severity", getSeverity());
if (FacesContext.getCurrentInstance() != null) {
// Only append text if running within a faces context
rtn.append("text", getText());
}
return rtn.toString();
}
public Message resolveMessage(MessageSource messageSource, Locale locale) {
return this;
}
/**
* @return The original {@link FacesMessage} adapted by this class.
*/
public FacesMessage getFacesMessage() {
return this.facesMessage;
}
}
/**
* A Spring Message {@link Message#getSource() Source} that originated from JSF.
*/
public static class FacesMessageSource implements Serializable {
private String clientId;
public FacesMessageSource(String clientId) {
if (StringUtils.hasLength(clientId)) {
this.clientId = clientId;
}
}
public String getClientId() {
return this.clientId;
}
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.clientId);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass().equals(FacesMessageSource.class)) {
return ObjectUtils.nullSafeEquals(getClientId(), ((FacesMessageSource) obj).getClientId());
}
return false;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,5 +44,4 @@ public class FlowFacesContextLifecycleListener extends FlowExecutionListenerAdap
public void requestProcessed(RequestContext context) {
FacesContext.getCurrentInstance().release();
}
}

View File

@@ -1,412 +0,0 @@
package org.springframework.faces.webflow;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.springframework.binding.message.Message;
import org.springframework.binding.message.MessageCriteria;
import org.springframework.binding.message.MessageResolver;
import org.springframework.binding.message.Severity;
import org.springframework.context.MessageSource;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.StringUtils;
import org.springframework.webflow.execution.RequestContext;
/**
* Helper delegate class for use with the {@link FlowFacesContext} that handles all faces message methods.
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class FlowFacesContextMessageDelegate {
private RequestContext context;
/**
* Key for identifying summary messages
*/
static final String SUMMARY_MESSAGE_KEY = "_summary";
/**
* Key for identifying detail messages
*/
static final String DETAIL_MESSAGE_KEY = "_detail";
/**
* Mappings between {@link FacesMessage} and {@link Severity}.
*/
private static final Map<FacesMessage.Severity, Severity> FACESSEVERITY_TO_SPRINGSEVERITY;
static {
FACESSEVERITY_TO_SPRINGSEVERITY = new HashMap<FacesMessage.Severity, Severity>();
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_INFO, Severity.INFO);
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_WARN, Severity.WARNING);
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_ERROR, Severity.ERROR);
}
public FlowFacesContextMessageDelegate(RequestContext context) {
super();
this.context = context;
}
/**
* Whether Web Flow's MessageContext contains any errors.
*/
public boolean hasErrorMessages() {
return context.getMessageContext().hasErrorMessages();
}
/**
* @see FlowFacesContext#addMessage(String, FacesMessage)
*/
public void addToFlowMessageContext(String clientId, FacesMessage message) {
String source = null;
if (StringUtils.hasText(clientId)) {
source = clientId;
}
context.getMessageContext().addMessage(new FlowFacesMessageAdapter(source, SUMMARY_MESSAGE_KEY, message));
context.getMessageContext().addMessage(new FlowFacesMessageAdapter(source, DETAIL_MESSAGE_KEY, message));
}
/**
* @see FlowFacesContext#getClientIdsWithMessages
*/
public Iterator<String> getClientIdsWithMessages() {
return new ClientIdIterator();
}
/**
* @see FlowFacesContext#getMaximumSeverity()
*/
public FacesMessage.Severity getMaximumSeverity() {
if (context.getMessageContext().getAllMessages().length == 0) {
return null;
}
FacesMessage.Severity max = FacesMessage.SEVERITY_INFO;
Iterator<FacesMessage> messages = getMessages();
while (messages.hasNext()) {
FacesMessage message = messages.next();
if (message.getSeverity().getOrdinal() > max.getOrdinal()) {
max = message.getSeverity();
}
if (max.getOrdinal() == FacesMessage.SEVERITY_FATAL.getOrdinal()) {
break;
}
}
return max;
}
/**
* @see FlowFacesContext#getMessages()
*/
public Iterator<FacesMessage> getMessages() {
return new FacesMessageIterator();
}
/**
* @see FlowFacesContext#getMessages(String)
*/
public Iterator<FacesMessage> getMessages(String clientId) {
return new FacesMessageIterator(clientId);
}
/**
* @see Jsf2FlowFacesContext#getMessageList()
*/
public List<FacesMessage> getMessageList() {
return new FacesMessageIterator().asList();
}
/**
* @see Jsf2FlowFacesContext#getMessageList(String)
*/
public List<FacesMessage> getMessageList(String clientId) {
return new FacesMessageIterator(clientId).asList();
}
// ------------------ Private helper methods ----------------------//
private FacesMessage toFacesMessage(Message summaryMessage, Message detailMessage) {
// If we can return the actual message instance.
if (summaryMessage instanceof FlowFacesMessageAdapter) {
return ((FlowFacesMessageAdapter) summaryMessage).getFacesMessage();
}
if (detailMessage instanceof FlowFacesMessageAdapter) {
return ((FlowFacesMessageAdapter) detailMessage).getFacesMessage();
}
// If we have not got an actual instance adapt the message
if (summaryMessage.getSeverity() == Severity.INFO) {
return new FacesMessage(FacesMessage.SEVERITY_INFO, summaryMessage.getText(), detailMessage.getText());
} else if (summaryMessage.getSeverity() == Severity.WARNING) {
return new FacesMessage(FacesMessage.SEVERITY_WARN, summaryMessage.getText(), detailMessage.getText());
} else if (summaryMessage.getSeverity() == Severity.ERROR) {
return new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryMessage.getText(), detailMessage.getText());
} else {
return new FacesMessage(FacesMessage.SEVERITY_FATAL, summaryMessage.getText(), detailMessage.getText());
}
}
private class FacesMessageIterator implements Iterator<FacesMessage> {
private List<FacesMessage> messages;
private int currentIndex = -1;
protected FacesMessageIterator() {
Message[] summaryMessages = context.getMessageContext().getMessagesByCriteria(new SummaryMessageCriteria());
Message[] detailMessages = context.getMessageContext().getMessagesByCriteria(new DetailMessageCriteria());
Message[] userMessages = context.getMessageContext().getMessagesByCriteria(new UserMessageCriteria());
messages = new ArrayList<FacesMessage>();
for (int i = 0; i < summaryMessages.length; i++) {
messages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
}
for (Message userMessage : userMessages) {
messages.add(toFacesMessage(userMessage, userMessage));
}
}
protected FacesMessageIterator(String clientId) {
Message[] summaryMessages = context.getMessageContext().getMessagesBySource(clientId + SUMMARY_MESSAGE_KEY);
Message[] detailMessages = context.getMessageContext().getMessagesBySource(clientId + DETAIL_MESSAGE_KEY);
Message[] userMessages = context.getMessageContext().getMessagesBySource(clientId);
this.messages = new ArrayList<FacesMessage>();
for (int i = 0; i < summaryMessages.length; i++) {
messages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
}
for (Message userMessage : userMessages) {
messages.add(toFacesMessage(userMessage, userMessage));
}
}
public boolean hasNext() {
return messages.size() > currentIndex + 1;
}
public FacesMessage next() {
currentIndex++;
return messages.get(currentIndex);
}
public void remove() {
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
}
public List<FacesMessage> asList() {
if (null == messages) {
return Collections.unmodifiableList(Collections.<FacesMessage> emptyList());
} else {
return Collections.unmodifiableList(messages);
}
}
}
private class ClientIdIterator implements Iterator<String> {
private Message[] messages;
int currentIndex = -1;
protected ClientIdIterator() {
this.messages = context.getMessageContext().getMessagesByCriteria(new IdentifiedMessageCriteria());
}
public boolean hasNext() {
return messages.length > currentIndex + 1;
}
public String next() {
Message next = messages[++currentIndex];
if (next.getSource() == null) {
return null;
} else if (next.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)) {
return next.getSource().toString().replaceAll(SUMMARY_MESSAGE_KEY, "");
} else {
return next.getSource().toString();
}
}
public void remove() {
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
}
}
private class SummaryMessageCriteria implements MessageCriteria {
public boolean test(Message message) {
if (message.getSource() == null) {
return false;
}
return message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY);
}
}
private class DetailMessageCriteria implements MessageCriteria {
public boolean test(Message message) {
if (message.getSource() == null) {
return false;
}
return message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
}
}
private class UserMessageCriteria implements MessageCriteria {
public boolean test(Message message) {
if (message.getSource() == null) {
return true;
}
return !message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)
&& !message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
}
}
private class IdentifiedMessageCriteria implements MessageCriteria {
String nullSummaryId = null + SUMMARY_MESSAGE_KEY;
private Set<String> identifiedMessageSources = new HashSet<String>();
// From getClientIdsWithMessages docs: If any messages have been queued that were not associated with
// any specific client identifier, a null value will be included in the iterated values.
public boolean test(Message message) {
if (message.getSource() != null && message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY)) {
return false;
} else if (message.getSource() == null || message.getSource().equals("")
|| message.getSource().equals(nullSummaryId)) {
return identifiedMessageSources.add(null);
}
return identifiedMessageSources.add((String) message.getSource());
}
}
/**
* Adapter class to convert a {@link FacesMessage} to a Spring {@link Message}. This adapter is required to allow
* <tt>FacesMessages</tt> to be registered with spring while still retaining their mutable nature. It is not
* uncommon for <tt>FacesMessages</tt> to be changed after they have been added to a <tt>FacesContext</tt>, for
* example, from a <tt>PhaseListener</tt>.
* <p>
* NOTE: Only {@link javax.faces.application.FacesMessage} instances are directly adapted, any subclasses will be
* converted to the standard FacesMessage implementation. This is to protect against bugs such as SWF-1073.
*
* For convenience this class also implements the {@link MessageResolver} interface.
*/
private static class FlowFacesMessageAdapter extends Message implements MessageResolver {
private String key;
private String source;
private transient FacesMessage facesMessage;
public FlowFacesMessageAdapter(String source, String key, FacesMessage message) {
super(null, null, null);
this.source = source;
this.key = key;
this.facesMessage = asStandardFacesMessageInstance(message);
}
// Custom serialization to work around myfaces bug MYFACES-1347
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeObject(facesMessage.getSummary());
oos.writeObject(facesMessage.getDetail());
oos.writeInt(facesMessage.getSeverity().getOrdinal());
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
String summary = (String) ois.readObject();
String detail = (String) ois.readObject();
int severityOrdinal = ois.readInt();
FacesMessage.Severity severity = FacesMessage.SEVERITY_INFO;
for (Iterator<?> iterator = FacesMessage.VALUES.iterator(); iterator.hasNext();) {
FacesMessage.Severity value = (FacesMessage.Severity) iterator.next();
if (value.getOrdinal() == severityOrdinal) {
severity = value;
}
}
facesMessage = new FacesMessage(severity, summary, detail);
}
/**
* Use standard faces message as required to protect against bugs such as SWF-1073.
*
* @param message {@link javax.faces.application.FacesMessage} or subclass.
* @return {@link javax.faces.application.FacesMessage} instance
*/
private FacesMessage asStandardFacesMessageInstance(FacesMessage message) {
if (FacesMessage.class.equals(message.getClass())) {
return message;
}
return new FacesMessage(message.getSeverity(), message.getSummary(), message.getDetail());
}
public Object getSource() {
return source + key;
}
public String getText() {
String text = null;
if (DETAIL_MESSAGE_KEY.equals(key)) {
text = facesMessage.getDetail();
} else if (SUMMARY_MESSAGE_KEY.equals(key)) {
text = facesMessage.getSummary();
} else {
throw new RuntimeException("Unknown faces message type key");
}
if (StringUtils.hasText(text)) {
return text;
}
return "";
}
public Severity getSeverity() {
Severity severity = null;
if (facesMessage.getSeverity() != null) {
severity = FACESSEVERITY_TO_SPRINGSEVERITY.get(facesMessage.getSeverity());
}
return (severity == null ? Severity.INFO : severity);
}
public String toString() {
ToStringCreator rtn = new ToStringCreator(this);
rtn.append("severity", getSeverity());
if (FacesContext.getCurrentInstance() != null) {
// Only append text if running within a faces context
rtn.append("text", getText());
}
return rtn.toString();
}
public Message resolveMessage(MessageSource messageSource, Locale locale) {
return this;
}
/**
* @return The original {@link FacesMessage} adapted by this class.
*/
public FacesMessage getFacesMessage() {
return facesMessage;
}
}
}

View File

@@ -15,18 +15,15 @@
*/
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf20;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.faces.support.LifecycleWrapper;
/**
* Custom {@link Lifecycle} for Spring Web Flow that only executes the APPLY_REQUEST_VALUES through INVOKE_APPLICATION
@@ -37,23 +34,27 @@ import org.apache.commons.logging.LogFactory;
* </p>
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class FlowLifecycle extends Lifecycle {
public class FlowLifecycle extends LifecycleWrapper {
private static final Log logger = LogFactory.getLog(FlowLifecycle.class);
private final Lifecycle delegate;
private final Lifecycle wrapped;
public static Lifecycle newInstance() {
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
LifecycleFactory lifecycleFactory = JsfUtils.findFactory(LifecycleFactory.class);
Lifecycle defaultLifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
return new FlowLifecycle(defaultLifecycle);
}
FlowLifecycle(Lifecycle delegate) {
this.delegate = delegate;
FlowLifecycle(Lifecycle wrapped) {
this.wrapped = wrapped;
}
public Lifecycle getWrapped() {
return this.wrapped;
}
/**
@@ -64,43 +65,12 @@ public class FlowLifecycle extends Lifecycle {
for (int p = PhaseId.APPLY_REQUEST_VALUES.getOrdinal(); p <= PhaseId.INVOKE_APPLICATION.getOrdinal(); p++) {
PhaseId phaseId = PhaseId.VALUES.get(p);
if (!skipPhase(context, phaseId)) {
if (isAtLeastJsf20()) {
context.setCurrentPhaseId(phaseId);
}
context.setCurrentPhaseId(phaseId);
invokePhase(context, phaseId);
}
}
}
/**
* Delegates to the wrapped {@link Lifecycle}.
* @throws FacesException
*/
public void render(FacesContext context) throws FacesException {
delegate.render(context);
}
/**
* Delegates to the wrapped {@link Lifecycle}.
*/
public void addPhaseListener(PhaseListener listener) {
delegate.addPhaseListener(listener);
}
/**
* Delegates to the wrapped {@link Lifecycle}.
*/
public PhaseListener[] getPhaseListeners() {
return delegate.getPhaseListeners();
}
/**
* Delegates to the wrapped {@link Lifecycle}.
*/
public void removePhaseListener(PhaseListener listener) {
delegate.removePhaseListener(listener);
}
private boolean skipPhase(FacesContext context, PhaseId phaseId) {
if (context.getResponseComplete()) {
return true;

View File

@@ -27,22 +27,22 @@ import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.execution.View;
/**
* Web Flow {@link PartialViewContext} implementation allowing ids for partial rendering to be specified from the
* Web Flow {@link PartialViewContext} implementation allowing IDs for partial rendering to be specified from the
* server-side. This is done in a flow definition with the &lt;render fragments="..." /&gt; action.
*
* @author Rossen Stoyanchev
*/
public class FlowPartialViewContext extends PartialViewContextWrapper {
private PartialViewContext delegate;
private final PartialViewContext wrapped;
public FlowPartialViewContext(PartialViewContext delegate) {
this.delegate = delegate;
public FlowPartialViewContext(PartialViewContext wrapped) {
this.wrapped = wrapped;
}
@Override
public PartialViewContext getWrapped() {
return delegate;
return this.wrapped;
}
@Override

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.el.CompositeELResolver;
import javax.faces.el.PropertyResolver;
import org.springframework.binding.collection.MapAdaptable;
import org.springframework.binding.expression.el.MapAdaptableELResolver;
import org.springframework.context.MessageSource;
import org.springframework.faces.expression.ELDelegatingPropertyResolver;
import org.springframework.webflow.expression.el.FlowResourceELResolver;
/**
* Custom property resolver for resolving properties on web flow specific structures with JSF 1.1 or > by delegating to
* web flow's EL resolvers.
*
* <p>
* This resolver handles resolving properties on a {@link MapAdaptable} collection and a flow-local
* {@link MessageSource}
* </p>
* @author Jeremy Grelle
*/
public class FlowPropertyResolver extends ELDelegatingPropertyResolver {
private static final CompositeELResolver composite = new CompositeELResolver();
static {
composite.add(new FlowResourceELResolver());
composite.add(new MapAdaptableELResolver());
}
public FlowPropertyResolver(PropertyResolver nextResolver) {
super(nextResolver, composite);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,43 +17,62 @@ package org.springframework.faces.webflow;
/**
* A render kit implementation that ensures use of Web Flow's FlowViewResponseStateManager, which takes over reading and
* writing JSF state and manages that in Web Flow's view scope. The FlowViewResponseStateManager is plugged in only in a
* JSF 2 environment.
*
* Note that partial state saving in Apache MyFaces is not yet supported. Use the javax.faces.PARTIAL_STATE_SAVING context
* parameter in web.xml to disable it.
*
* writing JSF state and manages that in Web Flow's view scope.
*
* @author Rossen Stoyanchev
* @author Phillip Webb
* @since 2.2.0
*/
import java.lang.reflect.Constructor;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitWrapper;
import javax.faces.render.ResponseStateManager;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.util.ClassUtils;
public class FlowRenderKit extends RenderKitWrapper {
private RenderKit delegate;
private final RenderKit wrapped;
private FlowViewResponseStateManager responseStateManager;
private final ResponseStateManager flowViewResponseStateManager;
public FlowRenderKit(RenderKit delegate) {
this.delegate = delegate;
if (JsfRuntimeInformation.isAtLeastJsf20()) {
this.responseStateManager = new FlowViewResponseStateManager(delegate.getResponseStateManager());
public FlowRenderKit(RenderKit wrapped) {
this.wrapped = wrapped;
this.flowViewResponseStateManager = initResponseStateManager(wrapped.getResponseStateManager());
}
private ResponseStateManager initResponseStateManager(ResponseStateManager wrapped) {
if (!JsfRuntimeInformation.isMyFacesPresent()) {
return new FlowResponseStateManager(wrapped);
}
Constructor<?> constructor;
try {
String className = "org.springframework.faces.webflow.MyFacesFlowResponseStateManager";
Class<?> clazz = ClassUtils.forName(className, FlowRenderKit.class.getClassLoader());
constructor = ClassUtils.getConstructorIfAvailable(clazz, FlowResponseStateManager.class);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Could not initialize MyFacesFlowResponseStateManager", e);
} catch (LinkageError e) {
throw new IllegalStateException("Could not initialize MyFacesFlowResponseStateManager", e);
}
return (ResponseStateManager) BeanUtils.instantiateClass(constructor, new FlowResponseStateManager(wrapped));
}
public RenderKit getWrapped() {
return delegate;
return this.wrapped;
}
/**
* Returns an instance of {@link FlowViewResponseStateManager} in a JSF 2 environment or returns the delegates's
* Returns an instance of {@link FlowResponseStateManager} in a JSF 2 environment or returns the delegates's
* ResponseStateManager instance otherwise.
*/
public ResponseStateManager getResponseStateManager() {
return (JsfUtils.isFlowRequest() && JsfRuntimeInformation.isPartialStateSavingSupported()) ? responseStateManager
: delegate.getResponseStateManager();
if (JsfUtils.isFlowRequest()) {
return this.flowViewResponseStateManager;
}
return this.wrapped.getResponseStateManager();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,17 +17,19 @@ package org.springframework.faces.webflow;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.faces.FacesException;
import javax.faces.view.facelets.ResourceResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import com.sun.facelets.impl.DefaultResourceResolver;
import com.sun.facelets.impl.ResourceResolver;
/**
* Resolves Facelets templates using Spring Resource paths such as "classpath:foo.xhtml". Configure it via a context
* parameter in web.xml:
@@ -41,14 +43,42 @@ import com.sun.facelets.impl.ResourceResolver;
*
* @see Jsf2FlowResourceResolver
*/
public class FlowResourceResolver implements ResourceResolver {
public class FlowResourceResolver extends ResourceResolver {
ResourceResolver delegateResolver = new DefaultResourceResolver();
/**
* All known {@link ResourceResolver} implementations in the priority order
*/
private static final List<String> RESOLVERS_CLASSES;
static {
List<String> resolvers = new ArrayList<String>();
resolvers.add("com.sun.faces.facelets.impl.DefaultResourceResolver");
resolvers.add("org.apache.myfaces.view.facelets.impl.DefaultResourceResolver");
RESOLVERS_CLASSES = Collections.unmodifiableList(resolvers);
}
private final ResourceResolver delegateResolver;
public FlowResourceResolver() {
this.delegateResolver = createDelegateResolver();
}
private ResourceResolver createDelegateResolver() {
try {
ClassLoader classLoader = getClass().getClassLoader();
for (String resolverClass : RESOLVERS_CLASSES) {
if (ClassUtils.isPresent(resolverClass, classLoader)) {
return (ResourceResolver) ClassUtils.forName(resolverClass, classLoader).newInstance();
}
}
} catch (Exception e) {
}
throw new IllegalStateException("Unable to find Default ResourceResolver");
}
public URL resolveUrl(String path) {
if (!JsfUtils.isFlowRequest()) {
return delegateResolver.resolveUrl(path);
return this.delegateResolver.resolveUrl(path);
}
try {
@@ -63,7 +93,7 @@ public class FlowResourceResolver implements ResourceResolver {
if (viewResource.exists()) {
return viewResource.getURL();
} else {
return delegateResolver.resolveUrl(path);
return this.delegateResolver.resolveUrl(path);
}
} catch (IOException ex) {
throw new FacesException(ex);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package org.springframework.faces.webflow;
import java.io.IOException;
import java.io.Writer;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKitFactory;
@@ -26,90 +25,62 @@ import javax.faces.render.ResponseStateManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.faces.support.ResponseStateManagerWrapper;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* <p>
* A custom ResponseStateManager that writes JSF state to a Web Flow managed view-scoped variable. This class is plugged
* in via {@link FlowRenderKit} in JSF 2 runtime environments only.
* </p>
*
* <p>
* In JSF 2 where a partial state saving algorithm is used, Web Flow delegates to the JSF 2 runtime to handle state
* saving. However, an instance of this class plugged in via {@link FlowRenderKit} will ensure that state is saved in a
* Web Flow managed view-scoped variable.
* </p>
* in via {@link FlowRenderKit}.
*
* @author Rossen Stoyanchev
* @author Phillip Webb
*
* @since 2.2.0
*/
public class FlowViewResponseStateManager extends ResponseStateManager {
public class FlowResponseStateManager extends ResponseStateManagerWrapper {
private static final Log logger = LogFactory.getLog(FlowViewResponseStateManager.class);
private static final Log logger = LogFactory.getLog(FlowResponseStateManager.class);
private ResponseStateManager delegate;
static final String FACES_VIEW_STATE = "facesViewState";
private char[] stateFieldStart = ("<input type=\"hidden\" name=\"" + ResponseStateManager.VIEW_STATE_PARAM
+ "\" id=\"" + ResponseStateManager.VIEW_STATE_PARAM + "\" value=\"").toCharArray();
private static final char[] STATE_FIELD_START = ("<input type=\"hidden\" name=\""
+ ResponseStateManager.VIEW_STATE_PARAM + "\" id=\"" + ResponseStateManager.VIEW_STATE_PARAM + "\" value=\"")
.toCharArray();
private char[] stateFieldEnd = "\" />".toCharArray();
private static final char[] STATE_FIELD_END = "\" />".toCharArray();
public FlowViewResponseStateManager(ResponseStateManager delegate) {
this.delegate = delegate;
private final ResponseStateManager wrapped;
public FlowResponseStateManager(ResponseStateManager wrapped) {
this.wrapped = wrapped;
}
public ResponseStateManager getWrapped() {
return this.wrapped;
}
/**
* <p>
* Wraps state in an instance of {@link FlowSerializedView} and stores it in view scope.
* </p>
*
* <p>
* Also complies with the contract for {@link ResponseStateManager#writeState(FacesContext, Object)} by writing the
* "javax.faces.ViewState" and optionally the "javax.faces.RenderKitId" hidden input fields to the response.
* </p>
*/
@Override
public void writeState(FacesContext facesContext, Object state) throws IOException {
if (!JsfUtils.isFlowRequest()) {
delegate.writeState(facesContext, state);
super.writeState(facesContext, state);
} else {
FlowSerializedView view = null;
if (state instanceof FlowSerializedView) {
view = (FlowSerializedView) state;
} else {
Object[] serializedState = (Object[]) state;
view = new FlowSerializedView(facesContext.getViewRoot().getViewId(), serializedState[0],
serializedState[1]);
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
requestContext.getViewScope().put(FlowViewStateManager.SERIALIZED_VIEW_STATE, view);
saveState(state);
ResponseWriter writer = facesContext.getResponseWriter();
writeViewStateField(facesContext, writer);
writeRenderKitIdField(facesContext, writer);
}
}
/**
* <p>
* Retrieves the state from view scope as an instance of {@link FlowSerializedView} and turns it to an array before
* returning.
* </p>
*/
@Override
public Object getState(FacesContext facesContext, String viewId) {
if (!JsfUtils.isFlowRequest()) {
return delegate.getState(facesContext, viewId);
return super.getState(facesContext, viewId);
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
FlowSerializedView view = (FlowSerializedView) requestContext.getViewScope().get(
FlowViewStateManager.SERIALIZED_VIEW_STATE);
Object[] state = null;
if (view == null) {
Object state = requestContext.getViewScope().get(FACES_VIEW_STATE);
if (state == null) {
logger.debug("No matching view in view scope");
} else {
state = new Object[] { view.getTreeStructure(), view.getComponentState() };
}
return state;
}
@@ -123,35 +94,17 @@ public class FlowViewResponseStateManager extends ResponseStateManager {
@Override
public String getViewState(FacesContext facesContext, Object state) {
if (!JsfUtils.isFlowRequest()) {
return delegate.getViewState(facesContext, state);
return super.getViewState(facesContext, state);
}
saveState(state);
return getFlowExecutionKey();
}
// ------------------- Delegation methods ------------------//
@Override
public boolean isPostback(FacesContext context) {
return delegate.isPostback(context);
private void saveState(Object state) {
RequestContext requestContext = RequestContextHolder.getRequestContext();
requestContext.getViewScope().put(FACES_VIEW_STATE, state);
}
@Override
public Object getTreeStructureToRestore(FacesContext context, String viewId) {
return delegate.getTreeStructureToRestore(context, viewId);
}
@Override
public Object getComponentStateToRestore(FacesContext context) {
return delegate.getComponentStateToRestore(context);
}
@Override
public void writeState(FacesContext context, SerializedView state) throws IOException {
delegate.writeState(context, state);
}
// ------------------- Private helper methods ------------------//
private String getFlowExecutionKey() {
RequestContext requestContext = RequestContextHolder.getRequestContext();
return requestContext.getFlowExecutionContext().getKey().toString();
@@ -165,9 +118,9 @@ public class FlowViewResponseStateManager extends ResponseStateManager {
* @throws IOException if an error occurs writing to the client
*/
private void writeViewStateField(FacesContext context, Writer writer) throws IOException {
writer.write(stateFieldStart);
writer.write(STATE_FIELD_START);
writer.write(getFlowExecutionKey());
writer.write(stateFieldEnd);
writer.write(STATE_FIELD_END);
}
/**
@@ -188,5 +141,4 @@ public class FlowViewResponseStateManager extends ResponseStateManager {
writer.endElement("input");
}
}
}

View File

@@ -1,51 +0,0 @@
package org.springframework.faces.webflow;
import java.io.Serializable;
import org.springframework.core.style.ToStringCreator;
/**
* Serialized UIViewRoot stored in view scope associated with a Web Flow View State.
*
* @author Jeremy Grelle
*/
public class FlowSerializedView implements Serializable {
private Object treeStructure;
private Object componentState;
private String viewId;
/**
* Creates a new serialized view
* @param viewId the view id
* @param treeStructure the tree structure of the view
* @param componentState the component state
*/
public FlowSerializedView(String viewId, Object treeStructure, Object componentState) {
this.viewId = viewId;
this.treeStructure = treeStructure;
this.componentState = componentState;
}
public String getViewId() {
return this.viewId;
}
public Object getTreeStructure() {
return this.treeStructure;
}
public Object getComponentState() {
return this.componentState;
}
public Object[] asTreeStructAndCompStateArray() {
return new Object[] { this.treeStructure, this.componentState };
}
public String toString() {
return new ToStringCreator(this).append("viewId", viewId).toString();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.faces.application.StateManager;
import javax.faces.application.StateManagerWrapper;
import javax.faces.context.FacesContext;
/**
* Custom {@link StateManager} that manages ensures web flow's state is always stored server side.
*
* @author Jeremy Grelle
* @author Rossen Stoyanchev
* @author Phillip Webb
*
* @since 2.4
*/
public class FlowStateManager extends StateManagerWrapper {
private final StateManager wrapped;
public FlowStateManager(StateManager wrapped) {
this.wrapped = wrapped;
}
public StateManager getWrapped() {
return this.wrapped;
}
public boolean isSavingStateInClient(FacesContext context) {
if (!JsfUtils.isFlowRequest()) {
return super.isSavingStateInClient(context);
} else {
return false;
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.el.CompositeELResolver;
import javax.faces.el.VariableResolver;
import org.springframework.faces.expression.ELDelegatingVariableResolver;
import org.springframework.webflow.expression.el.FlowResourceELResolver;
import org.springframework.webflow.expression.el.ImplicitFlowVariableELResolver;
import org.springframework.webflow.expression.el.RequestContextELResolver;
import org.springframework.webflow.expression.el.ScopeSearchingELResolver;
/**
* Custom variabe resolver for resolving properties on web flow specific variables with JSF 1.1 or > by delegating to
* web flow's EL resolvers.
*
* @author Jeremy Grelle
*/
public class FlowVariableResolver extends ELDelegatingVariableResolver {
private static final CompositeELResolver composite = new CompositeELResolver();
static {
composite.add(new RequestContextELResolver());
composite.add(new ImplicitFlowVariableELResolver());
composite.add(new FlowResourceELResolver());
composite.add(new ScopeSearchingELResolver());
}
public FlowVariableResolver(VariableResolver nextResolver) {
super(nextResolver, composite);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,11 +15,10 @@
*/
package org.springframework.faces.webflow;
import java.io.IOException;
import java.util.Locale;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.application.ViewHandlerWrapper;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
@@ -32,31 +31,31 @@ import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.execution.View;
/**
* Simple delegating {@link ViewHandler} implementation that provides JSF Form's with the correct FlowExecution URL,
* including the current FlowExecutionKey, so that postbacks may be properly intercepted and handled by Web Flow.
* Simple {@link ViewHandler} implementation that provides JSF Form's with the correct FlowExecution URL, including the
* current FlowExecutionKey, so that postbacks may be properly intercepted and handled by Web Flow.
*
* @author Jeremy Grelle
*
* @see Jsf2FlowViewHandler
* @author Rossen Stoyanchev
* @author Phillip Webb
*/
public class FlowViewHandler extends ViewHandler {
public class FlowViewHandler extends ViewHandlerWrapper {
private ViewHandler delegate;
private final ViewHandler wrapped;
public FlowViewHandler(ViewHandler delegate) {
Assert.notNull(delegate, "The delegate ViewHandler instance must not be null!");
this.delegate = delegate;
public FlowViewHandler(ViewHandler wrapped) {
Assert.notNull(wrapped, "The wrapped ViewHandler instance must not be null!");
this.wrapped = wrapped;
}
protected ViewHandler getDelegate() {
return delegate;
public ViewHandler getWrapped() {
return this.wrapped;
}
public String getActionURL(FacesContext context, String viewId) {
if (JsfUtils.isFlowRequest()) {
return RequestContextHolder.getRequestContext().getFlowExecutionUrl();
} else {
return delegate.getActionURL(context, viewId);
return super.getActionURL(context, viewId);
}
}
@@ -64,7 +63,7 @@ public class FlowViewHandler extends ViewHandler {
if (JsfUtils.isFlowRequest()) {
return RequestContextHolder.getRequestContext().getExternalContext().getLocale();
} else {
return delegate.calculateLocale(context);
return super.calculateLocale(context);
}
}
@@ -73,7 +72,7 @@ public class FlowViewHandler extends ViewHandler {
if (JsfUtils.isFlowRequest()) {
resourcePath = resolveResourcePath(RequestContextHolder.getRequestContext(), viewId);
}
return delegate.createView(context, resourcePath);
return super.createView(context, resourcePath);
}
public UIViewRoot restoreView(FacesContext context, String viewId) {
@@ -82,37 +81,17 @@ public class FlowViewHandler extends ViewHandler {
resourcePath = resolveResourcePath(RequestContextHolder.getRequestContext(), viewId);
return restoreFlowView(context, resourcePath);
}
return delegate.restoreView(context, resourcePath);
}
// ------------------- Pass-through delegate methods ------------------//
public String calculateRenderKitId(FacesContext context) {
return delegate.calculateRenderKitId(context);
}
public String getResourceURL(FacesContext context, String path) {
return delegate.getResourceURL(context, path);
}
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
delegate.renderView(context, viewToRender);
}
public void writeState(FacesContext context) throws IOException {
delegate.writeState(context);
return super.restoreView(context, resourcePath);
}
public String deriveViewId(FacesContext context, String rawViewId) {
if (JsfUtils.isFlowRequest()) {
return resolveResourcePath(RequestContextHolder.getRequestContext(), rawViewId);
} else {
return getDelegate().deriveViewId(context, rawViewId);
return super.deriveViewId(context, rawViewId);
}
}
// --------------------- Private Helpers ------------------------------//
private String resolveResourcePath(RequestContext context, String viewId) {
if (viewId.startsWith("/")) {
return viewId;
@@ -141,8 +120,7 @@ public class FlowViewHandler extends ViewHandler {
if (holder != null && holder.getViewRoot() != null && holder.getViewRoot().getViewId().equals(resourcePath)) {
return holder.getViewRoot();
} else {
return delegate.restoreView(facesContext, resourcePath);
return super.restoreView(facesContext, resourcePath);
}
}
}

View File

@@ -1,231 +0,0 @@
/*
* Copyright 2004-2011 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.IOException;
import javax.faces.application.StateManager;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* Custom {@link StateManager} that manages the JSF component state in web flow's view scope.
*
* @author Jeremy Grelle
* @author Rossen Stoyanchev
*/
public class FlowViewStateManager extends StateManager {
private static final Log logger = LogFactory.getLog(FlowViewStateManager.class);
protected static final String SERIALIZED_VIEW_STATE = "flowSerializedViewState";
private StateManager delegate;
public FlowViewStateManager(StateManager delegate) {
this.delegate = delegate;
}
protected Object getComponentStateToSave(FacesContext context) {
if (!JsfUtils.isFlowRequest()) {
return super.getComponentStateToSave(context);
}
UIViewRoot viewRoot = context.getViewRoot();
if (viewRoot.isTransient()) {
return null;
} else {
return viewRoot.processSaveState(context);
}
}
protected Object getTreeStructureToSave(FacesContext context) {
if (!JsfUtils.isFlowRequest()) {
return super.getTreeStructureToSave(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) {
if (!JsfUtils.isFlowRequest()) {
super.restoreComponentState(context, viewRoot, renderKitId);
return;
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
FlowSerializedView view = (FlowSerializedView) requestContext.getViewScope().get(SERIALIZED_VIEW_STATE);
viewRoot.processRestoreState(context, view.getComponentState());
logger.debug("UIViewRoot component state restored");
}
protected UIViewRoot restoreTreeStructure(FacesContext context, String viewId, String renderKitId) {
if (!JsfUtils.isFlowRequest()) {
return super.restoreTreeStructure(context, viewId, renderKitId);
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
FlowSerializedView view = (FlowSerializedView) requestContext.getViewScope().get(SERIALIZED_VIEW_STATE);
if (view == null || !view.getViewId().equals(viewId)) {
logger.debug("No matching view in view scope");
return null;
}
if (logger.isDebugEnabled()) {
logger.debug("Restoring view root with id '" + viewId + "' from view scope");
}
if (view.getTreeStructure() == null) {
logger.debug("Tree structure is null indicating transient UIViewRoot; returning null");
return null;
}
UIViewRoot viewRoot = new TreeStructureManager().restoreTreeStructure(view.getTreeStructure());
logger.debug("UIViewRoot structure restored");
return viewRoot;
}
public void writeState(FacesContext context, javax.faces.application.StateManager.SerializedView state)
throws IOException {
// Ensures that javax.faces.ViewState hidden field always gets written - needed for third-party component
// compatibility
delegate.writeState(context, state);
}
public void writeState(FacesContext context, Object state) throws IOException {
if (state instanceof Object[]) {
delegate.writeState(context, state); // MyFaces
} else if (state instanceof FlowSerializedView) { // Mojarra
FlowSerializedView view = (FlowSerializedView) state;
delegate.writeState(context, view.asTreeStructAndCompStateArray());
} else {
super.writeState(context, state);
}
}
public boolean isSavingStateInClient(FacesContext context) {
if (!JsfUtils.isFlowRequest()) {
return delegate.isSavingStateInClient(context);
} else {
return false;
}
}
/**
* JSF 1.1 version of state saving
*/
public javax.faces.application.StateManager.SerializedView saveSerializedView(FacesContext context) {
if (context.getViewRoot().isTransient()) {
return null;
}
if (!JsfUtils.isFlowRequest()) {
return delegate.saveSerializedView(context);
}
Object state = saveView(context);
if (state instanceof FlowSerializedView) {
FlowSerializedView serializedState = (FlowSerializedView) state;
return new javax.faces.application.StateManager.SerializedView(serializedState.getTreeStructure(),
serializedState.getComponentState());
} else {
Object[] serializedState = (Object[]) state;
return new javax.faces.application.StateManager.SerializedView(serializedState[0], serializedState[1]);
}
}
/**
* <p>
* JSF 1.2 (or higher) version of state saving.
*
* <p>
* In JSF 2, if partial state saving is enabled this method delegates in order to obtain the serialized view state.
* During rendering JSF calls this method to prepare the state and then calls {@link FlowViewResponseStateManager}
* which writes it to Web Flow's view scope.
*
* <p>
* Nevertheless this method always writes the serialized state to Web Flow's view scope to ensure it is up-to-date
* for cases outside of rendering (e.g. ViewState.updateHistory()) or when the render phase doesn't call
* {@link FlowViewResponseStateManager} such as when processing a partial request.
*/
public Object saveView(FacesContext context) {
if (context.getViewRoot().isTransient()) {
return null;
}
if (!JsfUtils.isFlowRequest()) {
return delegate.saveView(context);
}
FlowSerializedView view = null;
if (JsfRuntimeInformation.isPartialStateSavingSupported()) {
Object[] state = (Object[]) delegate.saveView(context);
view = new FlowSerializedView(context.getViewRoot().getViewId(), state[0], state[1]);
} else {
view = new FlowSerializedView(context.getViewRoot().getViewId(), getTreeStructureToSave(context),
getComponentStateToSave(context));
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (logger.isDebugEnabled()) {
logger.debug("Saving view root '" + context.getViewRoot().getViewId() + "' in view scope");
}
requestContext.getViewScope().put(SERIALIZED_VIEW_STATE, view);
return view;
}
/**
* <p>
* In JSF 2 where a partial state saving algorithm is used, this method merely delegates to the next
* ViewStateManager. Thus partial state saving is handled by the JSF 2 runtime. However, a
* {@link FlowViewResponseStateManager} plugged in via {@link FlowRenderKit} will ensure the state is saved in a Web
* Flow view-scoped variable.
* </p>
*/
public UIViewRoot restoreView(FacesContext context, String viewId, String renderKitId) {
if ((!JsfUtils.isFlowRequest()) || JsfRuntimeInformation.isPartialStateSavingSupported()) {
return delegate.restoreView(context, viewId, renderKitId);
} else {
UIViewRoot viewRoot = restoreTreeStructure(context, viewId, renderKitId);
if (viewRoot != null) {
context.setViewRoot(viewRoot);
restoreComponentState(context, viewRoot, renderKitId);
}
return viewRoot;
}
}
@Override
public String getViewState(FacesContext context) {
if (!JsfUtils.isFlowRequest()) {
return delegate.getViewState(context);
}
/*
* Mojarra 2: PartialRequestContextImpl.renderState() invokes this method during Ajax request rendering. We
* overridde it to convert FlowSerializedView state to an array before calling the
* ResponseStateManager.getViewState(), which in turn calls the ServerSideStateHelper and expects state to be an
* array.
*/
Object state = saveView(context);
if (state != null) {
if (state instanceof FlowSerializedView) {
FlowSerializedView view = (FlowSerializedView) state;
state = view.asTreeStructAndCompStateArray();
}
return context.getRenderKit().getResponseStateManager().getViewState(context, state);
}
return null;
}
}

View File

@@ -1,136 +0,0 @@
/*
* Copyright 2004-2010 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.util.Iterator;
import java.util.Map;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.ProjectStage;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.Behavior;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
/**
* Extends FlowApplication in order to provide JSF 2 delegation method. This is necessary because some of the methods
* use JSF 2 specific types as input or output parameters.
*
* @author Rossen Stoyanchev
*/
public class Jsf2FlowApplication extends FlowApplication {
public Jsf2FlowApplication(Application delegate) {
super(delegate);
}
// ------------------- JSF 2 pass-through delegate methods ------------------//
public void addBehavior(String behaviorId, String behaviorClass) {
getDelegate().addBehavior(behaviorId, behaviorClass);
}
public void addDefaultValidatorId(String validatorId) {
getDelegate().addDefaultValidatorId(validatorId);
}
public Behavior createBehavior(String behaviorId) throws FacesException {
return getDelegate().createBehavior(behaviorId);
}
public UIComponent createComponent(FacesContext context, Resource componentResource) {
return getDelegate().createComponent(context, componentResource);
}
public UIComponent createComponent(FacesContext context, String componentType, String rendererType) {
return getDelegate().createComponent(context, componentType, rendererType);
}
public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType,
String rendererType) {
return getDelegate().createComponent(componentExpression, context, componentType, rendererType);
}
public Iterator<String> getBehaviorIds() {
return getDelegate().getBehaviorIds();
}
public Map<String, String> getDefaultValidatorInfo() {
return getDelegate().getDefaultValidatorInfo();
}
public ProjectStage getProjectStage() {
return getDelegate().getProjectStage();
}
public ResourceHandler getResourceHandler() {
return getDelegate().getResourceHandler();
}
public void publishEvent(FacesContext context, Class<? extends SystemEvent> systemEventClass,
Class<?> sourceBaseType, Object source) {
getDelegate().publishEvent(context, systemEventClass, sourceBaseType, source);
}
public void publishEvent(FacesContext context, Class<? extends SystemEvent> systemEventClass, Object source) {
getDelegate().publishEvent(context, systemEventClass, source);
}
public void setResourceHandler(ResourceHandler resourceHandler) {
getDelegate().setResourceHandler(resourceHandler);
}
public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
SystemEventListener listener) {
getDelegate().subscribeToEvent(systemEventClass, sourceClass, listener);
}
public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener) {
getDelegate().subscribeToEvent(systemEventClass, listener);
}
public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
SystemEventListener listener) {
getDelegate().unsubscribeFromEvent(systemEventClass, sourceClass, listener);
}
public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener) {
getDelegate().unsubscribeFromEvent(systemEventClass, listener);
}
// Ideally this method should be in JsfView
// We keep it here to avoid ClassNotFoundExceptions for JSF 1.2 apps
static void publishPostRestoreStateEvent() {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
try {
facesContext.getViewRoot().visitTree(VisitContext.createVisitContext(facesContext),
new PostRestoreStateEventVisitCallback());
} catch (AbortProcessingException e) {
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, facesContext.getCurrentPhaseId()));
}
}
}

View File

@@ -1,269 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.List;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.application.FacesMessage;
import javax.faces.application.ProjectStage;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.context.PartialViewContext;
import javax.faces.context.PartialViewContextFactory;
import javax.faces.event.PhaseId;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.webflow.execution.RequestContext;
/**
* Extends FlowFacesContext in order to provide JSF 2 delegation method.
*
* @author Rossen Stoyanchev
*/
public class Jsf2FlowFacesContext extends FlowFacesContext {
private ExternalContext externalContext;
private PartialViewContext partialViewContext;
public Jsf2FlowFacesContext(RequestContext context, FacesContext delegate) {
super(context, delegate);
this.externalContext = new Jsf2FlowExternalContext(getDelegate().getExternalContext());
PartialViewContextFactory factory = (PartialViewContextFactory) FactoryFinder
.getFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY);
PartialViewContext partialViewContextDelegate = factory.getPartialViewContext(this);
this.partialViewContext = new FlowPartialViewContext(partialViewContextDelegate);
}
public ExternalContext getExternalContext() {
return externalContext;
}
// --------------- JSF 2.0 Pass-through delegate methods ------------------//
public Map<Object, Object> getAttributes() {
return getDelegate().getAttributes();
}
public PartialViewContext getPartialViewContext() {
return partialViewContext;
}
/**
* Returns a List for all Messages in the current MessageContext that does translation to FacesMessages.
*/
public List<FacesMessage> getMessageList() {
return getMessageDelegate().getMessageList();
}
/**
* Returns a List for all Messages with the given clientId in the current MessageContext that does translation to
* FacesMessages.
*/
public List<FacesMessage> getMessageList(String clientId) {
return getMessageDelegate().getMessageList(clientId);
}
public boolean isPostback() {
return getDelegate().isPostback();
}
public PhaseId getCurrentPhaseId() {
return getDelegate().getCurrentPhaseId();
}
public void setCurrentPhaseId(PhaseId currentPhaseId) {
getDelegate().setCurrentPhaseId(currentPhaseId);
}
public ExceptionHandler getExceptionHandler() {
return getDelegate().getExceptionHandler();
}
public boolean isProcessingEvents() {
return getDelegate().isProcessingEvents();
}
public boolean isProjectStage(ProjectStage stage) {
return getDelegate().isProjectStage(stage);
}
public boolean isValidationFailed() {
if (getMessageDelegate().hasErrorMessages()) {
return true;
} else {
return getDelegate().isValidationFailed();
}
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
getDelegate().setExceptionHandler(exceptionHandler);
}
public void setProcessingEvents(boolean processingEvents) {
getDelegate().setProcessingEvents(processingEvents);
}
public void validationFailed() {
getDelegate().validationFailed();
}
// --------------- JSF 2.1 Pass-through delegate methods ------------------//
public boolean isReleased() {
return getDelegate().isReleased();
}
protected class Jsf2FlowExternalContext extends FlowExternalContext {
Log logger = LogFactory.getLog(FlowExternalContext.class);
public Jsf2FlowExternalContext(ExternalContext delegate) {
super(delegate);
}
public void responseSendError(int statusCode, String message) throws IOException {
logger.debug("Sending error HTTP status code " + statusCode + " with message '" + message + "'");
delegate.responseSendError(statusCode, message);
}
// --------------- JSF 2.0 Pass-through delegate methods ------------------//
public String getContextName() {
return delegate.getContextName();
}
public void addResponseCookie(String name, String value, Map<String, Object> properties) {
delegate.addResponseCookie(name, value, properties);
}
public Flash getFlash() {
return delegate.getFlash();
}
public String getMimeType(String file) {
return delegate.getMimeType(file);
}
public String getRequestScheme() {
return delegate.getRequestScheme();
}
public String getRequestServerName() {
return delegate.getRequestServerName();
}
public int getRequestServerPort() {
return delegate.getRequestServerPort();
}
public String getRealPath(String path) {
return delegate.getRealPath(path);
}
public int getRequestContentLength() {
return delegate.getRequestContentLength();
}
public OutputStream getResponseOutputStream() throws IOException {
return delegate.getResponseOutputStream();
}
public Writer getResponseOutputWriter() throws IOException {
return delegate.getResponseOutputWriter();
}
public void setResponseContentType(String contentType) {
delegate.setResponseContentType(contentType);
}
public void invalidateSession() {
delegate.invalidateSession();
}
public void setResponseHeader(String name, String value) {
delegate.setResponseHeader(name, value);
}
public void addResponseHeader(String name, String value) {
delegate.addResponseHeader(name, value);
}
public void setResponseBufferSize(int size) {
delegate.setResponseBufferSize(size);
}
public int getResponseBufferSize() {
return delegate.getResponseBufferSize();
}
public boolean isResponseCommitted() {
return delegate.isResponseCommitted();
}
public void responseReset() {
delegate.responseReset();
}
public void setResponseStatus(int statusCode) {
delegate.setResponseStatus(statusCode);
}
public void responseFlushBuffer() throws IOException {
delegate.responseFlushBuffer();
}
public void setResponseContentLength(int length) {
delegate.setResponseContentLength(length);
}
public String encodeBookmarkableURL(String baseUrl, Map<String, List<String>> parameters) {
return delegate.encodeBookmarkableURL(baseUrl, parameters);
}
public String encodeRedirectURL(String baseUrl, Map<String, List<String>> parameters) {
return delegate.encodeRedirectURL(baseUrl, parameters);
}
public String encodePartialActionURL(String url) {
return delegate.encodePartialActionURL(url);
}
// --------------- JSF 2.1 Pass-through delegate methods ------------------//
public int getSessionMaxInactiveInterval() {
return delegate.getSessionMaxInactiveInterval();
}
public boolean isSecure() {
return delegate.isSecure();
}
public void setSessionMaxInactiveInterval(int interval) {
delegate.setSessionMaxInactiveInterval(interval);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,57 +15,18 @@
*/
package org.springframework.faces.webflow;
import java.io.IOException;
import java.net.URL;
import javax.faces.FacesException;
import javax.faces.view.facelets.ResourceResolver;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import com.sun.faces.facelets.impl.DefaultResourceResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Resolves Facelets templates using Spring Resource paths such as "classpath:foo.xhtml". Configure it via a context
* parameter in web.xml:
*
* <pre>
* &lt;context-param/&gt;
* &lt;param-name&gt;facelets.RESOURCE_RESOLVER&lt;/param-name&gt;
* &lt;param-value&gt;org.springframework.faces.webflow.FlowResourceResolver&lt;/param-value&gt;
* &lt;/context-param&gt;
* </pre>
* @deprecated Use FlowResourceResolver
*/
public class Jsf2FlowResourceResolver extends ResourceResolver {
@Deprecated
public class Jsf2FlowResourceResolver extends FlowResourceResolver {
ResourceResolver delegateResolver = new DefaultResourceResolver();
Log logger = LogFactory.getLog(FlowExternalContext.class);
public URL resolveUrl(String path) {
if (!JsfUtils.isFlowRequest()) {
return delegateResolver.resolveUrl(path);
}
try {
RequestContext context = RequestContextHolder.getRequestContext();
ApplicationContext flowContext = context.getActiveFlow().getApplicationContext();
if (flowContext == null) {
throw new IllegalStateException("A Flow ApplicationContext is required to resolve Flow View Resources");
}
ApplicationContext appContext = flowContext.getParent();
Resource viewResource = appContext.getResource(path);
if (viewResource.exists()) {
return viewResource.getURL();
} else {
return delegateResolver.resolveUrl(path);
}
} catch (IOException ex) {
throw new FacesException(ex);
}
public Jsf2FlowResourceResolver() {
this.logger.warn("Jsf2FlowResourceResolver has been deprecated, please update your faces-config.xml to use FlowResourceResolver");
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.util.List;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewDeclarationLanguage;
/**
* Extends FlowViewHandler in order to provide JSF 2 delegation method. This is necessary because some of the methods
* use JSF 2 specific types as input or output parameters.
*
* @author Rossen Stoyanchev
*/
public class Jsf2FlowViewHandler extends FlowViewHandler {
public Jsf2FlowViewHandler(ViewHandler delegate) {
super(delegate);
}
// --------------- JSF 2.0 Pass-through delegate methods ------------------//
public String calculateCharacterEncoding(FacesContext context) {
return getDelegate().calculateCharacterEncoding(context);
}
public String getBookmarkableURL(FacesContext context, String viewId, Map<String, List<String>> parameters,
boolean includeViewParams) {
return getDelegate().getBookmarkableURL(context, viewId, parameters, includeViewParams);
}
public String getRedirectURL(FacesContext context, String viewId, Map<String, List<String>> parameters,
boolean includeViewParams) {
return getDelegate().getRedirectURL(context, viewId, parameters, includeViewParams);
}
public ViewDeclarationLanguage getViewDeclarationLanguage(FacesContext context, String viewId) {
return getDelegate().getViewDeclarationLanguage(context, viewId);
}
public void initView(FacesContext context) throws FacesException {
getDelegate().initView(context);
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.faces.webflow;
import java.io.IOException;
import java.io.Writer;
import javax.faces.FactoryFinder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialResponseWriter;
@@ -89,7 +88,7 @@ public class JsfAjaxHandler extends AbstractAjaxHandler {
ResponseWriter responseWriter = null;
Writer out = externalContext.getResponseOutputWriter();
if (out != null) {
RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKitFactory factory = JsfUtils.findFactory(RenderKitFactory.class);
RenderKit renderKit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);
responseWriter = renderKit.createResponseWriter(out, "text/xml", encoding);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@ import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
/**
* An extension of {@link FlowHandlerAdapter} that replaces the default {@link AjaxHandler} instance with a
* {@link JsfAjaxHandler} assuming JSF 2 is the runtime environment.
* {@link JsfAjaxHandler}.
*
* @author Rossen Stoyanchev
* @since 2.2.0
@@ -35,11 +35,9 @@ public class JsfFlowHandlerAdapter extends FlowHandlerAdapter {
boolean initializeAjaxHandler = getAjaxHandler() == null;
super.afterPropertiesSet();
if (initializeAjaxHandler) {
if (JsfRuntimeInformation.isAtLeastJsf20()) {
JsfAjaxHandler ajaxHandler = new JsfAjaxHandler();
ajaxHandler.setApplicationContext(getApplicationContext());
setAjaxHandler(ajaxHandler);
}
JsfAjaxHandler ajaxHandler = new JsfAjaxHandler();
ajaxHandler.setApplicationContext(getApplicationContext());
setAjaxHandler(ajaxHandler);
}
}
@@ -47,5 +45,4 @@ public class JsfFlowHandlerAdapter extends FlowHandlerAdapter {
throws Exception {
return super.handle(request, response, handler);
}
}

View File

@@ -66,14 +66,14 @@ public class JsfManagedBeanAwareELExpressionParser extends ELExpressionParser {
private static class WebFlowELContext extends ELContext {
private ELResolver resolver;
private final ELResolver resolver;
public WebFlowELContext(ELResolver resolver) {
this.resolver = resolver;
}
public ELResolver getELResolver() {
return resolver;
return this.resolver;
}
public FunctionMapper getFunctionMapper() {

View File

@@ -20,8 +20,8 @@ import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import org.springframework.util.Assert;
import org.springframework.webflow.execution.RequestContext;
@@ -35,6 +35,7 @@ import org.springframework.webflow.execution.RequestContextHolder;
* initialization will be triggered if the bean has not already been initialized by JSF.
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class JsfManagedBeanResolver extends ELResolver {
@@ -118,14 +119,13 @@ public class JsfManagedBeanResolver extends ELResolver {
* @return The JSF Managed Bean instance if found.
*/
private Object getFacesBean(Object beanName) {
FacesContext facesContext = getFacesContext();
Object result = null;
FacesContext context = getFacesContext();
try {
ValueBinding vb = facesContext.getApplication().createValueBinding("#{" + beanName + "}");
result = vb.getValue(facesContext);
Application application = context.getApplication();
String expression = "#{" + beanName + "}";
return application.evaluateExpressionGet(context, expression, Object.class);
} finally {
facesContext.release();
context.release();
}
return result;
}
}

View File

@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow;
import javax.faces.context.FacesContext;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.webflow.execution.RequestContext;
@@ -24,6 +26,7 @@ import org.springframework.webflow.execution.RequestContext;
/**
* Helper class to provide information about the JSF runtime environment such as JSF version and implementation.
*
* @author Rossen Stoyanchev
* @author Phillip Webb
*/
public class JsfRuntimeInformation {
@@ -39,8 +42,7 @@ public class JsfRuntimeInformation {
private static final int jsfVersion;
private static final boolean myFacesPresent = ClassUtils.isPresent("org.apache.myfaces.webapp.MyFacesServlet",
JsfUtils.class.getClassLoader());
private static final boolean myFacesPresent = ClassUtils.isPresent("org.apache.myfaces.webapp.MyFacesServlet", JsfUtils.class.getClassLoader());
static {
if (ReflectionUtils.findMethod(FacesContext.class, "isPostback") != null) {
@@ -52,14 +54,26 @@ public class JsfRuntimeInformation {
}
}
/**
* @deprecated As of Web Flow 2.4.0 JSF 2.0 is a minimum requirement
*/
@Deprecated
public static boolean isAtLeastJsf20() {
return jsfVersion >= JSF_20;
}
/**
* @deprecated As of Web Flow 2.4.0 JSF 2.0 is a minimum requirement
*/
@Deprecated
public static boolean isAtLeastJsf12() {
return jsfVersion >= JSF_12;
}
/**
* @deprecated As of Web Flow 2.4.0 JSF 2.0 is a minimum requirement
*/
@Deprecated
public static boolean isLessThanJsf20() {
return jsfVersion < JSF_20;
}
@@ -68,20 +82,36 @@ public class JsfRuntimeInformation {
return myFacesPresent;
}
/**
* Determine if the specified {@link FacesContext} is from a portlet request.
*
* @param context the faces context
* @return <tt>true</tt> if the request is from a portlet
*/
public static boolean isPortletRequest(FacesContext context) {
return context.getExternalContext().getContext().getClass().getName().indexOf("Portlet") != -1;
}
public static boolean isPortletRequest(RequestContext context) {
return (null != ClassUtils.getMethodIfAvailable(context.getExternalContext().getNativeContext().getClass(),
"getPortletContextName"));
Assert.notNull(context, "Context must not be null");
return isPortletContext(context.getExternalContext().getContext());
}
/**
* Returns true if Web Flow supports partial state saving in the current runtime environment.
* Determine if the specified {@link RequestContext} is from a portlet request.
*
* @param context the request context
* @return <tt>true</tt> if the request is from a portlet
*/
public static boolean isPartialStateSavingSupported() {
return (JsfRuntimeInformation.isAtLeastJsf20() && (!JsfRuntimeInformation.isMyFacesPresent()));
public static boolean isPortletRequest(RequestContext context) {
Assert.notNull(context, "Context must not be null");
return isPortletContext(context.getExternalContext().getNativeContext());
}
/**
* Determine if the specified context object is from portlet.
*
* @param nativeContext the native context
* @return <tt>true</tt> if the context is from a portlet
*/
public static boolean isPortletContext(Object nativeContext) {
Assert.notNull(nativeContext, "Context must not be null");
return ClassUtils.getMethodIfAvailable(nativeContext.getClass(), "getPortletContextName") != null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,21 +15,35 @@
*/
package org.springframework.faces.webflow;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.application.ApplicationFactory;
import javax.faces.component.visit.VisitContextFactory;
import javax.faces.context.ExceptionHandlerFactory;
import javax.faces.context.ExternalContextFactory;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.context.PartialViewContextFactory;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.render.RenderKitFactory;
import javax.faces.view.ViewDeclarationLanguageFactory;
import javax.faces.view.facelets.FaceletCacheFactory;
import javax.faces.view.facelets.TagHandlerDelegateFactory;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.Assert;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* Common support for the JSF integration with Spring Web Flow.
*
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class JsfUtils {
@@ -69,18 +83,35 @@ public class JsfUtils {
}
}
// This method is here for JSF 1.2 backwards compatibility
static void publishPostRestoreStateEvent() {
try {
Class<?> clazz = Class.forName("org.springframework.faces.webflow.Jsf2FlowApplication");
Method method = ReflectionUtils.findMethod(clazz, "publishPostRestoreStateEvent");
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, null);
} catch (ClassNotFoundException ex) {
throw new IllegalStateException("Expected Jsf2FlowApplication: " + ex);
}
/**
* Find a factory of the specified class using JSFs {@link FactoryFinder} class.
* @param factoryClass the factory class to find
* @return the factory instance
*/
@SuppressWarnings("unchecked")
public static <T> T findFactory(Class<T> factoryClass) {
Assert.notNull(factoryClass, "FactoryClass must not be null");
String name = FACTORY_NAMES.get(factoryClass);
Assert.state(name != null, "Unknown factory class " + factoryClass.getName());
return (T) FactoryFinder.getFactory(name);
}
private static final Map<Class<?>, String> FACTORY_NAMES;
static {
FACTORY_NAMES = new HashMap<Class<?>, String>();
FACTORY_NAMES.put(ApplicationFactory.class, FactoryFinder.APPLICATION_FACTORY);
FACTORY_NAMES.put(ExceptionHandlerFactory.class, FactoryFinder.EXCEPTION_HANDLER_FACTORY);
FACTORY_NAMES.put(ExternalContextFactory.class, FactoryFinder.EXTERNAL_CONTEXT_FACTORY);
FACTORY_NAMES.put(FaceletCacheFactory.class, FactoryFinder.FACELET_CACHE_FACTORY);
FACTORY_NAMES.put(FacesContextFactory.class, FactoryFinder.FACES_CONTEXT_FACTORY);
FACTORY_NAMES.put(LifecycleFactory.class, FactoryFinder.LIFECYCLE_FACTORY);
FACTORY_NAMES.put(PartialViewContextFactory.class, FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY);
FACTORY_NAMES.put(RenderKitFactory.class, FactoryFinder.RENDER_KIT_FACTORY);
FACTORY_NAMES.put(TagHandlerDelegateFactory.class, FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY);
FACTORY_NAMES.put(ViewDeclarationLanguageFactory.class, FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY);
FACTORY_NAMES.put(VisitContextFactory.class, FactoryFinder.VISIT_CONTEXT_FACTORY);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2011 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf12;
import java.io.IOException;
import java.io.Serializable;
@@ -35,6 +33,7 @@ import org.springframework.webflow.execution.View;
* JSF-specific {@link View} implementation.
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class JsfView implements View {
@@ -44,13 +43,12 @@ public class JsfView implements View {
private UIViewRoot viewRoot;
private Lifecycle facesLifecycle;
private final Lifecycle facesLifecycle;
private RequestContext requestContext;
private final RequestContext requestContext;
private String viewId;
/**
* Creates a new JSF view.
* @param viewRoot the view root
@@ -84,16 +82,14 @@ public class JsfView implements View {
if (facesContext.getResponseComplete()) {
return;
}
facesContext.setViewRoot(viewRoot);
facesContext.setViewRoot(this.viewRoot);
try {
logger.debug("Asking faces lifecycle to render");
facesLifecycle.render(facesContext);
this.facesLifecycle.render(facesContext);
/* Ensure serialized view state is always updated even if JSF didn't call StateManager.writeState(). */
if (JsfRuntimeInformation.isAtLeastJsf20()) {
if (requestContext.getExternalContext().isAjaxRequest()) {
saveState();
}
// Ensure serialized view state is always updated even if JSF didn't call StateManager.writeState().
if (this.requestContext.getExternalContext().isAjaxRequest()) {
saveState();
}
} finally {
logger.debug("View rendering complete");
@@ -102,11 +98,7 @@ public class JsfView implements View {
}
public boolean userEventQueued() {
if (isAtLeastJsf12()) {
return requestContext.getRequestParameters().contains("javax.faces.ViewState");
} else {
return requestContext.getRequestParameters().size() > 1;
}
return this.requestContext.getRequestParameters().contains("javax.faces.ViewState");
}
/**
@@ -115,10 +107,10 @@ public class JsfView implements View {
*/
public void processUserEvent() {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
facesContext.setViewRoot(viewRoot);
facesContext.setViewRoot(this.viewRoot);
// Must respect these flags in case user set them during RESTORE_VIEW phase
if (!facesContext.getRenderResponse() && !facesContext.getResponseComplete()) {
facesLifecycle.execute(facesContext);
this.facesLifecycle.execute(facesContext);
}
}
@@ -128,34 +120,33 @@ public class JsfView implements View {
*/
public void saveState() {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
if (viewRoot instanceof AjaxViewRoot) {
facesContext.setViewRoot(((AjaxViewRoot) viewRoot).getOriginalViewRoot());
if (this.viewRoot instanceof AjaxViewRoot) {
facesContext.setViewRoot(((AjaxViewRoot) this.viewRoot).getOriginalViewRoot());
} else {
facesContext.setViewRoot(viewRoot);
facesContext.setViewRoot(this.viewRoot);
}
facesContext.getApplication().getStateManager().saveSerializedView(facesContext);
facesContext.getApplication().getStateManager().saveView(facesContext);
}
public Serializable getUserEventState() {
// Set the temporary UIViewRoot state so that it will be available across the redirect
// Set the temporary UIViewRoot state so that it will be available across the redirect (see comments in render()
// method)
return new ViewRootHolder(getViewRoot());
}
public boolean hasFlowEvent() {
return requestContext.getExternalContext().getRequestMap().contains(EVENT_KEY);
return this.requestContext.getExternalContext().getRequestMap().contains(EVENT_KEY);
}
public Event getFlowEvent() {
return new Event(this, getEventId());
}
public String toString() {
return "[JSFView = '" + viewId + "']";
}
// internal helpers
private String getEventId() {
return (String) requestContext.getExternalContext().getRequestMap().get(EVENT_KEY);
return (String) this.requestContext.getExternalContext().getRequestMap().get(EVENT_KEY);
}
}
public String toString() {
return "[JSFView = '" + this.viewId + "']";
}
}

View File

@@ -15,18 +15,20 @@
*/
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf12;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf20;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isPortletRequest;
import java.util.Iterator;
import javax.el.ValueExpression;
import javax.faces.application.ViewHandler;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseId;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
@@ -38,6 +40,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.binding.expression.Expression;
import org.springframework.faces.ui.AjaxViewRoot;
import org.springframework.js.ajax.SpringJavascriptAjaxHandler;
import org.springframework.util.Assert;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.View;
@@ -47,9 +50,9 @@ import org.springframework.webflow.execution.ViewFactory;
* JSF-specific {@link ViewFactory} implementation.
* <p>
* This factory is responsible for performing the duties of the RESTORE_VIEW phase of the JSF lifecycle.
* </p>
*
* @author Jeremy Grelle
* @author Phillip Webb
*/
public class JsfViewFactory implements ViewFactory {
@@ -72,78 +75,90 @@ public class JsfViewFactory implements ViewFactory {
*/
public View getView(RequestContext context) {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
if (facesContext == null) {
throw new IllegalStateException(
"FacesContext has not been initialized within the current Web Flow request."
+ " Check the configuration for your <webflow:flow-executor>."
+ " For JSF you will need FlowFacesContextLifecycleListener configured as one of its flow execution listeners.");
Assert.state(
facesContext != null,
"FacesContext has not been initialized within the current Web Flow request."
+ " Check the configuration for your <webflow:flow-executor>."
+ " For JSF you will need FlowFacesContextLifecycleListener configured as one of its flow execution listeners.");
facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
// only publish a RESTORE_VIEW event if this is the first phase of the lifecycle
// this won't be true when this method is called after a transition from one view-state to another
boolean notifyPhaseListeners = !facesContext.getRenderResponse();
if (notifyPhaseListeners) {
JsfUtils.notifyBeforeListeners(PhaseId.RESTORE_VIEW, this.lifecycle, facesContext);
}
if (isAtLeastJsf20()) {
facesContext.setCurrentPhaseId(PhaseId.RESTORE_VIEW);
UIViewRoot viewRoot = getViewRoot(context, facesContext);
facesContext.setViewRoot(viewRoot);
publishPostRestoreStateEvent(facesContext);
if (notifyPhaseListeners) {
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, this.lifecycle, facesContext);
}
if (!facesContext.getRenderResponse()) {
// only publish a RESTORE_VIEW event if this is the first phase of the lifecycle
// this won't be true when this method is called after a transition from one view-state to another
JsfUtils.notifyBeforeListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext);
return createJsfView(viewRoot, this.lifecycle, context);
}
private UIViewRoot getViewRoot(RequestContext context, FacesContext facesContext) {
ViewHandler viewHandler = getViewHandler(facesContext);
String viewName = (String) this.viewIdExpression.getValue(context);
if (viewAlreadySet(facesContext, viewName)) {
return getViewRootForAlreadySetView(context, facesContext);
}
if (context.inViewState()) {
return getViewStateViewRoot(context, facesContext, viewHandler, viewName);
}
return getTransientViewRoot(context, facesContext, viewHandler, viewName);
}
private ViewHandler getViewHandler(FacesContext facesContext) {
ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
if (isAtLeastJsf12() && (!isPortletRequest(facesContext))) {
if (!isPortletRequest(facesContext)) {
viewHandler.initView(facesContext);
}
JsfView view;
String viewName = (String) viewIdExpression.getValue(context);
if (viewAlreadySet(facesContext, viewName)) {
if (logger.isDebugEnabled()) {
logger.debug("Existing view root found with id '" + facesContext.getViewRoot().getId() + "'");
}
UIViewRoot viewRoot = facesContext.getViewRoot();
viewRoot.setLocale(context.getExternalContext().getLocale());
processTree(facesContext, viewRoot);
view = createJsfView(facesContext.getViewRoot(), lifecycle, context);
} else {
if (context.inViewState()) {
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName);
if (viewRoot != null) {
if (logger.isDebugEnabled()) {
logger.debug("UIViewRoot restored for '" + viewName + "'");
}
facesContext.setViewRoot(viewRoot);
processTree(facesContext, viewRoot);
view = createJsfView(viewRoot, lifecycle, context);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Creating UIViewRoot from '" + viewName + "'");
}
viewRoot = viewHandler.createView(facesContext, viewName);
facesContext.setViewRoot(viewRoot);
view = createJsfView(viewRoot, lifecycle, context);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Creating transient UIViewRoot from '" + viewName + "'");
}
UIViewRoot viewRoot = viewHandler.createView(facesContext, viewName);
viewRoot.setTransient(true);
facesContext.setViewRoot(viewRoot);
view = createJsfView(viewRoot, lifecycle, context);
}
}
if (isAtLeastJsf20()) {
JsfUtils.publishPostRestoreStateEvent();
}
if (!facesContext.getRenderResponse()) {
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext);
}
return view;
return viewHandler;
}
private boolean viewAlreadySet(FacesContext facesContext, String viewName) {
if (facesContext.getViewRoot() != null && facesContext.getViewRoot().getViewId().equals(viewName)) {
// the corner case where a before RESTORE_VIEW PhaseListener has handled setting the UIViewRoot
return true;
} else {
return false;
// the corner case where a before RESTORE_VIEW PhaseListener has handled setting the UIViewRoot
return (facesContext.getViewRoot() != null && facesContext.getViewRoot().getViewId().equals(viewName));
}
private UIViewRoot getViewRootForAlreadySetView(RequestContext context, FacesContext facesContext) {
if (logger.isDebugEnabled()) {
logger.debug("Existing view root found with id '" + facesContext.getViewRoot().getId() + "'");
}
UIViewRoot viewRoot = facesContext.getViewRoot();
viewRoot.setLocale(context.getExternalContext().getLocale());
processTree(facesContext, viewRoot);
return viewRoot;
}
private UIViewRoot getViewStateViewRoot(RequestContext context, FacesContext facesContext, ViewHandler viewHandler,
String viewName) {
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName);
if (viewRoot != null) {
if (logger.isDebugEnabled()) {
logger.debug("UIViewRoot restored for '" + viewName + "'");
}
processTree(facesContext, viewRoot);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Creating UIViewRoot from '" + viewName + "'");
}
viewRoot = viewHandler.createView(facesContext, viewName);
}
return viewRoot;
}
private UIViewRoot getTransientViewRoot(RequestContext context, FacesContext facesContext, ViewHandler viewHandler,
String viewName) {
if (logger.isDebugEnabled()) {
logger.debug("Creating transient UIViewRoot from '" + viewName + "'");
}
UIViewRoot viewRoot = viewHandler.createView(facesContext, viewName);
viewRoot.setTransient(true);
return viewRoot;
}
private JsfView createJsfView(UIViewRoot root, Lifecycle lifecycle, RequestContext context) {
@@ -175,14 +190,23 @@ public class JsfViewFactory implements ViewFactory {
if (!context.getRenderResponse() && component instanceof EditableValueHolder) {
((EditableValueHolder) component).setValid(true);
}
ValueBinding binding = component.getValueBinding("binding");
ValueExpression binding = component.getValueExpression("binding");
if (binding != null) {
binding.setValue(context, component);
binding.setValue(context.getELContext(), component);
}
Iterator<UIComponent> it = component.getFacetsAndChildren();
while (it.hasNext()) {
UIComponent child = it.next();
processTree(context, child);
processTree(context, it.next());
}
}
private void publishPostRestoreStateEvent(FacesContext facesContext) {
try {
facesContext.getViewRoot().visitTree(VisitContext.createVisitContext(facesContext),
new PostRestoreStateEventVisitCallback());
} catch (AbortProcessingException e) {
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, facesContext.getCurrentPhaseId()));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import org.springframework.webflow.execution.ViewFactory;
/**
* A {@link ViewFactoryCreator} implementation for creating instances of a JSF-specific {@link ViewFactory}.
*
*
* @author Jeremy Grelle
*/
public class JsfViewFactoryCreator implements ViewFactoryCreator {
@@ -46,10 +46,10 @@ public class JsfViewFactoryCreator implements ViewFactoryCreator {
}
private Lifecycle getLifecycle() {
if (lifecycle == null) {
lifecycle = FlowLifecycle.newInstance();
if (this.lifecycle == null) {
this.lifecycle = FlowLifecycle.newInstance();
}
return lifecycle;
return this.lifecycle;
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.IOException;
import javax.faces.FacesWrapper;
import javax.faces.application.StateManager.SerializedView;
import javax.faces.context.FacesContext;
import javax.faces.render.ResponseStateManager;
import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
import org.apache.myfaces.renderkit.StateCacheUtils;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* A wrapper for {@link FlowResponseStateManager} used to support MyFaces partial state saving. MyFaces supports an
* extension to the {@link ResponseStateManager} that reduces the amount of buffering required when writing a response.
* Empty state is provided at the time that the {@link #writeState(FacesContext, Object) writeState} method is invoked
* with an additional {@link #saveState(FacesContext, Object) saveState} method called later containing the real state
* to save.
* <p>
* Since JSF 2.0, the strategy used by MyFaces to determine if a {@link MyfacesResponseStateManager} is available will
* always succeed since it follows {@link FacesWrapper}s to find the root <tt>HtmlResponseStateManager</tt>
* implementation. Since state management for web flow requests is handled by the {@link FlowResponseStateManager} this
* assumption causes problems and results in empty state data being saved. This wrapper provides the additional hook
* required to ensure that the {@link #saveState(FacesContext, Object) saveState} method also triggers web flow state
* management.
*
* @see FlowResponseStateManager
* @see FlowRenderKit
*
* @author Phillip Webb
*
* @since 2.4
*/
@SuppressWarnings("deprecation")
public class MyFacesFlowResponseStateManager extends MyfacesResponseStateManager implements
FacesWrapper<ResponseStateManager> {
private final ResponseStateManager wrapped;
public MyFacesFlowResponseStateManager(FlowResponseStateManager wrapped) {
this.wrapped = wrapped;
}
public ResponseStateManager getWrapped() {
return this.wrapped;
}
private MyfacesResponseStateManager getWrappedMyfacesResponseStateManager() {
return StateCacheUtils.getMyFacesResponseStateManager(this.wrapped);
}
public boolean isWriteStateAfterRenderViewRequired(FacesContext facesContext) {
MyfacesResponseStateManager wrapped = getWrappedMyfacesResponseStateManager();
if (wrapped != null) {
return wrapped.isWriteStateAfterRenderViewRequired(facesContext);
}
return super.isWriteStateAfterRenderViewRequired(facesContext);
}
public void saveState(FacesContext facesContext, Object state) {
RequestContext requestContext = RequestContextHolder.getRequestContext();
requestContext.getViewScope().put(FlowResponseStateManager.FACES_VIEW_STATE, state);
}
public void writeStateAsUrlParams(FacesContext facesContext, SerializedView serializedview) {
MyfacesResponseStateManager wrapped = getWrappedMyfacesResponseStateManager();
if (wrapped != null) {
wrapped.writeStateAsUrlParams(facesContext, serializedview);
}
super.writeStateAsUrlParams(facesContext, serializedview);
}
public Object getComponentStateToRestore(FacesContext context) {
return getWrapped().getComponentStateToRestore(context);
}
public Object getState(FacesContext context, String viewId) {
return getWrapped().getState(context, viewId);
}
public Object getTreeStructureToRestore(FacesContext context, String viewId) {
return getWrapped().getTreeStructureToRestore(context, viewId);
}
public String getViewState(FacesContext context, Object state) {
return getWrapped().getViewState(context, state);
}
public boolean isPostback(FacesContext context) {
return getWrapped().isPostback(context);
}
public void writeState(FacesContext context, Object state) throws IOException {
getWrapped().writeState(context, state);
}
@Deprecated
public void writeState(FacesContext context, SerializedView state) throws IOException {
getWrapped().writeState(context, state);
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.faces.component.UIComponent;
@@ -22,7 +37,7 @@ class PostRestoreStateEventVisitCallback implements VisitCallback {
} else {
this.event.setComponent(target);
}
target.processEvent(event);
target.processEvent(this.event);
return VisitResult.ACCEPT;
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright 2004-2008 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import javax.faces.context.FacesContext;
import javax.faces.el.VariableResolver;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.web.jsf.SpringBeanVariableResolver;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* JSF 1.1 variable resolver for Spring Beans accessible to the flow's local bean factory.
*
* @author Jeremy Grelle
*/
public class SpringBeanWebFlowVariableResolver extends SpringBeanVariableResolver {
private static final BeanFactory EMPTY_BEAN_FACTORY = new StaticListableBeanFactory();
public SpringBeanWebFlowVariableResolver(VariableResolver originalVariableResolver) {
super(originalVariableResolver);
}
protected BeanFactory getBeanFactory(FacesContext facesContext) {
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (requestContext == null) {
return EMPTY_BEAN_FACTORY;
}
BeanFactory beanFactory = requestContext.getActiveFlow().getApplicationContext();
return beanFactory != null ? beanFactory : EMPTY_BEAN_FACTORY;
}
}

View File

@@ -1,172 +0,0 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.execution.RequestContextHolder;
/**
* Helper class for building and restoring the structure of the JSF component tree.
*
* Largely based on MyFaces implementation, with minor changes for Spring Web Flow's state saving strategy.
*
* @author Jeremy Grelle
* @author Manfred Geiler
*/
class TreeStructureManager {
public Serializable buildTreeStructureToSave(UIViewRoot viewRoot) {
return internalBuildTreeStructureToSave(viewRoot);
}
private TreeStructComponent internalBuildTreeStructureToSave(UIComponent component) {
TreeStructComponent structComp = new TreeStructComponent(component.getClass().getName(), component.getId());
// children
if (component.getChildCount() > 0) {
List<UIComponent> childList = component.getChildren();
List<TreeStructComponent> structChildList = new ArrayList<TreeStructComponent>();
for (int i = 0, len = childList.size(); i < len; i++) {
UIComponent child = childList.get(i);
if (!child.isTransient()) {
TreeStructComponent structChild = internalBuildTreeStructureToSave(child);
structChildList.add(structChild);
}
}
TreeStructComponent[] childArray = structChildList.toArray(new TreeStructComponent[structChildList.size()]);
structComp.setChildren(childArray);
}
// facets
Map<String, UIComponent> facetMap = component.getFacets();
if (!facetMap.isEmpty()) {
List<Object[]> structFacetList = new ArrayList<Object[]>();
for (Map.Entry<String, UIComponent> entry : facetMap.entrySet()) {
UIComponent child = entry.getValue();
if (!child.isTransient()) {
String facetName = entry.getKey();
TreeStructComponent structChild = internalBuildTreeStructureToSave(child);
structFacetList.add(new Object[] { facetName, structChild });
}
}
Object[] facetArray = structFacetList.toArray(new Object[structFacetList.size()]);
structComp.setFacets(facetArray);
}
return structComp;
}
public UIViewRoot restoreTreeStructure(Object treeStructRoot) {
if (treeStructRoot instanceof TreeStructComponent) {
return (UIViewRoot) internalRestoreTreeStructure((TreeStructComponent) treeStructRoot);
}
throw new IllegalArgumentException("TreeStructure of type " + treeStructRoot.getClass().getName()
+ " is not supported.");
}
private UIComponent internalRestoreTreeStructure(TreeStructComponent treeStructComp) {
String compClass = treeStructComp.getComponentClass();
String compId = treeStructComp.getComponentId();
UIComponent component;
try {
component = (UIComponent) BeanUtils.instantiateClass(ClassUtils.forName(compClass));
} catch (Exception ex) {
throw new FacesException("Could not restore the component tree structure.", ex);
}
component.setId(compId);
// children
TreeStructComponent[] childArray = treeStructComp.getChildren();
if (childArray != null) {
List<UIComponent> childList = component.getChildren();
for (TreeStructComponent element : childArray) {
UIComponent child = internalRestoreTreeStructure(element);
childList.add(child);
}
}
// facets
Object[] facetArray = treeStructComp.getFacets();
if (facetArray != null) {
Map<String, UIComponent> facetMap = component.getFacets();
for (Object element : facetArray) {
Object[] tuple = (Object[]) element;
String facetName = (String) tuple[0];
TreeStructComponent structChild = (TreeStructComponent) tuple[1];
UIComponent child = internalRestoreTreeStructure(structChild);
facetMap.put(facetName, child);
}
}
return component;
}
public static class TreeStructComponent implements Serializable {
private static final long serialVersionUID = 5069109074684737231L;
private String componentClass;
private String componentId;
private TreeStructComponent[] children = null; // Array of children
private Object[] facets = null; // Array of Array-tuples with Facetname and TreeStructComponent
TreeStructComponent(String componentClass, String componentId) {
this.componentClass = componentClass;
this.componentId = componentId;
}
public String getComponentClass() {
return componentClass;
}
public String getComponentId() {
return componentId;
}
void setChildren(TreeStructComponent[] children) {
this.children = children;
}
TreeStructComponent[] getChildren() {
return children;
}
Object[] getFacets() {
return facets;
}
void setFacets(Object[] facets) {
this.facets = facets;
}
public String toString() {
if (JsfUtils.isFlowRequest()) {
return RequestContextHolder.getRequestContext().getFlowExecutionContext().getKey().toString();
} else {
return super.toString();
}
}
}
}

View File

@@ -33,7 +33,7 @@ class ViewRootHolder implements Serializable {
}
public UIViewRoot getViewRoot() {
return viewRoot;
return this.viewRoot;
}
}

View File

@@ -13,139 +13,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.faces.webflow.application.portlet;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.portlet.RenderResponse;
import org.springframework.faces.webflow.JsfRuntimeInformation;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.sun.facelets.FaceletViewHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.faces.webflow.context.portlet.PortletViewHandler;
/**
* <p>
* This {@link ViewHandler} implementation is needed because portions of the native Facelets ViewHandler depend on the
* Servlet API and cannot be used directly in a Portlet environment.
* </p>
*
* <p>
* Note: the basis for this code was a Facelets sample provided with Apache MyFaces Portlet Bridge for JSF version
* 2.0.0.alpha-2.
* </p>
* {@link ViewHandler} implementation for Portlets. This class is provided for compatibility with Web Flow v2.2.0, users
* should replace references in their <tt>faces-confix.xml</tt> with
* {@link org.springframework.faces.webflow.context.portlet.PortletViewHandler}.
*
* @author Rossen Stoyanchev
* @author Phillip Webb
* @since 2.2.0
* @deprecated In favor of org.springframework.faces.webflow.context.portlet.PortletViewHandler
*/
public class PortletFaceletViewHandler extends FaceletViewHandler {
@Deprecated
public class PortletFaceletViewHandler extends PortletViewHandler {
private static final String FACELETS_CONTENT_TYPE_KEY = "facelets.ContentType";
private static final String FACELETS_ENCODING_KEY = "facelets.Encoding";
private Log logger = LogFactory.getLog(getClass());
public PortletFaceletViewHandler(ViewHandler parent) {
super(parent);
public PortletFaceletViewHandler(ViewHandler wrapped) {
super(wrapped);
this.logger.warn("*****");
this.logger.warn("***** PLEASE UPDATE YOUR faces-confix.xml");
this.logger.warn("*****");
this.logger.warn("***** org.springframework.faces.webflow.application.portlet.PortletFaceletViewHandler has been deprecated");
this.logger.warn("***** please update references to use org.springframework.faces.webflow.context.portlet.PortletViewHandler");
this.logger.warn("*****");
}
protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException {
if (!JsfRuntimeInformation.isPortletRequest(context)) {
return super.createResponseWriter(context);
}
// Create a temporary ResponseWriter to see what content type the ReponseWriter is going to ask for.
ResponseWriter writer = createNoopResponseWriter(context);
RenderResponse response = (RenderResponse) context.getExternalContext().getResponse();
String contentType = getResponseContentType(context, writer.getContentType());
String encoding = getResponseEncoding(context, writer.getCharacterEncoding());
// Set the content type and the encoding and clone writer with the real ResponseWriter
response.setContentType(contentType + "; charset=" + encoding);
return writer.cloneWithWriter(response.getWriter());
}
private ResponseWriter createNoopResponseWriter(FacesContext context) {
RenderKit renderKit = context.getRenderKit();
Assert.notNull(renderKit, context.getViewRoot().getRenderKitId());
// Append */* to the contentType so createResponseWriter will succeed no matter the requested contentType.
String contentType = (String) context.getExternalContext().getRequestMap().get(FACELETS_CONTENT_TYPE_KEY);
if (StringUtils.hasText(contentType) && (!contentType.equals("*/*"))) {
contentType += ",*/*";
}
ResponseWriter writer;
String encoding = (String) context.getExternalContext().getRequestMap().get(FACELETS_ENCODING_KEY);
try {
writer = renderKit.createResponseWriter(NoopWriter.INSTANCE, contentType, encoding);
} catch (IllegalArgumentException e) {
// See RI bug prior to 1.2_05-b3. Might as well leave it:
// https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
log.fine("The impl didn't correctly handle '*/*' in the content type list.. try '*/*' directly.");
writer = renderKit.createResponseWriter(NoopWriter.INSTANCE, "*/*", encoding);
}
return writer;
}
protected String getResponseEncoding(FacesContext context, String originalEncoding) {
String encoding = originalEncoding;
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
// 1. check the request attribute
if (requestMap.containsKey(FACELETS_ENCODING_KEY)) {
encoding = (String) requestMap.get(FACELETS_ENCODING_KEY);
sessionMap.put(CHARACTER_ENCODING_KEY, encoding);
}
// 2. get it from request
if (encoding == null) {
encoding = context.getExternalContext().getResponseCharacterEncoding();
}
// 3. get it from the session
if (encoding == null) {
encoding = (String) sessionMap.get(CHARACTER_ENCODING_KEY);
}
// 4. default it
if (encoding == null) {
encoding = "UTF-8";
}
return encoding;
}
protected static class NoopWriter extends Writer {
static final NoopWriter INSTANCE = new NoopWriter();
public void write(char[] buffer) {
}
public void write(char[] buffer, int off, int len) {
}
public void write(String str) {
}
public void write(int c) {
}
public void write(String str, int off, int len) {
}
public void close() {
}
public void flush() {
}
}
}

View File

@@ -38,7 +38,7 @@ public class InitParameterMap extends StringKeyedMapAdapter<String> {
@Override
protected String getAttribute(String key) {
return portletContext.getInitParameter(key);
return this.portletContext.getInitParameter(key);
}
@Override
@@ -53,7 +53,7 @@ public class InitParameterMap extends StringKeyedMapAdapter<String> {
@Override
protected Iterator<String> getAttributeNames() {
return CollectionUtils.toIterator(portletContext.getInitParameterNames());
return CollectionUtils.toIterator(this.portletContext.getInitParameterNames());
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow.context.portlet;
import java.io.IOException;
import java.util.Map;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.context.FacesContext;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.PortletRequest;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import org.springframework.core.Ordered;
import org.springframework.faces.webflow.FacesContextHelper;
import org.springframework.http.HttpStatus;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.portlet.HandlerAdapter;
import org.springframework.web.portlet.HandlerExecutionChain;
import org.springframework.web.portlet.HandlerMapping;
import org.springframework.web.portlet.ModelAndView;
import org.springframework.web.portlet.handler.PortletContentGenerator;
/**
* Handles a request by delegating to the JSF ResourceHandler, which serves web application and classpath resources such
* as images, CSS and JavaScript files from well-known locations.
*
* @since 2.4.0
* @author Phillip Webb
* @see ResourceHandler
*/
public class JsfResourceRequestHandler extends PortletContentGenerator implements HandlerAdapter, HandlerMapping, Ordered {
private static final String FACES_RESOURCE = "javax.faces.resource";
private static final String RESOURCE_EXCLUDES_DEFAULT = ".class .jsp .jspx .properties .xhtml .groovy";
private static final String RESOURCE_EXCLUDES_PARAM_NAME = "javax.faces.RESOURCE_EXCLUDES";
private int order = Ordered.HIGHEST_PRECEDENCE;
public HandlerExecutionChain getHandler(PortletRequest request) throws Exception {
if (request instanceof ResourceRequest && request.getParameter(FACES_RESOURCE) != null) {
return new HandlerExecutionChain(new JsfResourceRequest());
}
return null;
}
public boolean supports(Object handler) {
return handler instanceof JsfResourceRequest;
}
public ModelAndView handleResource(ResourceRequest request, ResourceResponse response, Object handler) throws IOException {
FacesContextHelper helper = new FacesContextHelper();
try {
FacesContext facesContext = helper.getFacesContext(getPortletContext(), request, response);
handleResourceRequest(facesContext, request, response);
} finally {
helper.releaseIfNecessary();
}
return null;
}
private void handleResourceRequest(FacesContext facesContext, ResourceRequest request, ResourceResponse response) throws IOException {
ResourceHandler resourceHandler = facesContext.getApplication().getResourceHandler();
String resourceName = request.getParameter(FACES_RESOURCE);
String libraryName = request.getParameter("ln");
int statusCodeNotFound = HttpStatus.NOT_FOUND.value();
if (isResourceExcluded(facesContext, resourceName)) {
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, String.valueOf(statusCodeNotFound));
PortletResponseUtils.setStatusCodeForPluto(response, statusCodeNotFound);
return;
}
Resource resource = createResource(resourceHandler, resourceName, libraryName);
if (resource == null) {
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, String.valueOf(statusCodeNotFound));
PortletResponseUtils.setStatusCodeForPluto(response, statusCodeNotFound);
return;
}
for (Map.Entry<String, String> entry : resource.getResponseHeaders().entrySet()) {
response.setProperty(entry.getKey(), entry.getValue());
}
response.setContentType(resource.getContentType());
FileCopyUtils.copy(resource.getInputStream(), response.getPortletOutputStream());
}
private boolean isResourceExcluded(FacesContext context, String resourceName) {
for (String resourceExclude : getResourceExcludes(context)) {
if (StringUtils.endsWithIgnoreCase(resourceName, resourceExclude)) {
return true;
}
}
return false;
}
private String[] getResourceExcludes(FacesContext context) {
String resourceExcludes = context.getExternalContext().getInitParameter(RESOURCE_EXCLUDES_PARAM_NAME);
if (resourceExcludes == null) {
resourceExcludes = RESOURCE_EXCLUDES_DEFAULT;
}
return StringUtils.tokenizeToStringArray(resourceExcludes, " ");
}
private Resource createResource(ResourceHandler resourceHandler, String resourceName, String libraryName) {
if (libraryName != null) {
return resourceHandler.createResource(resourceName, libraryName);
}
return resourceHandler.createResource(resourceName);
}
public void handleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception {
}
public ModelAndView handleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception {
return null;
}
public void handleEvent(EventRequest request, EventResponse response, Object handler) throws Exception {
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
private static class JsfResourceRequest {
}
}

View File

@@ -17,55 +17,67 @@ package org.springframework.faces.webflow.context.portlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Principal;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.Flash;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.ClientDataRequest;
import javax.portlet.MimeResponse;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceResponse;
import javax.servlet.http.Cookie;
import org.apache.myfaces.shared.context.flash.FlashImpl;
import org.springframework.binding.collection.MapAdaptable;
import org.springframework.faces.webflow.JsfRuntimeInformation;
import org.springframework.util.Assert;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.webflow.context.portlet.PortletContextMap;
import org.springframework.webflow.context.portlet.PortletRequestMap;
import org.springframework.webflow.context.portlet.PortletSessionMap;
import org.springframework.webflow.core.collection.CollectionUtils;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import com.sun.faces.context.flash.ELFlash;
/**
* An implementation of {@link ExternalContext} for use with Portlet requests.
*
*
* @author Rossen Stoyanchev
* @author Phillip Webb
* @since 2.2.0
*/
public class PortletExternalContextImpl extends ExternalContext {
private ActionRequest actionRequest;
private Map<String, Object> applicationMap;
private boolean isActionRequest;
private PortletContext portletContext;
private PortletRequest portletRequest;
private PortletRequest request;
private PortletResponse portletResponse;
private PortletResponse response;
private boolean isActionRequest;
private Map<String, String> initParameterMap;
@@ -81,22 +93,52 @@ public class PortletExternalContextImpl extends ExternalContext {
private MapAdaptable<String, Object> sessionMap;
private Flash flash;
public PortletExternalContextImpl(PortletContext portletContext, PortletRequest portletRequest,
PortletResponse portletResponse) {
this.portletContext = portletContext;
this.portletRequest = portletRequest;
this.portletResponse = portletResponse;
this.request = portletRequest;
this.response = portletResponse;
if (portletRequest instanceof ActionRequest) {
this.actionRequest = (ActionRequest) portletRequest;
this.isActionRequest = true;
}
}
public void release() {
portletContext = null;
request = null;
response = null;
applicationMap = null;
sessionMap = null;
requestMap = null;
requestParameterMap = null;
requestParameterValuesMap = null;
requestHeaderMap = null;
requestHeaderValuesMap = null;
initParameterMap = null;
}
public Flash getFlash() {
if(this.flash == null) {
this.flash = createFlash();
}
return this.flash;
}
private Flash createFlash() {
if (JsfRuntimeInformation.isMyFacesPresent()) {
return new MyFacesFlashFactory().newFlash(this);
} else {
return new MojarraFlashFactory().newFlash(this);
}
}
public void dispatch(String path) throws IOException {
Assert.isTrue(!isActionRequest);
PortletRequestDispatcher requestDispatcher = portletContext.getRequestDispatcher(path);
try {
requestDispatcher.include((RenderRequest) portletRequest, (RenderResponse) portletResponse);
requestDispatcher.include((RenderRequest) request, (RenderResponse) response);
} catch (PortletException exception) {
if (exception.getMessage() != null) {
throw new FacesException(exception.getMessage(), exception);
@@ -105,20 +147,78 @@ public class PortletExternalContextImpl extends ExternalContext {
}
}
public String encodeActionURL(String url) {
Assert.notNull(url);
return portletResponse.encodeURL(url);
@Override
public void redirect(String url) throws IOException {
Assert.isInstanceOf(ActionResponse.class, response);
((ActionResponse) response).sendRedirect(url);
}
public String encodeNamespace(String name) {
Assert.isTrue(!isActionRequest);
return name + ((RenderResponse) portletResponse).getNamespace();
return name + ((RenderResponse) response).getNamespace();
}
public String encodeActionURL(String url) {
Assert.notNull(url);
return response.encodeURL(url);
}
@Override
public String encodeResourceURL(String url) {
Assert.notNull(url);
return portletResponse.encodeURL(url);
return response.encodeURL(url);
}
public String encodePartialActionURL(String url) {
Assert.notNull(url);
return response.encodeURL(url);
}
public String encodeBookmarkableURL(String baseUrl, Map<String, List<String>> parameters) {
return encodeUrl(baseUrl, parameters);
}
public String encodeRedirectURL(String baseUrl, Map<String, List<String>> parameters) {
return response.encodeURL(encodeUrl(baseUrl, parameters));
}
private String encodeUrl(String baseUrl, Map<String, List<String>> parameters) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(baseUrl);
for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue().toArray());
}
return builder.buildAndExpand().toUriString();
}
@Override
public Object getContext() {
return portletContext;
}
public String getContextName() {
return portletContext.getPortletContextName();
}
public String getMimeType(String file) {
return portletContext.getMimeType(file);
}
public String getRealPath(String path) {
return portletContext.getRealPath(path);
}
@Override
public void log(String message) {
Assert.notNull(message);
portletContext.log(message);
}
@Override
public void log(String message, Throwable exception) {
Assert.notNull(message);
Assert.notNull(exception);
portletContext.log(message, exception);
}
@Override
@@ -129,16 +229,6 @@ public class PortletExternalContextImpl extends ExternalContext {
return applicationMap;
}
@Override
public String getAuthType() {
return portletRequest.getAuthType();
}
@Override
public Object getContext() {
return portletContext;
}
@Override
public String getInitParameter(String name) {
return portletContext.getInitParameter(name);
@@ -152,104 +242,6 @@ public class PortletExternalContextImpl extends ExternalContext {
return initParameterMap;
}
@Override
public String getRemoteUser() {
return portletRequest.getRemoteUser();
}
@Override
public Object getRequest() {
return portletRequest;
}
@Override
public String getRequestContentType() {
return null;
}
@Override
public String getRequestContextPath() {
return portletRequest.getContextPath();
}
@Override
public Map<String, Object> getRequestCookieMap() {
return Collections.emptyMap();
}
@Override
public Map<String, String> getRequestHeaderMap() {
if (requestHeaderMap == null) {
requestHeaderMap = new SingleValueRequestPropertyMap(portletRequest);
}
return requestHeaderMap;
}
@Override
public Map<String, String[]> getRequestHeaderValuesMap() {
if (requestHeaderValuesMap == null) {
requestHeaderValuesMap = new MultiValueRequestPropertyMap(portletRequest);
}
return requestHeaderValuesMap;
}
@Override
public Locale getRequestLocale() {
return portletRequest.getLocale();
}
@Override
public Iterator<Locale> getRequestLocales() {
return CollectionUtils.toIterator(portletRequest.getLocales());
}
@Override
public Map<String, Object> getRequestMap() {
if (requestMap == null) {
requestMap = new PortletRequestMap(portletRequest);
}
return requestMap;
}
@Override
public Map<String, String> getRequestParameterMap() {
if (requestParameterMap == null) {
requestParameterMap = new SingleValueRequestParameterMap(portletRequest);
}
return requestParameterMap;
}
@Override
public Iterator<String> getRequestParameterNames() {
return CollectionUtils.toIterator(portletRequest.getParameterNames());
}
@Override
public Map<String, String[]> getRequestParameterValuesMap() {
if (requestParameterValuesMap == null) {
requestParameterValuesMap = new MultiValueRequestParameterMap(portletRequest);
}
return requestParameterValuesMap;
}
@Override
public String getRequestPathInfo() {
return null;
}
@Override
public String getRequestServletPath() {
//
// Return "" instead of null in order to prevent NullPointerException in Apache MyFaces 1.2 when it tries to
// determine the servlet mappings in DefaultViewHandlerSupport.calculateFacesServletMapping(..).
// Note that the FacesServlet mapping in Web Flow is not relevant so this should be ok.
//
// Alternatively this method could be implemented to provide an actual servlet path derived from the
// viewId when that becomes available during rendering as the MyFaces Portlet Bridge does.
//
return (JsfRuntimeInformation.isMyFacesPresent()) ? "" : null;
}
@Override
public URL getResource(String path) throws MalformedURLException {
Assert.notNull(path);
@@ -269,96 +261,180 @@ public class PortletExternalContextImpl extends ExternalContext {
}
@Override
public Object getResponse() {
return portletResponse;
public Object getRequest() {
return request;
}
@Override
public String getResponseContentType() {
public void setRequest(Object request) {
this.request = (PortletRequest) request;
}
@Override
public String getRequestContentType() {
if (request instanceof ClientDataRequest) {
ClientDataRequest clientDataRequest = (ClientDataRequest) request;
return clientDataRequest.getContentType();
}
return null;
}
@Override
public Object getSession(boolean create) {
return portletRequest.getPortletSession(create);
public String getRequestContextPath() {
return request.getContextPath();
}
public String getRequestScheme() {
return request.getScheme();
}
public String getRequestServerName() {
return request.getServerName();
}
public int getRequestServerPort() {
return request.getServerPort();
}
@Override
public Map<String, Object> getSessionMap() {
if (sessionMap == null) {
sessionMap = new LocalAttributeMap<Object>(new PortletSessionMap(portletRequest));
public Locale getRequestLocale() {
return request.getLocale();
}
@Override
public Iterator<Locale> getRequestLocales() {
return CollectionUtils.toIterator(request.getLocales());
}
@Override
public String getRequestCharacterEncoding() {
return getActionRequest().getCharacterEncoding();
}
public void setRequestCharacterEncoding(String encoding) throws java.io.UnsupportedEncodingException {
getActionRequest().setCharacterEncoding(encoding);
}
@Override
public Map<String, Object> getRequestCookieMap() {
return Collections.emptyMap();
}
@Override
public Map<String, String> getRequestHeaderMap() {
if (requestHeaderMap == null) {
requestHeaderMap = new SingleValueRequestPropertyMap(request);
}
return sessionMap.asMap();
return requestHeaderMap;
}
@Override
public Map<String, String[]> getRequestHeaderValuesMap() {
if (requestHeaderValuesMap == null) {
requestHeaderValuesMap = new MultiValueRequestPropertyMap(request);
}
return requestHeaderValuesMap;
}
@Override
public Map<String, Object> getRequestMap() {
if (requestMap == null) {
requestMap = new PortletRequestMap(request);
}
return requestMap;
}
@Override
public Map<String, String> getRequestParameterMap() {
if (requestParameterMap == null) {
requestParameterMap = new SingleValueRequestParameterMap(request);
}
return requestParameterMap;
}
@Override
public Iterator<String> getRequestParameterNames() {
return CollectionUtils.toIterator(request.getParameterNames());
}
@Override
public Map<String, String[]> getRequestParameterValuesMap() {
if (requestParameterValuesMap == null) {
requestParameterValuesMap = new MultiValueRequestParameterMap(request);
}
return requestParameterValuesMap;
}
@Override
public String getRequestPathInfo() {
return null;
}
@Override
public String getRequestServletPath() {
// Return "" instead of null in order to prevent NullPointerException in Apache MyFaces 1.2 when it tries to
// determine the servlet mappings in DefaultViewHandlerSupport.calculateFacesServletMapping(..).
// Note that the FacesServlet mapping in Web Flow is not relevant so this should be ok.
//
// Alternatively this method could be implemented to provide an actual servlet path derived from the
// viewId when that becomes available during rendering as the MyFaces Portlet Bridge does.
//
return (JsfRuntimeInformation.isMyFacesPresent()) ? "" : null;
}
public int getRequestContentLength() {
Assert.isInstanceOf(ClientDataRequest.class, request);
return ((ClientDataRequest) request).getContentLength();
}
private ActionRequest getActionRequest() {
Assert.isInstanceOf(ActionRequest.class, request);
return (ActionRequest) request;
}
@Override
public String getAuthType() {
return request.getAuthType();
}
@Override
public String getRemoteUser() {
return request.getRemoteUser();
}
@Override
public Principal getUserPrincipal() {
return portletRequest.getUserPrincipal();
return request.getUserPrincipal();
}
@Override
public boolean isUserInRole(String role) {
Assert.notNull(role);
return portletRequest.isUserInRole(role);
return request.isUserInRole(role);
}
public boolean isSecure() {
return request.isSecure();
}
@Override
public void log(String message) {
Assert.notNull(message);
portletContext.log(message);
public Object getResponse() {
return response;
}
@Override
public void log(String message, Throwable exception) {
Assert.notNull(message);
Assert.notNull(exception);
portletContext.log(message, exception);
public void setResponse(Object response) {
this.response = (PortletResponse) response;
}
@Override
public void redirect(String url) throws IOException {
if (actionRequest instanceof ActionResponse) {
((ActionResponse) portletResponse).sendRedirect(url);
} else {
throw new IllegalArgumentException("Only ActionResponse supported");
}
}
public void release() {
portletContext = null;
portletRequest = null;
portletResponse = null;
applicationMap = null;
sessionMap = null;
requestMap = null;
requestParameterMap = null;
requestParameterValuesMap = null;
requestHeaderMap = null;
requestHeaderValuesMap = null;
initParameterMap = null;
actionRequest = null;
}
@Override
public void setRequest(Object request) {
this.portletRequest = (PortletRequest) request;
this.actionRequest = (portletRequest instanceof ActionRequest) ? (ActionRequest) request : null;
}
public void setRequestCharacterEncoding(String encoding) throws java.io.UnsupportedEncodingException {
Assert.notNull(actionRequest, "The request be an action request.");
actionRequest.setCharacterEncoding(encoding);
}
@Override
public String getRequestCharacterEncoding() {
Assert.notNull(actionRequest, "The request be an action request.");
return actionRequest.getCharacterEncoding();
public String getResponseContentType() {
return getMimeResponse().getContentType();
}
@Override
public String getResponseCharacterEncoding() {
return null;
return getMimeResponse().getCharacterEncoding();
}
@Override
@@ -366,9 +442,154 @@ public class PortletExternalContextImpl extends ExternalContext {
// no-op
}
@Override
public void setResponse(Object response) {
this.portletResponse = (PortletResponse) response;
public OutputStream getResponseOutputStream() throws IOException {
return getMimeResponse().getPortletOutputStream();
}
public Writer getResponseOutputWriter() throws IOException {
return getMimeResponse().getWriter();
}
public void addResponseCookie(String name, String value, Map<String, Object> properties) {
Cookie cookie = new Cookie(name, value);
setCookieProperties(cookie, properties);
response.addProperty(cookie);
}
private void setCookieProperties(Cookie cookie, Map<String, Object> properties) {
if (properties != null) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
setCookieProperty(cookie, entry.getKey(), entry.getValue());
}
}
}
private void setCookieProperty(Cookie cookie, String property, Object value) {
if ("domain".equalsIgnoreCase(property)) {
cookie.setDomain((String) value);
return;
}
if ("maxAge".equalsIgnoreCase(property)) {
cookie.setMaxAge((Integer) value);
return;
}
if ("path".equalsIgnoreCase(property)) {
cookie.setPath((String) value);
return;
}
if ("secure".equalsIgnoreCase(property)) {
cookie.setSecure((Boolean) value);
return;
}
throw new IllegalStateException("Unknown cookie property " + property);
}
public void addResponseHeader(String name, String value) {
response.addProperty(name, value);
}
public void responseFlushBuffer() throws IOException {
getMimeResponse().flushBuffer();
}
public void responseReset() {
MimeResponse mimeResponse = getMimeResponse(false);
if (mimeResponse != null) {
mimeResponse.reset();
}
}
public void responseSendError(int statusCode, String message) throws IOException {
throw new IOException(statusCode + ": " + message);
}
public void setResponseBufferSize(int size) {
getMimeResponse().setBufferSize(size);
}
public void setResponseContentLength(int length) {
if (portletContext instanceof ResourceResponse) {
((ResourceResponse) portletContext).setContentLength(length);
}
}
public void setResponseContentType(String contentType) {
MimeResponse mimeResponse = getMimeResponse(false);
if (mimeResponse != null) {
mimeResponse.setContentType(contentType);
}
}
public void setResponseHeader(String name, String value) {
response.setProperty(name, value);
}
public void setResponseStatus(int statusCode) {
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, String.valueOf(statusCode));
PortletResponseUtils.setStatusCodeForPluto(response, statusCode);
}
public boolean isResponseCommitted() {
MimeResponse mimeResponse = getMimeResponse(false);
return ((mimeResponse != null) ? mimeResponse.isCommitted() : false);
}
public int getResponseBufferSize() {
return getMimeResponse().getBufferSize();
}
private MimeResponse getMimeResponse() {
return getMimeResponse(true);
}
private MimeResponse getMimeResponse(boolean required) {
if (response instanceof MimeResponse) {
return (MimeResponse) response;
}
if (!required) {
return null;
}
throw new IllegalStateException("Portlet response is not a MimeResponse");
}
@Override
public Object getSession(boolean create) {
return request.getPortletSession(create);
}
@Override
public Map<String, Object> getSessionMap() {
if (sessionMap == null) {
sessionMap = new LocalAttributeMap<Object>(new PortletSessionMap(request));
}
return sessionMap.asMap();
}
public int getSessionMaxInactiveInterval() {
return request.getPortletSession().getMaxInactiveInterval();
}
public void invalidateSession() {
PortletSession portletSession = request.getPortletSession(false);
if (portletSession != null) {
portletSession.invalidate();
}
}
public void setSessionMaxInactiveInterval(int interval) {
request.getPortletSession().setMaxInactiveInterval(interval);
}
private static class MojarraFlashFactory {
public Flash newFlash(ExternalContext context) {
return ELFlash.getFlash(context, true);
}
}
private static class MyFacesFlashFactory {
public Flash newFlash(ExternalContext context) {
return FlashImpl.getCurrentInstance(context);
}
}
}

View File

@@ -18,9 +18,12 @@ package org.springframework.faces.webflow.context.portlet;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.el.ELContext;
import javax.el.ELContextEvent;
@@ -28,23 +31,30 @@ import javax.el.ELContextListener;
import javax.el.ELResolver;
import javax.el.FunctionMapper;
import javax.el.VariableMapper;
import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.application.FacesMessage;
import javax.faces.application.ProjectStage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialViewContext;
import javax.faces.context.PartialViewContextFactory;
import javax.faces.context.ResponseStream;
import javax.faces.context.ResponseWriter;
import javax.faces.event.PhaseId;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import org.springframework.faces.webflow.JsfUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
/**
* The default FacesContext implementation in Mojarra and in Apache MyFaces depends on the Servlet API. This
@@ -53,22 +63,27 @@ import org.springframework.util.ClassUtils;
* methods in the default FacesContext implementation.
*
* @author Rossen Stoyanchev
* @author Phillip Webb
* @since 2.2.0
*/
public class PortletFacesContextImpl extends FacesContext {
private static final List<FacesMessage> NO_MESSAGES = Collections.unmodifiableList(Collections
.<FacesMessage> emptyList());
private static final Iterator<String> NO_CLIENT_IDS_WITH_MESSAGES = Collections.unmodifiableSet(
Collections.<String> emptySet()).iterator();
private Application application;
private ELContext elContext;
private ExternalContext externalContext;
private List<Message> messages;
private FacesMessage.Severity maximumSeverity;
private List<String> messageClientIds;
private List<FacesMessage> messages;
private boolean released = false;
private RenderKitFactory renderKitFactory;
@@ -83,72 +98,67 @@ public class PortletFacesContextImpl extends FacesContext {
private UIViewRoot viewRoot;
public PortletFacesContextImpl(PortletContext portletContext, PortletRequest portletRequest,
PortletResponse portletResponse) {
application = ((ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY))
.getApplication();
renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
this.externalContext = new PortletExternalContextImpl(portletContext, portletRequest, portletResponse);
FacesContext.setCurrentInstance(this);
}
private Map<Object, Object> attributes;
private PhaseId currentPhaseId;
private ExceptionHandler exceptionHandler;
private boolean validationFailed;
private PartialViewContext partialViewContext;
private boolean processingEvents;
public PortletFacesContextImpl(ExternalContext externalContext) {
this.externalContext = externalContext;
}
public PortletFacesContextImpl(PortletContext portletContext, PortletRequest portletRequest,
PortletResponse portletResponse) {
application = JsfUtils.findFactory(ApplicationFactory.class).getApplication();
renderKitFactory = JsfUtils.findFactory(RenderKitFactory.class);
this.externalContext = new PortletExternalContextImpl(portletContext, portletRequest, portletResponse);
this.exceptionHandler = JsfUtils.findFactory(ExceptionHandlerFactory.class).getExceptionHandler();
FacesContext.setCurrentInstance(this);
}
public void release() {
assertNotReleased();
if (externalContext != null) {
Method delegateMethod = ClassUtils.getMethodIfAvailable(externalContext.getClass(), "release");
if (delegateMethod != null) {
try {
delegateMethod.invoke(externalContext);
} catch (Exception e) {
externalContext.log("Failed to release external context", e);
}
externalContext = null;
}
}
messages = null;
maximumSeverity = null;
application = null;
responseStream = null;
responseWriter = null;
viewRoot = null;
exceptionHandler = null;
attributes = null;
released = true;
FacesContext.setCurrentInstance(null);
}
public ExternalContext getExternalContext() {
assertFacesContextIsNotReleased();
assertNotReleased();
return externalContext;
}
public FacesMessage.Severity getMaximumSeverity() {
assertFacesContextIsNotReleased();
return maximumSeverity;
}
@SuppressWarnings("unchecked")
public Iterator<FacesMessage> getMessages() {
assertFacesContextIsNotReleased();
return (messages != null) ? messages.iterator() : Collections.EMPTY_LIST.iterator();
}
public Application getApplication() {
assertFacesContextIsNotReleased();
assertNotReleased();
return application;
}
public Iterator<String> getClientIdsWithMessages() {
assertFacesContextIsNotReleased();
if (messages == null || messages.isEmpty()) {
return new ArrayList<String>().iterator();
}
return new LinkedHashSet<String>(messageClientIds).iterator();
}
@SuppressWarnings("unchecked")
public Iterator<FacesMessage> getMessages(String clientId) {
assertFacesContextIsNotReleased();
if (messages == null) {
return Collections.EMPTY_LIST.iterator();
}
List<FacesMessage> list = new ArrayList<FacesMessage>();
for (int i = 0; i < messages.size(); i++) {
Object current = messageClientIds.get(i);
if (clientId == null) {
if (current == null) {
list.add(messages.get(i));
}
} else {
if (clientId.equals(current)) {
list.add(messages.get(i));
}
}
}
return list.iterator();
}
public RenderKit getRenderKit() {
if (getViewRoot() == null) {
return null;
@@ -164,22 +174,22 @@ public class PortletFacesContextImpl extends FacesContext {
}
public boolean getRenderResponse() {
assertFacesContextIsNotReleased();
assertNotReleased();
return renderResponse;
}
public boolean getResponseComplete() {
assertFacesContextIsNotReleased();
assertNotReleased();
return responseComplete;
}
public ResponseStream getResponseStream() {
assertFacesContextIsNotReleased();
assertNotReleased();
return responseStream;
}
public void setResponseStream(ResponseStream responseStream) {
assertFacesContextIsNotReleased();
assertNotReleased();
if (responseStream == null) {
throw new NullPointerException("responseStream");
}
@@ -187,12 +197,12 @@ public class PortletFacesContextImpl extends FacesContext {
}
public ResponseWriter getResponseWriter() {
assertFacesContextIsNotReleased();
assertNotReleased();
return responseWriter;
}
public void setResponseWriter(ResponseWriter responseWriter) {
assertFacesContextIsNotReleased();
assertNotReleased();
if (responseWriter == null) {
throw new NullPointerException("responseWriter");
}
@@ -200,95 +210,199 @@ public class PortletFacesContextImpl extends FacesContext {
}
public UIViewRoot getViewRoot() {
assertFacesContextIsNotReleased();
assertNotReleased();
return viewRoot;
}
public void setViewRoot(UIViewRoot viewRoot) {
assertFacesContextIsNotReleased();
assertNotReleased();
if (viewRoot == null) {
throw new NullPointerException("viewRoot");
}
this.viewRoot = viewRoot;
}
public void addMessage(String clientId, FacesMessage message) {
assertFacesContextIsNotReleased();
if (message == null) {
throw new NullPointerException("message");
}
if (messages == null) {
messages = new ArrayList<FacesMessage>();
messageClientIds = new ArrayList<String>();
}
messages.add(message);
messageClientIds.add((clientId != null) ? clientId : null);
FacesMessage.Severity severity = message.getSeverity();
if (severity != null) {
if (maximumSeverity == null) {
maximumSeverity = severity;
} else if (severity.compareTo(maximumSeverity) > 0) {
maximumSeverity = severity;
}
}
}
public void release() {
assertFacesContextIsNotReleased();
if (externalContext != null) {
Method delegateMethod = ClassUtils.getMethodIfAvailable(externalContext.getClass(), "release");
if (delegateMethod != null) {
try {
delegateMethod.invoke(externalContext);
} catch (Exception e) {
externalContext.log("Failed to release external context", e);
}
externalContext = null;
}
}
messageClientIds = null;
messages = null;
application = null;
responseStream = null;
responseWriter = null;
viewRoot = null;
released = true;
FacesContext.setCurrentInstance(null);
}
public void renderResponse() {
assertFacesContextIsNotReleased();
assertNotReleased();
renderResponse = true;
}
public void responseComplete() {
assertFacesContextIsNotReleased();
assertNotReleased();
responseComplete = true;
}
public ELContext getELContext() {
if (elContext == null) {
Application application = getApplication();
elContext = new PortletELContextImpl(application.getELResolver());
elContext.putContext(FacesContext.class, FacesContext.getCurrentInstance());
UIViewRoot root = getViewRoot();
if (null != root) {
elContext.setLocale(root.getLocale());
}
ELContextListener[] listeners = application.getELContextListeners();
if (listeners.length > 0) {
ELContextEvent event = new ELContextEvent(elContext);
for (ELContextListener listener : listeners) {
listener.contextCreated(event);
}
}
createELContext();
}
return elContext;
}
private void assertFacesContextIsNotReleased() {
private void createELContext() {
elContext = new PortletELContextImpl(getApplication().getELResolver());
elContext.putContext(FacesContext.class, FacesContext.getCurrentInstance());
if (getViewRoot() != null) {
elContext.setLocale(getViewRoot().getLocale());
}
fireContextCreated(getApplication().getELContextListeners());
}
private void fireContextCreated(ELContextListener[] listeners) {
if (listeners.length > 0) {
ELContextEvent event = new ELContextEvent(elContext);
for (ELContextListener listener : listeners) {
listener.contextCreated(event);
}
}
}
public void addMessage(String clientId, FacesMessage message) {
assertNotReleased();
if (message == null) {
throw new NullPointerException("message");
}
if (messages == null) {
messages = new ArrayList<Message>();
}
messages.add(new Message(clientId, message));
recalculateMaximumSeverity(message.getSeverity());
}
private void recalculateMaximumSeverity(FacesMessage.Severity severity) {
if (severity != null) {
if (maximumSeverity == null || severity.compareTo(maximumSeverity) > 0) {
maximumSeverity = severity;
}
}
}
public FacesMessage.Severity getMaximumSeverity() {
assertNotReleased();
return maximumSeverity;
}
public Iterator<FacesMessage> getMessages() {
return getMessageList().iterator();
}
public List<FacesMessage> getMessageList() {
assertNotReleased();
if (messages == null || messages.isEmpty()) {
return NO_MESSAGES;
}
List<FacesMessage> messageList = new ArrayList<FacesMessage>();
for (Message message : messages) {
messageList.add(message.getFacesMessage());
}
return Collections.unmodifiableList(messageList);
}
public Iterator<FacesMessage> getMessages(String clientId) {
return getMessageList(clientId).iterator();
}
public List<FacesMessage> getMessageList(String clientId) {
assertNotReleased();
if (messages == null || messages.isEmpty()) {
return NO_MESSAGES;
}
List<FacesMessage> messageList = new ArrayList<FacesMessage>();
for (Message message : messages) {
if (message.isForClientId(clientId)) {
messageList.add(message.getFacesMessage());
}
}
return Collections.unmodifiableList(messageList);
}
public Iterator<String> getClientIdsWithMessages() {
assertNotReleased();
if (messages == null || messages.isEmpty()) {
return NO_CLIENT_IDS_WITH_MESSAGES;
}
Set<String> clientIdsWithMessags = new LinkedHashSet<String>();
for (Message message : messages) {
clientIdsWithMessags.add(message.getClientId());
}
return Collections.unmodifiableSet(clientIdsWithMessags).iterator();
}
public Map<Object, Object> getAttributes() {
assertNotReleased();
if (attributes == null) {
attributes = new HashMap<Object, Object>();
}
return attributes;
}
public PhaseId getCurrentPhaseId() {
assertNotReleased();
return currentPhaseId;
}
public ExceptionHandler getExceptionHandler() {
return exceptionHandler;
}
public boolean isPostback() {
RenderKit renderKit = getRenderKit();
if (renderKit == null) {
String renderKitId = getApplication().getViewHandler().calculateRenderKitId(this);
renderKit = JsfUtils.findFactory(RenderKitFactory.class).getRenderKit(this, renderKitId);
}
return renderKit.getResponseStateManager().isPostback(this);
}
public boolean isReleased() {
return released;
}
public boolean isValidationFailed() {
assertNotReleased();
return validationFailed;
}
public void setCurrentPhaseId(PhaseId currentPhaseId) {
assertNotReleased();
this.currentPhaseId = currentPhaseId;
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
assertNotReleased();
this.exceptionHandler = exceptionHandler;
}
public void validationFailed() {
assertNotReleased();
validationFailed = true;
}
public PartialViewContext getPartialViewContext() {
assertNotReleased();
if (partialViewContext == null) {
partialViewContext = JsfUtils.findFactory(PartialViewContextFactory.class).getPartialViewContext(this);
}
return partialViewContext;
}
public boolean isProcessingEvents() {
assertNotReleased();
return processingEvents;
}
public void setProcessingEvents(boolean processingEvents) {
assertNotReleased();
this.processingEvents = processingEvents;
}
public boolean isProjectStage(ProjectStage stage) {
Assert.notNull(stage, "Stage must not be null");
return (stage.equals(getApplication().getProjectStage()));
}
private void assertNotReleased() {
Assert.isTrue(!released, "FacesContext already released");
}
@@ -319,4 +433,27 @@ public class PortletFacesContextImpl extends FacesContext {
}
private static class Message {
private String clientId;
private FacesMessage facesMessage;
public Message(String clientId, FacesMessage facesMessage) {
this.clientId = clientId;
this.facesMessage = facesMessage;
}
public String getClientId() {
return clientId;
}
public boolean isForClientId(String clientId) {
return ObjectUtils.nullSafeEquals(this.clientId, clientId);
}
public FacesMessage getFacesMessage() {
return facesMessage;
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow.context.portlet;
import java.lang.reflect.Method;
import javax.portlet.PortletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.ReflectionUtils;
/**
* Utilities when dealing with {@link PortletResponse}s.
*
* @since 2.4.0
* @author Phillip Webb
*/
class PortletResponseUtils {
// Work around for PLUTO-603
public static void setStatusCodeForPluto(PortletResponse response, int statusCode) {
if (response.getClass().getName().startsWith("org.apache.pluto")) {
Method servletResponseMethod = ReflectionUtils.findMethod(response.getClass(), "getServletResponse");
if (servletResponseMethod != null) {
try {
ReflectionUtils.makeAccessible(servletResponseMethod);
HttpServletResponse servletResponse = (HttpServletResponse) servletResponseMethod.invoke(response);
servletResponse.setStatus(statusCode);
} catch (Exception e) {
}
}
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2004-2012 the original author or authors.
*
* Licensed 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.springframework.faces.webflow.context.portlet;
import java.util.List;
import java.util.Map;
import javax.faces.application.ViewHandler;
import javax.faces.application.ViewHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.portlet.MimeResponse;
import javax.portlet.ResourceURL;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
/**
* JSF {@link ViewHandler} that adds support for generating Portlet compatible resource URLs.
*
* @since 2.4.0
* @author Phillip Webb
*/
public class PortletViewHandler extends ViewHandlerWrapper {
private static final String FACES_RESOURCE = "javax.faces.resource";
private ViewHandler wrapped;
public PortletViewHandler(ViewHandler wrapped) {
this.wrapped = wrapped;
}
public ViewHandler getWrapped() {
return this.wrapped;
}
public String getResourceURL(FacesContext context, String path) {
String uri = super.getResourceURL(context, path);
int facesResourceIndex = (uri == null ? -1 : uri.indexOf(FACES_RESOURCE));
if (facesResourceIndex == -1) {
return uri;
}
UriComponents components = UriComponentsBuilder.fromUriString(uri.substring(facesResourceIndex + FACES_RESOURCE.length() + 1)).build();
MimeResponse response = (MimeResponse) context.getExternalContext().getResponse();
ResourceURL resourceURL = response.createResourceURL();
for (Map.Entry<String, List<String>> entry : components.getQueryParams().entrySet()) {
String name = entry.getKey();
List<String> value = entry.getValue();
resourceURL.setParameter(name, value.toArray(new String[value.size()]));
}
resourceURL.setParameter(FACES_RESOURCE, components.getPath());
return resourceURL.toString();
}
}

View File

@@ -36,9 +36,9 @@ import org.springframework.webflow.context.portlet.PortletRequestParameterMap;
*/
public abstract class RequestParameterMap<V> extends StringKeyedMapAdapter<V> {
private PortletRequest portletRequest;
private final PortletRequest portletRequest;
private Delegate delegate;
private final Delegate delegate;
public RequestParameterMap(PortletRequest portletRequest) {
this.portletRequest = portletRequest;
@@ -46,19 +46,19 @@ public abstract class RequestParameterMap<V> extends StringKeyedMapAdapter<V> {
}
protected final PortletRequest getPortletRequest() {
return portletRequest;
return this.portletRequest;
}
protected void setAttribute(String key, V value) {
delegate.setAttribute(key, value);
this.delegate.setAttribute(key, value);
}
protected void removeAttribute(String key) {
delegate.removeAttribute(key);
this.delegate.removeAttribute(key);
}
protected Iterator<String> getAttributeNames() {
return delegate.getAttributeNames();
return this.delegate.getAttributeNames();
}
private static class Delegate extends PortletRequestParameterMap {

View File

@@ -43,7 +43,7 @@ public abstract class RequestPropertyMap<V> extends StringKeyedMapAdapter<V> {
}
protected final PortletRequest getPortletRequest() {
return portletRequest;
return this.portletRequest;
}
@Override
@@ -58,6 +58,6 @@ public abstract class RequestPropertyMap<V> extends StringKeyedMapAdapter<V> {
@Override
protected Iterator<String> getAttributeNames() {
return CollectionUtils.toIterator(portletRequest.getPropertyNames());
return CollectionUtils.toIterator(this.portletRequest.getPropertyNames());
}
}

View File

@@ -1,16 +1,14 @@
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<action-listener>org.springframework.faces.webflow.FlowActionListener</action-listener>
<action-listener>org.springframework.faces.model.SelectionTrackingActionListener</action-listener>
<variable-resolver>org.springframework.faces.webflow.FlowVariableResolver</variable-resolver>
<property-resolver>org.springframework.faces.webflow.FlowPropertyResolver</property-resolver>
<variable-resolver>org.springframework.faces.webflow.SpringBeanWebFlowVariableResolver</variable-resolver>
<el-resolver>org.springframework.faces.webflow.FlowELResolver</el-resolver>
</application>
<factory>

View File

@@ -26,52 +26,52 @@ public class FacesFlowBuilderServicesBeanDefinitionParserTests extends TestCase
private ClassPathXmlApplicationContext context;
private FlowBuilderServices builderServices;
private JSFMockHelper jsf = new JSFMockHelper();
private final JSFMockHelper jsf = new JSFMockHelper();
public void setUp() throws Exception {
jsf.setUp();
context = new ClassPathXmlApplicationContext("org/springframework/faces/config/flow-builder-services.xml");
this.jsf.setUp();
this.context = new ClassPathXmlApplicationContext("org/springframework/faces/config/flow-builder-services.xml");
}
protected void tearDown() throws Exception {
jsf.tearDown();
this.jsf.tearDown();
}
public void testConfigureDefaults() {
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesDefault");
assertNotNull(builderServices);
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertTrue(builderServices.getConversionService() instanceof FacesConversionService);
assertFalse(builderServices.getDevelopment());
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesDefault");
assertNotNull(this.builderServices);
assertTrue(this.builderServices.getExpressionParser() instanceof SpringELExpressionParser);
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
assertFalse(this.builderServices.getDevelopment());
}
public void testEnableManagedBeans() {
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesLegacy");
assertNotNull(builderServices);
assertTrue(builderServices.getExpressionParser() instanceof FacesSpringELExpressionParser);
assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertTrue(builderServices.getConversionService() instanceof FacesConversionService);
assertFalse(builderServices.getDevelopment());
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesLegacy");
assertNotNull(this.builderServices);
assertTrue(this.builderServices.getExpressionParser() instanceof FacesSpringELExpressionParser);
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
assertFalse(this.builderServices.getDevelopment());
}
public void testFlowBuilderServicesAllCustomized() {
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesAllCustom");
assertNotNull(builderServices);
assertTrue(builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
assertTrue(builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
assertTrue(builderServices.getDevelopment());
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesAllCustom");
assertNotNull(this.builderServices);
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
assertTrue(this.builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
assertTrue(this.builderServices.getDevelopment());
}
public void testFlowBuilderServicesConversionServiceCustomized() {
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesConversionServiceCustom");
assertNotNull(builderServices);
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
assertTrue(builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertFalse(builderServices.getDevelopment());
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesConversionServiceCustom");
assertNotNull(this.builderServices);
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
assertTrue(((SpringELExpressionParser) this.builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
assertFalse(this.builderServices.getDevelopment());
}
public static class TestViewFactoryCreator implements ViewFactoryCreator {

View File

@@ -14,21 +14,21 @@ public class ResourcesBeanDefinitionParserTests extends TestCase {
private ClassPathXmlApplicationContext context;
public void setUp() throws Exception {
context = new ClassPathXmlApplicationContext("org/springframework/faces/config/resources.xml");
this.context = new ClassPathXmlApplicationContext("org/springframework/faces/config/resources.xml");
}
protected void tearDown() throws Exception {
}
public void testConfigureDefaults() {
Map<String, ?> map = context.getBeansOfType(HttpRequestHandlerAdapter.class);
Map<String, ?> map = this.context.getBeansOfType(HttpRequestHandlerAdapter.class);
assertEquals(1, map.values().size());
Object resourceHandler = context.getBean(ResourcesBeanDefinitionParser.RESOURCE_HANDLER_BEAN_NAME);
Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.RESOURCE_HANDLER_BEAN_NAME);
assertNotNull(resourceHandler);
assertTrue(resourceHandler instanceof JsfResourceRequestHandler);
map = context.getBeansOfType(SimpleUrlHandlerMapping.class);
map = this.context.getBeansOfType(SimpleUrlHandlerMapping.class);
assertEquals(1, map.values().size());
SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) map.values().iterator().next();
assertEquals(ResourcesBeanDefinitionParser.RESOURCE_HANDLER_BEAN_NAME,

View File

@@ -26,7 +26,7 @@ public class SelectionTrackingActionListenerTests extends TestCase {
/**
* JSF Mock Helper
*/
private JSFMockHelper jsfMockHelper = new JSFMockHelper();
private final JSFMockHelper jsfMockHelper = new JSFMockHelper();
/**
* The JSF view to simulate
@@ -41,58 +41,58 @@ public class SelectionTrackingActionListenerTests extends TestCase {
/**
* The delegate action listener that should be called
*/
private TestDelegateActionListener delegateListener = new TestDelegateActionListener();
private final TestDelegateActionListener delegateListener = new TestDelegateActionListener();
/**
* The class under test
*/
private ActionListener selectionTrackingListener = new SelectionTrackingActionListener(delegateListener);
private final ActionListener selectionTrackingListener = new SelectionTrackingActionListener(this.delegateListener);
public void setUp() throws Exception {
jsfMockHelper.setUp();
viewToTest = new UIViewRoot();
this.jsfMockHelper.setUp();
this.viewToTest = new UIViewRoot();
List<Object> rows = new ArrayList<Object>();
rows.add(new TestRowData());
rows.add(new TestRowData());
rows.add(new TestRowData());
dataModel = new OneSelectionTrackingListDataModel<Object>(rows);
this.dataModel = new OneSelectionTrackingListDataModel<Object>(rows);
}
protected void tearDown() throws Exception {
jsfMockHelper.tearDown();
this.jsfMockHelper.tearDown();
}
public void testProcessActionWithUIData() {
UIData dataTable = new UIData();
dataTable.setValue(dataModel);
dataTable.setValue(this.dataModel);
UIColumn column = new UIColumn();
UICommand commandButton = new UICommand();
column.getChildren().add(commandButton);
dataTable.getChildren().add(column);
viewToTest.getChildren().add(dataTable);
this.viewToTest.getChildren().add(dataTable);
dataTable.setRowIndex(1);
ActionEvent event = new ActionEvent(commandButton);
selectionTrackingListener.processAction(event);
this.selectionTrackingListener.processAction(event);
assertTrue(dataModel.isCurrentRowSelected());
assertSame(dataModel.getSelectedRow(), dataModel.getRowData());
assertTrue(delegateListener.processedEvent);
assertTrue(this.dataModel.isCurrentRowSelected());
assertSame(this.dataModel.getSelectedRow(), this.dataModel.getRowData());
assertTrue(this.delegateListener.processedEvent);
dataModel.setRowIndex(2);
assertFalse(dataModel.isCurrentRowSelected());
assertTrue(dataModel.getSelectedRow() != dataModel.getRowData());
this.dataModel.setRowIndex(2);
assertFalse(this.dataModel.isCurrentRowSelected());
assertTrue(this.dataModel.getSelectedRow() != this.dataModel.getRowData());
}
public void testProcessActionWithUIRepeat() {
UIRepeat uiRepeat = new UIRepeat();
uiRepeat.setValue(dataModel);
uiRepeat.setValue(this.dataModel);
UICommand commandButton = new UICommand();
uiRepeat.getChildren().add(commandButton);
viewToTest.getChildren().add(uiRepeat);
this.viewToTest.getChildren().add(uiRepeat);
Method indexMutator = ReflectionUtils.findMethod(UIRepeat.class, "setIndex", new Class[] { FacesContext.class,
int.class });
@@ -102,15 +102,15 @@ public class SelectionTrackingActionListenerTests extends TestCase {
ActionEvent event = new ActionEvent(commandButton);
selectionTrackingListener.processAction(event);
this.selectionTrackingListener.processAction(event);
assertTrue(dataModel.isCurrentRowSelected());
assertSame(dataModel.getSelectedRow(), dataModel.getRowData());
assertTrue(delegateListener.processedEvent);
assertTrue(this.dataModel.isCurrentRowSelected());
assertSame(this.dataModel.getSelectedRow(), this.dataModel.getRowData());
assertTrue(this.delegateListener.processedEvent);
ReflectionUtils.invokeMethod(indexMutator, uiRepeat, new Object[] { new MockFacesContext(), 2 });
assertFalse(dataModel.isCurrentRowSelected());
assertTrue(dataModel.getSelectedRow() != dataModel.getRowData());
assertFalse(this.dataModel.isCurrentRowSelected());
assertTrue(this.dataModel.getSelectedRow() != this.dataModel.getRowData());
}
private class TestRowData {
@@ -122,7 +122,7 @@ public class SelectionTrackingActionListenerTests extends TestCase {
public boolean processedEvent = false;
public void processAction(ActionEvent event) throws AbortProcessingException {
processedEvent = true;
this.processedEvent = true;
}
}
}

View File

@@ -20,7 +20,7 @@ public class DataModelConverterTests extends TestCase {
public void testConvertListToDataModel() throws Exception {
List<Object> sourceList = new ArrayList<Object>();
DataModel<Object> resultModel = (DataModel<Object>) converter.convertSourceToTargetClass(sourceList,
DataModel<Object> resultModel = (DataModel<Object>) this.converter.convertSourceToTargetClass(sourceList,
DataModel.class);
assertNotNull(resultModel);
@@ -31,7 +31,7 @@ public class DataModelConverterTests extends TestCase {
public void testConvertListToListDataModel() throws Exception {
List<Object> sourceList = new ArrayList<Object>();
DataModel<Object> resultModel = (DataModel<Object>) converter.convertSourceToTargetClass(sourceList,
DataModel<Object> resultModel = (DataModel<Object>) this.converter.convertSourceToTargetClass(sourceList,
ListDataModel.class);
assertNotNull(resultModel);
@@ -42,7 +42,7 @@ public class DataModelConverterTests extends TestCase {
public void testConvertListToSerializableListDataModel() throws Exception {
List<Object> sourceList = new ArrayList<Object>();
DataModel<Object> resultModel = (DataModel<Object>) converter.convertSourceToTargetClass(sourceList,
DataModel<Object> resultModel = (DataModel<Object>) this.converter.convertSourceToTargetClass(sourceList,
SerializableListDataModel.class);
assertNotNull(resultModel);
@@ -54,7 +54,7 @@ public class DataModelConverterTests extends TestCase {
public void testConvertListToSerializableListDataModelNullSource() throws Exception {
List<Object> sourceList = null;
DataModel<Object> resultModel = (DataModel<Object>) converter.convertSourceToTargetClass(sourceList,
DataModel<Object> resultModel = (DataModel<Object>) this.converter.convertSourceToTargetClass(sourceList,
SerializableListDataModel.class);
assertNotNull(resultModel);

View File

@@ -13,11 +13,11 @@ public class FacesConversionServiceTests extends TestCase {
private FacesConversionService service;
protected void setUp() throws Exception {
service = new FacesConversionService();
this.service = new FacesConversionService();
}
public void testGetAbstractType() {
ConversionExecutor executor = service.getConversionExecutor(List.class, DataModel.class);
ConversionExecutor executor = this.service.getConversionExecutor(List.class, DataModel.class);
ArrayList<Object> list = new ArrayList<Object>();
list.add("foo");
executor.execute(list);

View File

@@ -21,30 +21,30 @@ public class JsfViewTests extends TestCase {
UrlBasedViewResolver resolver;
private JSFMockHelper jsfMock = new JSFMockHelper();
private final JSFMockHelper jsfMock = new JSFMockHelper();
public void setUp() throws Exception {
jsfMock.setUp();
jsfMock.facesContext().getApplication().setViewHandler(new ResourceCheckingViewHandler());
this.jsfMock.setUp();
this.jsfMock.facesContext().getApplication().setViewHandler(new ResourceCheckingViewHandler());
resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".xhtml");
resolver.setViewClass(JsfView.class);
resolver.setApplicationContext(new StaticWebApplicationContext());
this.resolver = new UrlBasedViewResolver();
this.resolver.setPrefix("/WEB-INF/views/");
this.resolver.setSuffix(".xhtml");
this.resolver.setViewClass(JsfView.class);
this.resolver.setApplicationContext(new StaticWebApplicationContext());
}
public void tearDown() throws Exception {
jsfMock.tearDown();
this.jsfMock.tearDown();
}
public void testViewResolution() throws Exception {
View view = resolver.resolveViewName("intro", new Locale("EN"));
View view = this.resolver.resolveViewName("intro", new Locale("EN"));
assertTrue(view instanceof JsfView);
}
public void testViewRender() throws Exception {
JsfView view = (JsfView) resolver.resolveViewName("intro", new Locale("EN"));
JsfView view = (JsfView) this.resolver.resolveViewName("intro", new Locale("EN"));
view.setApplicationContext(new StaticWebApplicationContext());
view.setServletContext(new MockServletContext());
view.render(new HashMap<String, Object>(), new MockHttpServletRequest(), new MockHttpServletResponse());

View File

@@ -22,16 +22,16 @@ public class AjaxViewRootTests extends TestCase {
UIViewRoot testTree = new UIViewRoot();
private StringWriter output = new StringWriter();
private final StringWriter output = new StringWriter();
protected void setUp() throws Exception {
jsf.setUp();
jsf.facesContext().getApplication().setViewHandler(new MockViewHandler());
jsf.facesContext().setResponseWriter(new MockResponseWriter(output, null, null));
this.jsf.setUp();
this.jsf.facesContext().getApplication().setViewHandler(new MockViewHandler());
this.jsf.facesContext().setResponseWriter(new MockResponseWriter(this.output, null, null));
UIForm form = new UIForm();
form.setId("foo");
testTree.getChildren().add(form);
this.testTree.getChildren().add(form);
UIPanel panel = new UIPanel();
panel.setId("bar");
form.getChildren().add(panel);
@@ -39,31 +39,31 @@ public class AjaxViewRootTests extends TestCase {
command.setId("baz");
panel.getChildren().add(command);
testTree.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
this.testTree.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
jsf.facesContext().setViewRoot(testTree);
this.jsf.facesContext().setViewRoot(this.testTree);
}
protected void tearDown() throws Exception {
jsf.tearDown();
this.jsf.tearDown();
}
public void testProcessDecodes() {
jsf.externalContext().getRequestParameterMap().put("processIds", "foo:bar, foo:baz");
this.jsf.externalContext().getRequestParameterMap().put("processIds", "foo:bar, foo:baz");
AjaxViewRoot ajaxRoot = new AjaxViewRoot(testTree);
AjaxViewRoot ajaxRoot = new AjaxViewRoot(this.testTree);
ajaxRoot.processDecodes(jsf.facesContext());
ajaxRoot.processDecodes(this.jsf.facesContext());
assertEquals(1, ajaxRoot.getProcessIds().length);
}
public void testEncodeAll_NoRenderIds() throws IOException {
jsf.externalContext().getRequestParameterMap().put("processIds", "foo:bar, foo:baz");
this.jsf.externalContext().getRequestParameterMap().put("processIds", "foo:bar, foo:baz");
AjaxViewRoot ajaxRoot = new AjaxViewRoot(testTree);
AjaxViewRoot ajaxRoot = new AjaxViewRoot(this.testTree);
ajaxRoot.encodeAll(jsf.facesContext());
ajaxRoot.encodeAll(this.jsf.facesContext());
assertEquals(1, ajaxRoot.getProcessIds().length);
assertEquals(1, ajaxRoot.getRenderIds().length);
@@ -73,14 +73,14 @@ public class AjaxViewRootTests extends TestCase {
public void testEncodeAll_RenderIdsExpr() throws IOException {
jsf.externalContext()
this.jsf.externalContext()
.getRequestMap()
.put(View.RENDER_FRAGMENTS_ATTRIBUTE,
StringUtils.delimitedListToStringArray("foo:bar,foo:baz", ",", " "));
AjaxViewRoot ajaxRoot = new AjaxViewRoot(testTree);
AjaxViewRoot ajaxRoot = new AjaxViewRoot(this.testTree);
ajaxRoot.encodeAll(jsf.facesContext());
ajaxRoot.encodeAll(this.jsf.facesContext());
assertEquals(1, ajaxRoot.getRenderIds().length);

View File

@@ -14,11 +14,11 @@ public class ProgressiveCommandLinkRendererTests extends TestCase {
ProgressiveCommandLinkRenderer renderer = new ProgressiveCommandLinkRenderer();
public void setUp() throws Exception {
jsf.setUp();
this.jsf.setUp();
}
public void tearDown() throws Exception {
jsf.tearDown();
this.jsf.tearDown();
}
public void testRenderOnClick_AjaxEnabled_NoParams() throws Exception {
@@ -31,15 +31,15 @@ public class ProgressiveCommandLinkRendererTests extends TestCase {
link.setId("foo");
form.getChildren().add(link);
RenderAttributeCallback callback = renderer.getAttributeCallbacks(link).get("onclick");
RenderAttributeCallback callback = this.renderer.getAttributeCallbacks(link).get("onclick");
jsf.facesContext().getResponseWriter().startElement("a", link);
this.jsf.facesContext().getResponseWriter().startElement("a", link);
callback.doRender(jsf.facesContext(), jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
callback.doRender(this.jsf.facesContext(), this.jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
jsf.facesContext().getResponseWriter().endElement("a");
this.jsf.facesContext().getResponseWriter().endElement("a");
assertEquals(expected, jsf.contentAsString());
assertEquals(expected, this.jsf.contentAsString());
}
public void testRenderOnClick_AjaxEnabled_WithParams() throws Exception {
@@ -61,15 +61,15 @@ public class ProgressiveCommandLinkRendererTests extends TestCase {
link.getChildren().add(param1);
link.getChildren().add(param2);
RenderAttributeCallback callback = renderer.getAttributeCallbacks(link).get("onclick");
RenderAttributeCallback callback = this.renderer.getAttributeCallbacks(link).get("onclick");
jsf.facesContext().getResponseWriter().startElement("a", link);
this.jsf.facesContext().getResponseWriter().startElement("a", link);
callback.doRender(jsf.facesContext(), jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
callback.doRender(this.jsf.facesContext(), this.jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
jsf.facesContext().getResponseWriter().endElement("a");
this.jsf.facesContext().getResponseWriter().endElement("a");
assertEquals(expected, jsf.contentAsString());
assertEquals(expected, this.jsf.contentAsString());
}
public void testRenderOnClick_AjaxDisabled_NoParams() throws Exception {
@@ -82,15 +82,15 @@ public class ProgressiveCommandLinkRendererTests extends TestCase {
link.setAjaxEnabled(false);
form.getChildren().add(link);
RenderAttributeCallback callback = renderer.getAttributeCallbacks(link).get("onclick");
RenderAttributeCallback callback = this.renderer.getAttributeCallbacks(link).get("onclick");
jsf.facesContext().getResponseWriter().startElement("a", link);
this.jsf.facesContext().getResponseWriter().startElement("a", link);
callback.doRender(jsf.facesContext(), jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
callback.doRender(this.jsf.facesContext(), this.jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
jsf.facesContext().getResponseWriter().endElement("a");
this.jsf.facesContext().getResponseWriter().endElement("a");
assertEquals(expected, jsf.contentAsString());
assertEquals(expected, this.jsf.contentAsString());
}
public void testRenderOnClick_AjaxDisabled_WithParams() throws Exception {
@@ -113,14 +113,14 @@ public class ProgressiveCommandLinkRendererTests extends TestCase {
link.getChildren().add(param1);
link.getChildren().add(param2);
RenderAttributeCallback callback = renderer.getAttributeCallbacks(link).get("onclick");
RenderAttributeCallback callback = this.renderer.getAttributeCallbacks(link).get("onclick");
jsf.facesContext().getResponseWriter().startElement("a", link);
this.jsf.facesContext().getResponseWriter().startElement("a", link);
callback.doRender(jsf.facesContext(), jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
callback.doRender(this.jsf.facesContext(), this.jsf.facesContext().getResponseWriter(), link, "onclick", null, "onclick");
jsf.facesContext().getResponseWriter().endElement("a");
this.jsf.facesContext().getResponseWriter().endElement("a");
assertEquals(expected, jsf.contentAsString());
assertEquals(expected, this.jsf.contentAsString());
}
}

View File

@@ -10,8 +10,7 @@ public class TestConverter implements Converter {
}
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Auto-generated method stub");
throw new UnsupportedOperationException();
}
public String getAsString(FacesContext context, UIComponent component, Object value) {

View File

@@ -15,13 +15,13 @@ public class FlowResourceHelperTests extends TestCase {
JSFMockHelper jsf = new JSFMockHelper();
protected void setUp() throws Exception {
jsf.setUp();
this.jsf.setUp();
// TODO figure out how to set the context path
jsf.facesContext().setResponseWriter(new MockResponseWriter(writer, "text/html", "UTF-8"));
this.jsf.facesContext().setResponseWriter(new MockResponseWriter(this.writer, "text/html", "UTF-8"));
}
protected void tearDown() throws Exception {
jsf.tearDown();
this.jsf.tearDown();
}
public final void testRenderScriptLink() throws IOException {
@@ -29,12 +29,12 @@ public class FlowResourceHelperTests extends TestCase {
String scriptPath = "/dojo/dojo.js";
String expectedUrl = "null/resources/dojo/dojo.js";
ResourceHelper.renderScriptLink(jsf.facesContext(), scriptPath);
ResourceHelper.renderScriptLink(jsf.facesContext(), scriptPath);
ResourceHelper.renderScriptLink(this.jsf.facesContext(), scriptPath);
ResourceHelper.renderScriptLink(this.jsf.facesContext(), scriptPath);
String expectedOutput = "<script type=\"text/javascript\" src=\"" + expectedUrl + "\"/>";
assertEquals(expectedOutput, writer.toString());
assertEquals(expectedOutput, this.writer.toString());
}
@@ -43,11 +43,11 @@ public class FlowResourceHelperTests extends TestCase {
String scriptPath = "/dijit/themes/dijit.css";
String expectedUrl = "null/resources/dijit/themes/dijit.css";
ResourceHelper.renderStyleLink(jsf.facesContext(), scriptPath);
ResourceHelper.renderStyleLink(jsf.facesContext(), scriptPath);
ResourceHelper.renderStyleLink(this.jsf.facesContext(), scriptPath);
ResourceHelper.renderStyleLink(this.jsf.facesContext(), scriptPath);
String expectedOutput = "<link type=\"text/css\" rel=\"stylesheet\" href=\"" + expectedUrl + "\"/>";
assertEquals(expectedOutput, writer.toString());
assertEquals(expectedOutput, this.writer.toString());
}
}

View File

@@ -27,18 +27,20 @@ public class FlowActionListenerTests extends TestCase {
RequestContext context = EasyMock.createMock(RequestContext.class);
protected void setUp() throws Exception {
jsfMock.setUp();
this.jsfMock.setUp();
listener = new FlowActionListener(jsfMock.application().getActionListener());
RequestContextHolder.setRequestContext(context);
this.listener = new FlowActionListener(this.jsfMock.application().getActionListener());
RequestContextHolder.setRequestContext(this.context);
LocalAttributeMap<Object> flash = new LocalAttributeMap<Object>();
EasyMock.expect(context.getFlashScope()).andStubReturn(flash);
EasyMock.expect(context.getCurrentState()).andStubReturn(new MockViewState());
EasyMock.replay(new Object[] { context });
EasyMock.expect(this.context.getFlashScope()).andStubReturn(flash);
EasyMock.expect(this.context.getCurrentState()).andStubReturn(new MockViewState());
EasyMock.replay(new Object[] { this.context });
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
super.tearDown();
this.jsfMock.tearDown();
RequestContextHolder.setRequestContext(null);
}
public final void testProcessAction() {
@@ -49,12 +51,12 @@ public class FlowActionListenerTests extends TestCase {
commandButton.setAction(binding);
ActionEvent event = new ActionEvent(commandButton);
listener.processAction(event);
this.listener.processAction(event);
assertTrue("The event was not signaled",
jsfMock.externalContext().getRequestMap().containsKey(JsfView.EVENT_KEY));
this.jsfMock.externalContext().getRequestMap().containsKey(JsfView.EVENT_KEY));
assertEquals("The event should be " + outcome, outcome,
jsfMock.externalContext().getRequestMap().get(JsfView.EVENT_KEY));
this.jsfMock.externalContext().getRequestMap().get(JsfView.EVENT_KEY));
}
public final void testProcessAction_NullOutcome() {
@@ -65,10 +67,10 @@ public class FlowActionListenerTests extends TestCase {
commandButton.setAction(binding);
ActionEvent event = new ActionEvent(commandButton);
listener.processAction(event);
this.listener.processAction(event);
assertFalse("An unexpected event was signaled",
jsfMock.externalContext().getRequestMap().containsKey(JsfView.EVENT_KEY));
this.jsfMock.externalContext().getRequestMap().containsKey(JsfView.EVENT_KEY));
}
private class MethodBindingStub extends MethodBinding {
@@ -95,8 +97,7 @@ public class FlowActionListenerTests extends TestCase {
super(new Flow("mockFlow"), "mockView", new ViewFactory() {
public View getView(RequestContext context) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Auto-generated method stub");
throw new UnsupportedOperationException();
}
});
}

View File

@@ -0,0 +1,94 @@
package org.springframework.faces.webflow;
import javax.el.ELContext;
import junit.framework.TestCase;
import org.apache.myfaces.test.el.MockELContext;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.test.MockRequestContext;
/**
* Tests for {@link FlowELResolver}.
*
* @author Phillip Webb
*/
public class FlowELResolverTests extends TestCase {
private final FlowELResolver resolver = new FlowELResolver();
private final RequestContext requestContext = new MockRequestContext();
private final ELContext elContext = new MockELContext();
protected void setUp() throws Exception {
RequestContextHolder.setRequestContext(this.requestContext);
}
protected void tearDown() throws Exception {
RequestContextHolder.setRequestContext(null);
}
public void testRequestContextResolve() throws Exception {
Object actual = this.resolver.getValue(this.elContext, null, "flowRequestContext");
assertTrue(this.elContext.isPropertyResolved());
assertNotNull(actual);
assertSame(this.requestContext, actual);
}
public void testImplicitFlowResolve() throws Exception {
Object actual = this.resolver.getValue(this.elContext, null, "flowScope");
assertTrue(this.elContext.isPropertyResolved());
assertNotNull(actual);
assertSame(this.requestContext.getFlowScope(), actual);
}
public void testFlowResourceResolve() throws Exception {
ApplicationContext applicationContext = new StaticWebApplicationContext();
((Flow) this.requestContext.getActiveFlow()).setApplicationContext(applicationContext);
Object actual = this.resolver.getValue(this.elContext, null, "resourceBundle");
assertTrue(this.elContext.isPropertyResolved());
assertNotNull(actual);
assertSame(applicationContext, actual);
}
public void testScopeResolve() throws Exception {
this.requestContext.getFlowScope().put("test", "test");
Object actual = this.resolver.getValue(this.elContext, null, "test");
assertTrue(this.elContext.isPropertyResolved());
assertEquals("test", actual);
}
public void testMapAdaptableResolve() throws Exception {
LocalAttributeMap<String> base = new LocalAttributeMap<String>();
base.put("test", "test");
Object actual = this.resolver.getValue(this.elContext, base, "test");
assertTrue(this.elContext.isPropertyResolved());
assertEquals("test", actual);
}
public void testBeanResolveWithRequestContext() throws Exception {
StaticWebApplicationContext applicationContext = new StaticWebApplicationContext();
((Flow) this.requestContext.getActiveFlow()).setApplicationContext(applicationContext);
applicationContext.registerSingleton("test", Bean.class);
Object actual = this.resolver.getValue(this.elContext, null, "test");
assertTrue(this.elContext.isPropertyResolved());
assertNotNull(actual);
assertTrue(actual instanceof Bean);
}
public void testBeanResolveWithoutRequestContext() throws Exception {
RequestContextHolder.setRequestContext(null);
Object actual = this.resolver.getValue(this.elContext, null, "test");
assertFalse(this.elContext.isPropertyResolved());
assertNull(actual);
}
public static class Bean {
}
}

View File

@@ -19,6 +19,7 @@ import org.springframework.binding.message.DefaultMessageContext;
import org.springframework.binding.message.Message;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.faces.webflow.FlowFacesContext.FacesMessageSource;
import org.springframework.webflow.execution.RequestContext;
public class FlowFacesContextTests extends TestCase {
@@ -35,45 +36,43 @@ public class FlowFacesContextTests extends TestCase {
@SuppressWarnings("cast")
protected void setUp() throws Exception {
jsf.setUp();
requestContext = (RequestContext) EasyMock.createMock(RequestContext.class);
facesContext = new Jsf2FlowFacesContext(requestContext, jsf.facesContext());
this.jsf.setUp();
this.requestContext = (RequestContext) EasyMock.createMock(RequestContext.class);
this.facesContext = new FlowFacesContext(this.requestContext, this.jsf.facesContext());
setupMessageContext();
}
protected void tearDown() throws Exception {
jsf.tearDown();
super.tearDown();
this.jsf.tearDown();
}
public final void testCurrentInstance() {
assertSame(FacesContext.getCurrentInstance(), facesContext);
assertSame(FacesContext.getCurrentInstance(), this.facesContext);
}
public final void testAddMessage() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = new DefaultMessageContext();
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
this.facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
assertEquals("Message count is incorrect", 2, messageContext.getAllMessages().length);
Message summaryMessage = messageContext.getMessagesBySource("foo_summary")[0];
assertEquals("foo", summaryMessage.getText());
Message detailMessage = messageContext.getMessagesBySource("foo_detail")[0];
assertEquals("bar", detailMessage.getText());
assertEquals("Message count is incorrect", 1, this.messageContext.getAllMessages().length);
Message message = this.messageContext.getMessagesBySource(new FacesMessageSource("foo"))[0];
assertEquals("foo : bar", message.getText());
}
public final void testGetGlobalMessagesOnly() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = new DefaultMessageContext();
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "FOO", "BAR"));
this.facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
this.facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "FOO", "BAR"));
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages(null);
Iterator<FacesMessage> i = this.facesContext.getMessages(null);
while (i.hasNext()) {
FacesMessage message = i.next();
assertNotNull(message);
@@ -83,15 +82,15 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testGetAllMessages() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = new DefaultMessageContext();
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "FOO", "BAR"));
this.facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
this.facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "FOO", "BAR"));
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages();
Iterator<FacesMessage> i = this.facesContext.getMessages();
while (i.hasNext()) {
FacesMessage message = i.next();
assertNotNull(message);
@@ -101,31 +100,26 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testAddMessages_MultipleNullIds() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = new DefaultMessageContext();
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "zoo", "zar"));
this.facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "foo", "bar"));
this.facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "zoo", "zar"));
assertEquals("Message count is incorrect", 4, messageContext.getAllMessages().length);
Message summaryMessage1 = messageContext.getMessagesBySource("null_summary")[0];
assertEquals("foo", summaryMessage1.getText());
Message detailMessage1 = messageContext.getMessagesBySource("null_detail")[0];
assertEquals("bar", detailMessage1.getText());
Message summaryMessage2 = messageContext.getMessagesBySource("null_summary")[1];
assertEquals("zoo", summaryMessage2.getText());
Message detailMessage2 = messageContext.getMessagesBySource("null_detail")[1];
assertEquals("zar", detailMessage2.getText());
assertEquals("Message count is incorrect", 2, this.messageContext.getAllMessages().length);
Message[] messages = this.messageContext.getMessagesBySource(new FacesMessageSource(null));
assertEquals("foo : bar", messages[0].getText());
assertEquals("zoo : zar", messages[1].getText());
}
public final void testGetMessages() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages();
Iterator<FacesMessage> i = this.facesContext.getMessages();
while (i.hasNext()) {
assertNotNull(i.next());
iterationCount++;
@@ -134,17 +128,17 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testMutableGetMessages() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("TESTID", new FacesMessage("summary1"));
FacesMessage soruceMessage = facesContext.getMessages("TESTID").next();
this.facesContext.addMessage("TESTID", new FacesMessage("summary1"));
FacesMessage soruceMessage = this.facesContext.getMessages("TESTID").next();
soruceMessage.setSummary("summary2");
// check that message sticks around even when the facesContext has been torn down and re-created during the
// processing of the current request
FacesContext newFacesContext = new FlowFacesContext(requestContext, jsf.facesContext());
FacesContext newFacesContext = new FlowFacesContext(this.requestContext, this.jsf.facesContext());
assertSame(FacesContext.getCurrentInstance(), newFacesContext);
FacesMessage gotMessage = newFacesContext.getMessages("TESTID").next();
@@ -152,12 +146,12 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testGetMessagesByClientId_ForComponent() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages("componentId");
Iterator<FacesMessage> i = this.facesContext.getMessages("componentId");
while (i.hasNext()) {
FacesMessage message = i.next();
assertNotNull(message);
@@ -169,12 +163,12 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testGetMessagesByClientId_ForUserMessage() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
int iterationCount = 0;
Iterator<FacesMessage> i = facesContext.getMessages("userMessage");
Iterator<FacesMessage> i = this.facesContext.getMessages("userMessage");
while (i.hasNext()) {
FacesMessage message = i.next();
assertNotNull(message);
@@ -186,18 +180,18 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testgetMessagesByClientId_InvalidId() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
Iterator<FacesMessage> i = facesContext.getMessages("unknown");
Iterator<FacesMessage> i = this.facesContext.getMessages("unknown");
assertFalse(i.hasNext());
}
public final void testGetClientIdsWithMessages() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
List<String> expectedOrderedIds = new ArrayList<String>();
expectedOrderedIds.add(null);
@@ -205,7 +199,7 @@ public class FlowFacesContextTests extends TestCase {
expectedOrderedIds.add("userMessage");
int iterationCount = 0;
Iterator<String> i = facesContext.getClientIdsWithMessages();
Iterator<String> i = this.facesContext.getClientIdsWithMessages();
while (i.hasNext()) {
String clientId = i.next();
assertEquals("Client id not expected", expectedOrderedIds.get(iterationCount), clientId);
@@ -216,11 +210,11 @@ public class FlowFacesContextTests extends TestCase {
public final void testMessagesAreSerializable() throws Exception {
DefaultMessageContext messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("TESTID", new FacesMessage("summary1"));
FacesMessage sourceMessage = facesContext.getMessages("TESTID").next();
this.facesContext.addMessage("TESTID", new FacesMessage("summary1"));
FacesMessage sourceMessage = this.facesContext.getMessages("TESTID").next();
sourceMessage.setSummary("summary2");
sourceMessage.setSeverity(FacesMessage.SEVERITY_FATAL);
@@ -238,11 +232,11 @@ public class FlowFacesContextTests extends TestCase {
ois.close();
messageContext.restoreMessages(mementoRead);
EasyMock.reset(new Object[] { requestContext });
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
EasyMock.reset(new Object[] { this.requestContext });
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { this.requestContext });
FacesContext newFacesContext = new FlowFacesContext(requestContext, jsf.facesContext());
FacesContext newFacesContext = new FlowFacesContext(this.requestContext, this.jsf.facesContext());
assertSame(FacesContext.getCurrentInstance(), newFacesContext);
FacesMessage gotMessage = newFacesContext.getMessages("TESTID").next();
assertEquals("summary2", gotMessage.getSummary());
@@ -250,50 +244,42 @@ public class FlowFacesContextTests extends TestCase {
}
public final void testGetMaximumSeverity() {
messageContext = prepopulatedMessageContext;
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = this.prepopulatedMessageContext;
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
assertEquals(FacesMessage.SEVERITY_FATAL, facesContext.getMaximumSeverity());
assertEquals(FacesMessage.SEVERITY_FATAL, this.facesContext.getMaximumSeverity());
}
public final void testGetELContext() {
assertNotNull(facesContext.getELContext());
assertSame(facesContext, facesContext.getELContext().getContext(FacesContext.class));
assertNotNull(this.facesContext.getELContext());
assertSame(this.facesContext, this.facesContext.getELContext().getContext(FacesContext.class));
}
public final void testValidationFailed() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
this.messageContext = new DefaultMessageContext();
EasyMock.expect(this.requestContext.getMessageContext()).andStubReturn(this.messageContext);
EasyMock.replay(new Object[] { this.requestContext });
facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_ERROR, "foo", "bar"));
this.facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_ERROR, "foo", "bar"));
assertEquals(true, facesContext.isValidationFailed());
assertEquals(true, this.facesContext.isValidationFailed());
}
private void setupMessageContext() {
prepopulatedMessageContext = new DefaultMessageContext();
prepopulatedMessageContext.addMessage(new MessageBuilder().source("null_summary").defaultText("foo").info()
.build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("null_detail").defaultText("foo").info()
.build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("componentId_summary")
.defaultText("componentId_summary1").warning().build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("componentId_detail")
.defaultText("componentId_detail1").warning().build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("componentId_summary")
.defaultText("componentId_summary2").warning().build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("componentId_detail")
.defaultText("componentId_detail2").warning().build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("userMessage").defaultText("userMessage")
this.prepopulatedMessageContext = new DefaultMessageContext();
this.prepopulatedMessageContext.addMessage(new FlowFacesContext.FlowFacesMessage(new FacesMessageSource(null),
new FacesMessage("foo")));
this.prepopulatedMessageContext.addMessage(new FlowFacesContext.FlowFacesMessage(new FacesMessageSource(
"componentId"), new FacesMessage("componentId_summary1", "componentId_detail1")));
this.prepopulatedMessageContext.addMessage(new FlowFacesContext.FlowFacesMessage(new FacesMessageSource(
"componentId"), new FacesMessage("componentId_summary2", "componentId_detail2")));
this.prepopulatedMessageContext.addMessage(new FlowFacesContext.FlowFacesMessage(new FacesMessageSource(null),
new FacesMessage("baz")));
this.prepopulatedMessageContext.addMessage(new MessageBuilder().source("userMessage").defaultText("userMessage")
.info().build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("null_summary").defaultText("baz").error()
.build());
prepopulatedMessageContext.addMessage(new MessageBuilder().source("null_detail").defaultText("baz").error()
.build());
prepopulatedMessageContext.addMessage(new MessageBuilder().defaultText("Subzero Wins - Fatality").fatal()
this.prepopulatedMessageContext.addMessage(new MessageBuilder().defaultText("Subzero Wins - Fatality").fatal()
.build());
}
}

View File

@@ -16,6 +16,11 @@ import org.springframework.webflow.test.MockRequestContext;
public class FlowPartialViewContextTests extends TestCase {
protected void tearDown() throws Exception {
super.tearDown();
RequestContextHolder.setRequestContext(null);
}
public void testReturnFragmentIds() throws Exception {
String[] fragmentIds = new String[] { "foo", "bar" };

View File

@@ -0,0 +1,74 @@
package org.springframework.faces.webflow;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.FlowExecutionContext;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.test.MockFlowExecutionKey;
public class FlowResponseStateManagerTests extends TestCase {
private final JSFMockHelper jsfMock = new JSFMockHelper();
private FlowResponseStateManager responseStateManager;
private RequestContext requestContext;
private FlowExecutionContext flowExecutionContext;
protected void setUp() throws Exception {
this.jsfMock.setUp();
StaticWebApplicationContext webappContext = new StaticWebApplicationContext();
webappContext.setServletContext(this.jsfMock.servletContext());
this.requestContext = EasyMock.createMock(RequestContext.class);
RequestContextHolder.setRequestContext(this.requestContext);
this.flowExecutionContext = EasyMock.createMock(FlowExecutionContext.class);
this.responseStateManager = new FlowResponseStateManager(null);
}
protected void tearDown() throws Exception {
super.tearDown();
this.jsfMock.tearDown();
RequestContextHolder.setRequestContext(null);
}
public void testname() throws Exception {
}
public void testWriteFlowSerializedView() throws Exception {
EasyMock.expect(this.flowExecutionContext.getKey()).andReturn(new MockFlowExecutionKey("e1s1"));
LocalAttributeMap<Object> viewMap = new LocalAttributeMap<Object>();
EasyMock.expect(this.requestContext.getViewScope()).andStubReturn(viewMap);
EasyMock.expect(this.requestContext.getFlowExecutionContext()).andReturn(this.flowExecutionContext);
EasyMock.replay(this.requestContext, this.flowExecutionContext);
Object state = new Object();
this.responseStateManager.writeState(this.jsfMock.facesContext(), state);
assertEquals(state, viewMap.get(FlowResponseStateManager.FACES_VIEW_STATE));
assertEquals(
"<input type=\"hidden\" name=\"javax.faces.ViewState\" id=\"javax.faces.ViewState\" value=\"e1s1\" />",
this.jsfMock.contentAsString());
EasyMock.verify(this.flowExecutionContext, this.requestContext);
}
public void testGetState() throws Exception {
Object state = new Object();
LocalAttributeMap<Object> viewMap = new LocalAttributeMap<Object>();
viewMap.put(FlowResponseStateManager.FACES_VIEW_STATE, state);
EasyMock.expect(this.requestContext.getViewScope()).andStubReturn(viewMap);
EasyMock.replay(this.requestContext);
Object actual = this.responseStateManager.getState(this.jsfMock.facesContext(), "viewId");
assertSame(state, actual);
EasyMock.verify(this.requestContext);
}
}

View File

@@ -1,73 +0,0 @@
package org.springframework.faces.webflow;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.FlowExecutionContext;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.test.MockFlowExecutionKey;
public class FlowViewResponseStateManagerTests extends TestCase {
private JSFMockHelper jsfMock = new JSFMockHelper();
private FlowViewResponseStateManager responseStateManager;
private RequestContext requestContext;
private FlowExecutionContext flowExecutionContext;
protected void setUp() throws Exception {
jsfMock.setUp();
StaticWebApplicationContext webappContext = new StaticWebApplicationContext();
webappContext.setServletContext(jsfMock.servletContext());
requestContext = EasyMock.createMock(RequestContext.class);
RequestContextHolder.setRequestContext(requestContext);
flowExecutionContext = EasyMock.createMock(FlowExecutionContext.class);
responseStateManager = new FlowViewResponseStateManager(null);
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
}
public void testWriteFlowSerializedView() throws Exception {
EasyMock.expect(flowExecutionContext.getKey()).andReturn(new MockFlowExecutionKey("e1s1"));
LocalAttributeMap<Object> viewMap = new LocalAttributeMap<Object>();
EasyMock.expect(requestContext.getViewScope()).andStubReturn(viewMap);
EasyMock.expect(requestContext.getFlowExecutionContext()).andReturn(flowExecutionContext);
EasyMock.replay(requestContext, flowExecutionContext);
FlowSerializedView flowSerializedView = new FlowSerializedView("viewId", null, null);
responseStateManager.writeState(jsfMock.facesContext(), flowSerializedView);
assertEquals(flowSerializedView, viewMap.get(FlowViewStateManager.SERIALIZED_VIEW_STATE));
assertEquals(
"<input type=\"hidden\" name=\"javax.faces.ViewState\" id=\"javax.faces.ViewState\" value=\"e1s1\" />",
jsfMock.contentAsString());
EasyMock.verify(flowExecutionContext, requestContext);
}
public void testGetState() throws Exception {
Object treeStructure = new Object();
Object componentState = new Object();
FlowSerializedView flowSerializedView = new FlowSerializedView("viewId", treeStructure, componentState);
LocalAttributeMap<Object> viewMap = new LocalAttributeMap<Object>();
viewMap.put(FlowViewStateManager.SERIALIZED_VIEW_STATE, flowSerializedView);
EasyMock.expect(requestContext.getViewScope()).andStubReturn(viewMap);
EasyMock.replay(requestContext);
Object state = responseStateManager.getState(jsfMock.facesContext(), "viewId");
assertTrue(state instanceof Object[]);
assertSame(treeStructure, ((Object[]) state)[0]);
assertSame(componentState, ((Object[]) state)[1]);
EasyMock.verify(requestContext);
}
}

View File

@@ -10,7 +10,7 @@ public class JSFManagedBean {
List<String> values = new ArrayList<String>();
public JSFModel getModel() {
return model;
return this.model;
}
public void setModel(JSFModel model) {
@@ -18,7 +18,7 @@ public class JSFManagedBean {
}
public String getProp1() {
return prop1;
return this.prop1;
}
public void setProp1(String prop1) {
@@ -26,10 +26,10 @@ public class JSFManagedBean {
}
public void addValue(String value) {
values.add(value);
this.values.add(value);
}
public List<String> getValues() {
return values;
return this.values;
}
}

View File

@@ -39,66 +39,66 @@ import org.apache.myfaces.test.mock.visit.MockVisitContextFactory;
*/
public class JSFMockHelper {
private JSFMock mock = new JSFMock();
private final JSFMock mock = new JSFMock();
public Application application() {
return mock.application();
return this.mock.application();
}
public MockServletConfig config() {
return mock.config();
return this.mock.config();
}
public String contentAsString() throws IOException {
return mock.contentAsString();
return this.mock.contentAsString();
}
public MockExternalContext externalContext() {
return mock.externalContext();
return this.mock.externalContext();
}
public FacesContext facesContext() {
return mock.facesContext();
return this.mock.facesContext();
}
public FacesContextFactory facesContextFactory() {
return mock.facesContextFactory();
return this.mock.facesContextFactory();
}
public MockLifecycle lifecycle() {
return mock.lifecycle();
return this.mock.lifecycle();
}
public MockLifecycleFactory lifecycleFactory() {
return mock.lifecycleFactory();
return this.mock.lifecycleFactory();
}
public MockRenderKit renderKit() {
return mock.renderKit();
return this.mock.renderKit();
}
public MockHttpServletRequest request() {
return mock.request();
return this.mock.request();
}
public MockHttpServletResponse response() {
return mock.response();
return this.mock.response();
}
public MockServletContext servletContext() {
return mock.servletContext();
return this.mock.servletContext();
}
public MockHttpSession session() {
return mock.session();
return this.mock.session();
}
public void setUp() throws Exception {
mock.setUp();
this.mock.setUp();
}
public void tearDown() throws Exception {
mock.tearDown();
this.mock.tearDown();
}
private static class JSFMock extends AbstractJsfTestCase {
@@ -120,18 +120,18 @@ public class JSFMockHelper {
}
// Set up a new thread context class loader
threadContextClassLoader = Thread.currentThread().getContextClassLoader();
this.threadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
new URLClassLoader(new URL[0], this.getClass().getClassLoader()));
// Set up Servlet API Objects
servletContext = new MockServletContext();
config = new MockServletConfig(servletContext);
session = new MockHttpSession();
session.setServletContext(servletContext);
request = new MockHttpServletRequest(session);
request.setServletContext(servletContext);
response = new MockHttpServletResponse();
this.servletContext = new MockServletContext();
this.config = new MockServletConfig(this.servletContext);
this.session = new MockHttpSession();
this.session.setServletContext(this.servletContext);
this.request = new MockHttpServletRequest(this.session);
this.request.setServletContext(this.servletContext);
this.response = new MockHttpServletResponse();
// Set up JSF API Objects
FactoryFinder.setFactory(FactoryFinder.APPLICATION_FACTORY, MockApplicationFactory.class.getName());
@@ -141,98 +141,98 @@ public class JSFMockHelper {
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
MockPartialViewContextFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY, MockVisitContextFactory.class.getName());
lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
lifecycle = (MockLifecycle) lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
facesContext = facesContextFactory.getFacesContext(servletContext, request, response, lifecycle);
externalContext = (MockExternalContext) facesContext.getExternalContext();
facesContext.setResponseWriter(new MockResponseWriter(response.getWriter()));
this.lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
this.lifecycle = (MockLifecycle) this.lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
this.facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
this.facesContext = this.facesContextFactory.getFacesContext(this.servletContext, this.request, this.response, this.lifecycle);
this.externalContext = (MockExternalContext) this.facesContext.getExternalContext();
this.facesContext.setResponseWriter(new MockResponseWriter(this.response.getWriter()));
UIViewRoot root = new UIViewRoot();
root.setViewId("/viewId");
root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);
facesContext.setViewRoot(root);
this.facesContext.setViewRoot(root);
ApplicationFactory applicationFactory = (ApplicationFactory) FactoryFinder
.getFactory(FactoryFinder.APPLICATION_FACTORY);
application = (org.apache.myfaces.test.mock.MockApplication) applicationFactory.getApplication();
this.application = (org.apache.myfaces.test.mock.MockApplication) applicationFactory.getApplication();
RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder
.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
renderKit = new MockRenderKit();
renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, renderKit);
this.renderKit = new MockRenderKit();
renderKitFactory.addRenderKit(RenderKitFactory.HTML_BASIC_RENDER_KIT, this.renderKit);
}
public void tearDown() throws Exception {
application = null;
config = null;
externalContext = null;
if (facesContext != null) {
facesContext.release();
this.application = null;
this.config = null;
this.externalContext = null;
if (this.facesContext != null) {
this.facesContext.release();
}
facesContext = null;
lifecycle = null;
lifecycleFactory = null;
renderKit = null;
request = null;
response = null;
servletContext = null;
session = null;
this.facesContext = null;
this.lifecycle = null;
this.lifecycleFactory = null;
this.renderKit = null;
this.request = null;
this.response = null;
this.servletContext = null;
this.session = null;
FactoryFinder.releaseFactories();
Thread.currentThread().setContextClassLoader(threadContextClassLoader);
threadContextClassLoader = null;
Thread.currentThread().setContextClassLoader(this.threadContextClassLoader);
this.threadContextClassLoader = null;
}
public org.apache.myfaces.test.mock.MockApplication application() {
return application;
return this.application;
}
public MockServletConfig config() {
return config;
return this.config;
}
public String contentAsString() throws IOException {
MockPrintWriter writer = (MockPrintWriter) response.getWriter();
MockPrintWriter writer = (MockPrintWriter) this.response.getWriter();
return new String(writer.content());
}
public MockExternalContext externalContext() {
return externalContext;
return this.externalContext;
}
public FacesContext facesContext() {
return facesContext;
return this.facesContext;
}
public FacesContextFactory facesContextFactory() {
return facesContextFactory;
return this.facesContextFactory;
}
public MockLifecycle lifecycle() {
return lifecycle;
return this.lifecycle;
}
public MockLifecycleFactory lifecycleFactory() {
return lifecycleFactory;
return this.lifecycleFactory;
}
public MockRenderKit renderKit() {
return renderKit;
return this.renderKit;
}
public MockHttpServletRequest request() {
return request;
return this.request;
}
public MockHttpServletResponse response() {
return response;
return this.response;
}
public MockServletContext servletContext() {
return servletContext;
return this.servletContext;
}
public MockHttpSession session() {
return session;
return this.session;
}
}

View File

@@ -4,7 +4,7 @@ public class JSFModel {
String value;
public String getValue() {
return value;
return this.value;
}
public void setValue(String value) {

View File

@@ -6,27 +6,27 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
public class JsfAjaxHandlerTests extends TestCase {
private JSFMockHelper jsfMock = new JSFMockHelper();
private final JSFMockHelper jsfMock = new JSFMockHelper();
private JsfAjaxHandler ajaxHandler;
protected void setUp() throws Exception {
jsfMock.setUp();
this.jsfMock.setUp();
StaticWebApplicationContext webappContext = new StaticWebApplicationContext();
webappContext.setServletContext(jsfMock.servletContext());
ajaxHandler = new JsfAjaxHandler();
ajaxHandler.setApplicationContext(webappContext);
webappContext.setServletContext(this.jsfMock.servletContext());
this.ajaxHandler = new JsfAjaxHandler();
this.ajaxHandler.setApplicationContext(webappContext);
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
this.jsfMock.tearDown();
}
public void testSendAjaxRedirect() throws Exception {
ajaxHandler.sendAjaxRedirectInternal("/target", jsfMock.request(), jsfMock.response(), false);
this.ajaxHandler.sendAjaxRedirectInternal("/target", this.jsfMock.request(), this.jsfMock.response(), false);
assertEquals(
"<?xml version='1.0' encoding='utf-8'?>\n<partial-response><redirect url=\"/target\"/></partial-response>",
jsfMock.contentAsString());
assertEquals("application/xml", jsfMock.response().getContentType());
this.jsfMock.contentAsString());
assertEquals("application/xml", this.jsfMock.response().getContentType());
}
}

View File

@@ -37,11 +37,11 @@ public class JsfFinalResponseActionTests extends TestCase {
private JsfViewFactory factory;
private JSFMockHelper jsfMock = new JSFMockHelper();
private final JSFMockHelper jsfMock = new JSFMockHelper();
private RequestContext context = EasyMock.createMock(RequestContext.class);
private final RequestContext context = EasyMock.createMock(RequestContext.class);
private ViewHandler viewHandler = new NoRenderViewHandler();
private final ViewHandler viewHandler = new NoRenderViewHandler();
private TestLifecycle lifecycle;
@@ -54,29 +54,31 @@ public class JsfFinalResponseActionTests extends TestCase {
}
protected void tearDown() throws Exception {
jsfMock.tearDown();
super.tearDown();
this.jsfMock.tearDown();
RequestContextHolder.setRequestContext(null);
}
private void configureJsf() throws Exception {
jsfMock.setUp();
this.jsfMock.setUp();
trackingListener = new TrackingPhaseListener();
jsfMock.lifecycle().addPhaseListener(trackingListener);
jsfMock.facesContext().setViewRoot(null);
jsfMock.facesContext().getApplication().setViewHandler(viewHandler);
lifecycle = new TestLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(parser.parseExpression("#{'" + VIEW_ID + "'}", new FluentParserContext()
.template().evaluate(RequestContext.class).expectResult(String.class)), lifecycle);
RequestContextHolder.setRequestContext(context);
this.trackingListener = new TrackingPhaseListener();
this.jsfMock.lifecycle().addPhaseListener(this.trackingListener);
this.jsfMock.facesContext().setViewRoot(null);
this.jsfMock.facesContext().getApplication().setViewHandler(this.viewHandler);
this.lifecycle = new TestLifecycle(this.jsfMock.lifecycle());
this.factory = new JsfViewFactory(this.parser.parseExpression("#{'" + VIEW_ID + "'}", new FluentParserContext()
.template().evaluate(RequestContext.class).expectResult(String.class)), this.lifecycle);
RequestContextHolder.setRequestContext(this.context);
MockExternalContext ext = new MockExternalContext();
ext.setNativeContext(new MockServletContext());
ext.setNativeRequest(new MockHttpServletRequest());
ext.setNativeResponse(new MockHttpServletResponse());
EasyMock.expect(context.getExternalContext()).andStubReturn(ext);
EasyMock.expect(this.context.getExternalContext()).andStubReturn(ext);
LocalAttributeMap<Object> requestMap = new LocalAttributeMap<Object>();
EasyMock.expect(context.getFlashScope()).andStubReturn(requestMap);
EasyMock.expect(context.getRequestParameters()).andStubReturn(
EasyMock.expect(this.context.getFlashScope()).andStubReturn(requestMap);
EasyMock.expect(this.context.getRequestParameters()).andStubReturn(
new LocalParameterMap(new HashMap<String, Object>()));
}
@@ -85,18 +87,18 @@ public class JsfFinalResponseActionTests extends TestCase {
UIViewRoot newRoot = new UIViewRoot();
newRoot.setViewId(VIEW_ID);
newRoot.setRenderKitId("HTML_BASIC");
((MockViewHandler) viewHandler).setCreateView(newRoot);
context.inViewState();
((MockViewHandler) this.viewHandler).setCreateView(newRoot);
this.context.inViewState();
EasyMock.expectLastCall().andReturn(false);
EasyMock.replay(new Object[] { context });
EasyMock.replay(new Object[] { this.context });
View view = factory.getView(context);
View view = this.factory.getView(this.context);
((JsfView) view).getViewRoot().setTransient(true);
view.render();
assertTrue(newRoot.isTransient());
assertTrue(((NoRenderViewHandler) viewHandler).rendered);
assertTrue(((NoRenderViewHandler) this.viewHandler).rendered);
}
private class TestLifecycle extends FlowLifecycle {
@@ -108,29 +110,29 @@ public class JsfFinalResponseActionTests extends TestCase {
}
public void execute(FacesContext context) throws FacesException {
assertFalse("Lifecycle executed more than once", executed);
assertFalse("Lifecycle executed more than once", this.executed);
super.execute(context);
executed = true;
this.executed = true;
}
}
private class TrackingPhaseListener implements PhaseListener {
private List<String> phaseCallbacks = new ArrayList<String>();
private final List<String> phaseCallbacks = new ArrayList<String>();
public void afterPhase(PhaseEvent event) {
String phaseCallback = "AFTER_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.",
phaseCallbacks.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
this.phaseCallbacks.contains(phaseCallback));
this.phaseCallbacks.add(phaseCallback);
}
public void beforePhase(PhaseEvent event) {
String phaseCallback = "BEFORE_" + event.getPhaseId();
assertFalse("Phase callback " + phaseCallback + " already executed.",
phaseCallbacks.contains(phaseCallback));
phaseCallbacks.add(phaseCallback);
this.phaseCallbacks.contains(phaseCallback));
this.phaseCallbacks.add(phaseCallback);
}
public PhaseId getPhaseId() {
@@ -142,7 +144,7 @@ public class JsfFinalResponseActionTests extends TestCase {
boolean rendered = false;
public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {
rendered = true;
this.rendered = true;
}
}

View File

@@ -19,22 +19,22 @@ public class JsfFlowHandlerAdapterTests extends TestCase {
protected void setUp() throws Exception {
StaticWebApplicationContext context = new StaticWebApplicationContext();
context.setServletContext(new MockServletContext());
handlerAdapter = new JsfFlowHandlerAdapter();
handlerAdapter.setApplicationContext(context);
handlerAdapter.setFlowExecutor(new StubFlowExecutor());
this.handlerAdapter = new JsfFlowHandlerAdapter();
this.handlerAdapter.setApplicationContext(context);
this.handlerAdapter.setFlowExecutor(new StubFlowExecutor());
}
public void testAjaxHandlerNotProvided() throws Exception {
handlerAdapter.afterPropertiesSet();
assertNotNull(handlerAdapter.getAjaxHandler());
assertTrue(handlerAdapter.getAjaxHandler() instanceof JsfAjaxHandler);
this.handlerAdapter.afterPropertiesSet();
assertNotNull(this.handlerAdapter.getAjaxHandler());
assertTrue(this.handlerAdapter.getAjaxHandler() instanceof JsfAjaxHandler);
}
public void testAjaxHandlerProvided() throws Exception {
AjaxHandler myAjaxHandler = new SpringJavascriptAjaxHandler();
handlerAdapter.setAjaxHandler(myAjaxHandler);
handlerAdapter.afterPropertiesSet();
assertTrue(myAjaxHandler == handlerAdapter.getAjaxHandler());
this.handlerAdapter.setAjaxHandler(myAjaxHandler);
this.handlerAdapter.afterPropertiesSet();
assertTrue(myAjaxHandler == this.handlerAdapter.getAjaxHandler());
}
private final class StubFlowExecutor implements FlowExecutor {

Some files were not shown because too many files have changed in this diff Show More