Package org.jboss.portletbridge.application

Source Code of org.jboss.portletbridge.application.PortletStateHolder$LRUMap

/******************************************************************************
* 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.application;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;

import javax.faces.FacesException;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.portlet.ActionRequest;
import javax.portlet.PortletContext;
import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;
import javax.portlet.PortletSessionUtil;
import javax.portlet.RenderRequest;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeException;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.portletbridge.StateId;
import org.jboss.portletbridge.context.PortalActionURL;

/**
* @author asmirnov
*
*/
public class PortletStateHolder {

  public static final String STATE_HOLDER = PortletStateHolder.class
      .getName();

  private static final String DEFAULT = "default-";

  private static final Log log = LogFactory.getLog(PortletStateHolder.class);

  private PortletMode lastMode = PortletMode.VIEW;

  public static final String WINDOW_ID_RETRIVER = "org.jboss.portletbridge.WINDOW_ID_RETRIVER";

  public static final String STATE_ID_PARAMETER = "javax.faces.portletbridge.STATE_ID";

  private static final int DEFAULT_MAX_MANAGED_SCOPES = 1000;

  /**
   * View states for a different portlet modes, Views and serial numbers.
   */
  private final Map<StateId, PortletWindowState> states;

  /**
   * Private constructor - instance must be stored in the session, and created
   * on nessesary by factory method.
   *
   * @param context
   */
  private PortletStateHolder(int max) {
    states = new LRUMap<StateId, PortletWindowState>(max);
  }

  public static PortletStateHolder init(PortletContext context) {
    PortletStateHolder stateHolder;
    synchronized (context) {
      stateHolder = (PortletStateHolder) context
          .getAttribute(STATE_HOLDER);
      if (null == stateHolder) {
        int maxScopes = DEFAULT_MAX_MANAGED_SCOPES;
        String maxScopesParameter = context
            .getInitParameter(Bridge.MAX_MANAGED_REQUEST_SCOPES);
        if (null != maxScopesParameter) {
          maxScopes = Integer.parseInt(maxScopesParameter);
        }
        stateHolder = new PortletStateHolder(
            maxScopes);
        context.setAttribute(STATE_HOLDER, stateHolder);
      }
    }
    return stateHolder;
  }

  /**
   * Get instance of portlet states, stored in the session. If no previsious
   * instance in session, create default value.
   *
   * @param context
   * @return
   */
  public static PortletStateHolder getInstance(FacesContext context) {
    ExternalContext externalContext = context.getExternalContext();
    PortletStateHolder stateHolder = (PortletStateHolder) externalContext
        .getApplicationMap().get(STATE_HOLDER);
    if (null == stateHolder) {
      throw new BridgeException(
          "Jsf portletbridge bridge not initialized");
    }
    return stateHolder;
  }




  public void addWindowState(StateId stateId, PortletWindowState state) {
    states.put(stateId, state);
  }
 
  /**
   * @param stateId
   * @return
   */
  public PortletWindowState getWindowState(StateId stateId) {
    PortletWindowState state = null;
    if (null != stateId) {
      state = (PortletWindowState) states.get(stateId);
    }
    return state;
  }

  public StateId getStateId(String portletName, ActionRequest actionRequest) {
    UUID uuid = UUID.randomUUID();
    PortletMode portletMode = actionRequest.getPortletMode();
    StateId stateId = new StateId(getScopeId(portletName, actionRequest),portletMode ,uuid.toString());
    return stateId;
  }

  public StateId getStateId(String portletName, RenderRequest renderRequest, String namespace) {
    PortletMode portletMode = renderRequest.getPortletMode();
    String scopeId = getScopeId(portletName, renderRequest);
    StateId stateId = null ;
    PortletSession session = renderRequest.getPortletSession(false);
    String stateIdParameter = renderRequest.getParameter(STATE_ID_PARAMETER);
    if (null == stateIdParameter) {
      stateId = getStateIdFromViewHistory(portletMode,
          session);
    } else {
      stateId = new StateId(stateIdParameter);
      // Check portlet mode for a changes:
      if (!portletMode.equals(stateId.getMode())) {
        StateId historyStateId = getStateIdFromViewHistory(portletMode,
            session);
        if(null != historyStateId){
          stateId = historyStateId;
        } else {
          stateId.setMode(portletMode);
        }
      }
    }
    if (null == stateId) {
      stateId = new StateId(scopeId,portletMode,namespace);
    }
    return stateId;
  }

  private StateId getStateIdFromViewHistory(PortletMode portletModeName,
       PortletSession session) {
    StateId stateId = null;
    if(null != session){
      String modeViewId = (String) session.getAttribute(Bridge.VIEWID_HISTORY+"."+portletModeName);
      if(null != modeViewId){
        try {
          PortalActionURL viewUrl = new PortalActionURL(modeViewId);
          String stateIdParameter = viewUrl.getParameter(STATE_ID_PARAMETER);
          if(null != stateIdParameter){
            stateId = new StateId(stateIdParameter);
          }
        } catch (MalformedURLException e) {
          // Ignore.
        }
       
      }
    }
    return stateId;
  }

