/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file 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.bridge.scope; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.portlet.PortletContext; import javax.portlet.PortletSession; import javax.portlet.faces.Bridge; import org.jboss.portletbridge.bridge.config.BridgeConfig; import org.jboss.portletbridge.bridge.context.BridgeContext; import org.jboss.portletbridge.bridge.factory.BridgeFactoryFinder; import org.jboss.portletbridge.bridge.factory.BridgeLoggerFactoryImpl; import org.jboss.portletbridge.bridge.factory.BridgeRequestScopeFactory; import org.jboss.portletbridge.bridge.logger.BridgeLogger; import org.jboss.portletbridge.bridge.logger.BridgeLogger.Level; /** * Manages a set of BridgeRequestScopes based on its policies. Clients interact with the manager to create and remove * BridgeRequestScopes, and to lookup one by its key. * * @author kenfinnigan */ public class BridgeRequestScopeManagerImpl implements BridgeRequestScopeManager, Serializable { private static final int DEFAULT_MAX_MANAGED_REQUEST_SCOPES = 100; private static final BridgeLogger logger = BridgeLoggerFactoryImpl.getLogger(BridgeRequestScopeManagerImpl.class .getName()); private transient BridgeRequestScopeFactory scopeFactory; private Map<String, BridgeRequestScope> bridgeRequestScopeCache; private Map<String, String> scopeIdMap; public BridgeRequestScopeManagerImpl(BridgeConfig bridgeConfig) { this.scopeFactory = retrieveScopeFactory(); this.bridgeRequestScopeCache = createBridgeRequestScopeCache(bridgeConfig.getPortletConfig() .getPortletContext()); this.scopeIdMap = new HashMap<String, String>(getCacheMax(bridgeConfig.getPortletConfig().getPortletContext())); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#createRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public BridgeRequestScope createRequestScope(BridgeContext ctx, String portletName, String sessionId, String viewId, String portletMode) { BridgeRequestScope scope = getScopeFactory().getBridgeRequestScope(portletName, sessionId, viewId, portletMode); this.bridgeRequestScopeCache.put(scope.getId(), scope); this.scopeIdMap.put( BridgeRequestScopeUtil.generateBridgeRequestScopeIdPrefix(portletName, sessionId, viewId, portletMode), scope.getId()); return scope; } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#createRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public BridgeRequestScope createRequestScope(BridgeContext ctx, String viewId) { return createRequestScope(ctx, ctx.getBridgeConfig().getPortletConfig().getPortletName(), ctx .getPortletRequest().getPortletSession(true).getId(), viewId, ctx.getPortletRequest().getPortletMode() .toString()); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#getRequestScopeById(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public BridgeRequestScope getRequestScopeById(BridgeContext ctx, String id) { return this.bridgeRequestScopeCache.get(id); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#getRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public BridgeRequestScope getRequestScope(BridgeContext ctx, String portletName, String sessionId, String viewId, String portletMode) { String idPrefix = BridgeRequestScopeUtil.generateBridgeRequestScopeIdPrefix(portletName, sessionId, viewId, portletMode); String scopeKey = this.scopeIdMap.get(idPrefix); BridgeRequestScope scope = null; if (null != scopeKey) { scope = getRequestScopeById(ctx, scopeKey); if (null == scope) { this.scopeIdMap.remove(idPrefix); } } return scope; } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#getRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String, java.lang.String) */ public BridgeRequestScope getRequestScope(BridgeContext ctx, String viewId, String portletMode) { return getRequestScope(ctx, ctx.getBridgeConfig().getPortletConfig().getPortletName(), ctx.getPortletRequest() .getPortletSession(true).getId(), viewId, portletMode); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#getRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public BridgeRequestScope getRequestScope(BridgeContext ctx, String viewId) { return getRequestScope(ctx, viewId, ctx.getPortletRequest().getPortletMode().toString()); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#getRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext) */ public BridgeRequestScope getRequestScope(BridgeContext ctx) { return getRequestScope(ctx, ctx.getFacesViewId(true)); } /** * Per JSR-329 6.8.2, removal of the {@link BridgeRequestScope} from being cached results in clear() being called on * the scope, which in turn calls preDestroy on Objects. * * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScopeById(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public BridgeRequestScope removeRequestScopeById(BridgeContext ctx, String id) { BridgeRequestScope scope = this.bridgeRequestScopeCache.remove(id); if (scope != null) { scope.clear(); } return scope; } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * org.jboss.portletbridge.bridge.scope.BridgeRequestScope) */ public BridgeRequestScope removeRequestScope(BridgeContext ctx, BridgeRequestScope scope) { return removeRequestScope(ctx, scope.getViewId()); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public BridgeRequestScope removeRequestScope(BridgeContext ctx, String portletName, String sessionId, String viewId, String portletMode) { String idPrefix = BridgeRequestScopeUtil.generateBridgeRequestScopeIdPrefix(portletName, sessionId, viewId, portletMode); String scopeKey = this.scopeIdMap.get(idPrefix); BridgeRequestScope scope = null; if (null != scopeKey) { scope = removeRequestScopeById(ctx, scopeKey); this.scopeIdMap.remove(idPrefix); } return scope; } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String, java.lang.String) */ public BridgeRequestScope removeRequestScope(BridgeContext ctx, String viewId, String portletMode) { return removeRequestScope(ctx, ctx.getBridgeConfig().getPortletConfig().getPortletName(), ctx .getPortletRequest().getPortletSession(true).getId(), viewId, portletMode); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScope(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public BridgeRequestScope removeRequestScope(BridgeContext ctx, String viewId) { return removeRequestScope(ctx, viewId, ctx.getPortletRequest().getPortletMode().toString()); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScopesByPortlet(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public void removeRequestScopesByPortlet(BridgeContext ctx, String portletName) { if (null != portletName) { Set<Map.Entry<String, BridgeRequestScope>> entries = this.bridgeRequestScopeCache.entrySet(); if (null != entries) { synchronized (this.bridgeRequestScopeCache) { for (Map.Entry<String, BridgeRequestScope> entry : entries) { BridgeRequestScope scope = entry.getValue(); if (portletName.equals(scope.getPortletName())) { this.removeRequestScopeById(ctx, entry.getKey()); } } } } } } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScopesByPortlet(org.jboss.portletbridge.bridge.context.BridgeContext) */ public void removeRequestScopesByPortlet(BridgeContext ctx) { removeRequestScopesByPortlet(ctx, ctx.getBridgeConfig().getPortletConfig().getPortletName()); } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScopesBySession(org.jboss.portletbridge.bridge.context.BridgeContext, * java.lang.String) */ public void removeRequestScopesBySession(BridgeContext ctx, String sessionId) { if (null != sessionId) { Set<Map.Entry<String, BridgeRequestScope>> entries = this.bridgeRequestScopeCache.entrySet(); if (null != entries) { synchronized (this.bridgeRequestScopeCache) { for (Map.Entry<String, BridgeRequestScope> entry : entries) { BridgeRequestScope scope = entry.getValue(); if (sessionId.equals(scope.getSessionId())) { this.removeRequestScopeById(ctx, entry.getKey()); } } } } } } /** * @see org.jboss.portletbridge.bridge.scope.BridgeRequestScopeManager#removeRequestScopesBySession(org.jboss.portletbridge.bridge.context.BridgeContext) */ public void removeRequestScopesBySession(BridgeContext ctx) { PortletSession portletSession = ctx.getPortletRequest().getPortletSession(false); if (null != portletSession) { removeRequestScopesBySession(ctx, portletSession.getId()); } } protected Map<String, BridgeRequestScope> createBridgeRequestScopeCache(PortletContext portletContext) { return Collections.synchronizedMap(new BridgeRequestScopeCache(getCacheMax(portletContext))); } /** * Per JSR-329 3.2, retrieves javax.portlet.faces.MAX_MANAGED_REQUEST_SCOPES portlet init parameter to determine the * maximum number of scopes to maintain. If not present, or invalid value, use the default for this implementation. * * @param portletContext * @return Max number of {@link BridgeRequestScope}'s to manage */ private int getCacheMax(PortletContext portletContext) { int maxManagedScopes = DEFAULT_MAX_MANAGED_REQUEST_SCOPES; String maxManagedScopesInitParam = portletContext.getInitParameter(Bridge.MAX_MANAGED_REQUEST_SCOPES); if (null != maxManagedScopesInitParam) { try { maxManagedScopes = Integer.parseInt(maxManagedScopesInitParam); } catch (NumberFormatException e) { logger .log(Level.WARNING, "portlet.xml contains invalid value for " + Bridge.MAX_MANAGED_REQUEST_SCOPES); } } return maxManagedScopes; } public BridgeRequestScopeFactory getScopeFactory() { if(scopeFactory == null) { scopeFactory = retrieveScopeFactory(); } return scopeFactory; } private BridgeRequestScopeFactory retrieveScopeFactory() { return (BridgeRequestScopeFactory) BridgeFactoryFinder.getFactoryInstance(BridgeRequestScopeFactory.class); } }