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 }