Skip to content

Commit

Permalink
fix for hazelcast#3049
Browse files Browse the repository at this point in the history
  • Loading branch information
serkanozal committed Aug 6, 2014
1 parent 8c8fc7e commit 3c7916e
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 11 deletions.
37 changes: 37 additions & 0 deletions hazelcast-wm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<properties>
<jsp.api.version>2.2.1</jsp.api.version>
<servlet.api.version>3.0.1</servlet.api.version>
<org.springframework.version>3.1.0.RELEASE</org.springframework.version>
<jetty.maven.plugin.version>8.1.2.v20120308</jetty.maven.plugin.version>
<!-- needed for checkstyle/findbugs -->
<main.basedir>${project.parent.basedir}</main.basedir>
Expand Down Expand Up @@ -183,6 +184,42 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${org.springframework.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
Expand Down
32 changes: 21 additions & 11 deletions hazelcast-wm/src/main/java/com/hazelcast/web/WebFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,14 @@
*/
public class WebFilter implements Filter {

public static final String WEB_FILTER_ATTRIBUTE_KEY = WebFilter.class.getName();

protected static final String HAZELCAST_SESSION_ATTRIBUTE_SEPARATOR = "::hz::";

private static final ILogger LOGGER = Logger.getLogger(WebFilter.class);
private static final LocalCacheEntry NULL_ENTRY = new LocalCacheEntry();
private static final String HAZELCAST_REQUEST = "*hazelcast-request";
private static final String HAZELCAST_SESSION_COOKIE_NAME = "hazelcast.sessionId";
protected static final ILogger LOGGER = Logger.getLogger(WebFilter.class);
protected static final LocalCacheEntry NULL_ENTRY = new LocalCacheEntry();
protected static final String HAZELCAST_REQUEST = "*hazelcast-request";
protected static final String HAZELCAST_SESSION_COOKIE_NAME = "hazelcast.sessionId";

protected ServletContext servletContext;
protected FilterConfig filterConfig;
Expand Down Expand Up @@ -166,7 +168,7 @@ public final void init(final FilterConfig config)
// Register the WebFilter with the ServletContext so SessionListener can look it up. The name
// here is WebFilter.class instead of getClass() because WebFilter can have subclasses
servletContext = config.getServletContext();
servletContext.setAttribute(WebFilter.class.getName(), this);
servletContext.setAttribute(WEB_FILTER_ATTRIBUTE_KEY, this);

initInstance();
initCookieParams();
Expand Down Expand Up @@ -296,7 +298,7 @@ private String extractAttributeKey(String key) {
return key.substring(key.indexOf(HAZELCAST_SESSION_ATTRIBUTE_SEPARATOR) + HAZELCAST_SESSION_ATTRIBUTE_SEPARATOR.length());
}

private HazelcastHttpSession createNewSession(RequestWrapper requestWrapper, String existingSessionId) {
protected HazelcastHttpSession createNewSession(RequestWrapper requestWrapper, String existingSessionId) {
String id = existingSessionId == null ? generateSessionId() : existingSessionId;
if (requestWrapper.getOriginalSession(false) != null) {
LOGGER.finest("Original session exists!!!");
Expand Down Expand Up @@ -345,7 +347,7 @@ private void updateSessionMaps(String sessionId, HttpSession originalSession, Ha
* in the cluster; otherwise, {@code false} to only remove the session globally if this
* node was the final node referencing it
*/
private void destroySession(HazelcastHttpSession session, boolean invalidate) {
protected void destroySession(HazelcastHttpSession session, boolean invalidate) {
if (LOGGER.isFinestEnabled()) {
LOGGER.finest("Destroying local session: " + session.getId());
}
Expand Down Expand Up @@ -483,21 +485,21 @@ private String getParam(String name) {
}
}

private static class ResponseWrapper extends HttpServletResponseWrapper {
protected static class ResponseWrapper extends HttpServletResponseWrapper {

public ResponseWrapper(final HttpServletResponse original) {
super(original);
}
}

private static class LocalCacheEntry {
protected static class LocalCacheEntry {
volatile boolean dirty;
volatile boolean reload;
boolean removed;
private Object value;
}

private class RequestWrapper extends HttpServletRequestWrapper {
protected class RequestWrapper extends HttpServletRequestWrapper {
final ResponseWrapper res;
HazelcastHttpSession hazelcastSession;
String requestedSessionId;
Expand Down Expand Up @@ -594,7 +596,7 @@ public HazelcastHttpSession getSession(final boolean create) {
}
} // END of RequestWrapper

private class HazelcastHttpSession implements HttpSession {
protected class HazelcastHttpSession implements HttpSession {

volatile boolean valid = true;
final String id;
Expand All @@ -612,6 +614,14 @@ public HazelcastHttpSession(final String sessionId, final HttpSession originalSe
this.localCache = deferredWrite ? buildLocalCache() : null;
}

public HttpSession getOriginalSession() {
return originalSession;
}

public String getOriginalSessionId() {
return originalSession != null ? originalSession.getId() : null;
}

public Object getAttribute(final String name) {
IMap<String, Object> clusterMap = getClusterMap();
if (deferredWrite) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright (c) 2008-2014, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.web.spring;

import com.hazelcast.web.WebFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.session.HttpSessionCreatedEvent;
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.util.logging.Level;

public class SpringAwareWebFilter extends WebFilter {

protected volatile SessionRegistry sessionRegistry;

protected void ensureSessionRegistryInitialized(ApplicationContext appContext) {
if (sessionRegistry == null) {
synchronized (this) {
if (sessionRegistry == null) {
sessionRegistry = appContext.getBean(SessionRegistry.class);
}
}
}
}

@Override
protected HazelcastHttpSession createNewSession(RequestWrapper requestWrapper,
String existingSessionId) {
HazelcastHttpSession session = super.createNewSession(requestWrapper, existingSessionId);
ApplicationContext appContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
if (appContext != null) {
ensureSessionRegistryInitialized(appContext);
if (sessionRegistry != null) {
String originalSessionId = session.getOriginalSessionId();
// If original session id is registered already, we don't need it.
// So, we should remove it.
sessionRegistry.removeSessionInformation(originalSessionId);
// Publish event if this session is not registered
if (!isSessionRegistered(session.getId())) {
/**
* Publish an event to notify
* {@link org.springframework.security.core.session.SessionRegistry} instance.
* So Spring knows our Hazelcast session.
*
* If session is already exist
* (
* possibly added by
* {@link org.springframework.security.web.session.HttpSessionEventPublisher} instance
* which is defined in {@code web.xml} before
* {@link com.hazelcast.web.SessionListener} to
* {@link org.springframework.security.core.session.SessionRegistry}
* ),
* it will be just updated.
*/
appContext.publishEvent(new HttpSessionCreatedEvent(session));
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Published create session event for Spring: " + session);
}
}
}
}
return session;
}

@Override
protected void destroySession(HazelcastHttpSession session, boolean invalidate) {
super.destroySession(session, invalidate);
if (invalidate) {
ApplicationContext appContext =
WebApplicationContextUtils.getWebApplicationContext(servletContext);
if (appContext != null) {
ensureSessionRegistryInitialized(appContext);
if (sessionRegistry != null) {
String originalSessionId = session.getOriginalSessionId();
// If original session id is registered already, we don't need it.
// So, we should remove it also.
sessionRegistry.removeSessionInformation(originalSessionId);
/**
* Publish an event to notify
* {@link org.springframework.security.core.session.SessionRegistry} instance.
* So Spring clears information about our Hazelcast session.
*/
appContext.publishEvent(new HttpSessionDestroyedEvent(session));
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Published destroy session event for Spring: " + session);
}
}
}
}
}

private boolean isSessionRegistered(String sessionId) {
if (sessionRegistry != null) {
return sessionRegistry.getSessionInformation(sessionId) != null;
} else {
return false;
}
}

}

0 comments on commit 3c7916e

Please sign in to comment.