Package org.jasig.portal.portlet.registry

Source Code of org.jasig.portal.portlet.registry.PortletWindowRegistryImpl

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you 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.jasig.portal.portlet.registry;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;

import javax.portlet.WindowState;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;

import org.apache.commons.lang.Validate;
import org.apache.pluto.container.PortletWindow;
import org.apache.pluto.container.PortletWindowID;
import org.apache.pluto.container.om.portlet.PortletDefinition;
import org.jasig.portal.IUserPreferencesManager;
import org.jasig.portal.IUserProfile;
import org.jasig.portal.concurrency.caching.RequestCache;
import org.jasig.portal.layout.IUserLayoutManager;
import org.jasig.portal.layout.dao.IStylesheetDescriptorDao;
import org.jasig.portal.layout.om.IStylesheetDescriptor;
import org.jasig.portal.layout.om.IStylesheetParameterDescriptor;
import org.jasig.portal.portlet.PortletUtils;
import org.jasig.portal.portlet.om.IPortletDefinition;
import org.jasig.portal.portlet.om.IPortletDefinitionId;
import org.jasig.portal.portlet.om.IPortletEntity;
import org.jasig.portal.portlet.om.IPortletEntityId;
import org.jasig.portal.portlet.om.IPortletWindow;
import org.jasig.portal.portlet.om.IPortletWindowId;
import org.jasig.portal.security.IPerson;
import org.jasig.portal.url.IPortalRequestInfo;
import org.jasig.portal.url.IPortalRequestUtils;
import org.jasig.portal.url.IUrlSyntaxProvider;
import org.jasig.portal.url.UrlState;
import org.jasig.portal.user.IUserInstance;
import org.jasig.portal.user.IUserInstanceManager;
import org.jasig.portal.utils.Tuple;
import org.jasig.portal.utils.web.PortalWebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.util.WebUtils;

import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;

/**
* Provides the default implementation of the window registry, the backing for the storage
* of IPortletWindow objects is a Map stored in the HttpSession for the user.
*
* @author Eric Dalquist
* @version $Revision$
*/
@Service
public class PortletWindowRegistryImpl implements IPortletWindowRegistry {
    public static final QName PORTLET_WINDOW_ID_ATTR_NAME = new QName("portletWindowId");
   
    static final char ID_PART_SEPERATOR = '.';
    static final Pattern ID_PART_SEPERATOR_PATTERN = Pattern.compile(Pattern.quote(String.valueOf(ID_PART_SEPERATOR)));
   
    static final String STATELESS_PORTLET_WINDOW_ID = "tw";
    static final String PORTLET_WINDOW_DATA_ATTRIBUTE = PortletWindowRegistryImpl.class.getName() + ".PORTLET_WINDOW_DATA";
    static final String PORTLET_WINDOW_ATTRIBUTE = PortletWindowRegistryImpl.class.getName() + ".PORTLET_WINDOW.thread-";
    static final String DISABLE_PERSISTENT_WINDOWS = PortletWindowRegistryImpl.class.getName() + ".DISABLE_PERSISTENT_WINDOWS";

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance();
   
    private Set<WindowState> persistentWindowStates = Sets.newHashSet(WindowState.MINIMIZED);
    private IPortletEntityRegistry portletEntityRegistry;
    private IPortletDefinitionRegistry portletDefinitionRegistry;
    private IStylesheetDescriptorDao stylesheetDescriptorDao;
    private IUserInstanceManager userInstanceManager;
    private IPortalRequestUtils portalRequestUtils;
    private IUrlSyntaxProvider urlSyntaxProvider;
   
   
    /**
     * The set of WindowStates that should be copied to the {@link IPortletEntity} when {@link #storePortletWindow(HttpServletRequest, IPortletWindow)}
     * is called
     */
    public void setPersistentWindowStates(Set<WindowState> persistentWindowStates) {
        this.persistentWindowStates = persistentWindowStates;
    }
   