  public synchronized String getScopeId(String portletName, PortletRequest request) {
    PortletSession portletSession = request.getPortletSession(true);
//    String scopeId = portletName.replace(':', '_') + portletSession.getId().replace(':', '_');
    // Check portlet SessionId retriver attribute.
    WindowIDRetriver idRetriver = (WindowIDRetriver) portletSession
        .getAttribute(WINDOW_ID_RETRIVER);
    if (null == idRetriver) {
      synchronized (this) {
        idRetriver = (WindowIDRetriver) portletSession
          .getAttribute(WINDOW_ID_RETRIVER);
        if (null == idRetriver) {
          UUID uuid = UUID.randomUUID();
          idRetriver = new WindowIDRetriver(uuid.toString());
          portletSession.setAttribute(WINDOW_ID_RETRIVER, idRetriver);
        }
      }
    }
    return idRetriver.getScopeId();
  }



  private void removeSessionStates(String scopeId) {
    synchronized (states) {
      // Iterate over copy of the keys, so LinkedHashSet do not support
      // concurrent modifications.
      for (Iterator<StateId> keysIterator = states.keySet().iterator(); keysIterator
          .hasNext();) {
        StateId key = keysIterator.next();
        if (key.getScopeId().equals(scopeId)) {
          keysIterator.remove();
        }
      }
 
    }
  }



  /**
   * Based on the Julien Viet idea.
   *
   * @author asmirnov
   *
   */
  public static final class WindowIDRetriver implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {

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

    public static final String PORTLET_SCOPE_PREFIX = "javax.portlet.p.";

    private final String scopeId;

    private String windowID;

    /**
     * @param scopeId
     */
    private WindowIDRetriver(String scopeId) {
      this.scopeId = scopeId;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet
     * .http.HttpSessionBindingEvent)
     */
    public void valueBound(HttpSessionBindingEvent event) {
      String name = event.getName();
      if (null == name || 0 == name.length()) {
        throw new FacesException(
            "WindowIDRetriver bind to session without name");
      }
      if (PortletSession.PORTLET_SCOPE != PortletSessionUtil
          .decodeScope(name)) {
        throw new FacesException(
            "WindowIDRetriver bind to APPLICATION_SCOPE. PORTLET_SCOPE is required");
      }
      windowID = name.substring(PORTLET_SCOPE_PREFIX.length(), name
          .indexOf('?'));
      if (log.isDebugEnabled()) {
        log
            .debug("WindowIDRetriver have been bind to session for a portletbridge window "
                + windowID);
      }

    }

    /*
     * (non-Javadoc)
     *
     * @see
     * javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.
     * servlet.http.HttpSessionBindingEvent)
     */
    public void valueUnbound(HttpSessionBindingEvent event) {
      PortletStateHolder stateHolder = (PortletStateHolder) event
          .getSession().getServletContext()
          .getAttribute(STATE_HOLDER);
      if (null != stateHolder) {
        stateHolder.removeSessionStates(scopeId);

      }
    }

    /**
     * @return the windowID
     */
    public String getWindowID() {
      return windowID;
    }

    /**
     * @return the scopeId
     */
    public String getScopeId() {
      return scopeId;
    }

    public void sessionDidActivate(HttpSessionEvent se) {
      // ??? restore window states for that session.
     
    }

    public void sessionWillPassivate(HttpSessionEvent se) {
      // ??? save window states for that session.
     
    }

  }

  /**
   * Last Recent Used Map cache. See {@link LinkedHashMap} for details.
   *
   * @author asmirnov
   *
   */
  private static class LRUMap<K, V> extends LinkedHashMap<K, V> implements
      Serializable {

    /**
      *
      */
    private static final long serialVersionUID = -7232885382582796665L;
    private int capacity;

    /**
     * @param capacity
     *            - maximal cache capacity.
     */
    public LRUMap(int capacity) {
      super(capacity, 1.0f, true);
      this.capacity = capacity;
    }

    protected boolean removeEldestEntry(Entry<K, V> entry) {
      // Remove last entry if size exceeded.
      return size() > capacity;
    }

    /**
     * Get most recent used element
     *
     * @return the most Recent value
     */
    public Object getMostRecent() {
      Iterator<V> iterator = values().iterator();
      Object mostRecent = null;
      while (iterator.hasNext()) {
        mostRecent = iterator.next();

      }
      return mostRecent;
    }
  }

}
TOP

Related Classes of org.jboss.portletbridge.application.PortletStateHolder$LRUMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.