001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.jetty.cluster; 019 020 import java.io.BufferedReader; 021 import java.io.IOException; 022 import java.io.UnsupportedEncodingException; 023 import java.security.Principal; 024 import java.util.Enumeration; 025 import java.util.Locale; 026 import java.util.Map; 027 028 import javax.servlet.RequestDispatcher; 029 import javax.servlet.ServletInputStream; 030 import javax.servlet.http.Cookie; 031 import javax.servlet.http.HttpServletRequest; 032 import javax.servlet.http.HttpSession; 033 034 import org.apache.geronimo.clustering.SessionAlreadyExistException; 035 import org.apache.geronimo.clustering.SessionListener; 036 import org.apache.geronimo.clustering.SessionManager; 037 import org.mortbay.jetty.servlet.AbstractSessionManager; 038 039 040 /** 041 * 042 * @version $Rev$ $Date$ 043 */ 044 public class ClusteredSessionManager extends AbstractSessionManager { 045 private static final Object ALL_SESSION_PLACEHOLDER = new Object(); 046 047 private final SessionManager sessionManager; 048 049 public ClusteredSessionManager(SessionManager sessionManager) { 050 this.sessionManager = sessionManager; 051 052 String workerName = sessionManager.getNode().getName(); 053 workerName = workerName.replaceAll(" ", ""); 054 setWorkerName(workerName); 055 // implementation note: enables cross context session id such that a mock HttpServletRequest having a defined 056 // requestedSessionId attribute can be used to re-create an HttpSession with a defined session ID in this 057 // manager. 058 setCrossContextSessionIDs(true); 059 060 sessionManager.registerListener(new MigrationListener()); 061 062 // sessions are not removed by this manager. They are invalidated via a callback mechanism 063 setMaxInactiveInterval(-1); 064 } 065 066 protected Session newSession(HttpServletRequest request) { 067 return new ClusteredSession(request); 068 } 069 070 private class MigrationListener implements SessionListener { 071 072 public void notifyInboundSessionMigration(org.apache.geronimo.clustering.Session session) { 073 String sessionId = session.getSessionId(); 074 synchronized (__allSessions) { 075 if (__allSessions.containsKey(sessionId)) { 076 throw new IllegalStateException("ID [" + sessionId + "] is already defined."); 077 } 078 __allSessions.add(sessionId, ALL_SESSION_PLACEHOLDER); 079 newHttpSession(new RequestWithBoundSession(session)); 080 __allSessions.removeValue(sessionId, ALL_SESSION_PLACEHOLDER); 081 } 082 } 083 084 public void notifyOutboundSessionMigration(org.apache.geronimo.clustering.Session session) { 085 String sessionId = session.getSessionId(); 086 synchronized (__allSessions) { 087 __allSessions.remove(sessionId); 088 } 089 090 synchronized (_sessions) { 091 _sessions.remove(sessionId); 092 } 093 } 094 } 095 096 protected class ClusteredSession extends Session { 097 private static final String FORCE_SET_VALUES = "$$$JETTY_FORCE_SET_VALUES$$$"; 098 099 private final org.apache.geronimo.clustering.Session session; 100 101 protected ClusteredSession(HttpServletRequest request) { 102 super(request); 103 104 if (request instanceof RequestWithBoundSession) { 105 this.session = ((RequestWithBoundSession) request).session; 106 // implementation note: set a dummy attribute such that the underlying attribute map is initialized 107 // with the state of the inbound session. 108 setAttribute(FORCE_SET_VALUES, FORCE_SET_VALUES); 109 } else { 110 try { 111 this.session = sessionManager.createSession(getId()); 112 } catch (SessionAlreadyExistException e) { 113 throw (IllegalStateException) new IllegalStateException().initCause(e); 114 } 115 } 116 } 117 118 protected Map newAttributeMap() { 119 return session.getState(); 120 } 121 } 122 123 /** 124 * Implementation note: this is a mock HttpServletRequest which is used to create an HttpSession with the same 125 * session ID than the wrapped Session. 126 */ 127 private class RequestWithBoundSession implements HttpServletRequest { 128 private final org.apache.geronimo.clustering.Session session; 129 130 public RequestWithBoundSession(org.apache.geronimo.clustering.Session session) { 131 this.session = session; 132 } 133 134 public void setAttribute(String arg0, Object arg1) { 135 } 136 137 public Object getAttribute(String arg0) { 138 return null; 139 } 140 141 public String getRequestedSessionId() { 142 return session.getSessionId(); 143 } 144 145 public String getAuthType() { 146 throw new UnsupportedOperationException(); 147 } 148 149 public String getContextPath() { 150 throw new UnsupportedOperationException(); 151 } 152 153 public Cookie[] getCookies() { 154 throw new UnsupportedOperationException(); 155 } 156 157 public long getDateHeader(String arg0) { 158 throw new UnsupportedOperationException(); 159 } 160 161 public String getHeader(String arg0) { 162 throw new UnsupportedOperationException(); 163 } 164 165 public Enumeration getHeaderNames() { 166 throw new UnsupportedOperationException(); 167 } 168 169 public Enumeration getHeaders(String arg0) { 170 throw new UnsupportedOperationException(); 171 } 172 173 public int getIntHeader(String arg0) { 174 throw new UnsupportedOperationException(); 175 } 176 177 public String getMethod() { 178 throw new UnsupportedOperationException(); 179 } 180 181 public String getPathInfo() { 182 throw new UnsupportedOperationException(); 183 } 184 185 public String getPathTranslated() { 186 throw new UnsupportedOperationException(); 187 } 188 189 public String getQueryString() { 190 throw new UnsupportedOperationException(); 191 } 192 193 public String getRemoteUser() { 194 throw new UnsupportedOperationException(); 195 } 196 197 public String getRequestURI() { 198 throw new UnsupportedOperationException(); 199 } 200 201 public StringBuffer getRequestURL() { 202 throw new UnsupportedOperationException(); 203 } 204 205 public String getServletPath() { 206 throw new UnsupportedOperationException(); 207 } 208 209 public HttpSession getSession() { 210 throw new UnsupportedOperationException(); 211 } 212 213 public HttpSession getSession(boolean arg0) { 214 throw new UnsupportedOperationException(); 215 } 216 217 public Principal getUserPrincipal() { 218 throw new UnsupportedOperationException(); 219 } 220 221 public boolean isRequestedSessionIdFromCookie() { 222 throw new UnsupportedOperationException(); 223 } 224 225 public boolean isRequestedSessionIdFromURL() { 226 throw new UnsupportedOperationException(); 227 } 228 229 public boolean isRequestedSessionIdFromUrl() { 230 throw new UnsupportedOperationException(); 231 } 232 233 public boolean isRequestedSessionIdValid() { 234 throw new UnsupportedOperationException(); 235 } 236 237 public boolean isUserInRole(String arg0) { 238 throw new UnsupportedOperationException(); 239 } 240 241 public Enumeration getAttributeNames() { 242 throw new UnsupportedOperationException(); 243 } 244 245 public String getCharacterEncoding() { 246 throw new UnsupportedOperationException(); 247 } 248 249 public int getContentLength() { 250 throw new UnsupportedOperationException(); 251 } 252 253 public String getContentType() { 254 throw new UnsupportedOperationException(); 255 } 256 257 public ServletInputStream getInputStream() throws IOException { 258 throw new UnsupportedOperationException(); 259 } 260 261 public String getLocalAddr() { 262 throw new UnsupportedOperationException(); 263 } 264 265 public String getLocalName() { 266 throw new UnsupportedOperationException(); 267 } 268 269 public int getLocalPort() { 270 throw new UnsupportedOperationException(); 271 } 272 273 public Locale getLocale() { 274 throw new UnsupportedOperationException(); 275 } 276 277 public Enumeration getLocales() { 278 throw new UnsupportedOperationException(); 279 } 280 281 public String getParameter(String arg0) { 282 throw new UnsupportedOperationException(); 283 } 284 285 public Map getParameterMap() { 286 throw new UnsupportedOperationException(); 287 } 288 289 public Enumeration getParameterNames() { 290 throw new UnsupportedOperationException(); 291 } 292 293 public String[] getParameterValues(String arg0) { 294 throw new UnsupportedOperationException(); 295 } 296 297 public String getProtocol() { 298 throw new UnsupportedOperationException(); 299 } 300 301 public BufferedReader getReader() throws IOException { 302 throw new UnsupportedOperationException(); 303 } 304 305 public String getRealPath(String arg0) { 306 throw new UnsupportedOperationException(); 307 } 308 309 public String getRemoteAddr() { 310 throw new UnsupportedOperationException(); 311 } 312 313 public String getRemoteHost() { 314 throw new UnsupportedOperationException(); 315 } 316 317 public int getRemotePort() { 318 throw new UnsupportedOperationException(); 319 } 320 321 public RequestDispatcher getRequestDispatcher(String arg0) { 322 throw new UnsupportedOperationException(); 323 } 324 325 public String getScheme() { 326 throw new UnsupportedOperationException(); 327 } 328 329 public String getServerName() { 330 throw new UnsupportedOperationException(); 331 } 332 333 public int getServerPort() { 334 throw new UnsupportedOperationException(); 335 } 336 337 public boolean isSecure() { 338 throw new UnsupportedOperationException(); 339 } 340 341 public void removeAttribute(String arg0) { 342 throw new UnsupportedOperationException(); 343 } 344 345 public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException { 346 throw new UnsupportedOperationException(); 347 } 348 } 349 }