1 // ======================================================================== 2 // $Id: Manager.java,v 1.6 2004/12/22 23:28:11 janb Exp $ 3 // Copyright 2002-2004 Mort Bay Consulting Pty. Ltd. 4 // ------------------------------------------------------------------------ 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // ======================================================================== 15 16 package org.mortbay.j2ee.session; 17 18 //---------------------------------------- 19 20 import java.rmi.RemoteException; 21 import java.util.ArrayList; 22 import java.util.Collection; 23 import java.util.EventListener; 24 import java.util.HashMap; 25 import java.util.Iterator; 26 import java.util.List; 27 import java.util.Map; 28 import java.util.Timer; 29 import java.util.TimerTask; 30 31 import javax.servlet.ServletContext; 32 import javax.servlet.http.Cookie; 33 import javax.servlet.http.HttpServletRequest; 34 import javax.servlet.http.HttpSession; 35 import javax.servlet.http.HttpSessionAttributeListener; 36 import javax.servlet.http.HttpSessionBindingEvent; 37 import javax.servlet.http.HttpSessionContext; 38 import javax.servlet.http.HttpSessionEvent; 39 import javax.servlet.http.HttpSessionListener; 40 41 import org.jboss.jetty.JBossWebAppContext; 42 import org.mortbay.jetty.HttpOnlyCookie; 43 import org.mortbay.jetty.SessionIdManager; 44 import org.mortbay.jetty.SessionManager; 45 import org.mortbay.jetty.servlet.AbstractSessionManager; 46 import org.mortbay.jetty.servlet.ServletHandler; 47 import org.mortbay.jetty.servlet.SessionHandler; 48 import org.mortbay.jetty.webapp.WebAppContext; 49 import org.mortbay.log.Log; 50 51 //---------------------------------------- 52 53 // TODO 54 // This class needs a lot of work to make it run. 55 //----- 56 57 // we need a SnapshotInterceptor 58 // we need to package this into JBoss and Mort Bay spaces 59 // Cluster/CMR & JDO Stores should be finished/done 60 // a DebugInterceptor could be fun.... 61 // Jetty should be user:jetty, role:webcontainer in order to use the session EJBs - wil probably need a SecurityInterceptor 62 // can I optimise return of objects from set/removeAttribute? 63 // CMPState should use local not remote interfaces 64 // FAQ entry should be finished 65 // Throttle/BufferInterceptor - could be written very like MigrationInterceptor 66 // StateAdaptor needs a name change 67 // We need some predefined containers 68 // tighten up access priviledges 69 // javadoc 70 //---------------------------------------- 71 72 // we need to rethink the strategies for flushing the local cache into 73 // the distributed cache - specifically how they can be aggregated 74 // (or-ed as opposed to and-ed). 75 76 // the spec does not say (?) whether session attribute events should 77 // be received in the order that the changes took place - we can 78 // control this by placing the SynchronizationInterceptor before or 79 // after the BindingInterceptor 80 81 // we could use a TransactionInterceptor to ensure that compound 82 // operations on e.g. a CMPState are atomic - or we could explicitly 83 // code the use of transactions where needed (we should be able to 84 // make all multiple calls collapse into one call to server - look 85 // into this). Since HttpSessions have no transactional semantics, 86 // there is no way for the user to inform us of any requirements... 87 88 //---------------------------------------- 89 90 public class Manager implements org.mortbay.jetty.SessionManager 91 { 92 // ---------------------------------------- 93 protected WebAppContext _context; 94 95 /** 96 * Whether or not the session manager will use cookies 97 * or URLs only. 98 */ 99 protected boolean _usingCookies = true; 100 getContext()101 public WebAppContext getContext() 102 { 103 return _context; 104 } 105 setContext(WebAppContext context)106 public void setContext(WebAppContext context) 107 { 108 _context = context; 109 } 110 111 // ---------------------------------------- 112 protected int _scavengerPeriod = 60; // every 1 min 113 setScavengerPeriod(int period)114 public void setScavengerPeriod(int period) 115 { 116 _scavengerPeriod = period; 117 } 118 getScavengerPeriod()119 public int getScavengerPeriod() 120 { 121 return _scavengerPeriod; 122 } 123 124 // ---------------------------------------- 125 protected StateInterceptor[] _interceptorStack = null; 126 getInterceptorStack()127 public StateInterceptor[] getInterceptorStack() 128 { 129 return _interceptorStack; 130 } 131 setInterceptorStack(StateInterceptor[] interceptorStack)132 public void setInterceptorStack(StateInterceptor[] interceptorStack) 133 { 134 _interceptorStack = interceptorStack; 135 } 136 137 // ---------------------------------------- 138 protected IdGenerator _idGenerator = null; 139 getIdGenerator()140 public IdGenerator getIdGenerator() 141 { 142 return _idGenerator; 143 } 144 setIdGenerator(IdGenerator idGenerator)145 public void setIdGenerator(IdGenerator idGenerator) 146 { 147 _idGenerator = idGenerator; 148 } 149 150 // ---------------------------------------- 151 protected int _maxInactiveInterval; 152 getMaxInactiveInterval()153 public int getMaxInactiveInterval() 154 { 155 return _maxInactiveInterval; 156 } 157 setMaxInactiveInterval(int seconds)158 public void setMaxInactiveInterval(int seconds) 159 { 160 _maxInactiveInterval = seconds; 161 } 162 163 // ---------------------------------------- 164 protected Store _store = null; 165 166 private boolean _crossContextSessionIDs = false; 167 getStore()168 public Store getStore() 169 { 170 return _store; 171 } 172 setStore(Store store)173 public void setStore(Store store) 174 { 175 _store = store; 176 177 if (_store != null) 178 _store.setManager(this); 179 } 180 181 // ---------------------------------------- 182 clone()183 public Object clone() 184 { 185 // Log.info("cloning Manager: "+this); 186 Manager m = new Manager(); 187 188 // deep-copy Store attribute - each Manager gets it's own Store instance 189 Store store = getStore(); 190 if (store != null) 191 m.setStore((Store) store.clone()); 192 193 // deep-copy IdGenerator attribute - each Manager gets it's own 194 // IdGenerator instance 195 IdGenerator ig = getIdGenerator(); 196 if (ig != null) 197 m.setIdGenerator((IdGenerator) ig.clone()); 198 199 // Container uses InterceptorStack as a prototype to clone a stack for 200 // each new session... 201 m.setInterceptorStack(getInterceptorStack()); 202 203 m.setMaxInactiveInterval(getMaxInactiveInterval()); 204 m.setScavengerPeriod(getScavengerPeriod()); 205 206 return m; 207 } 208 209 // ---------------------------------------- 210 211 final Map _sessions = new HashMap(); 212 getContextPath()213 public String getContextPath() 214 { 215 return _context.getContextPath(); 216 } 217 218 // ---------------------------------------- 219 // LifeCycle API 220 // ---------------------------------------- 221 222 boolean _started = false; 223 224 Object _startedLock = new Object(); 225 226 Timer _scavenger; 227 228 class Scavenger extends TimerTask 229 { run()230 public void run() 231 { 232 try 233 { 234 scavenge(); 235 } 236 catch (Throwable e) 237 { 238 Log.warn("could not scavenge local sessions", e); 239 } 240 } 241 } 242 start()243 public void start() 244 { 245 Log.debug("starting..."); 246 synchronized (_startedLock) 247 { 248 if (_started) 249 { 250 Log.warn("already started"); 251 return; 252 } 253 254 if (_store == null) 255 { 256 Log.warn("No Store. Falling back to a local session implementation - NO HTTPSESSION DISTRIBUTION"); 257 setStore(new LocalStore()); 258 } 259 260 if (_idGenerator == null) 261 _idGenerator = new DistributableIdGenerator(); 262 263 try 264 { 265 _store.start(); 266 } 267 catch (Exception e) 268 { 269 Log.warn("Faulty Store. Falling back to a local session implementation - NO HTTPSESSION DISTRIBUTION", e); 270 setStore(new LocalStore()); 271 try 272 { 273 _store.start(); 274 } 275 catch (Exception e2) 276 { 277 Log.warn("could not start Store", e2); 278 } 279 } 280 281 if (Log.isDebugEnabled()) 282 Log.debug("starting local scavenger thread...(period: " + getScavengerPeriod() + " secs)"); 283 long delay = getScavengerPeriod() * 1000; 284 boolean isDaemon = true; 285 _scavenger = new Timer(isDaemon); 286 _scavenger.scheduleAtFixedRate(new Scavenger(), delay, delay); 287 Log.debug("...local scavenger thread started"); 288 _started = true; 289 } 290 291 Log.debug("...started"); 292 } 293 isStarted()294 public boolean isStarted() 295 { 296 synchronized (_startedLock) 297 { 298 return _started; 299 } 300 } 301 stop()302 public void stop() 303 { 304 Log.debug("stopping..."); 305 306 synchronized (_startedLock) 307 { 308 if (!_started) 309 { 310 Log.warn("already stopped/not yet started"); 311 return; 312 } 313 314 // I guess we will have to ask the store for a list of sessions 315 // to migrate... - TODO 316 317 synchronized (_sessions) 318 { 319 List copy = new ArrayList(_sessions.values()); 320 for (Iterator i = copy.iterator(); i.hasNext();) 321 ((StateAdaptor) i.next()).migrate(); 322 323 _sessions.clear(); 324 } 325 326 Log.debug("stopping local scavenger thread..."); 327 _scavenger.cancel(); 328 _scavenger = null; 329 Log.debug("...local scavenger thread stopped"); 330 scavenge(); 331 332 _store.stop(); 333 _store.destroy(); 334 setStore(null); 335 _started = false; 336 } 337 338 Log.debug("...stopped"); 339 } 340 341 // ---------------------------------------- 342 // SessionManager API 343 // ---------------------------------------- 344 345 protected SessionHandler _handler; 346 setSessionHandler(SessionHandler handler)347 public void setSessionHandler(SessionHandler handler) 348 { 349 this._handler = handler; 350 } 351 352 // ---------------------------------------- 353 // SessionManager API 354 // ---------------------------------------- 355 getHttpSession(String id)356 public HttpSession getHttpSession(String id) 357 { 358 return findSession(id, true); 359 } 360 sessionExists(String id)361 public boolean sessionExists(String id) 362 { 363 return findSession(id, false) != null; 364 } 365 newHttpSession(HttpServletRequest request)366 public HttpSession newHttpSession(HttpServletRequest request) // TODO 367 { 368 return newSession(request); 369 } 370 371 // ---------------------------------------- 372 // this does not need locking as it is an int and access should be atomic... 373 374 // ---------------------------------------- 375 // Listeners 376 377 // These lists are only modified at webapp [un]deployment time, by a 378 // single thread, so although read by multiple threads whilst the 379 // Manager is running, need no synchronization... 380 381 final List _sessionListeners = new ArrayList(); 382 383 final List _sessionAttributeListeners = new ArrayList(); 384 addEventListener(EventListener listener)385 public void addEventListener(EventListener listener) throws IllegalArgumentException, IllegalStateException 386 { 387 synchronized (_startedLock) 388 { 389 if (isStarted()) 390 throw new IllegalStateException("EventListeners must be added before a Session Manager starts"); 391 392 boolean known = false; 393 if (listener instanceof HttpSessionAttributeListener) 394 { 395 // Log.info("adding HttpSessionAttributeListener: "+listener); 396 _sessionAttributeListeners.add(listener); 397 known = true; 398 } 399 if (listener instanceof HttpSessionListener) 400 { 401 // Log.info("adding HttpSessionListener: "+listener); 402 _sessionListeners.add(listener); 403 known = true; 404 } 405 406 if (!known) 407 throw new IllegalArgumentException("Unknown EventListener type " + listener); 408 } 409 } 410 clearEventListeners()411 public void clearEventListeners() 412 { 413 _sessionAttributeListeners.clear(); 414 _sessionListeners.clear(); 415 } 416 removeEventListener(EventListener listener)417 public void removeEventListener(EventListener listener) throws IllegalStateException 418 { 419 synchronized (_startedLock) 420 { 421 if (isStarted()) 422 throw new IllegalStateException("EventListeners may not be removed while a Session Manager is running"); 423 424 if (listener instanceof HttpSessionAttributeListener) 425 _sessionAttributeListeners.remove(listener); 426 if (listener instanceof HttpSessionListener) 427 _sessionListeners.remove(listener); 428 } 429 } 430 431 // ---------------------------------------- 432 // Implementation... 433 // ---------------------------------------- 434 getServletContext()435 public ServletContext getServletContext() 436 { 437 return _context.getServletHandler().getServletContext(); 438 } 439 getSessionContext()440 public HttpSessionContext getSessionContext() 441 { 442 return null; 443 } 444 445 // -------------------- 446 // session lifecycle 447 // -------------------- 448 449 // I need to think more about where the list of extant sessions is 450 // held... 451 452 // is it held by the State Factory/Type (static), which best knows 453 // how to find it ? The trouble is we are not asking for just the 454 // State but the whole container... 455 456 // if the State was an EJB, the Manager could hold a HashMap of 457 // id:State and the State would just be an EJB handle... 458 459 // How does the ThrottleInterceptor fit into this. If it is holding 460 // a local cache in front of a DistributedState, do we check them 461 // both and compare timestamps, or flush() all ThrottleInterceptors 462 // in the WebApp before we do the lookup (could be expensive...) 463 464 // when finding a distributed session assume we are on nodeB 465 // receiving a request for a session immediately after it has just 466 // been created on NodeA. If we can't find it straight away, we need 467 // to take into account how long it's flushing and distribution may 468 // take, wait that long and then look again. This may hold up the 469 // request, but without the session the request is not much good. 470 471 // overload this to change the construction of the Container.... 472 newContainer(String id, State state)473 protected HttpSession newContainer(String id, State state) 474 { 475 // put together the make-believe container and HttpSession state 476 477 return Container.newContainer(this, id, state, getMaxInactiveInterval(), currentSecond(), getInterceptorStack()); 478 } 479 newSession(HttpServletRequest request)480 protected Session newSession(HttpServletRequest request) 481 { 482 String id = null; 483 HttpSession session = null; 484 try 485 { 486 id = _store.allocateId(request); 487 State state = _store.newState(id, getMaxInactiveInterval()); 488 session = newContainer(id, state); 489 } 490 catch (Exception e) 491 { 492 Log.debug("could not create HttpSession", e); 493 return null; // BAD - TODO 494 } 495 496 if (Log.isDebugEnabled()) 497 Log.debug("remembering session - " + id); 498 499 synchronized (_sessions) 500 { 501 _sessions.put(id, session); 502 } 503 504 notifySessionCreated(session); 505 506 return (Session) session; 507 } 508 destroyContainer(HttpSession session)509 protected State destroyContainer(HttpSession session) 510 { 511 return Container.destroyContainer(session, getInterceptorStack()); 512 } 513 destroySession(HttpSession container)514 protected void destroySession(HttpSession container) 515 { 516 String id = container.getId(); 517 if (Log.isDebugEnabled()) 518 Log.debug("forgetting session - " + id); 519 Object tmp; 520 synchronized (_sessions) 521 { 522 tmp = _sessions.remove(id); 523 } 524 container = (HttpSession) tmp; 525 if (Log.isDebugEnabled()) 526 Log.debug("forgetting session - " + container); 527 528 if (container == null) 529 { 530 Log.warn("session - " + id + " has already been destroyed"); 531 return; 532 } 533 534 // TODO remove all the attributes - generating correct events 535 // check ordering on unbind and destroy notifications - The 536 // problem is that we want these calls to go all the way through 537 // the container - but not to the store - because that would be 538 // too expensive and we can predict the final state... 539 540 // we don't need to do this if we know that none of the attributes 541 // are BindingListers AND there are no AttributeListeners 542 // registered... - TODO 543 544 // This will do for the moment... 545 546 // LATER - TODO 547 548 try 549 { 550 State state = ((StateAdaptor) container).getState(); 551 552 // filthy hack... 553 // stop InvalidInterceptors - otherwise we can't clean up session... 554 // - TODO 555 { 556 State s = state; 557 StateInterceptor si = null; 558 while (s instanceof StateInterceptor) 559 { 560 si = (StateInterceptor) s; 561 s = si.getState(); // next interceptor 562 if (si instanceof ValidatingInterceptor) 563 si.stop(); 564 } 565 } 566 567 String[] names = state.getAttributeNameStringArray(); 568 for (int i = 0; i < names.length; i++) 569 state.removeAttribute(names[i], false); 570 571 // should just do this for attributes which are BindingListeners 572 // - then just clear() the rest... - TODO 573 } 574 catch (RemoteException e) 575 { 576 Log.debug("could not raise events on session destruction - problem in distribution layer", e); 577 } 578 579 if (Log.isDebugEnabled()) 580 Log.debug("notifying session - " + id); 581 notifySessionDestroyed(container); 582 583 if (Log.isDebugEnabled()) 584 Log.debug("destroying container - " + id); 585 State state = destroyContainer(container); 586 587 try 588 { 589 if (state != null) // an interceptor may preempt us, if 590 // it does not want this state 591 // removed... 592 { 593 if (Log.isDebugEnabled()) 594 Log.debug("removing state - " + id); 595 _store.removeState(state); 596 } 597 } 598 catch (Exception e) 599 { 600 Log.debug("could not remove session state", e); 601 } 602 } 603 findSession(String id, boolean create)604 protected HttpSession findSession(String id, boolean create) 605 { 606 HttpSession container = null; 607 608 try 609 { 610 // find the state 611 State state = _store.loadState(id); 612 613 // is it valid ? 614 state = ((state != null) && state.isValid()) ? state : null; // expensive 615 // ? 616 617 // if so 618 if (state != null) 619 { 620 621 // this looks slow - but to be 100% safe we need to make sure 622 // that no-one can enter another container for the same id, 623 // whilst we are thinking about it... 624 625 // is there a container already available ? 626 synchronized (_sessions) 627 { 628 // do we have an existing container ? 629 container = (HttpSession) _sessions.get(id); 630 631 // if not... 632 if (container == null && create) 633 { 634 // make a new one... 635 container = newContainer(id, state);// we could lower 636 // contention by 637 // preconstructing 638 // containers... - 639 // TODO 640 _sessions.put(id, container); 641 } 642 } 643 } 644 } 645 catch (Exception ignore) 646 { 647 if (Log.isDebugEnabled()) 648 Log.debug("did not find distributed session: " + id); 649 } 650 651 return container; 652 } 653 654 // -------------------- 655 // session events 656 // -------------------- 657 658 // should this all be delegated to the event raising interceptor.... 659 notifyAttributeAdded(HttpSession session, String name, Object value)660 public Object notifyAttributeAdded(HttpSession session, String name, Object value) 661 { 662 int n = _sessionAttributeListeners.size(); 663 if (n > 0) 664 { 665 HttpSessionBindingEvent event = new HttpSessionBindingEvent(session, name, value); 666 667 for (int i = 0; i < n; i++) 668 ((HttpSessionAttributeListener) _sessionAttributeListeners.get(i)).attributeAdded(event); 669 670 event = null; 671 } 672 673 return value; 674 } 675 notifyAttributeReplaced(HttpSession session, String name, Object value)676 public Object notifyAttributeReplaced(HttpSession session, String name, Object value) 677 { 678 int n = _sessionAttributeListeners.size(); 679 if (n > 0) 680 { 681 HttpSessionBindingEvent event = new HttpSessionBindingEvent(session, name, value); 682 683 for (int i = 0; i < n; i++) 684 ((HttpSessionAttributeListener) _sessionAttributeListeners.get(i)).attributeReplaced(event); 685 686 event = null; 687 } 688 689 return value; 690 } 691 notifyAttributeRemoved(HttpSession session, String name, Object value)692 public Object notifyAttributeRemoved(HttpSession session, String name, Object value) 693 { 694 int n = _sessionAttributeListeners.size(); 695 if (n > 0) 696 { 697 HttpSessionBindingEvent event = new HttpSessionBindingEvent(session, name, value); 698 699 for (int i = 0; i < n; i++) 700 ((HttpSessionAttributeListener) _sessionAttributeListeners.get(i)).attributeRemoved(event); 701 702 event = null; 703 } 704 705 return value; 706 } 707 notifySessionCreated(HttpSession session)708 public void notifySessionCreated(HttpSession session) 709 { 710 int n = _sessionListeners.size(); 711 if (n > 0) 712 { 713 HttpSessionEvent event = new HttpSessionEvent(session); 714 715 for (int i = 0; i < n; i++) 716 ((HttpSessionListener) _sessionListeners.get(i)).sessionCreated(event); 717 718 event = null; 719 } 720 } 721 notifySessionDestroyed(HttpSession session)722 public void notifySessionDestroyed(HttpSession session) 723 { 724 int n = _sessionListeners.size(); 725 if (n > 0) 726 { 727 HttpSessionEvent event = new HttpSessionEvent(session); 728 729 for (int i = 0; i < n; i++) 730 ((HttpSessionListener) _sessionListeners.get(i)).sessionDestroyed(event); 731 732 event = null; 733 } 734 } 735 736 // this is to help sessions decide if they have timed out... It is 737 // wrapped here so that if I decide that System.currentTimeMillis() 738 // is too heavy, I can figure out a lighter way to return a rough 739 // time to the sessions... 740 currentSecond()741 public long currentSecond() 742 { 743 return System.currentTimeMillis(); 744 } 745 746 // ensure that this code is run with the correct ContextClassLoader... scavenge()747 protected void scavenge() 748 { 749 Log.debug("starting local scavenging..."); 750 try 751 { 752 // prevent session destruction (from scavenging) 753 // from being replicated to other members in the cluster. 754 // Let them scavenge locally instead. 755 AbstractReplicatedStore.setReplicating(true); 756 // 757 // take a quick copy... 758 Collection copy; 759 synchronized (_sessions) 760 { 761 copy = new ArrayList(_sessions.values()); 762 } 763 if (Log.isDebugEnabled()) 764 Log.debug(copy.size() + " local sessions"); 765 // 766 // iterate over it at our leisure... 767 int n = 0; 768 for (Iterator i = copy.iterator(); i.hasNext();) 769 { 770 // all we have to do is check if a session isValid() to force it 771 // to examine itself and invalidate() itself if necessary... - 772 // because it has a local cache of the necessary details, it 773 // will only go to the Stored State if it really thinks that it 774 // is invalid... 775 StateAdaptor sa = null; 776 try 777 { 778 sa = (StateAdaptor) i.next(); 779 // the ValidationInterceptor should pick this up and throw an IllegalStateException 780 long lat = sa.getLastAccessedTime(); 781 } 782 catch (IllegalStateException ignore) 783 { 784 if (Log.isDebugEnabled()) 785 Log.debug("scavenging local session " + sa.getId()); 786 destroySession(sa); 787 i.remove(); 788 ++n; 789 } 790 } 791 if (Log.isDebugEnabled()) 792 Log.debug("scavenged " + n + " local sessions"); 793 } 794 finally 795 { 796 AbstractReplicatedStore.setReplicating(false); 797 } 798 Log.debug("...finished local scavenging"); 799 } 800 801 /** 802 * @return True if cross context session IDs are first considered for new 803 * session IDs 804 */ getCrossContextSessionIDs()805 public boolean getCrossContextSessionIDs() 806 { 807 return _crossContextSessionIDs; 808 } 809 810 /* ------------------------------------------------------------ */ 811 /** Set Cross Context sessions IDs 812 * This option activates a mode where a requested session ID can be used to create a 813 * new session. This facilitates the sharing of session cookies when cross context 814 * dispatches use sessions. 815 * 816 * @param useRequestedId True if cross context session ID are first considered for new 817 * session IDs 818 */ setCrossContextSessionIDs(boolean useRequestedId)819 public void setCrossContextSessionIDs(boolean useRequestedId) 820 { 821 _crossContextSessionIDs = useRequestedId; 822 } 823 getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)824 public Cookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure) 825 { 826 // if (_handler.isUsingCookies()) 827 // { what's the jetty6 counterpart for isUsingCookies? - nik 828 Cookie cookie = _handler.getSessionManager().getHttpOnly() ? new HttpOnlyCookie(SessionManager.__SessionCookieProperty, session.getId()) : new Cookie( 829 SessionManager.__SessionCookieProperty, session.getId()); 830 String domain = getServletContext().getInitParameter(SessionManager.__SessionDomainProperty); 831 String maxAge = getServletContext().getInitParameter(SessionManager.__MaxAgeProperty); 832 String path = getServletContext().getInitParameter(SessionManager.__SessionPathProperty); 833 if (path == null) 834 path = getCrossContextSessionIDs() ? "/" : ((JBossWebAppContext)_context).getUniqueName(); 835 if (path == null || path.length() == 0) 836 path = "/"; 837 838 if (domain != null) 839 cookie.setDomain(domain); 840 if (maxAge != null) 841 cookie.setMaxAge(Integer.parseInt(maxAge)); 842 else 843 cookie.setMaxAge(-1); 844 845 cookie.setSecure(requestIsSecure && getSecureCookies()); 846 cookie.setPath(path); 847 848 return cookie; 849 // } 850 // return null; 851 } 852 isStarting()853 public boolean isStarting() 854 { 855 // TODO Auto-generated method stub 856 return false; 857 } 858 getMetaManager()859 public SessionIdManager getMetaManager() 860 { 861 // TODO Auto-generated method stub 862 return null; 863 } 864 isFailed()865 public boolean isFailed() 866 { 867 // TODO Auto-generated method stub 868 return false; 869 } 870 isRunning()871 public boolean isRunning() 872 { 873 // TODO Auto-generated method stub 874 return false; 875 } 876 isStopped()877 public boolean isStopped() 878 { 879 // TODO Auto-generated method stub 880 return false; 881 } 882 isStopping()883 public boolean isStopping() 884 { 885 // TODO Auto-generated method stub 886 return false; 887 } 888 889 getSessionPath()890 public String getSessionPath() 891 { 892 // TODO Auto-generated method stub 893 return null; 894 } 895 getSessionCookie()896 public String getSessionCookie() 897 { 898 // TODO Auto-generated method stub 899 return null; 900 } 901 getSessionURL()902 public String getSessionURL() 903 { 904 // TODO Auto-generated method stub 905 return null; 906 } 907 access(HttpSession arg0,boolean secure)908 public Cookie access(HttpSession arg0,boolean secure) 909 { 910 // TODO Auto-generated method stub 911 return null; 912 } 913 complete(HttpSession arg0)914 public void complete(HttpSession arg0) 915 { 916 // TODO Auto-generated method stub 917 918 } 919 getHttpOnly()920 public boolean getHttpOnly() 921 { 922 // TODO Auto-generated method stub 923 return false; 924 } 925 getMaxCookieAge()926 public int getMaxCookieAge() 927 { 928 // TODO Auto-generated method stub 929 return 0; 930 } 931 getSecureCookies()932 public boolean getSecureCookies() 933 { 934 // TODO Auto-generated method stub 935 return false; 936 } 937 getSessionDomain()938 public String getSessionDomain() 939 { 940 // TODO Auto-generated method stub 941 return null; 942 } 943 getSessionURLPrefix()944 public String getSessionURLPrefix() 945 { 946 // TODO Auto-generated method stub 947 return null; 948 } 949 isValid(HttpSession session)950 public boolean isValid(HttpSession session) 951 { 952 // TODO Auto-generated method stub 953 return ((Session)session).isValid(); 954 } 955 setIdManager(SessionIdManager arg0)956 public void setIdManager(SessionIdManager arg0) 957 { 958 // TODO Auto-generated method stub 959 960 } 961 setMaxCookieAge(int arg0)962 public void setMaxCookieAge(int arg0) 963 { 964 // TODO Auto-generated method stub 965 966 } 967 setSessionCookie(String arg0)968 public void setSessionCookie(String arg0) 969 { 970 // TODO Auto-generated method stub 971 972 } 973 setSessionDomain(String arg0)974 public void setSessionDomain(String arg0) 975 { 976 // TODO Auto-generated method stub 977 978 } 979 setSessionPath(String arg0)980 public void setSessionPath(String arg0) 981 { 982 // TODO Auto-generated method stub 983 984 } 985 setSessionURL(String arg0)986 public void setSessionURL(String arg0) 987 { 988 // TODO Auto-generated method stub 989 990 } 991 992 public interface Session extends HttpSession 993 { 994 /* ------------------------------------------------------------ */ isValid()995 public boolean isValid(); 996 997 /* ------------------------------------------------------------ */ access()998 public void access(); 999 } 1000 1001 /** 1002 * @see org.mortbay.jetty.SessionManager#getClusterId(javax.servlet.http.HttpSession) 1003 */ getClusterId(HttpSession session)1004 public String getClusterId(HttpSession session) 1005 { 1006 // TODO check that this is correct. There does not 1007 // seem to be any difference between the id as the 1008 // node knows it and the id within the cluster, so 1009 // we presume that the id is unique within the cluster. 1010 return session.getId(); 1011 } 1012 1013 /** 1014 * @see org.mortbay.jetty.SessionManager#getIdManager() 1015 */ getIdManager()1016 public SessionIdManager getIdManager() 1017 { 1018 // TODO Auto-generated method stub 1019 return null; 1020 } 1021 1022 /** 1023 * @see org.mortbay.jetty.SessionManager#getNodeId(javax.servlet.http.HttpSession) 1024 */ getNodeId(HttpSession session)1025 public String getNodeId(HttpSession session) 1026 { 1027 // TODO check that this is correct. There does not 1028 // seem to be any difference between the id as the 1029 // node knows it and the id within the cluster, so 1030 // we presume that the id is unique within the cluster. 1031 return session.getId(); 1032 } 1033 1034 /** 1035 * @see org.mortbay.jetty.SessionManager#isUsingCookies() 1036 */ isUsingCookies()1037 public boolean isUsingCookies() 1038 { 1039 return _usingCookies; 1040 } 1041 } 1042