All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.portletbridge.BridgeRequestScope Maven / Gradle / Ivy

/******************************************************************************
 * JBoss, a division of Red Hat                                               *
 * Copyright 2006, Red Hat Middleware, LLC, and individual                    *
 * contributors as indicated by the @authors tag. See the                     *
 * copyright.txt in the distribution for a full listing of                    *
 * individual contributors.                                                   *
 *                                                                            *
 * This is free software; you can redistribute it and/or modify it            *
 * under the terms of the GNU Lesser General Public License as                *
 * published by the Free Software Foundation; either version 2.1 of           *
 * the License, or (at your option) any later version.                        *
 *                                                                            *
 * This software is distributed in the hope that it will be useful,           *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU           *
 * Lesser General Public License for more details.                            *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public           *
 * License along with this software; if not, write to the Free                *
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA         *
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.                   *
 ******************************************************************************/
package org.jboss.portletbridge;

import java.io.IOException;
import java.io.Serializable;
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.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.render.ResponseStateManager;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.annotation.ExcludeFromManagedRequestScope;

import org.jboss.portletbridge.context.AbstractExternalContext;
import org.jboss.portletbridge.context.PortletBridgeContext;

/**
 * That class keep all request attributes that requires to store between portlet requests.
 * These parameters described by the chapter 5.1.2 "Managing Lifecycle State"
 * TODO - synchronize access to state for concurrent AJAX requests.
 * @author asmirnov
 * 
 */
public class BridgeRequestScope implements Serializable {

	public static final String AJAX_PARAMETER_NAME = "AJAXREQUEST";

	/**
    *
    */
	private static final long serialVersionUID = 5630637804542426710L;

	/**
	 * Array of classes that are not stored in the request scope. See PP5.1.2
	 */
	private static final Class[] excludedClasses = {
			javax.portlet.PortletConfig.class,
			javax.portlet.PortletContext.class,
			javax.portlet.PortletRequest.class,
			javax.portlet.PortletResponse.class,
			javax.portlet.PortletSession.class,
			javax.portlet.PortletPreferences.class,
			javax.portlet.PortalContext.class,
			javax.faces.context.FacesContext.class,
			javax.faces.context.ExternalContext.class,
			javax.servlet.ServletConfig.class,
			javax.servlet.ServletContext.class,
			javax.servlet.ServletRequest.class,
			javax.servlet.ServletResponse.class,
			javax.servlet.http.HttpSession.class };

	/**
	 * Names of request attributes that are not stored in the request scope.
	 */
	private static final String[] excludedRequestAttributes = { "ajaxContext",
			"javax.servlet.", "javax.portlet.", "javax.faces.",
			ResponseStateManager.VIEW_STATE_PARAM,
			AbstractExternalContext.INITIAL_REQUEST_ATTRIBUTES_NAMES };

	/**
	 * Saved {@link FacesMessage}
	 */
	private Map> messages = new HashMap>();

	/**
	 * Request scope beans. That map saved by the {@code writeObject} method to
	 * avoid serialization exceptions.
	 */
	private transient Map beans = new HashMap();

	/**
	 * JSF View Tree from the last ActionRerquest
	 */
	private transient UIViewRoot viewRoot;

	/**
	 * Latest viewId
	 */
	private String viewId;

	/**
	 * Request paremeters saved for consequentual render requests.
	 */
	private Map requestParameters = new HashMap(4);

	/**
	 * Namespace from the last render request or default portlet namespace.
	 */
	private String namespace;

	/**
	 * Captured value of the {@link ResponseStateManager#VIEW_STATE_PARAM} to
	 * proper restore view state during consequentual render requests, as
	 * required bu PP 5.1.2
	 */
	private String viewStateParameter;

	private String conversationIdParameter = "conversationId";

	private String conversationId;

	public BridgeRequestScope() {
	}

	/**
	 * @return the viewId
	 */
	public String getViewId() {
		return viewId;
	}

	/**
	 * @param viewId
	 *            the viewId to set
	 */
	public void setViewId(String viewId) {
		this.viewId = viewId;
	}

	/**
	 * @return the _messages
	 */
	public Map> getMessages() {
		return messages;
	}

	/**
	 * @param _messages
	 *            the _messages to set
	 */
	public void setMessages(Map> _messages) {
		this.messages = _messages;
	}

	/**
	 * @return the beans
	 */
	public Map getBeans() {
		return beans;
	}

