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

br.gov.frameworkdemoiselle.internal.context.FacesViewBeanStore Maven / Gradle / Ivy

There is a newer version: 2.5.4
Show newest version
package br.gov.frameworkdemoiselle.internal.context;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;

import br.gov.frameworkdemoiselle.context.ViewContext;
import br.gov.frameworkdemoiselle.util.ResourceBundle;

/**
 * Store that keeps view scoped beans. It associates all view scoped beans with a view ID. When the ID changes (meaning
 * the view changed) all old view scoped beans are destroyed before new beans for the new view are created and stored.
 * 
 * @author SERPRO
 */
public class FacesViewBeanStore implements Serializable {

	private static final long serialVersionUID = -8265458933971929432L;

	private final ConcurrentHashMap viewStore = new ConcurrentHashMap();

	private long maxInactiveTimeInSeconds;

	public FacesViewBeanStore(long maxInactiveTimeInSeconds) {
		this.maxInactiveTimeInSeconds = maxInactiveTimeInSeconds;
	}

	/**
	 * Gets the store that contains the view scoped beans for that view ID. If no store exists (new view) one is
	 * created.
	 * 
	 * @param viewId
	 *            ID of the current view
	 * @param context
	 *            Reference to the {@link ViewContext} class managing the view scope
	 * @return The {@link BeanStore} that stores view scoped beans for this view ID
	 * @throws IllegalStateException
	 *             if the view associated with the requested view ID has expired
	 */
	public BeanStore getStoreForView(Long viewId, AbstractCustomContext context) {
		FacesViewData data = null;
		synchronized (viewStore) {
			data = viewStore.get(viewId);
			if (data == null) {
				BeanStore store = AbstractCustomContext.createStore();
				data = new FacesViewData();
				data.store = store;
				viewStore.put(viewId, data);
			} else if (data.isExpired(maxInactiveTimeInSeconds)) {
				throw new IllegalStateException(ResourceBundle.getBundle("demoiselle-jsf-bundle").getString(
						"view-expired"));
			}
		}

		data.lastTimeAccessed = System.currentTimeMillis();
		return data.store;
	}

	/**
	 * @see #destroyStoresInSession(AbstractCustomContext, boolean)
	 */
	public void destroyStoresInSession(AbstractCustomContext context) {
		destroyStoresInSession(context, false);
	}

	/**
	 * Destroys all View scoped beans and the associated {@link BeanStore} for this user's session. The destroyed beans
	 * will respect CDI bean lifecycle, thus they'll trigger any events associated with destroying beans.
	 * 
	 * @param context
	 *            ViewContext managing the view scoped beans
	 * @param onlyExpired
	 *            Only destroy beans if the underlying view has expired
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void destroyStoresInSession(final AbstractCustomContext context, final boolean onlyExpired) {
		for (Iterator> it = viewStore.entrySet().iterator(); it.hasNext();) {
			Entry currentEntry = it.next();
			FacesViewData data = currentEntry.getValue();

			if (data != null && data.store != null) {
				if (!onlyExpired || data.isExpired(maxInactiveTimeInSeconds)) {
					for (String id : data.store) {
						Contextual contextual = context.getContextualStore().getContextual(id);
						Object instance = data.store.getInstance(id);
						CreationalContext creationalContext = data.store.getCreationalContext(id);

						if (contextual != null && instance != null) {
							contextual.destroy(instance, creationalContext);
						}
					}

					data.store.clear();
					it.remove();
				}
			}
		}
	}

	/**
	 * Contains a {@link BeanStore} with some metadata, like the last time this store was accessed (used to determine
	 * when a store expires).
	 * 
	 * @author serpro
	 */
	private static class FacesViewData {

		long lastTimeAccessed;

		BeanStore store;

		public synchronized boolean isExpired(long viewTimeoutInSeconds) {
			return ((System.currentTimeMillis() - lastTimeAccessed) / 1000) > viewTimeoutInSeconds;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy