/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * 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 the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>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.apereo.portal.utils.web; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.portlet.PortletRequest; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.util.Assert; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.portlet.context.PortletRequestAttributes; import org.springframework.web.util.WebUtils; /** */ public final class PortalWebUtils { private PortalWebUtils() {} /** Key for the mutex request session attribute */ public static final String REQUEST_MUTEX_ATTRIBUTE = PortalWebUtils.class.getName() + ".MUTEX"; /** * Return the best available mutex for the given request attributes: that is, an object to * synchronize on for the given request attributes. * * <p>Returns the request attributes mutex attribute if available; usually, this means that the * RequestAttributeMutexListener needs to be defined in <code>web.xml</code>. Falls back to the * ServletRequest itself if no mutex attribute found. * * <p>The request attributes mutex is guaranteed to be the same object during the entire * lifetime of the request, available under the key defined by the <code>REQUEST_MUTEX_ATTRIBUTE * </code> constant. It serves as a safe reference to synchronize on for locking on the current * request attributes. * * @param servletRequest the ServletRequest to find a mutex for * @return the mutex object (never <code>null</code>) * @see #REQUEST_MUTEX_ATTRIBUTE * @see RequestAttributeMutexListener */ public static Object getRequestAttributeMutex(ServletRequest servletRequest) { Assert.notNull(servletRequest, "ServletRequest must not be null"); Object mutex = servletRequest.getAttribute(REQUEST_MUTEX_ATTRIBUTE); if (mutex == null) { mutex = servletRequest; } return mutex; } /** * Get a {@link ConcurrentMap} for the specified name from the {@link ServletRequest} * attributes. If it doesn't exist create it and store it in the attributes. This is done in a * thread-safe matter that ensures only one Map per name & request will be created @See {@link * #getRequestAttributeMutex(ServletRequest)} */ public static <K, V> ConcurrentMap<K, V> getMapRequestAttribute( ServletRequest servletRequest, String name) { return getMapRequestAttribute(servletRequest, name, true); } @SuppressWarnings("unchecked") public static <K, V> ConcurrentMap<K, V> getMapRequestAttribute( ServletRequest servletRequest, String name, boolean create) { final Object mutex = getRequestAttributeMutex(servletRequest); synchronized (mutex) { ConcurrentMap<K, V> map = (ConcurrentMap<K, V>) servletRequest.getAttribute(name); if (map == null) { if (!create) { return null; } map = new ConcurrentHashMap<K, V>(); servletRequest.setAttribute(name, map); } return map; } } /** * Get a {@link ConcurrentMap} for the specified name from the {@link HttpSession} attributes. * If it doesn't exist create it and store it in the attributes. This is done in a thread-safe * matter that ensures only one Map per name & session will be created @See {@link * WebUtils#getSessionMutex(HttpSession)} */ public static <K, V> ConcurrentMap<K, V> getMapSessionAttribute( HttpSession session, String name) { return getMapSessionAttribute(session, name, true); } @SuppressWarnings("unchecked") public static <K, V> ConcurrentMap<K, V> getMapSessionAttribute( HttpSession session, String name, boolean create) { final Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { ConcurrentMap<K, V> map = (ConcurrentMap<K, V>) session.getAttribute(name); if (map == null) { if (!create) { return null; } map = new ConcurrentHashMap<K, V>(); session.setAttribute(name, map); } return map; } } /** * Get the request context path from the current request. Copes with both HttpServletRequest and * PortletRequest and so usable when handling Spring-processed Servlet or Portlet requests. * Requires that Spring have bound the request, as in the case of dispatcher servlet or portlet * or when the binding filter or listener is active. This should be the case for all requests in * the uPortal framework and framework portlets. * * @return request.getContextPath() for the relevant servlet or portlet request * @throws IllegalStateException if the request is not Spring-bound or is neither Servlet nor * Portlet flavored */ public static String currentRequestContextPath() { final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if (null == requestAttributes) { throw new IllegalStateException( "Request attributes are not bound. " + "Not operating in context of a Spring-processed Request?"); } if (requestAttributes instanceof ServletRequestAttributes) { final ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; final HttpServletRequest request = servletRequestAttributes.getRequest(); return request.getContextPath(); } else if (requestAttributes instanceof PortletRequestAttributes) { final PortletRequestAttributes portletRequestAttributes = (PortletRequestAttributes) requestAttributes; final PortletRequest request = portletRequestAttributes.getRequest(); return request.getContextPath(); } else { throw new IllegalStateException( "Request attributes are an unrecognized implementation."); } } }