	/**
	 * @param beans the beans to set
	 */
	public void setBeans(Map beans) {
		this.beans = beans;
	}

	/**
	 * @return the _viewRoot
	 */
	public UIViewRoot getViewRoot() {
		return viewRoot;
	}

	/**
	 * @param root
	 *            the _viewRoot to set
	 */
	public void setViewRoot(UIViewRoot root) {
		viewRoot = root;
	}

	/**
	 * @return the viewStateParameter
	 */
	public String getViewStateParameter() {
		return viewStateParameter;
	}

	/**
	 * @param viewStateParameter
	 *            the viewStateParameter to set
	 */
	public void setViewStateParameter(String viewStateParameter) {
		this.viewStateParameter = viewStateParameter;
	}

	/**
	 * @return the namespace
	 */
	public String getNamespace() {
		return namespace;
	}

	/**
	 * @param namespace
	 *            the namespace to set
	 */
	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	/**
	 * @return the conversationIdParameter
	 */
	public String getConversationIdParameter() {
		return conversationIdParameter;
	}

	/**
	 * @param conversationIdParameter
	 *            the conversationIdParameter to set
	 */
	public void setConversationIdParameter(String conversationIdParameter) {
		this.conversationIdParameter = conversationIdParameter;
	}

	/**
	 * @return the conversationId
	 */
	public String getConversationId() {
		return conversationId;
	}

	/**
	 * @param conversationId
	 *            the conversationId to set
	 */
	public void setConversationId(String conversationId) {
		this.conversationId = conversationId;
	}

	public Map getRequestParameters() {
		return requestParameters;
	}

	public void setRequestParameters(Map requestParameters) {
		this.requestParameters = requestParameters;
	}

	/**
	 * @param facesContext
	 * @param render
	 */
	public void restoreRequest(FacesContext facesContext, boolean render) {
		if (render) {
			facesContext.setViewRoot(getViewRoot());
			setViewRoot(null);
		}
		restoreMessages(facesContext);
		restoreBeans(facesContext);
	}

	/**
	 * @param facesContext
	 * @param withViewRoot
	 */
	public void saveRequest(FacesContext facesContext, boolean withViewRoot) {
		if (withViewRoot) {
			UIViewRoot root = facesContext.getViewRoot();
			setViewRoot(root);
			if (null != root) {
				setViewId(root.getViewId());
			}

		}
		saveBeans(facesContext);
		saveMessages(facesContext);
		saveRequestParameters(facesContext);
	}

	/**
	 * @param facesContext
	 */
	public void saveMessages(FacesContext facesContext) {
		Iterator idsWithMessages = facesContext
				.getClientIdsWithMessages();
		while (idsWithMessages.hasNext()) {
			String id = idsWithMessages.next();
			Iterator messages = facesContext.getMessages(id);
			while (messages.hasNext()) {
				FacesMessage message = messages.next();
				addMessage(id, message);
			}
		}
	}

	/**
	 * @param facesContext
	 */
	public void restoreMessages(FacesContext facesContext) {
			Iterator idsWithMessages = getClientIdsWithMessages();
			while (idsWithMessages.hasNext()) {
				String id = idsWithMessages.next();
				Iterator messages = getMessages(id);
				while (messages.hasNext()) {
					FacesMessage message = messages.next();
					facesContext.addMessage(id, message);
				}
			}
	}

	/**
	 * Save request-scope beans, as described in the JSR-301 5.1
	 * 
	 * @param facesContext
	 */
	public void saveBeans(FacesContext facesContext) {
		ExternalContext externalContext = facesContext.getExternalContext();
		PortletBridgeContext bridgeContext = PortletBridgeContext
				.getCurrentInstance(facesContext);
		BridgeConfig bridgeConfig = bridgeContext.getBridgeConfig();
		Set existingAttributes = null;
		if (null != bridgeContext) {
			existingAttributes = bridgeContext
					.getInitialRequestAttributeNames();
		}
		if (null == existingAttributes) {
			existingAttributes = new HashSet();
		} else {
			// Create local copy for merge with initial parameters.
			existingAttributes = new HashSet(existingAttributes);
		}
		// Get list of request attributes preventing to save.
		// in the JSR 301 PLT 5.1
		Set excluded = bridgeConfig
		        .getExcludedAttributes();
		Map requestMap = externalContext.getRequestMap();
		for (Iterator> iterator = requestMap.entrySet()
		        .iterator(); iterator.hasNext();) {
			Entry entry = iterator.next();
			String attributeName = entry.getKey();
			if (!existingAttributes.contains(attributeName)
			        && includeAttributeName(attributeName, excluded)) {
				Object bean = entry.getValue();
				if (null != bean && includeAttributeValue(bean)) {
					beans.put(attributeName, bean);
				}
			}
		}
	}