    @Autowired
    public void setUrlSyntaxProvider(IUrlSyntaxProvider urlSyntaxProvider) {
        this.urlSyntaxProvider = urlSyntaxProvider;
    }
    @Autowired
    public void setStylesheetDescriptorDao(IStylesheetDescriptorDao stylesheetDescriptorDao) {
        this.stylesheetDescriptorDao = stylesheetDescriptorDao;
    }
    @Autowired
    public void setUserInstanceManager(IUserInstanceManager userInstanceManager) {
        this.userInstanceManager = userInstanceManager;
    }
    @Autowired
    public void setPortletEntityRegistry(IPortletEntityRegistry portletEntityRegistry) {
        this.portletEntityRegistry = portletEntityRegistry;
    }
    @Autowired
    public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry) {
        this.portletDefinitionRegistry = portletDefinitionRegistry;
    }
    @Autowired
  public void setPortalRequestUtils(IPortalRequestUtils portalRequestUtils) {
    this.portalRequestUtils = portalRequestUtils;
  }
   
  /* (non-Javadoc)
     * @see org.jasig.portal.portlet.registry.IPortletWindowRegistry#convertPortletWindow(javax.servlet.http.HttpServletRequest, org.apache.pluto.PortletWindow)
     */
    @Override
    public IPortletWindow convertPortletWindow(HttpServletRequest request, PortletWindow plutoPortletWindow) {
        Validate.notNull(request, "request can not be null");
        Validate.notNull(plutoPortletWindow, "portletWindow can not be null");
       
        //Conver the pluto portlet window ID into a uPortal portlet window ID
        final PortletWindowID plutoWindowId = plutoPortletWindow.getId();
        final IPortletWindowId portletWindowId;
        if (plutoWindowId instanceof IPortletWindowId) {
            portletWindowId = (IPortletWindowId)plutoWindowId;
        }
        else {
            portletWindowId = this.getPortletWindowId(request, plutoWindowId.getStringId());
        }
       
        //Do a new get to make sure the referenced data gets updated correctly
        return this.getPortletWindow(request, portletWindowId);
    }
   
    @Override
    public IPortletWindow getOrCreateDefaultPortletWindowByFname(HttpServletRequest request, String fname) {
        Validate.notNull(request, "HttpServletRequest cannot be null");
        Validate.notNull(fname, "fname cannot be null");
       
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IPortletEntity portletEntity = this.portletEntityRegistry.getOrCreatePortletEntityByFname(request, userInstance, fname);
        if (portletEntity == null) {
            return null;
        }
       
        final IPortletWindow portletWindow = this.getOrCreateDefaultPortletWindow(request, portletEntity.getPortletEntityId());
        logger.trace("Found portlet window {} for portlet definition fname {}", portletWindow, fname);
       
        return portletWindow;
    }
   
    @Override
    public IPortletWindow getOrCreateDefaultPortletWindowByLayoutNodeId(HttpServletRequest request, String subscribeId) {
        Validate.notNull(request, "HttpServletRequest cannot be null");
        Validate.notNull(subscribeId, "subscribeId cannot be null");
       
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IPortletEntity portletEntity = this.portletEntityRegistry.getOrCreatePortletEntity(request, userInstance, subscribeId);
        if (portletEntity == null) {
            logger.debug("No portlet entity found for id {}, no IPortletWindow will be returned.", subscribeId);
            return null;
        }
        logger.trace("Found portlet entity {} for id {}", portletEntity, subscribeId);
       
        final IPortletWindow portletWindow = this.getOrCreateDefaultPortletWindow(request, portletEntity.getPortletEntityId());
        logger.trace("Found portlet window {} for layout node {}", portletWindow, subscribeId);
       
        return portletWindow;
    }
   
    @Override
    public IPortletWindow getOrCreateDefaultPortletWindow(HttpServletRequest request, IPortletDefinitionId portletDefinitionId) {
        Validate.notNull(request, "HttpServletRequest cannot be null");
        Validate.notNull(portletDefinitionId, "portletDefinition cannot be null");
    
        final IPortletEntity portletEntity = this.portletEntityRegistry.getOrCreateDefaultPortletEntity(request, portletDefinitionId);
        final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId();
       
        return this.getOrCreateDefaultPortletWindow(request, portletEntityId);
    }

    @Override
    public IPortletWindow getOrCreateDefaultPortletWindow(HttpServletRequest request, IPortletEntityId portletEntityId) {
        Validate.notNull(request, "request can not be null");
        Validate.notNull(portletEntityId, "portletEntityId can not be null");
       
        final IPortletWindowId portletWindowId = this.getDefaultPortletWindowId(request, portletEntityId);

        final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);
       
        //Check if there is portlet window cached in the request
        IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
        if (portletWindow != null) {
            logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
            return portletWindow;
        }
       
        final PortletWindowData portletWindowData = this.getOrCreateDefaultPortletWindowData(request, portletEntityId, portletWindowId);
        portletWindow = wrapPortletWindowData(request, portletWindowData);
        if (portletWindow == null) {
            return null;
        }
       
        //Cache the wrapped window in the request
        return portletWindowMap.storeIfAbsentWindow(portletWindow);
    }

    /* (non-Javadoc)
     * @see org.jasig.portal.portlet.registry.IPortletWindowRegistry#getPortletWindow(javax.servlet.http.HttpServletRequest, org.jasig.portal.portlet.om.IPortletWindowId)
     */
    @Override
    public IPortletWindow getPortletWindow(HttpServletRequest request, IPortletWindowId portletWindowId) {
        Validate.notNull(request, "request can not be null");
        Validate.notNull(portletWindowId, "portletWindowId can not be null");
       
        final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);
       
        IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
        if (portletWindow != null) {
            logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
            return portletWindow;
        }
       
        final PortletWindowIdImpl localPortletWindowId = this.convertPortletWindowId(request, portletWindowId);
       
        //Find the window data from the correct window data map
        final PortletWindowData portletWindowData;
        if (STATELESS_PORTLET_WINDOW_ID.equals(localPortletWindowId.getWindowInstanceId())) {
            final PortletWindowCache<PortletWindowData> statelessPortletWindowDataMap = this.getStatelessPortletWindowDataMap(request, false);
            if (statelessPortletWindowDataMap != null) {
                portletWindowData = statelessPortletWindowDataMap.getWindow(portletWindowId);
            }
            else {
                portletWindowData = null;
            }
        }
        else {
            portletWindowData = this.getPortletWindowData(request, portletWindowId);
        }
       
        if (portletWindowData == null) {
            logger.trace("No IPortletWindow {} exists, returning null", portletWindowId);
            return null;
        }
       
        portletWindow = this.wrapPortletWindowData(request, portletWindowData);
       
        //Cache the wrapped window in the request
        return portletWindowMap.storeIfAbsentWindow(portletWindow);
    }

    /* (non-Javadoc)
     * @see org.jasig.portal.portlet.registry.IPortletWindowRegistry#getPortletWindowId(java.lang.String)
     */
    @Override
    public PortletWindowIdImpl getPortletWindowId(HttpServletRequest request, String portletWindowId) {
        Validate.notNull(portletWindowId, "portletWindowId can not be null");
       
        final String[] portletWindowIdParts = ID_PART_SEPERATOR_PATTERN.split(portletWindowId);
       
        final String entityIdStr;
        final String instanceId;
        if (portletWindowIdParts.length == 1) {
            entityIdStr = portletWindowIdParts[0];
            instanceId = null;
        }
        else if (portletWindowIdParts.length == 2) {
            entityIdStr = portletWindowIdParts[0];
            instanceId = portletWindowIdParts[1];
        }
        else  {
            throw new IllegalArgumentException("Provided portlet window ID '" + portletWindowId + "' is not valid");
        }
       
        final IPortletEntity portletEntity = this.portletEntityRegistry.getPortletEntity(request, entityIdStr);
        if (portletEntity == null) {
            throw new IllegalArgumentException("No parent IPortletEntity found for id '" + entityIdStr + "' from portlet window id: " + portletWindowId);
        }

        return createPortletWindowId(instanceId, portletEntity.getPortletEntityId());
    }
   
    /* (non-Javadoc)
     * @see org.jasig.portal.portlet.registry.IPortletWindowRegistry#getDefaultPortletWindowId(org.jasig.portal.portlet.om.IPortletEntityId)
     */
    @Override
    public IPortletWindowId getDefaultPortletWindowId(HttpServletRequest request, IPortletEntityId portletEntityId) {
        final IPortletWindowId portletWindowId = this.createPortletWindowId(null, portletEntityId);
        logger.trace("Determined default portlet window id {} for portlet entity {}", portletWindowId, portletEntityId);
        return portletWindowId;
    }
   
    @Override
    public IPortletWindow createDelegatePortletWindow(HttpServletRequest request, IPortletEntityId portletEntityId, IPortletWindowId delegationParentId) {
        Validate.notNull(request, "request can not be null");
        Validate.notNull(portletEntityId, "portletEntityId can not be null");
       
        //TODO does a delegate portlet entity need some sort of special treatment or do we just assume that the calling code is using one?
       
        final IPortletWindowId portletWindowId = this.getDefaultPortletWindowId(request, portletEntityId);

        final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);
       
        //Check if there is portlet window cached in the request
        IPortletWindow portletWindow = portletWindowMap.getWindow(portletWindowId);
        if (portletWindow != null) {
            logger.trace("Found IPortletWindow {} in request cache", portletWindow.getPortletWindowId());
            return portletWindow;
        }
       
        final PortletWindowData portletWindowData = this.getOrCreateDefaultPortletWindowData(request, portletEntityId, portletWindowId, delegationParentId);
        portletWindow = wrapPortletWindowData(request, portletWindowData);
        if (portletWindow == null) {
            return null;
        }
       
        //Cache the wrapped window in the request
        return portletWindowMap.storeIfAbsentWindow(portletWindow);
    }
   
    @Override
    public Set<IPortletWindow> getAllPortletWindowsForEntity(HttpServletRequest request, IPortletEntityId portletEntityId) {
        Validate.notNull(request, "request can not be null");
        Validate.notNull(portletEntityId, "portletEntityId can not be null");
       
       
        final PortletWindowCache<IPortletWindow> portletWindowMap = getPortletWindowMap(request);
        final Set<IPortletWindow> portletWindows = new LinkedHashSet<IPortletWindow>(portletWindowMap.getWindows(portletEntityId));
       
        //Check for session cached windows that haven't been accessed in this request
        final PortletWindowCache<PortletWindowData> portletWindowDataMap = this.getPortletWindowDataMap(request);
        this.addPortletWindowData(request, portletEntityId, portletWindows, portletWindowMap, portletWindowDataMap);

        //Check for stateless windows that exist on this request
        final PortletWindowCache<PortletWindowData> statelessPortletWindowDataMap = this.getStatelessPortletWindowDataMap(request, false);
        if (statelessPortletWindowDataMap != null) {
            this.addPortletWindowData(request, portletEntityId, portletWindows, portletWindowMap, statelessPortletWindowDataMap);
        }
       
        //If there were no windows in the set create the default one for the entity
        if (portletWindows.isEmpty()) {
            final IPortletWindow portletWindow = this.getOrCreateDefaultPortletWindow(request, portletEntityId);
            portletWindows.add(portletWindow);
        }

        return portletWindows;
    }

    @Override
    public Tuple<IPortletWindow, StartElement> getPortletWindow(HttpServletRequest request, StartElement element) {
        //Check if the layout node explicitly specifies the window id
        final Attribute windowIdAttribute = element.getAttributeByName(PORTLET_WINDOW_ID_ATTR_NAME);
        if (windowIdAttribute != null) {
            final String windowIdStr = windowIdAttribute.getValue();
            final IPortletWindowId portletWindowId = this.getPortletWindowId(request, windowIdStr);
            final IPortletWindow portletWindow = this.getPortletWindow(request, portletWindowId);
            return new Tuple<IPortletWindow, StartElement>(portletWindow, element);
        }

        //No explicit window id, look it up based on the layout node id
        final Attribute nodeIdAttribute = element.getAttributeByName(IUserLayoutManager.ID_ATTR_NAME);
        final String layoutNodeId = nodeIdAttribute.getValue();

        IPortletWindow portletWindow = this.getOrCreateDefaultPortletWindowByLayoutNodeId(request, layoutNodeId);
        if (portletWindow == null) {
            //No window for the layout node, return null
            return null;
        }

        final IPortalRequestInfo portalRequestInfo = this.urlSyntaxProvider.getPortalRequestInfo(request);
        if (portalRequestInfo.getUrlState() == UrlState.DETACHED) {
            /*
             * We want to handle DETACHED portlet windows differently/explicitly,
             * but we need to be aware there may be other portlets on the page
             * besides the targeted one.  These would be portlets in regions
             * (Respondr theme) -- such as DynamicRespondrSkin.
             *
             * We need to confirm, therefore, that this is actually the portlet
             * in DETACHED.  If it is, we'll send back a 'stateless' PortletWindow.
             */
            if (portalRequestInfo.getTargetedPortletWindowId().toString().contains("_" + layoutNodeId + "_")) {
                final IPortletWindowId portletWindowId = portletWindow.getPortletWindowId();
                portletWindow = this.getOrCreateStatelessPortletWindow(request, portletWindowId);
            }

        }

        element = this.addPortletWindowId(element, portletWindow.getPortletWindowId());

        return new Tuple<IPortletWindow, StartElement>(portletWindow, element);
    }

    protected StartElement addPortletWindowId(StartElement element, IPortletWindowId portletWindowId) {
        final Attribute windowIdAttribute = xmlEventFactory.createAttribute(PORTLET_WINDOW_ID_ATTR_NAME, portletWindowId.getStringId());

        //Clone the start element to add the new attribute
        final QName name = element.getName();
        final String prefix = name.getPrefix();
        final String namespaceURI = name.getNamespaceURI();
        final String localPart = name.getLocalPart();
        @SuppressWarnings("unchecked")
        final Iterator<Attribute> attributes = element.getAttributes();
        @SuppressWarnings("unchecked")
        final Iterator<Namespace> namespaces = element.getNamespaces();
        final NamespaceContext namespaceContext = element.getNamespaceContext();
       
        //Create a new iterator of the existing attributes + the new window id attribute
        final Iterator<Attribute> newAttributes = Iterators.concat(attributes, Iterators.forArray(windowIdAttribute));
       
        return xmlEventFactory.createStartElement(prefix, namespaceURI, localPart, newAttributes, namespaces, namespaceContext);
    }

    /**
     * @param request
     * @param portletEntityId
     * @param portletWindows
     * @param portletWindowMap
     * @param portletWindowDataMap
     */
    protected void addPortletWindowData(HttpServletRequest request, IPortletEntityId portletEntityId,
            final Set<IPortletWindow> portletWindows, final PortletWindowCache<IPortletWindow> portletWindowMap,
            final PortletWindowCache<PortletWindowData> portletWindowDataMap) {
       
        final Set<PortletWindowData> windows = portletWindowDataMap.getWindows(portletEntityId);
        if (windows == null) {
            return;
        }
       
        for (final PortletWindowData portletWindowData : windows) {
            final IPortletWindowId portletWindowId = portletWindowData.getPortletWindowId();
           
            //Skip data windows that aren't for this entity and for windows that are already in the request cache
            if (!portletEntityId.equals(portletWindowData.getPortletEntityId()) || portletWindowMap.containsWindow(portletWindowId)) {
                continue;
            }

            //Wrap the data in a window and stick it in the request cache
            IPortletWindow portletWindow = this.wrapPortletWindowData(request, portletWindowData);
            portletWindow = portletWindowMap.storeIfAbsentWindow(portletWindow);
           
            portletWindows.add(portletWindow);
        }
    }
   
    @Override
    public IPortletWindow getOrCreateStatelessPortletWindow(HttpServletRequest request, IPortletWindowId basePortletWindowId) {
        //Need the basePortletWindowId to be an instance of PortletWindowIdImpl so that we can extract the entity ID
        if (!(basePortletWindowId instanceof PortletWindowIdImpl)) {
            final String basePortletWindowIdStr = basePortletWindowId.getStringId();
            basePortletWindowId = this.getPortletWindowId(request, basePortletWindowIdStr);
        }
       
        //Get the entity ID for the portlet window
        final IPortletEntityId portletEntityId = ((PortletWindowIdImpl)basePortletWindowId).getPortletEntityId();
       
        //Create the stateless ID
        final PortletWindowIdImpl statelessPortletWindowId = this.createPortletWindowId(STATELESS_PORTLET_WINDOW_ID, portletEntityId);
       
        //See if there is already a request cached stateless window
        IPortletWindow statelessPortletWindow = this.getPortletWindow(request, statelessPortletWindowId);
        if (statelessPortletWindow != null) {
            return statelessPortletWindow;
        }
       
        //Lookup the base portlet window to clone the stateless from
        final IPortletWindow basePortletWindow = this.getPortletWindow(request, basePortletWindowId);
       
        final PortletWindowCache<PortletWindowData> statelessPortletWindowDataMap = this.getStatelessPortletWindowDataMap(request, true);
       
        //If no base to clone from lookup the entity and pluto definition data
        if (basePortletWindow == null) {
            final IPortletEntity portletEntity = this.portletEntityRegistry.getPortletEntity(request, portletEntityId);
            if (portletEntity == null) {
                throw new IllegalArgumentException("No IPortletEntity could be found for " + portletEntity + " while creating stateless portlet window for " + basePortletWindowId);
            }
           
            final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition();
            final IPortletDefinitionId portletDefinitionId = portletDefinition.getPortletDefinitionId();
            final PortletDefinition portletDescriptor = this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinitionId);
           
            final PortletWindowData portletWindowData = new PortletWindowData(statelessPortletWindowId, portletEntityId);
            statelessPortletWindowDataMap.storeWindow(portletWindowData);
           
            statelessPortletWindow = new StatelessPortletWindowImpl(portletWindowData, portletEntity, portletDescriptor);
        }
        //Clone the existing base window
        else {
            final PortletWindowData portletWindowData = new PortletWindowData(statelessPortletWindowId, portletEntityId);
            portletWindowData.setExpirationCache(basePortletWindow.getExpirationCache());
            portletWindowData.setPortletMode(basePortletWindow.getPortletMode());
            portletWindowData.setWindowState(basePortletWindow.getWindowState());
            portletWindowData.setPublicRenderParameters(basePortletWindow.getPublicRenderParameters());
            portletWindowData.setRenderParameters(basePortletWindow.getRenderParameters());
           
            statelessPortletWindowDataMap.storeWindow(portletWindowData);

            final IPortletEntity portletEntity = basePortletWindow.getPortletEntity();
            final PortletDefinition portletDescriptor = basePortletWindow.getPlutoPortletWindow().getPortletDefinition();
            statelessPortletWindow = new StatelessPortletWindowImpl(portletWindowData, portletEntity, portletDescriptor);
        }
       
        //Cache the stateless window in the request
        final PortletWindowCache<IPortletWindow> portletWindowMap = this.getPortletWindowMap(request);
        portletWindowMap.storeWindow(statelessPortletWindow);
       
        return statelessPortletWindow;
    }
   
    @Override
    public void disablePersistentWindowStates(HttpServletRequest request) {
        request = this.portalRequestUtils.getOriginalPortalRequest(request);
        request.setAttribute(DISABLE_PERSISTENT_WINDOWS, Boolean.TRUE);
    }
   
    protected boolean isDisablePersistentWindowStates(HttpServletRequest request) {
        request = this.portalRequestUtils.getOriginalPortalRequest(request);
        return Boolean.TRUE == request.getAttribute(DISABLE_PERSISTENT_WINDOWS);
    }
   
    @Override
    public void storePortletWindow(HttpServletRequest request, IPortletWindow portletWindow) {
        if (isDisablePersistentWindowStates(request)) {
            return;
        }
       
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IPerson person = userInstance.getPerson();
        if (person.isGuest()) {
            //Never persist things for the guest user, just rely on in-memory storage
            return;
        }
       
        final IStylesheetDescriptor themeStylesheetDescriptor = this.getThemeStylesheetDescriptor(request);
       
        final WindowState windowState = portletWindow.getWindowState();
       
        final IPortletEntity portletEntity = portletWindow.getPortletEntity();
        final WindowState entityWindowState = portletEntity.getWindowState(themeStylesheetDescriptor);
       
        //If the window and entity states are different
        if (windowState != entityWindowState && !windowState.equals(entityWindowState)) {
            final WindowState defaultWindowState = this.getDefaultWindowState(themeStylesheetDescriptor);
           
            //If a window state is set and is one of the persistent states set it on the entity
            if (!defaultWindowState.equals(windowState) && persistentWindowStates.contains(windowState)) {
                portletEntity.setWindowState(themeStylesheetDescriptor, windowState);
            }
            //If not remove the state from the entity
            else if (entityWindowState != null) {
                portletEntity.setWindowState(themeStylesheetDescriptor, null);
            }
           
            //Persist the modified entity
            this.portletEntityRegistry.storePortletEntity(request, portletEntity);
        }
    }
   
    @Override
    @RequestCache(keyMask = {false})
    public Set<IPortletWindow> getAllLayoutPortletWindows(HttpServletRequest request) {
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
        final IUserLayoutManager userLayoutManager = preferencesManager.getUserLayoutManager();
        final Set<String> allSubscribedChannels = userLayoutManager.getAllSubscribedChannels();
       
        final Set<IPortletWindow> allLayoutWindows = new LinkedHashSet<IPortletWindow>(allSubscribedChannels.size());

        for (final String channelSubscribeId : allSubscribedChannels) {
            final IPortletEntity portletEntity = this.portletEntityRegistry.getOrCreatePortletEntity(request, userInstance, channelSubscribeId);
            if (portletEntity == null) {
                this.logger.debug("No portlet entity found for layout node {} for user {}", channelSubscribeId, userInstance.getPerson().getUserName());
                continue;
            }
           
            final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId();
            final IPortletWindow portletWindow = this.getOrCreateDefaultPortletWindow(request, portletEntityId);
            if (portletWindow == null) {
                this.logger.debug("No portlet window found for {}", portletEntity);
                continue;
            }
           
          allLayoutWindows.add(portletWindow);
        }
       
        return allLayoutWindows;
    }
   
    @Override
    @RequestCache(keyMask = {false})
    public Set<IPortletWindow> getAllPortletWindows(HttpServletRequest request) {
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
        final IUserLayoutManager userLayoutManager = preferencesManager.getUserLayoutManager();
        final Set<String> allSubscribedChannels = userLayoutManager.getAllSubscribedChannels();
       
        final Set<IPortletWindow> allLayoutWindows = new LinkedHashSet<IPortletWindow>(allSubscribedChannels.size());

        for (final String channelSubscribeId : allSubscribedChannels) {
            final IPortletEntity portletEntity = this.portletEntityRegistry.getOrCreatePortletEntity(request, userInstance, channelSubscribeId);
           
            final IPortletEntityId portletEntityId = portletEntity.getPortletEntityId();
            final Set<IPortletWindow> portletWindows = this.getAllPortletWindowsForEntity(request, portletEntityId);
            allLayoutWindows.addAll(portletWindows);
        }
       
        return allLayoutWindows;
    }
   
    protected PortletWindowIdImpl convertPortletWindowId(HttpServletRequest request, IPortletWindowId portletWindowId) {
        if (portletWindowId instanceof PortletWindowIdImpl) {
            return (PortletWindowIdImpl)portletWindowId;
        }
       
        return this.getPortletWindowId(request, portletWindowId.getStringId());
    }

    protected IPortletWindow wrapPortletWindowData(HttpServletRequest request, PortletWindowData portletWindowData) {
        final IPortletEntityId portletEntityId = portletWindowData.getPortletEntityId();
        final IPortletEntity portletEntity = this.portletEntityRegistry.getPortletEntity(request, portletEntityId);
        if (portletEntity == null) {
            return null;
        }
       
        final IPortletDefinition portletDefinition = portletEntity.getPortletDefinition();
        final PortletDefinition portletDescriptor = this.portletDefinitionRegistry.getParentPortletDescriptor(portletDefinition.getPortletDefinitionId());
        if (portletDescriptor == null) {
            return null;
        }
       
        final IPortletWindow portletWindow = new PortletWindowImpl(portletDescriptor, portletEntity, portletWindowData);
       
        logger.trace("Wrapping PortletWindowData {} as IPortletWindow", portletWindow.getPortletWindowId());
       
        return portletWindow;
    }

    protected PortletWindowData getPortletWindowData(HttpServletRequest request, IPortletWindowId portletWindowId) {
        final PortletWindowCache<PortletWindowData> portletWindowDataMap = getPortletWindowDataMap(request, false);
        if (portletWindowDataMap == null) {
            return null;
        }
       
        final PortletWindowData portletWindowData = portletWindowDataMap.getWindow(portletWindowId);
        if (portletWindowData == null) {
            logger.trace("No PortletWindowData {} in session cache", portletWindowId);
            return null;
        }
       
        logger.trace("Found PortletWindowData {} in session cache", portletWindowData.getPortletWindowId());
        return portletWindowData;
    }

    protected PortletWindowCache<IPortletWindow> getPortletWindowMap(HttpServletRequest request) {
        request = portalRequestUtils.getOriginalPortletOrPortalRequest(request);
       
        final String mapAttributeName = PORTLET_WINDOW_ATTRIBUTE + Thread.currentThread().getId();
       
        //No need to do this in a request attribute mutex since the map is scoped to a specific thread
        @SuppressWarnings("unchecked")
        PortletWindowCache<IPortletWindow> windowCache = (PortletWindowCache<IPortletWindow>)request.getAttribute(mapAttributeName);
        if (windowCache == null) {
            windowCache = new PortletWindowCache<IPortletWindow>(false);
            request.setAttribute(mapAttributeName, windowCache);
        }
       
        return windowCache;
    }

    protected PortletWindowCache<PortletWindowData> getPortletWindowDataMap(HttpServletRequest request) {
        return this.getPortletWindowDataMap(request, true);
    }
   
    @SuppressWarnings("unchecked")
    protected PortletWindowCache<PortletWindowData> getPortletWindowDataMap(HttpServletRequest request, boolean create) {
        request = portalRequestUtils.getOriginalPortalRequest(request);
        final HttpSession session = request.getSession(create);
        if (!create && session == null) {
            return null;
        }
       
        PortletWindowCache<PortletWindowData> windowCache;
       
        final Object mutex = WebUtils.getSessionMutex(session);
        synchronized (mutex) {
            windowCache = (PortletWindowCache<PortletWindowData>)session.getAttribute(PORTLET_WINDOW_DATA_ATTRIBUTE);
            if (windowCache == null) {
                windowCache = new PortletWindowCache<PortletWindowData>();
                session.setAttribute(PORTLET_WINDOW_DATA_ATTRIBUTE, windowCache);
            }
        }
       
        return windowCache;
    }
   
    @SuppressWarnings("unchecked")
    protected PortletWindowCache<PortletWindowData> getStatelessPortletWindowDataMap(HttpServletRequest request, boolean create) {
        request = portalRequestUtils.getOriginalPortalRequest(request);
       
        PortletWindowCache<PortletWindowData> windowCache;
       
        final Object mutex = PortalWebUtils.getRequestAttributeMutex(request);
        synchronized (mutex) {
            windowCache = (PortletWindowCache<PortletWindowData>)request.getAttribute(PORTLET_WINDOW_DATA_ATTRIBUTE);
            if (windowCache == null) {
                windowCache = new PortletWindowCache<PortletWindowData>();
                request.setAttribute(PORTLET_WINDOW_DATA_ATTRIBUTE, windowCache);
            }
        }
       
        return windowCache;
    }
   
    protected PortletWindowData getOrCreateDefaultPortletWindowData(HttpServletRequest request, IPortletEntityId portletEntityId, IPortletWindowId portletWindowId) {
        return getOrCreateDefaultPortletWindowData(request, portletEntityId, portletWindowId, null);
    }

    protected PortletWindowData getOrCreateDefaultPortletWindowData(HttpServletRequest request, IPortletEntityId portletEntityId, IPortletWindowId portletWindowId, IPortletWindowId delegationParentId) {
        //Sync on session map to make sure duplicate PortletWindowData is never created
        final PortletWindowCache<PortletWindowData> portletWindowDataMap = getPortletWindowDataMap(request);
        //Check if there portlet window data cached in the session
        PortletWindowData portletWindowData = portletWindowDataMap.getWindow(portletWindowId);
        if (portletWindowData != null) {
            logger.trace("Found PortletWindowData {} in session cache", portletWindowData.getPortletWindowId());
            return portletWindowData;
        }
       
        //Create new window data for and initialize
        portletWindowData = new PortletWindowData(portletWindowId, portletEntityId, delegationParentId);
        this.initializePortletWindowData(request, portletWindowData);
       
        //Store in the session cache
        portletWindowData = portletWindowDataMap.storeIfAbsentWindow(portletWindowData);
        logger.trace("Created PortletWindowData {} and stored session cache, wrapping as IPortletWindow and returning", portletWindowData.getPortletWindowId());
       
        return portletWindowData;
    }

    /**
     * Initializes a newly created {@link PortletWindow}, the default implementation sets up the appropriate
     * {@link WindowState} and {@link javax.portlet.PortletMode}
     */
    protected void initializePortletWindowData(HttpServletRequest request, PortletWindowData portletWindowData) {
        final IStylesheetDescriptor stylesheetDescriptor = getThemeStylesheetDescriptor(request);
        final IPortletEntityId portletEntityId = portletWindowData.getPortletEntityId();
        final IPortletEntity portletEntity = this.portletEntityRegistry.getPortletEntity(request, portletEntityId);
        final WindowState entityWindowState = portletEntity.getWindowState(stylesheetDescriptor);
        if (persistentWindowStates.contains(entityWindowState)) {
            portletWindowData.setWindowState(entityWindowState);
        }
        else if (entityWindowState != null) {
            //Set of persistent window states must have changed, nuke the old value
            this.logger.warn("PortletEntity.windowState=" + entityWindowState + " but that state is not in the set of persistent WindowStates. PortletEntity.windowState will be set to null");
            portletEntity.setWindowState(stylesheetDescriptor, null);
            this.portletEntityRegistry.storePortletEntity(request, portletEntity);
        }
    }

    protected WindowState getDefaultWindowState(final IStylesheetDescriptor stylesheetDescriptor) {
        final IStylesheetParameterDescriptor defaultWindowStateParam = stylesheetDescriptor.getStylesheetParameterDescriptor("dashboardForcedWindowState");
       
        if (defaultWindowStateParam != null) {
            return PortletUtils.getWindowState(defaultWindowStateParam.getDefaultValue());
        }
       
        return WindowState.NORMAL;
    }

    protected IStylesheetDescriptor getThemeStylesheetDescriptor(HttpServletRequest request) {
        final IUserInstance userInstance = this.userInstanceManager.getUserInstance(request);
        final IUserPreferencesManager preferencesManager = userInstance.getPreferencesManager();
        final IUserProfile userProfile = preferencesManager.getUserProfile();
        final int themeStylesheetId = userProfile.getThemeStylesheetId();
       
        return stylesheetDescriptorDao.getStylesheetDescriptor(themeStylesheetId);
    }
   
    /**
     * Generates a new, unique, portlet window ID for the window instance ID & entity id.
     *
     * @param windowInstanceId The window instance id.
     * @param portletEntityId The parent entity id.
     * @return A portlet window id for the parameters.
     */
    protected PortletWindowIdImpl createPortletWindowId(String windowInstanceId, IPortletEntityId portletEntityId) {
        final StringBuilder compositeIdString = new StringBuilder(portletEntityId.getStringId());
       
        if (windowInstanceId != null) {
            compositeIdString.append(ID_PART_SEPERATOR).append(windowInstanceId);
        }
       
        return new PortletWindowIdImpl(portletEntityId, windowInstanceId, compositeIdString.toString());
    }
}
TOP

Related Classes of org.jasig.portal.portlet.registry.PortletWindowRegistryImpl

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.