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