	private boolean includeAttributeValue(Object bean) {
	    boolean include = true;
		if (bean.getClass().isAnnotationPresent(
	    		ExcludeFromManagedRequestScope.class)) {
	    	include  = false;
	    }
	    for (int i = 0; (i < excludedClasses.length) && include; i++) {
	    	if (excludedClasses[i].isInstance(bean)) {
	    		include = false;
	    	}
	    }
	    return include;
    }

	private boolean includeAttributeName(String attributeName,Set excluded) {
	    boolean include=true;
	    // Force error messages to save.
		if (!attributeName.startsWith("javax.servlet.error.")) {
			for (int i = 0; (i < excludedRequestAttributes.length) && include; i++) {
				if (attributeName.startsWith(excludedRequestAttributes[i])) {
					include = false;
				}
			}

        }		if (include && null != excluded) {
			for (ExcludedRequestAttribute excludedRequestAttribute : excluded) {
				if (excludedRequestAttribute.match(attributeName)) {
					include = false;
					break;
				}
			}
		}
	    return include;
    }

	public void saveRequestParameters(FacesContext facesContext) {
		// Save request parameters ( all or a View state only ) restored as
		// requered
		// in the JSR 301 PLT 5.1
		ExternalContext externalContext = facesContext.getExternalContext();
		PortletBridgeContext bridgeContext = PortletBridgeContext
				.getCurrentInstance(facesContext);
		BridgeConfig bridgeConfig = bridgeContext.getBridgeConfig();
		boolean preserveActionParam = bridgeConfig.isPreserveActionParams();
		if (preserveActionParam) {
			requestParameters.putAll(externalContext
					.getRequestParameterValuesMap());
			requestParameters.remove(AJAX_PARAMETER_NAME);
			requestParameters.remove(ResponseStateManager.VIEW_STATE_PARAM);
		}
	}

	public void restoreBeans(FacesContext facesContext) {
		Map requestMap = facesContext.getExternalContext()
				.getRequestMap();
		requestMap.putAll(beans);
		Map requestParameters = getRequestParameters();
		if (requestParameters
				.containsKey(ResponseStateManager.VIEW_STATE_PARAM)) {
			requestMap.put(Bridge.IS_POSTBACK_ATTRIBUTE, Boolean.TRUE);
		}
		if (null != conversationId) {
			requestParameters.put(conversationIdParameter,
					new String[] { conversationId });
		}
	}

	public void reset() {
		this.requestParameters = new HashMap(4);
		this.beans = new HashMap();
		this.messages = new HashMap>();
		this.viewRoot = null;
		this.viewId = null;
		this.conversationIdParameter = "conversationId";
		this.conversationId = null;
	}

	private void addMessage(String clientId, FacesMessage message) {
		List list = messages.get(clientId);
		if (list == null) {
			list = new ArrayList();
			messages.put(clientId, list);
		}
		list.add(message);
	}

	private Iterator getClientIdsWithMessages() {
		return (messages.keySet().iterator());
	}

	private Iterator getMessages(String clientId) {
		List list = messages.get(clientId);
		if (list != null) {
			return (list.iterator());
		} else {
			return Collections. emptyList().iterator();
		}
	}

	private void writeObject(java.io.ObjectOutputStream out) throws IOException {
		// Save all default fields
		out.defaultWriteObject();
		// Save serializable request-scope beans.
		for (Map.Entry entry : beans.entrySet()) {
			String key = entry.getKey();
			Object bean = entry.getValue();
			if (null != key && key.length() > 0 && null != bean
			        && bean instanceof Serializable) {
				out.writeUTF(key);
				out.writeObject(bean);
			}
		} // End of request scope beans marker.
		out.writeUTF("");
	}

	private void readObject(java.io.ObjectInputStream in) throws IOException,
			ClassNotFoundException {
		in.defaultReadObject();
		String key = in.readUTF();
		if (key.length() > 0) {
			beans = new HashMap();
			while (key.length() > 0) {
				Object bean = in.readObject();
				beans.put(key, bean);
				key = in.readUTF();
			}
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy