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

io.guise.framework.platform.web.HTTPServletGuiseSessionManager Maven / Gradle / Ivy

There is a newer version: 0.5.3
Show newest version
/*
 * Copyright © 2005-2009 GlobalMentor, Inc. 

 *
 * Licensed 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 io.guise.framework.platform.web;

import java.util.*;

import static java.util.Collections.*;

import javax.servlet.http.*;

import io.guise.framework.GuiseApplication;
import io.guise.framework.GuiseSession;

import static com.globalmentor.java.Objects.*;
import static com.globalmentor.servlet.http.HTTPServlets.*;

/**
 * Manages Guise sessions for an HTTP web application. Guise sessions are created and released in conjunction with associated HTTP servlet sessions. There may
 * be multiple Guise applications within one web application.
 * 

* A HTTP request may override any HTTP session identified by the request by exlicitly identifying the Guise session UUID using the * {@link WebPlatform#GUISE_SESSION_UUID_URI_QUERY_PARAMETER} parameter. *

* @author Garret Wilson * @see HTTPServletGuiseContainer */ public class HTTPServletGuiseSessionManager implements HttpSessionListener { /** The synchronized map of Guise containers keyed to HTTP sessions. */ private static final Map guiseContainerMap = synchronizedMap(new HashMap()); private static HttpSession spiderSession = null; //TODO fix to be separate for each application; testing /** * Retrieves a session for the given HTTP request, creating a session if necessary. If a {@link WebPlatform#GUISE_SESSION_UUID_URI_QUERY_PARAMETER} parameter * is present in the HTTP request, it will be used to directly look up a Guise session, ignoring any identified HTTP session. If there is no Guise session * matching a specified UUID, the Guise session will be retrieved normally. * @param guiseContainer The Guise container that owns the application. * @param guiseApplication The application to install to own the created session.. * @param httpRequest The HTTP request with which the Guise session is to be associated. * @return The Guise session associated with the provided HTTP session. * @throws IllegalArgumentException if the provided HTTP session is not a session from this web application or the HTTP session has been invalidated, and * there is therefore no corresponding Guise session. */ protected static GuiseSession getGuiseSession(final HTTPServletGuiseContainer guiseContainer, final GuiseApplication guiseApplication, final HttpServletRequest httpRequest) { return getGuiseSession(guiseContainer, guiseApplication, httpRequest, true); //get a Guise session, creating one if necessary } /** * Retrieves a session for the given HTTP request. If a {@link WebPlatform#GUISE_SESSION_UUID_URI_QUERY_PARAMETER} parameter is present in the HTTP request, * it will be used to directly look up a Guise session, ignoring any identified HTTP session. If there is no Guise session matching a specified UUID, the * Guise session will be retrieved normally. * @param guiseContainer The Guise container that owns the application. * @param guiseApplication The application to install to own the created session.. * @param httpRequest The HTTP request with which the Guise session is to be associated. * @param createSession Whether a Guise session should be created if one does not already exist. * @return The Guise session associated with the provided HTTP request, or null if there is no Guise session and session creation was not * requested. * @throws IllegalArgumentException if the provided HTTP session is not a session from this web application or the HTTP session has been invalidated, and * there is therefore no corresponding Guise session. */ protected static GuiseSession getGuiseSession(final HTTPServletGuiseContainer guiseContainer, final GuiseApplication guiseApplication, final HttpServletRequest httpRequest, final boolean createSession) { final String guiseSessionUUIDString = httpRequest.getParameter(WebPlatform.GUISE_SESSION_UUID_URI_QUERY_PARAMETER); //see if a Guise session UUID is specified if(guiseSessionUUIDString != null) { //if a Guise session UUID is specified final UUID guiseSessionUUID = UUID.fromString(guiseSessionUUIDString); //create a UUID from the string final GuiseSession guiseSession = guiseApplication.getSession(guiseSessionUUID); //see if the application knows of such a session if(guiseSession != null) { //if we found the session return guiseSession; //return the session we found } } //TODO del Log.trace("requested session ID: ", httpRequest.getRequestedSessionId()); HttpSession httpSession = httpRequest.getSession(false); //get the current HTTP session from the HTTP request, if there is a session if(httpSession == null) { //if there is no session yet for this request, we'll create one final Map userAgentProperties = getUserAgentProperties(httpRequest); //get user agent-related properties TODO have the method cache these in the request final String userAgentName = asInstance(userAgentProperties.get(USER_AGENT_NAME_PROPERTY), String.class).orElse(null); //get the user agent name final boolean isSpider = UNSESSIONED_SPIDER_USER_AGENT_NAMES.contains(userAgentName); //see if the user agent is a spider that does not support sessions boolean useSpiderSession = isSpider && spiderSession != null; //we'll use the spider session if the user agent is a spider and we have a spider session if(useSpiderSession) { //even if the user agent is a spider, make sure the spider session is valid try { if((System.currentTimeMillis() - spiderSession.getLastAccessedTime()) / 1000 > spiderSession.getMaxInactiveInterval() - 2) //if the existing spider session is almost expired { useSpiderSession = false; //don't use the spider session } } catch(final IllegalStateException illegalStateException) { //if the spider session is already invalidated (the servlet API seems to allow no way to check this explicitly for arbitrary sessions) useSpiderSession = false; } } if(useSpiderSession) { //if this is a spider and we have a spider session //TODO del Debug.info("using spider session for user agent name", userAgentName); httpSession = spiderSession; //use the spider session } else { //if this isn't a spider, we have no existing spider session, or the existing spider session is almost expired, create a session //TODO del Debug.info("creating session for user agent name", userAgentName); httpSession = httpRequest.getSession(true); //create a new HTTP session for the HTTP request //TODO is there a race condition here? could two requests requesting the same session happen concurrently? guiseContainerMap.put(httpSession, guiseContainer); //store our Guise container so we'll know with which container this session is associated (this servlet may serve many Guise applications in many Guise containers in the web application) if(isSpider) { //if we just created a session for a spider //TODO del Debug.info("storing this session as a spider session"); spiderSession = httpSession; //store the spider session for future sharing } } } return guiseContainer.getGuiseSession(guiseApplication, httpRequest, httpSession); //ask the Guise application for a Guise session corresponding to the HTTP session } /** * {@inheritDoc} *

* This implementation does nothing, as there is no way to tell with which Guise container and Guise application application a new Guise application should be * associated. *

*/ @Override public void sessionCreated(final HttpSessionEvent httpSessionEvent) { } /** * {@inheritDoc} *

* This implementation removes the corresponding Guise session. *

*/ @Override public void sessionDestroyed(final HttpSessionEvent httpSessionEvent) { synchronized(guiseContainerMap) { //don't allow anyone to modify our map of applications while we access it final HttpSession httpSession = httpSessionEvent.getSession(); //get the HTTP session just invalidated final HTTPServletGuiseContainer guiseContainer = guiseContainerMap.get(httpSession); //see if we have a Guise container associated with this HTTP request if(guiseContainer != null) { //if we know the Guise container associated with this HTTP request guiseContainerMap.remove(httpSession); //remove the association between this HTTP session and the container final Set guiseSessions = guiseContainer.removeGuiseSessions(httpSession); //remove the Guise sessions associated with the HTTP session in the application assert !guiseSessions.isEmpty() : "Guise container associated with HTTP session unexpectedly did not have any associated Guise sessions."; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy