001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.jetty6.cluster; 018 019 import java.util.HashMap; 020 import java.util.Map; 021 022 import javax.servlet.http.HttpServletRequest; 023 import javax.servlet.http.HttpSession; 024 025 import org.apache.geronimo.clustering.SessionAlreadyExistException; 026 import org.apache.geronimo.clustering.SessionListener; 027 import org.apache.geronimo.clustering.SessionManager; 028 import org.mortbay.jetty.servlet.AbstractSessionManager; 029 import org.mortbay.jetty.servlet.HashSessionIdManager; 030 031 032 /** 033 * @version $Rev$ $Date$ 034 */ 035 public class ClusteredSessionManager extends AbstractSessionManager { 036 037 private final SessionManager sessionManager; 038 private final Map<String, ClusteredSession> idToSession = new HashMap<String, ClusteredSession>(); 039 040 public ClusteredSessionManager(SessionManager sessionManager) { 041 this.sessionManager = sessionManager; 042 043 String workerName = sessionManager.getNode().getName(); 044 workerName = workerName.replaceAll(" ", ""); 045 HashSessionIdManager sessionIdManager = new HashSessionIdManager(); 046 sessionIdManager.setWorkerName(workerName); 047 setIdManager(sessionIdManager); 048 049 sessionManager.registerListener(new MigrationListener()); 050 } 051 052 @Override 053 protected Session newSession(HttpServletRequest request) { 054 return new ClusteredSession(request); 055 } 056 057 @Override 058 public void complete(HttpSession session) { 059 ClusteredSession clusteredSession = (ClusteredSession) session; 060 clusteredSession.session.onEndAccess(); 061 } 062 063 @Override 064 protected void addSession(Session session) { 065 ClusteredSession clusteredSession = (ClusteredSession) session; 066 synchronized (idToSession) { 067 idToSession.put(clusteredSession.getClusterId(), clusteredSession); 068 } 069 } 070 071 @Override 072 protected void removeSession(String idInCluster) { 073 synchronized (idToSession) { 074 idToSession.remove(idInCluster); 075 } 076 } 077 078 @Override 079 public Session getSession(String idInCluster) { 080 synchronized (idToSession) { 081 return idToSession.get(idInCluster); 082 } 083 } 084 085 @Override 086 public int getSessions() { 087 synchronized (idToSession) { 088 return idToSession.size(); 089 } 090 } 091 092 @Override 093 public Map getSessionMap() { 094 throw new AssertionError("getSessionMap is never used."); 095 } 096 097 @Override 098 protected void invalidateSessions() { 099 // We do not need to clear idToSession: when the SessionManager GBean is stopped, all the sessions 100 // it defines are migrated to other SessionManagers. These outbound session migrations will remove 101 // them from idToSession. 102 } 103 104 private class MigrationListener implements SessionListener { 105 106 public void notifyInboundSessionMigration(org.apache.geronimo.clustering.Session session) { 107 addSession(new ClusteredSession(session), false); 108 } 109 110 public void notifyOutboundSessionMigration(org.apache.geronimo.clustering.Session session) { 111 ClusteredSession clusteredSession = getClusteredSession(session); 112 removeSession(clusteredSession, false); 113 } 114 115 public void notifySessionDestruction(org.apache.geronimo.clustering.Session session) { 116 ClusteredSession clusteredSession = getClusteredSession(session); 117 removeSession(clusteredSession, true); 118 } 119 120 private ClusteredSession getClusteredSession(org.apache.geronimo.clustering.Session session) throws AssertionError { 121 ClusteredSession clusteredSession; 122 synchronized (idToSession) { 123 clusteredSession = idToSession.remove(session.getSessionId()); 124 } 125 if (null == clusteredSession) { 126 throw new AssertionError("Session [" + session + "] is undefined"); 127 } 128 return clusteredSession; 129 } 130 131 132 } 133 134 public class ClusteredSession extends Session { 135 private final org.apache.geronimo.clustering.Session session; 136 137 protected ClusteredSession(HttpServletRequest request) { 138 super(request); 139 try { 140 this.session = sessionManager.createSession(getClusterId()); 141 } catch (SessionAlreadyExistException e) { 142 throw (IllegalStateException) new IllegalStateException().initCause(e); 143 } 144 initValues(); 145 } 146 147 protected ClusteredSession(org.apache.geronimo.clustering.Session session) { 148 super(System.currentTimeMillis(), session.getSessionId()); 149 this.session = session; 150 initValues(); 151 } 152 153 @Override 154 protected Map newAttributeMap() { 155 return session.getState(); 156 } 157 158 @Override 159 protected String getClusterId() { 160 return super.getClusterId(); 161 } 162 163 @Override 164 public void invalidate() throws IllegalStateException { 165 super.invalidate(); 166 session.release(); 167 } 168 } 169 170 }