SWF-1379 Remove dependency on the Portlet bridge for JSF and provide basic support within Web Flow for working Portlets and JSF. Update portlet samples
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<classpathentry kind="var" path="IVY_CACHE/com.sun.faces/jsf-api/2.0.3/jsf-api-2.0.3.jar" sourcepath="/IVY_CACHE/com.sun.faces/jsf-api/2.0.3/jsf-api-2.0.3-sources.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.4.0/com.springsource.javax.servlet-2.4.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.4.0/com.springsource.javax.servlet-sources-2.4.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-2.0.0.jar" sourcepath="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-sources-2.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-1.7.0.jar" sourcepath="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.beanutils/1.7.0/com.springsource.org.apache.commons.beanutils-sources-1.7.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-3.2.0.jar" sourcepath="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.collections/3.2.0/com.springsource.org.apache.commons.collections-sources-3.2.0.jar"/>
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<conf name="mojarra12" visibility="public"/>
|
||||
<conf name="myfaces12" visibility="public"/>
|
||||
<conf name="jsf11" visibility="public"/>
|
||||
<conf name="myfacesPortlet20" visibility="public"/>
|
||||
</configurations>
|
||||
|
||||
<publications>
|
||||
@@ -29,6 +28,7 @@
|
||||
<dependency org="com.sun.facelets" name="com.springsource.com.sun.facelets" rev="1.1.14" conf="optional->runtime" />
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->runtime" />
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.4.0" conf="provided->runtime" />
|
||||
<dependency org="javax.portlet" name="com.springsource.javax.portlet" rev="2.0.0" conf="provided->runtime" />
|
||||
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->runtime"/>
|
||||
<dependency org="org.richfaces" name="com.springsource.org.richfaces" rev="3.1.4.GA" conf="optional->runtime" />
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.4.RELEASE" conf="compile->runtime"/>
|
||||
@@ -36,6 +36,7 @@
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.4.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.4.RELEASE" conf="compile->runtime" />
|
||||
<dependency org="org.springframework" name="org.springframework.web" rev="3.0.4.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.web.portlet" rev="3.0.4.RELEASE" conf="optional->runtime" />
|
||||
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="3.0.4.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework.security" name="org.springframework.security.core" rev="3.0.2.RELEASE" conf="optional->runtime" />
|
||||
<dependency org="org.springframework.security" name="org.springframework.security.web" rev="3.0.2.RELEASE" conf="optional->runtime" />
|
||||
@@ -63,10 +64,6 @@
|
||||
<dependency org="org.apache.myfaces" name="com.springsource.org.apache.myfaces.javax.faces" rev="1.1.5" conf="jsf11->runtime" />
|
||||
<dependency org="org.apache.myfaces" name="com.springsource.org.apache.myfaces" rev="1.1.5" conf="jsf11->runtime" />
|
||||
|
||||
<!-- MyFaces JSF-Portlet Bridge for Portlet 2.0 and JSF 1.2 -->
|
||||
<dependency org="org.apache.myfaces.portlet-bridge" name="portlet-bridge-api" rev="2.0.0-alpha-2" conf="myfacesPortlet20->default" />
|
||||
<dependency org="org.apache.myfaces.portlet-bridge" name="portlet-bridge-impl" rev="2.0.0-alpha-2" conf="myfacesPortlet20->default" />
|
||||
|
||||
<!-- test time only dependencies -->
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="test->runtime" />
|
||||
<dependency org="org.apache.myfaces.test" name="myfaces-test20" rev="1.0.0-beta" conf="test->default" />
|
||||
|
||||
@@ -69,6 +69,12 @@
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.portlet</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
|
||||
@@ -30,8 +30,12 @@ import javax.faces.context.ResponseStream;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
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.context.MessageSource;
|
||||
import org.springframework.faces.webflow.context.portlet.PortletFacesContextImpl;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
@@ -66,11 +70,18 @@ public class FlowFacesContext extends FacesContext {
|
||||
private FacesContext delegate;
|
||||
|
||||
public static FlowFacesContext newInstance(RequestContext context, Lifecycle lifecycle) {
|
||||
FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
|
||||
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
|
||||
FacesContext defaultFacesContext = facesContextFactory.getFacesContext(context.getExternalContext()
|
||||
.getNativeContext(), context.getExternalContext().getNativeRequest(), context.getExternalContext()
|
||||
.getNativeResponse(), 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);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import javax.faces.context.FacesContext;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Helper class to provide information about the JSF runtime environment such as JSF version and implementation.
|
||||
@@ -63,7 +64,7 @@ public class JsfRuntimeInformation {
|
||||
return jsfVersion < JSF_20;
|
||||
}
|
||||
|
||||
protected static boolean isMyFacesPresent() {
|
||||
public static boolean isMyFacesPresent() {
|
||||
return myFacesPresent;
|
||||
}
|
||||
|
||||
@@ -71,4 +72,9 @@ public class JsfRuntimeInformation {
|
||||
return context.getExternalContext().getContext().getClass().getName().indexOf("Portlet") != -1;
|
||||
}
|
||||
|
||||
public static boolean isPortletRequest(RequestContext context) {
|
||||
return (null != ClassUtils.getMethodIfAvailable(context.getExternalContext().getNativeContext().getClass(),
|
||||
"getPortletContextName"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* <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>
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class PortletFaceletViewHandler extends FaceletViewHandler {
|
||||
|
||||
private static final String FACELETS_CONTENT_TYPE_KEY = "facelets.ContentType";
|
||||
private static final String FACELETS_ENCODING_KEY = "facelets.Encoding";
|
||||
|
||||
public PortletFaceletViewHandler(ViewHandler parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected String getResponseEncoding(FacesContext context, String originalEncoding) {
|
||||
String encoding = originalEncoding;
|
||||
|
||||
Map requestMap = context.getExternalContext().getRequestMap();
|
||||
Map 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() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.context.portlet;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.binding.collection.StringKeyedMapAdapter;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Map backed by a PortletContext for accessing Portlet initialization parameters.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class InitParameterMap extends StringKeyedMapAdapter {
|
||||
|
||||
final private PortletContext portletContext;
|
||||
|
||||
public InitParameterMap(PortletContext portletContext) {
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getAttribute(String key) {
|
||||
return portletContext.getInitParameter(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAttribute(String key, Object value) {
|
||||
throw new UnsupportedOperationException("Cannot set PortletContext InitParameter");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeAttribute(String key) {
|
||||
throw new UnsupportedOperationException("Cannot remove PortletContext InitParameter");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Iterator<String> getAttributeNames() {
|
||||
return CollectionUtils.toIterator(portletContext.getInitParameterNames());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* 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.context.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletException;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
import org.springframework.binding.collection.MapAdaptable;
|
||||
import org.springframework.faces.webflow.JsfRuntimeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
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;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ExternalContext} for use with Portlet requests.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @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 PortletResponse portletResponse;
|
||||
|
||||
private Map<String, String> initParameterMap;
|
||||
|
||||
private Map<String, String> requestHeaderMap;
|
||||
|
||||
private Map<String, String[]> requestHeaderValuesMap;
|
||||
|
||||
private Map<String, Object> requestMap;
|
||||
|
||||
private Map<String, String> requestParameterMap;
|
||||
|
||||
private Map<String, String[]> requestParameterValuesMap;
|
||||
|
||||
private MapAdaptable sessionMap;
|
||||
|
||||
public PortletExternalContextImpl(PortletContext portletContext, PortletRequest portletRequest,
|
||||
PortletResponse portletResponse) {
|
||||
this.portletContext = portletContext;
|
||||
this.portletRequest = portletRequest;
|
||||
this.portletResponse = portletResponse;
|
||||
if (portletRequest instanceof ActionRequest) {
|
||||
this.actionRequest = (ActionRequest) portletRequest;
|
||||
this.isActionRequest = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatch(String path) throws IOException {
|
||||
Assert.isTrue(!isActionRequest);
|
||||
PortletRequestDispatcher requestDispatcher = portletContext.getRequestDispatcher(path);
|
||||
try {
|
||||
requestDispatcher.include((RenderRequest) portletRequest, (RenderResponse) portletResponse);
|
||||
} catch (PortletException exception) {
|
||||
if (exception.getMessage() != null) {
|
||||
throw new FacesException(exception.getMessage(), exception);
|
||||
}
|
||||
throw new FacesException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
public String encodeActionURL(String url) {
|
||||
Assert.notNull(url);
|
||||
return portletResponse.encodeURL(url);
|
||||
}
|
||||
|
||||
public String encodeNamespace(String name) {
|
||||
Assert.isTrue(!isActionRequest);
|
||||
return name + ((RenderResponse) portletResponse).getNamespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeResourceURL(String url) {
|
||||
Assert.notNull(url);
|
||||
return portletResponse.encodeURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getApplicationMap() {
|
||||
if (applicationMap == null) {
|
||||
applicationMap = new PortletContextMap(portletContext);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> getInitParameterMap() {
|
||||
if (initParameterMap == null) {
|
||||
initParameterMap = new InitParameterMap(portletContext);
|
||||
}
|
||||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getRequestCookieMap() {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> getRequestHeaderMap() {
|
||||
if (requestHeaderMap == null) {
|
||||
RequestPropertyMap map = new RequestPropertyMap(portletRequest);
|
||||
map.setUseArrayForMultiValueAttributes(Boolean.FALSE);
|
||||
requestHeaderMap = map;
|
||||
}
|
||||
return requestHeaderMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String[]> getRequestHeaderValuesMap() {
|
||||
if (requestHeaderValuesMap == null) {
|
||||
RequestPropertyMap map = new RequestPropertyMap(portletRequest);
|
||||
map.setUseArrayForMultiValueAttributes(Boolean.TRUE);
|
||||
requestHeaderValuesMap = map;
|
||||
}
|
||||
return requestHeaderValuesMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getRequestLocale() {
|
||||
return portletRequest.getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<Locale> getRequestLocales() {
|
||||
return CollectionUtils.toIterator(portletRequest.getLocales());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getRequestMap() {
|
||||
if (requestMap == null) {
|
||||
requestMap = new PortletRequestMap(portletRequest);
|
||||
}
|
||||
return requestMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> getRequestParameterMap() {
|
||||
if (requestParameterMap == null) {
|
||||
RequestParameterMap map = new RequestParameterMap(portletRequest);
|
||||
map.setUseArrayForMultiValueAttributes(Boolean.FALSE);
|
||||
requestParameterMap = map;
|
||||
}
|
||||
return requestParameterMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<String> getRequestParameterNames() {
|
||||
return CollectionUtils.toIterator(portletRequest.getParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String[]> getRequestParameterValuesMap() {
|
||||
if (requestParameterValuesMap == null) {
|
||||
RequestParameterMap map = new RequestParameterMap(portletRequest);
|
||||
map.setUseArrayForMultiValueAttributes(Boolean.TRUE);
|
||||
requestParameterValuesMap = map;
|
||||
}
|
||||
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);
|
||||
return portletContext.getResource(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String path) {
|
||||
Assert.notNull(path);
|
||||
return portletContext.getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getResourcePaths(String path) {
|
||||
Assert.notNull(path);
|
||||
return portletContext.getResourcePaths(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getResponse() {
|
||||
return portletResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponseContentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSession(boolean create) {
|
||||
return portletRequest.getPortletSession(create);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getSessionMap() {
|
||||
if (sessionMap == null) {
|
||||
sessionMap = new LocalAttributeMap(new PortletSessionMap(portletRequest));
|
||||
}
|
||||
return sessionMap.asMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return portletRequest.getUserPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
Assert.notNull(role);
|
||||
return portletRequest.isUserInRole(role);
|
||||
}
|
||||
|
||||
@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
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponseCharacterEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResponseCharacterEncoding(String encoding) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResponse(Object response) {
|
||||
this.portletResponse = (PortletResponse) response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* 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.context.portlet;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.el.ELContextEvent;
|
||||
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.component.UIViewRoot;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseStream;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
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.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* The default FacesContext implementation in Mojarra and in Apache MyFaces depends on the Servlet API. This
|
||||
* implementation provides an alternative that accepts Portlet request and response structures and creates a
|
||||
* {@link PortletExternalContextImpl} in its constructor. The rest of the method implementations mimic the equivalent
|
||||
* methods in the default FacesContext implementation.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.2.0
|
||||
*/
|
||||
public class PortletFacesContextImpl extends FacesContext {
|
||||
|
||||
private Application application;
|
||||
|
||||
private ELContext elContext;
|
||||
|
||||
private ExternalContext externalContext;
|
||||
|
||||
private FacesMessage.Severity maximumSeverity;
|
||||
|
||||
private List<String> messageClientIds;
|
||||
|
||||
private List<FacesMessage> messages;
|
||||
|
||||
private boolean released = false;
|
||||
|
||||
private RenderKitFactory renderKitFactory;
|
||||
|
||||
private boolean renderResponse = false;
|
||||
|
||||
private boolean responseComplete = false;
|
||||
|
||||
private ResponseStream responseStream;
|
||||
|
||||
private ResponseWriter responseWriter;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public PortletFacesContextImpl(ExternalContext externalContext) {
|
||||
this.externalContext = externalContext;
|
||||
}
|
||||
|
||||
public ExternalContext getExternalContext() {
|
||||
assertFacesContextIsNotReleased();
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
String renderKitId = getViewRoot().getRenderKitId();
|
||||
|
||||
if (renderKitId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return renderKitFactory.getRenderKit(this, renderKitId);
|
||||
}
|
||||
|
||||
public boolean getRenderResponse() {
|
||||
assertFacesContextIsNotReleased();
|
||||
return renderResponse;
|
||||
}
|
||||
|
||||
public boolean getResponseComplete() {
|
||||
assertFacesContextIsNotReleased();
|
||||
return responseComplete;
|
||||
}
|
||||
|
||||
public ResponseStream getResponseStream() {
|
||||
assertFacesContextIsNotReleased();
|
||||
return responseStream;
|
||||
}
|
||||
|
||||
public void setResponseStream(ResponseStream responseStream) {
|
||||
assertFacesContextIsNotReleased();
|
||||
if (responseStream == null) {
|
||||
throw new NullPointerException("responseStream");
|
||||
}
|
||||
this.responseStream = responseStream;
|
||||
}
|
||||
|
||||
public ResponseWriter getResponseWriter() {
|
||||
assertFacesContextIsNotReleased();
|
||||
return responseWriter;
|
||||
}
|
||||
|
||||
public void setResponseWriter(ResponseWriter responseWriter) {
|
||||
assertFacesContextIsNotReleased();
|
||||
if (responseWriter == null) {
|
||||
throw new NullPointerException("responseWriter");
|
||||
}
|
||||
this.responseWriter = responseWriter;
|
||||
}
|
||||
|
||||
public UIViewRoot getViewRoot() {
|
||||
assertFacesContextIsNotReleased();
|
||||
return viewRoot;
|
||||
}
|
||||
|
||||
public void setViewRoot(UIViewRoot viewRoot) {
|
||||
assertFacesContextIsNotReleased();
|
||||
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();
|
||||
renderResponse = true;
|
||||
}
|
||||
|
||||
public void responseComplete() {
|
||||
assertFacesContextIsNotReleased();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elContext;
|
||||
}
|
||||
|
||||
private void assertFacesContextIsNotReleased() {
|
||||
Assert.isTrue(!released, "FacesContext already released");
|
||||
}
|
||||
|
||||
private class PortletELContextImpl extends ELContext {
|
||||
|
||||
private FunctionMapper functionMapper;
|
||||
private VariableMapper variableMapper;
|
||||
private ELResolver resolver;
|
||||
|
||||
public PortletELContextImpl(ELResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionMapper getFunctionMapper() {
|
||||
return functionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VariableMapper getVariableMapper() {
|
||||
return variableMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ELResolver getELResolver() {
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.context.portlet;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.webflow.context.portlet.PortletRequestParameterMap;
|
||||
|
||||
/**
|
||||
* Map backed by a PortletContext for accessing Portlet request parameters. Request parameters can have multiple values.
|
||||
* The {@link RequestParameterMap#setUseArrayForMultiValueAttributes(Boolean)} property allows choosing whether the map
|
||||
* will return:
|
||||
* <ul>
|
||||
* <li>String - selects the first value in case of multiple value parameters</li>
|
||||
* <li>String[] - wraps single-values parameters as array</li>
|
||||
* <li>String or String[] - depends on the values of the parameter</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @see PortletRequest#getParameter(String)
|
||||
* @see PortletRequest#getParameterValues(String)
|
||||
*/
|
||||
public class RequestParameterMap extends PortletRequestParameterMap {
|
||||
|
||||
private Boolean useArrayForMultiValueAttributes;
|
||||
|
||||
private PortletRequest portletRequest;
|
||||
|
||||
public RequestParameterMap(PortletRequest portletRequest) {
|
||||
super(portletRequest);
|
||||
this.portletRequest = portletRequest;
|
||||
}
|
||||
|
||||
public void setUseArrayForMultiValueAttributes(Boolean useArrayForMultiValueAttributes) {
|
||||
this.useArrayForMultiValueAttributes = useArrayForMultiValueAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* This property allows choosing what kind of attributes the map will return:
|
||||
* <ol>
|
||||
* <li>String - selects the first value in case of multiple value parameters</li>
|
||||
* <li>String[] - wraps single-values parameters as array</li>
|
||||
* <li>String or String[] - depends on the values of the parameter</li>
|
||||
* </ol>
|
||||
* The above choices correspond to the following values for useArrayForMultiValueAttributes:
|
||||
* <ol>
|
||||
* <li>False</li>
|
||||
* <li>True</li>
|
||||
* <li>null</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param useArrayForMultiValueAttributes
|
||||
*/
|
||||
public Boolean useArrayForMultiValueAttributes() {
|
||||
return useArrayForMultiValueAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getAttribute(String key) {
|
||||
if (null == useArrayForMultiValueAttributes) {
|
||||
return super.getAttribute(key);
|
||||
} else {
|
||||
if (useArrayForMultiValueAttributes) {
|
||||
return portletRequest.getParameterValues(key);
|
||||
} else {
|
||||
return portletRequest.getParameter(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.context.portlet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.binding.collection.StringKeyedMapAdapter;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Map backed by a PortletContext for accessing Portlet request properties. Request properties can have multiple values.
|
||||
* The {@link RequestPropertyMap#setUseArrayForMultiValueAttributes(Boolean)} property allows choosing whether the map
|
||||
* will return:
|
||||
* <ul>
|
||||
* <li>String - selects the first element in case of multiple values</li>
|
||||
* <li>String[] - wraps single-values attributes as array</li>
|
||||
* <li>String or String[] - depends on the values of the property</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.2.0
|
||||
*
|
||||
* @see PortletRequest#getProperty(String)
|
||||
* @see PortletRequest#getProperties(String)
|
||||
*/
|
||||
public class RequestPropertyMap extends StringKeyedMapAdapter {
|
||||
|
||||
private Boolean useArrayForMultiValueAttributes;
|
||||
|
||||
private final PortletRequest portletRequest;
|
||||
|
||||
public RequestPropertyMap(PortletRequest portletRequest) {
|
||||
this.portletRequest = portletRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* This property allows choosing what kind of attributes the map will return:
|
||||
* <ol>
|
||||
* <li>String - selects the first element in case of multiple values</li>
|
||||
* <li>String[] - wraps single-values attributes as array</li>
|
||||
* <li>String or String[] - depends on the values of the property</li>
|
||||
* </ol>
|
||||
* The above choices correspond to the following values for useArrayForMultiValueAttributes:
|
||||
* <ol>
|
||||
* <li>False</li>
|
||||
* <li>True</li>
|
||||
* <li>null</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param useArrayForMultiValueAttributes
|
||||
*/
|
||||
public void setUseArrayForMultiValueAttributes(Boolean useArrayForMultiValueAttributes) {
|
||||
this.useArrayForMultiValueAttributes = useArrayForMultiValueAttributes;
|
||||
}
|
||||
|
||||
public Boolean useArrayForMultiValueAttributes() {
|
||||
return useArrayForMultiValueAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getAttribute(String key) {
|
||||
if (null == useArrayForMultiValueAttributes) {
|
||||
List<String> list = Collections.list(portletRequest.getProperties(key));
|
||||
if (1 == list.size()) {
|
||||
return list.get(0);
|
||||
} else {
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
} else {
|
||||
if (useArrayForMultiValueAttributes) {
|
||||
List<String> list = Collections.list(portletRequest.getProperties(key));
|
||||
return list.toArray(new String[list.size()]);
|
||||
} else {
|
||||
return portletRequest.getProperty(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setAttribute(String key, Object value) {
|
||||
throw new UnsupportedOperationException("Cannot set PortletRequest property");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeAttribute(String key) {
|
||||
throw new UnsupportedOperationException("Cannot remove PortletRequest property");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Iterator<String> getAttributeNames() {
|
||||
return CollectionUtils.toIterator(portletRequest.getPropertyNames());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
<factory>
|
||||
<application-factory>org.springframework.faces.webflow.FlowApplicationFactory</application-factory>
|
||||
</factory>
|
||||
|
||||
|
||||
<lifecycle>
|
||||
<phase-listener>org.springframework.faces.support.RequestLoggingPhaseListener</phase-listener>
|
||||
</lifecycle>
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.springframework.faces.webflow.context.portlet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.portlet.MockPortletRequest;
|
||||
|
||||
public class RequestParameterMapTests extends TestCase {
|
||||
|
||||
private RequestParameterMap requestMap;
|
||||
|
||||
private MockPortletRequest request;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
request = new MockPortletRequest();
|
||||
requestMap = new RequestParameterMap(request);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
request = null;
|
||||
requestMap = null;
|
||||
}
|
||||
|
||||
public void testSingleValueParameter() throws Exception {
|
||||
request.setParameter("key", "value");
|
||||
assertEquals("value", requestMap.getAttribute("key"));
|
||||
}
|
||||
|
||||
public void testMultiValueParameter() throws Exception {
|
||||
request.setParameter("key", "value");
|
||||
request.addParameter("key", "value2");
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertTrue(actual.getClass().isArray());
|
||||
assertEquals(2, ((String[]) actual).length);
|
||||
assertEquals("value", ((String[]) actual)[0]);
|
||||
assertEquals("value2", ((String[]) actual)[1]);
|
||||
}
|
||||
|
||||
public void testSingleValueParameterAsArray() throws Exception {
|
||||
request.setParameter("key", "value");
|
||||
requestMap.setUseArrayForMultiValueAttributes(Boolean.TRUE);
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertTrue(actual.getClass().isArray());
|
||||
assertEquals(1, ((String[]) actual).length);
|
||||
assertEquals("value", ((String[]) actual)[0]);
|
||||
}
|
||||
|
||||
public void testMultiValueParameterAsString() throws Exception {
|
||||
request.setParameter("key", "value");
|
||||
request.addParameter("key", "value2");
|
||||
requestMap.setUseArrayForMultiValueAttributes(Boolean.FALSE);
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertEquals("value", actual);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.springframework.faces.webflow.context.portlet;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.mock.web.portlet.MockPortletRequest;
|
||||
|
||||
public class RequestPropertyMapTests extends TestCase {
|
||||
|
||||
private RequestPropertyMap requestMap;
|
||||
|
||||
private MockPortletRequest request;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
request = new MockPortletRequest();
|
||||
requestMap = new RequestPropertyMap(request);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
request = null;
|
||||
requestMap = null;
|
||||
}
|
||||
|
||||
public void testSingleValueProperty() throws Exception {
|
||||
request.setProperty("key", "value");
|
||||
assertEquals("value", requestMap.getAttribute("key"));
|
||||
}
|
||||
|
||||
public void testMultiValueProperty() throws Exception {
|
||||
request.setProperty("key", "value");
|
||||
request.addProperty("key", "value2");
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertTrue(actual.getClass().isArray());
|
||||
assertEquals(2, ((String[]) actual).length);
|
||||
assertEquals("value", ((String[]) actual)[0]);
|
||||
assertEquals("value2", ((String[]) actual)[1]);
|
||||
}
|
||||
|
||||
public void testSingleValuePropertyAsArray() throws Exception {
|
||||
request.setProperty("key", "value");
|
||||
requestMap.setUseArrayForMultiValueAttributes(Boolean.TRUE);
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertTrue(actual.getClass().isArray());
|
||||
assertEquals(1, ((String[]) actual).length);
|
||||
assertEquals("value", ((String[]) actual)[0]);
|
||||
}
|
||||
|
||||
public void testMultiValuePropertyAsString() throws Exception {
|
||||
request.setProperty("key", "value");
|
||||
request.addProperty("key", "value2");
|
||||
requestMap.setUseArrayForMultiValueAttributes(Boolean.FALSE);
|
||||
Object actual = requestMap.getAttribute("key");
|
||||
assertEquals("value", actual);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ Import-Template:
|
||||
org.springframework.*;version="[3.0.4.RELEASE, 3.1.0)",
|
||||
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
|
||||
javax.el;version="[1.0.0, 2.0.0)",
|
||||
javax.portlet;version="[2.0.0, 3.0.0)";resolution:=optional,
|
||||
javax.servlet;version="[2.4.0, 3.0.0)",
|
||||
javax.servlet.http;version="[2.4.0, 3.0.0)",
|
||||
javax.faces.*;version="[1.2.0, 3.0.0)",
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-3.8.2.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-sources-3.8.2.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-2.0.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.javax.portlet-sources-2.0.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#Wed Jun 02 12:02:05 BST 2010
|
||||
#Sun Sep 12 18:04:00 GMT 2010
|
||||
eclipse.preferences.version=1
|
||||
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
@@ -56,13 +56,13 @@ org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
|
||||
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_block_comments=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_header=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
|
||||
org.eclipse.jdt.core.formatter.comment.format_html=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_line_comments=false
|
||||
org.eclipse.jdt.core.formatter.comment.format_source_code=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
|
||||
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
|
||||
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
|
||||
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
|
||||
@@ -83,6 +83,9 @@ org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
|
||||
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
|
||||
org.eclipse.jdt.core.formatter.indentation.size=4
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
|
||||
@@ -251,6 +254,8 @@ org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
|
||||
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
|
||||
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
|
||||
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
|
||||
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
|
||||
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
|
||||
@@ -261,7 +266,7 @@ org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
|
||||
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
|
||||
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
|
||||
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=mixed
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=8
|
||||
org.eclipse.jdt.core.formatter.tabulation.char=tab
|
||||
org.eclipse.jdt.core.formatter.tabulation.size=4
|
||||
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
|
||||
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#Thu Aug 09 13:12:30 EDT 2007
|
||||
#Sun Sep 12 18:04:00 GMT 2010
|
||||
eclipse.preferences.version=1
|
||||
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
|
||||
formatter_profile=_Spring Java Conventions
|
||||
formatter_profile=_Spring
|
||||
formatter_settings_version=11
|
||||
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
|
||||
sp_cleanup.add_default_serial_version_id=true
|
||||
|
||||
@@ -47,8 +47,11 @@
|
||||
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="3.0.4.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework.webflow" name="org.springframework.webflow" rev="latest.integration" conf="compile->compile"/>
|
||||
|
||||
<dependency org="org.springframework.webflow" name="org.springframework.faces" rev="latest.integration" conf="compile->myfaces12,myfacesPortlet20"/>
|
||||
<dependency org="org.springframework.webflow" name="org.springframework.faces" rev="latest.integration" conf="compile->myfaces12"/>
|
||||
<dependency org="com.sun.facelets" name="com.springsource.com.sun.facelets" rev="1.1.14" conf="compile->compile"/>
|
||||
|
||||
<!-- Temporarily add these while experimenting without portlet bridge -->
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->runtime" />
|
||||
|
||||
<!-- test-time only dependencies -->
|
||||
<dependency org="org.junit" name="com.springsource.junit" rev="3.8.2" conf="test->compile"/>
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
/**
|
||||
* 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.webflow.samples;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.faces.FacesException;
|
||||
import javax.faces.application.ViewHandler;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.render.RenderKit;
|
||||
import javax.portlet.MimeResponse;
|
||||
import javax.portlet.faces.Bridge;
|
||||
|
||||
import com.sun.facelets.FaceletViewHandler;
|
||||
|
||||
/**
|
||||
* See: http://www.mail-archive.com/users@myfaces.apache.org/msg55213.html
|
||||
*/
|
||||
public class PortletFaceletViewHandler extends FaceletViewHandler {
|
||||
|
||||
public PortletFaceletViewHandler(ViewHandler parent) {
|
||||
super(new FaceletViewHandler(parent));
|
||||
}
|
||||
|
||||
protected ResponseWriter createResponseWriter(FacesContext context) throws IOException, FacesException {
|
||||
// Only override if in a portlet request
|
||||
if (context.getExternalContext().getRequestMap().get(Bridge.PORTLET_LIFECYCLE_PHASE) == null) {
|
||||
return super.createResponseWriter(context);
|
||||
}
|
||||
|
||||
ExternalContext extContext = context.getExternalContext();
|
||||
RenderKit renderKit = context.getRenderKit();
|
||||
// Avoid a cryptic NullPointerException when the renderkit ID
|
||||
// is incorrectly set
|
||||
if (renderKit == null) {
|
||||
String id = context.getViewRoot().getRenderKitId();
|
||||
throw new IllegalStateException("No render kit was available for id \"" + id + "\"");
|
||||
}
|
||||
|
||||
MimeResponse response = (MimeResponse) extContext.getResponse();
|
||||
|
||||
// get our content type
|
||||
String contentType = (String) extContext.getRequestMap().get("facelets.ContentType");
|
||||
|
||||
// get the encoding
|
||||
String encoding = (String) extContext.getRequestMap().get("facelets.Encoding");
|
||||
|
||||
ResponseWriter writer;
|
||||
// append */* to the contentType so createResponseWriter will succeed no matter
|
||||
// the requested contentType.
|
||||
if (contentType != null && !contentType.equals("*/*")) {
|
||||
contentType += ",*/*";
|
||||
}
|
||||
// Create a dummy ResponseWriter with a bogus writer,
|
||||
// so we can figure out what content type the ReponseWriter
|
||||
// is really going to ask for
|
||||
try {
|
||||
writer = renderKit.createResponseWriter(NullWriter.Instance, contentType, encoding);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Added because of an RI bug prior to 1.2_05-b3. Might as well leave it in case other impls have the same
|
||||
// problem.
|
||||
// https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=613
|
||||
log.fine("The impl didn't correctly handled '*/*' in the content type list. Trying '*/*' directly.");
|
||||
writer = renderKit.createResponseWriter(NullWriter.Instance, "*/*", encoding);
|
||||
}
|
||||
|
||||
// Override the JSF provided content type if necessary
|
||||
contentType = getResponseContentType(context, writer.getContentType());
|
||||
encoding = getResponseEncoding(context, writer.getCharacterEncoding());
|
||||
|
||||
// apply them to the response
|
||||
response.setContentType(contentType + "; charset=" + encoding);
|
||||
|
||||
// removed 2005.8.23 to comply with J2EE 1.3
|
||||
// response.setCharacterEncoding(encoding);
|
||||
|
||||
// Now, clone with the real writer
|
||||
writer = writer.cloneWithWriter(response.getWriter());
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the encoding
|
||||
*
|
||||
* @param context
|
||||
* @param orig
|
||||
* @return
|
||||
*/
|
||||
protected String getResponseEncoding(FacesContext context, String orig) {
|
||||
String encoding = orig;
|
||||
|
||||
// see if we need to override the encoding
|
||||
Map m = context.getExternalContext().getRequestMap();
|
||||
Map sm = context.getExternalContext().getSessionMap();
|
||||
|
||||
// 1. check the request attribute
|
||||
if (m.containsKey("facelets.Encoding")) {
|
||||
encoding = (String) m.get("facelets.Encoding");
|
||||
if (log.isLoggable(Level.FINEST)) {
|
||||
log.finest("Facelet specified alternate encoding '" + encoding + "'");
|
||||
}
|
||||
sm.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) sm.get(CHARACTER_ENCODING_KEY);
|
||||
if (log.isLoggable(Level.FINEST)) {
|
||||
log.finest("Session specified alternate encoding '" + encoding + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// 4. default it
|
||||
if (encoding == null) {
|
||||
encoding = "UTF-8";
|
||||
if (log.isLoggable(Level.FINEST)) {
|
||||
log.finest("ResponseWriter created had a null CharacterEncoding, defaulting to UTF-8");
|
||||
}
|
||||
}
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
protected static class NullWriter extends Writer {
|
||||
|
||||
static final NullWriter Instance = new NullWriter();
|
||||
|
||||
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() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
<faces-config>
|
||||
<application>
|
||||
<!-- Enables Facelets -->
|
||||
<view-handler>org.springframework.webflow.samples.PortletFaceletViewHandler</view-handler>
|
||||
<view-handler>org.springframework.faces.webflow.application.portlet.PortletFaceletViewHandler</view-handler>
|
||||
</application>
|
||||
</faces-config>
|
||||
</faces-config>
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:sf="http://www.springframework.org/tags/faces">
|
||||
xmlns:f="http://java.sun.com/jsf/core">
|
||||
|
||||
<f:view contentType="text/html">
|
||||
|
||||
@@ -45,11 +44,9 @@
|
||||
<h:outputLabel for="checkinDate">Check In Date:</h:outputLabel>
|
||||
</td>
|
||||
<td class="input">
|
||||
<sf:clientDateValidator required="true" >
|
||||
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</sf:clientDateValidator>
|
||||
<h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field">
|
||||
@@ -57,11 +54,9 @@
|
||||
<h:outputLabel for="checkoutDate">Check Out Date:</h:outputLabel>
|
||||
</td>
|
||||
<td class="input">
|
||||
<sf:clientDateValidator required="true">
|
||||
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</sf:clientDateValidator>
|
||||
<h:inputText id="checkoutDate" value="#{booking.checkoutDate}" required="true">
|
||||
<f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/>
|
||||
</h:inputText>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field">
|
||||
@@ -89,9 +84,7 @@
|
||||
<h:outputLabel for="creditCard">Credit Card #:</h:outputLabel>
|
||||
</td>
|
||||
<td class="input">
|
||||
<sf:clientTextValidator required="true" regExp="[0-9]{16}" invalidMessage="A 16-digit credit card number is required.">
|
||||
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true"/>
|
||||
</sf:clientTextValidator>
|
||||
<h:inputText id="creditCard" value="#{booking.creditCard}" required="true"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field">
|
||||
@@ -99,9 +92,7 @@
|
||||
<h:outputLabel for="creditCardName">Credit Card Name:</h:outputLabel>
|
||||
</td>
|
||||
<td class="input">
|
||||
<sf:clientTextValidator required="true">
|
||||
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true"/>
|
||||
</sf:clientTextValidator>
|
||||
<h:inputText id="creditCardName" value="#{booking.creditCardName}" required="true"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="field">
|
||||
@@ -119,9 +110,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="buttonGroup">
|
||||
<sf:validateAllOnClick>
|
||||
<h:commandButton id="proceed" action="proceed" value="Proceed"/> 
|
||||
</sf:validateAllOnClick>
|
||||
<h:commandButton id="proceed" action="proceed" value="Proceed"/> 
|
||||
<h:commandButton id="cancel" immediate="true" value="Cancel" action="cancel"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -2,82 +2,76 @@
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:sf="http://www.springframework.org/tags/faces">
|
||||
xmlns:f="http://java.sun.com/jsf/core">
|
||||
|
||||
<f:view contentType="text/html">
|
||||
|
||||
<ui:fragment id="hotelSearchFragment">
|
||||
<div id="hotelSearch">
|
||||
<h2>Search Hotels</h2>
|
||||
<span class="errors">
|
||||
<h:messages globalOnly="true" />
|
||||
</span>
|
||||
<h:form id="mainForm">
|
||||
<fieldset>
|
||||
<div class="searchGroup">
|
||||
<div class="searchField">
|
||||
<sf:clientTextValidator promptMessage="Search hotels by name, address, city, or zip.">
|
||||
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;" />
|
||||
</sf:clientTextValidator>
|
||||
</div>
|
||||
<div class="searchSize">
|
||||
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
|
||||
<h:selectOneMenu id="pageSize" value="#{searchCriteria.pageSize}">
|
||||
<f:selectItems value="#{referenceData.pageSizeOptions}" />
|
||||
</h:selectOneMenu>
|
||||
</div>
|
||||
<div class="searchButton">
|
||||
<sf:commandButton id="findHotels" value="Find Hotels" processIds="hotelSearchFragment" action="search" />
|
||||
</div>
|
||||
<div id="hotelSearch">
|
||||
<h2>Search Hotels</h2>
|
||||
<span class="errors">
|
||||
<h:messages globalOnly="true" />
|
||||
</span>
|
||||
<h:form id="mainForm">
|
||||
<fieldset>
|
||||
<div class="searchGroup">
|
||||
<div class="searchField">
|
||||
<h:outputLabel for="searchString">Search String:</h:outputLabel>
|
||||
<h:inputText id="searchString" value="#{searchCriteria.searchString}" style="width: 165px; height: 15px;" />
|
||||
</div>
|
||||
</fieldset>
|
||||
</h:form>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
<div class="searchSize">
|
||||
<h:outputLabel for="pageSize">Maximum results:</h:outputLabel>
|
||||
<h:selectOneMenu id="pageSize" value="#{searchCriteria.pageSize}">
|
||||
<f:selectItems value="#{referenceData.pageSizeOptions}" />
|
||||
</h:selectOneMenu>
|
||||
</div>
|
||||
<div class="searchButton">
|
||||
<h:commandButton value="Find Hotels" action="search" />
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
<ui:fragment id="bookingsFragment">
|
||||
<div id="bookingsSection">
|
||||
<h:form id="bookingsForm">
|
||||
<h2>Current Hotel Bookings</h2>
|
||||
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount == 0}"/>
|
||||
<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" rendered="#{bookings.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{booking.hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{booking.hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{booking.hotel.city}, #{booking.hotel.state}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check in date</f:facet>
|
||||
<h:outputText value="#{booking.checkinDate}">
|
||||
<f:convertDateTime dateStyle="short"/>
|
||||
</h:outputText>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check out date</f:facet>
|
||||
<h:outputText value="#{booking.checkoutDate}">
|
||||
<f:convertDateTime dateStyle="short"/>
|
||||
</h:outputText>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Confirmation number</f:facet>
|
||||
#{booking.id}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<sf:commandLink id="cancel" value="Cancel" processIds="bookingsFragment" action="cancelBooking" />
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
</h:form>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
<div id="bookingsSection">
|
||||
<h:form id="bookingsForm">
|
||||
<h2>Current Hotel Bookings</h2>
|
||||
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount == 0}"/>
|
||||
<h:dataTable id="bookings" styleClass="summary" value="#{bookings}" var="booking" rendered="#{bookings.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{booking.hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{booking.hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{booking.hotel.city}, #{booking.hotel.state}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check in date</f:facet>
|
||||
<h:outputText value="#{booking.checkinDate}">
|
||||
<f:convertDateTime dateStyle="short"/>
|
||||
</h:outputText>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Check out date</f:facet>
|
||||
<h:outputText value="#{booking.checkoutDate}">
|
||||
<f:convertDateTime dateStyle="short"/>
|
||||
</h:outputText>
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Confirmation number</f:facet>
|
||||
#{booking.id}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<h:commandLink value="Cancel" action="cancelBooking" />
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
</h:form>
|
||||
</div>
|
||||
|
||||
</f:view>
|
||||
</ui:composition>
|
||||
@@ -12,7 +12,6 @@
|
||||
<transition on="search" to="reviewHotels" />
|
||||
<transition on="cancelBooking">
|
||||
<evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
|
||||
<render fragments="bookingsFragment"/>
|
||||
</transition>
|
||||
</view-state>
|
||||
|
||||
@@ -22,14 +21,12 @@
|
||||
</on-render>
|
||||
<transition on="previous">
|
||||
<evaluate expression="searchCriteria.previousPage()" />
|
||||
<render fragments="hotels:searchResultsFragment" />
|
||||
</transition>
|
||||
<transition on="next">
|
||||
<evaluate expression="searchCriteria.nextPage()" />
|
||||
<render fragments="hotels:searchResultsFragment" />
|
||||
</transition>
|
||||
<transition on="select" to="reviewHotel" />
|
||||
<transition on="changeSearch" to="changeSearchCriteria" />
|
||||
<transition on="changeSearch" to="enterSearchCriteria" />
|
||||
</view-state>
|
||||
|
||||
<view-state id="reviewHotel">
|
||||
@@ -46,15 +43,6 @@
|
||||
<transition on="bookingCancelled" to="enterSearchCriteria" />
|
||||
</subflow-state>
|
||||
|
||||
<view-state id="changeSearchCriteria" view="enterSearchCriteria.xhtml" popup="true">
|
||||
<on-entry>
|
||||
<render fragments="hotelSearchFragment" />
|
||||
</on-entry>
|
||||
<transition on="search" to="reviewHotels">
|
||||
<evaluate expression="searchCriteria.resetPage()"/>
|
||||
</transition>
|
||||
</view-state>
|
||||
|
||||
<end-state id="finish" />
|
||||
|
||||
</flow>
|
||||
@@ -2,8 +2,7 @@
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:sf="http://www.springframework.org/tags/faces">
|
||||
xmlns:f="http://java.sun.com/jsf/core">
|
||||
|
||||
<f:view contentType="text/html">
|
||||
|
||||
@@ -45,10 +44,8 @@
|
||||
|
||||
<h:form id="hotel">
|
||||
<input name="execution" type="hidden" value="${flowExecutionContext.key}"/>
|
||||
<fieldset class="buttonGroup">
|
||||
<sf:commandButton id="book" ajaxEnabled="false" action="book" value="Book Hotel"/> 
|
||||
<sf:commandButton id="cancel" ajaxEnabled="false" action="cancel" value="Back to Search"/>
|
||||
</fieldset>
|
||||
<h:commandButton id="book" action="book" value="Book Hotel"/> 
|
||||
<h:commandButton id="cancel" action="cancel" value="Back to Search"/>
|
||||
</h:form>
|
||||
|
||||
</f:view>
|
||||
|
||||
@@ -2,49 +2,46 @@
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:sf="http://www.springframework.org/tags/faces">
|
||||
xmlns:f="http://java.sun.com/jsf/core">
|
||||
|
||||
<f:view contentType="text/html">
|
||||
|
||||
<h:form id="hotels">
|
||||
<h2>Hotel Results</h2>
|
||||
<p>
|
||||
<sf:commandLink value="Change Search" action="changeSearch"/>
|
||||
<h:commandLink value="Change Search" action="changeSearch"/>
|
||||
</p>
|
||||
<ui:fragment id="searchResultsFragment">
|
||||
<div id="searchResults">
|
||||
<h:outputText id="noHotelsText" value="No Hotels Found" rendered="#{hotels.rowCount == 0}"/>
|
||||
<h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{hotel.city}, #{hotel.state}, #{hotel.country}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Zip</f:facet>
|
||||
#{hotel.zip}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<sf:commandLink id="viewHotelLink" value="View Hotel" action="select"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
<div class="next">
|
||||
<sf:commandLink id="nextPageLink" value="More Results" action="next" rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/>
|
||||
</div>
|
||||
<div class="previous">
|
||||
<sf:commandLink id="previousPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page > 0}"/>
|
||||
</div>
|
||||
<div id="searchResults">
|
||||
<h:outputText id="noHotelsText" value="No Hotels Found" rendered="#{hotels.rowCount == 0}"/>
|
||||
<h:dataTable id="hotels" styleClass="summary" value="#{hotels}" var="hotel" rendered="#{hotels.rowCount > 0}">
|
||||
<h:column>
|
||||
<f:facet name="header">Name</f:facet>
|
||||
#{hotel.name}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Address</f:facet>
|
||||
#{hotel.address}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">City, State</f:facet>
|
||||
#{hotel.city}, #{hotel.state}, #{hotel.country}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Zip</f:facet>
|
||||
#{hotel.zip}
|
||||
</h:column>
|
||||
<h:column>
|
||||
<f:facet name="header">Action</f:facet>
|
||||
<h:commandLink id="viewHotelLink" value="View Hotel" action="select"/>
|
||||
</h:column>
|
||||
</h:dataTable>
|
||||
<div class="next">
|
||||
<h:commandLink id="nextPageLink" value="More Results" action="next" rendered="#{not empty hotels and hotels.rowCount == searchCriteria.pageSize}"/>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
<div class="previous">
|
||||
<h:commandLink id="previousPageLink" value="Previous results" action="previous" rendered="#{searchCriteria.page > 0}"/>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
|
||||
</f:view>
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.springframework.webflow.samples.booking;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
|
||||
*
|
||||
@@ -53,4 +52,17 @@ public class SearchCriteria implements Serializable {
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public void nextPage() {
|
||||
page++;
|
||||
}
|
||||
|
||||
public void previousPage() {
|
||||
page--;
|
||||
}
|
||||
|
||||
public void resetPage() {
|
||||
page = 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
<form:errors path="*"/>
|
||||
</span>
|
||||
<fieldset>
|
||||
<label for="searchString">Search For:</label>
|
||||
<form:input path="searchString"/>
|
||||
<label for="pageSize">Maximum results:</label>
|
||||
<form:select path="pageSize">
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findBookings(currentUser.name)" result="requestScope.bookings" />
|
||||
</on-render>
|
||||
<transition on="search" to="reviewHotels" />
|
||||
<transition on="search" to="reviewHotels" >
|
||||
<evaluate expression="searchCriteria.resetPage()" />
|
||||
</transition>
|
||||
<transition on="cancelBooking" to="cancelBooking" bind="false" />
|
||||
</view-state>
|
||||
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
|
||||
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
|
||||
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
|
||||
|
||||
<h2>Hotel Results</h2>
|
||||
|
||||
<portlet:actionURL var="changeSearchUrl">
|
||||
<portlet:param name="execution" value="${flowExecutionKey}" />
|
||||
<portlet:param name="_eventId" value="changeSearch" />
|
||||
</portlet:actionURL>
|
||||
<a href="${changeSearchUrl}">Change Search</a>
|
||||
|
||||
<table class="summary">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -38,3 +45,19 @@
|
||||
</c:if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<c:if test="${searchCriteria.page > 0}">
|
||||
<portlet:actionURL var="prevResultsUrl">
|
||||
<portlet:param name="execution" value="${flowExecutionKey}" />
|
||||
<portlet:param name="_eventId" value="previous" />
|
||||
</portlet:actionURL>
|
||||
<a href="${prevResultsUrl}">Previous Results</a>
|
||||
</c:if>
|
||||
<c:if test="${not empty hotels && fn:length(hotels) == searchCriteria.pageSize}">
|
||||
<portlet:actionURL var="moreResultsUrl">
|
||||
<portlet:param name="execution" value="${flowExecutionKey}" />
|
||||
<portlet:param name="_eventId" value="next" />
|
||||
</portlet:actionURL>
|
||||
<a href="${moreResultsUrl}">More Results</a>
|
||||
</c:if>
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<dependency>
|
||||
<groupId>javax.portlet</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -232,7 +232,9 @@ public class ViewState extends TransitionableState {
|
||||
context.getFlashScope().put(View.USER_EVENT_STATE_ATTRIBUTE, view.getUserEventState());
|
||||
externalContext.requestFlowExecutionRedirect();
|
||||
} else {
|
||||
render(context, view);
|
||||
if (externalContext.isResponseAllowed()) {
|
||||
render(context, view);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user