1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server.session;
20
21 import static java.lang.Math.round;
22
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Enumeration;
26 import java.util.EventListener;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.concurrent.CopyOnWriteArrayList;
31
32 import javax.servlet.SessionCookieConfig;
33 import javax.servlet.SessionTrackingMode;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpSession;
36 import javax.servlet.http.HttpSessionAttributeListener;
37 import javax.servlet.http.HttpSessionBindingEvent;
38 import javax.servlet.http.HttpSessionContext;
39 import javax.servlet.http.HttpSessionEvent;
40 import javax.servlet.http.HttpSessionIdListener;
41 import javax.servlet.http.HttpSessionListener;
42
43 import org.eclipse.jetty.http.HttpCookie;
44 import org.eclipse.jetty.server.Server;
45 import org.eclipse.jetty.server.SessionIdManager;
46 import org.eclipse.jetty.server.SessionManager;
47 import org.eclipse.jetty.server.handler.ContextHandler;
48 import org.eclipse.jetty.util.annotation.ManagedAttribute;
49 import org.eclipse.jetty.util.annotation.ManagedObject;
50 import org.eclipse.jetty.util.annotation.ManagedOperation;
51 import org.eclipse.jetty.util.component.ContainerLifeCycle;
52 import org.eclipse.jetty.util.log.Logger;
53 import org.eclipse.jetty.util.statistic.CounterStatistic;
54 import org.eclipse.jetty.util.statistic.SampleStatistic;
55
56
57
58
59
60
61
62
63 @SuppressWarnings("deprecation")
64 @ManagedObject("Abstract Session Manager")
65 public abstract class AbstractSessionManager extends ContainerLifeCycle implements SessionManager
66 {
67 final static Logger __log = SessionHandler.LOG;
68
69 public Set<SessionTrackingMode> __defaultSessionTrackingModes =
70 Collections.unmodifiableSet(
71 new HashSet<SessionTrackingMode>(
72 Arrays.asList(new SessionTrackingMode[]{SessionTrackingMode.COOKIE,SessionTrackingMode.URL})));
73
74
75
76
77 public final static int __distantFuture=60*60*24*7*52*20;
78
79 static final HttpSessionContext __nullSessionContext=new HttpSessionContext()
80 {
81 @Override
82 public HttpSession getSession(String sessionId)
83 {
84 return null;
85 }
86
87 @Override
88 @SuppressWarnings({ "rawtypes", "unchecked" })
89 public Enumeration getIds()
90 {
91 return Collections.enumeration(Collections.EMPTY_LIST);
92 }
93 };
94
95 private boolean _usingCookies=true;
96
97
98
99
100 protected int _dftMaxIdleSecs=-1;
101 protected SessionHandler _sessionHandler;
102 protected boolean _httpOnly=false;
103 protected SessionIdManager _sessionIdManager;
104 protected boolean _secureCookies=false;
105 protected boolean _secureRequestOnly=true;
106
107 protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
108 protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
109 protected final List<HttpSessionIdListener> _sessionIdListeners = new CopyOnWriteArrayList<HttpSessionIdListener>();
110
111 protected ClassLoader _loader;
112 protected ContextHandler.Context _context;
113 protected String _sessionCookie=__DefaultSessionCookie;
114 protected String _sessionIdPathParameterName = __DefaultSessionIdPathParameterName;
115 protected String _sessionIdPathParameterNamePrefix =";"+ _sessionIdPathParameterName +"=";
116 protected String _sessionDomain;
117 protected String _sessionPath;
118 protected int _maxCookieAge=-1;
119 protected int _refreshCookieAge;
120 protected boolean _nodeIdInSessionId;
121 protected boolean _checkingRemoteSessionIdEncoding;
122 protected String _sessionComment;
123
124 public Set<SessionTrackingMode> _sessionTrackingModes;
125
126 private boolean _usingURLs;
127
128 protected final CounterStatistic _sessionsStats = new CounterStatistic();
129 protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
130
131
132
133 public AbstractSessionManager()
134 {
135 setSessionTrackingModes(__defaultSessionTrackingModes);
136 }
137
138
139 public ContextHandler.Context getContext()
140 {
141 return _context;
142 }
143
144
145 public ContextHandler getContextHandler()
146 {
147 return _context.getContextHandler();
148 }
149
150 @ManagedAttribute("path of the session cookie, or null for default")
151 public String getSessionPath()
152 {
153 return _sessionPath;
154 }
155
156 @ManagedAttribute("if greater the zero, the time in seconds a session cookie will last for")
157 public int getMaxCookieAge()
158 {
159 return _maxCookieAge;
160 }
161
162
163 @Override
164 public HttpCookie access(HttpSession session,boolean secure)
165 {
166 long now=System.currentTimeMillis();
167
168 AbstractSession s = ((SessionIf)session).getSession();
169
170 if (s.access(now))
171 {
172
173 if (isUsingCookies() &&
174 (s.isIdChanged() ||
175 (getSessionCookieConfig().getMaxAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
176 )
177 )
178 {
179 HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
180 s.cookieSet();
181 s.setIdChanged(false);
182 return cookie;
183 }
184 }
185 return null;
186 }
187
188
189 @Override
190 public void addEventListener(EventListener listener)
191 {
192 if (listener instanceof HttpSessionAttributeListener)
193 _sessionAttributeListeners.add((HttpSessionAttributeListener)listener);
194 if (listener instanceof HttpSessionListener)
195 _sessionListeners.add((HttpSessionListener)listener);
196 if (listener instanceof HttpSessionIdListener)
197 _sessionIdListeners.add((HttpSessionIdListener)listener);
198 addBean(listener,false);
199 }
200
201
202 @Override
203 public void clearEventListeners()
204 {
205 for (EventListener e :getBeans(EventListener.class))
206 removeBean(e);
207 _sessionAttributeListeners.clear();
208 _sessionListeners.clear();
209 _sessionIdListeners.clear();
210 }
211
212
213 @Override
214 public void complete(HttpSession session)
215 {
216 AbstractSession s = ((SessionIf)session).getSession();
217 s.complete();
218 }
219
220
221 @Override
222 public void doStart() throws Exception
223 {
224 _context=ContextHandler.getCurrentContext();
225 _loader=Thread.currentThread().getContextClassLoader();
226
227 final Server server=getSessionHandler().getServer();
228 synchronized (server)
229 {
230 if (_sessionIdManager==null)
231 {
232 _sessionIdManager=server.getSessionIdManager();
233 if (_sessionIdManager==null)
234 {
235
236
237
238
239 ClassLoader serverLoader = server.getClass().getClassLoader();
240 try
241 {
242 Thread.currentThread().setContextClassLoader(serverLoader);
243 _sessionIdManager=new HashSessionIdManager();
244 server.setSessionIdManager(_sessionIdManager);
245 server.manage(_sessionIdManager);
246 _sessionIdManager.start();
247 }
248 finally
249 {
250 Thread.currentThread().setContextClassLoader(_loader);
251 }
252 }
253
254
255 addBean(_sessionIdManager,false);
256 }
257 }
258
259
260
261 if (_context!=null)
262 {
263 String tmp=_context.getInitParameter(SessionManager.__SessionCookieProperty);
264 if (tmp!=null)
265 _sessionCookie=tmp;
266
267 tmp=_context.getInitParameter(SessionManager.__SessionIdPathParameterNameProperty);
268 if (tmp!=null)
269 setSessionIdPathParameterName(tmp);
270
271
272 if (_maxCookieAge==-1)
273 {
274 tmp=_context.getInitParameter(SessionManager.__MaxAgeProperty);
275 if (tmp!=null)
276 _maxCookieAge=Integer.parseInt(tmp.trim());
277 }
278
279
280 if (_sessionDomain==null)
281 _sessionDomain=_context.getInitParameter(SessionManager.__SessionDomainProperty);
282
283
284 if (_sessionPath==null)
285 _sessionPath=_context.getInitParameter(SessionManager.__SessionPathProperty);
286
287 tmp=_context.getInitParameter(SessionManager.__CheckRemoteSessionEncoding);
288 if (tmp!=null)
289 _checkingRemoteSessionIdEncoding=Boolean.parseBoolean(tmp);
290 }
291
292 super.doStart();
293 }
294
295
296 @Override
297 public void doStop() throws Exception
298 {
299 super.doStop();
300
301 shutdownSessions();
302
303 _loader=null;
304 }
305
306
307
308
309
310 @Override
311 @ManagedAttribute("true if cookies use the http only flag")
312 public boolean getHttpOnly()
313 {
314 return _httpOnly;
315 }
316
317
318 @Override
319 public HttpSession getHttpSession(String nodeId)
320 {
321 String cluster_id = getSessionIdManager().getClusterId(nodeId);
322
323 AbstractSession session = getSession(cluster_id);
324 if (session!=null && !session.getNodeId().equals(nodeId))
325 session.setIdChanged(true);
326 return session;
327 }
328
329
330
331
332
333 @Override
334 @ManagedAttribute("Session ID Manager")
335 public SessionIdManager getSessionIdManager()
336 {
337 return _sessionIdManager;
338 }
339
340
341
342
343
344
345 @Override
346 @ManagedAttribute("defailt maximum time a session may be idle for (in s)")
347 public int getMaxInactiveInterval()
348 {
349 return _dftMaxIdleSecs;
350 }
351
352
353
354
355
356 @ManagedAttribute("maximum number of simultaneous sessions")
357 public int getSessionsMax()
358 {
359 return (int)_sessionsStats.getMax();
360 }
361
362
363
364
365
366 @ManagedAttribute("total number of sessions")
367 public int getSessionsTotal()
368 {
369 return (int)_sessionsStats.getTotal();
370 }
371
372
373 @ManagedAttribute("time before a session cookie is re-set (in s)")
374 public int getRefreshCookieAge()
375 {
376 return _refreshCookieAge;
377 }
378
379
380
381
382
383
384
385 @ManagedAttribute("if true, secure cookie flag is set on session cookies")
386 public boolean getSecureCookies()
387 {
388 return _secureCookies;
389 }
390
391
392
393
394
395 public boolean isSecureRequestOnly()
396 {
397 return _secureRequestOnly;
398 }
399
400
401
402
403
404
405
406
407 public void setSecureRequestOnly(boolean secureRequestOnly)
408 {
409 _secureRequestOnly = secureRequestOnly;
410 }
411
412
413 @ManagedAttribute("the set session cookie")
414 public String getSessionCookie()
415 {
416 return _sessionCookie;
417 }
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447 @Override
448 public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)
449 {
450 if (isUsingCookies())
451 {
452 String sessionPath = (_cookieConfig.getPath()==null) ? contextPath : _cookieConfig.getPath();
453 sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath;
454 String id = getNodeId(session);
455 HttpCookie cookie = null;
456 if (_sessionComment == null)
457 {
458 cookie = new HttpCookie(
459 _cookieConfig.getName(),
460 id,
461 _cookieConfig.getDomain(),
462 sessionPath,
463 _cookieConfig.getMaxAge(),
464 _cookieConfig.isHttpOnly(),
465 _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure));
466 }
467 else
468 {
469 cookie = new HttpCookie(
470 _cookieConfig.getName(),
471 id,
472 _cookieConfig.getDomain(),
473 sessionPath,
474 _cookieConfig.getMaxAge(),
475 _cookieConfig.isHttpOnly(),
476 _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure),
477 _sessionComment,
478 1);
479 }
480
481 return cookie;
482 }
483 return null;
484 }
485
486 @ManagedAttribute("domain of the session cookie, or null for the default")
487 public String getSessionDomain()
488 {
489 return _sessionDomain;
490 }
491
492
493
494
495
496 public SessionHandler getSessionHandler()
497 {
498 return _sessionHandler;
499 }
500
501
502 @ManagedAttribute("number of currently active sessions")
503 public int getSessions()
504 {
505 return (int)_sessionsStats.getCurrent();
506 }
507
508
509 @Override
510 @ManagedAttribute("name of use for URL session tracking")
511 public String getSessionIdPathParameterName()
512 {
513 return _sessionIdPathParameterName;
514 }
515
516
517 @Override
518 public String getSessionIdPathParameterNamePrefix()
519 {
520 return _sessionIdPathParameterNamePrefix;
521 }
522
523
524
525
526
527 @Override
528 public boolean isUsingCookies()
529 {
530 return _usingCookies;
531 }
532
533
534 @Override
535 public boolean isValid(HttpSession session)
536 {
537 AbstractSession s = ((SessionIf)session).getSession();
538 return s.isValid();
539 }
540
541
542 @Override
543 public String getClusterId(HttpSession session)
544 {
545 AbstractSession s = ((SessionIf)session).getSession();
546 return s.getClusterId();
547 }
548
549
550 @Override
551 public String getNodeId(HttpSession session)
552 {
553 AbstractSession s = ((SessionIf)session).getSession();
554 return s.getNodeId();
555 }
556
557
558
559
560
561 @Override
562 public HttpSession newHttpSession(HttpServletRequest request)
563 {
564 AbstractSession session=newSession(request);
565 session.setMaxInactiveInterval(_dftMaxIdleSecs);
566 if (request.isSecure())
567 session.setAttribute(AbstractSession.SESSION_CREATED_SECURE, Boolean.TRUE);
568 addSession(session,true);
569 return session;
570 }
571
572
573 @Override
574 public void removeEventListener(EventListener listener)
575 {
576 if (listener instanceof HttpSessionAttributeListener)
577 _sessionAttributeListeners.remove(listener);
578 if (listener instanceof HttpSessionListener)
579 _sessionListeners.remove(listener);
580 if (listener instanceof HttpSessionIdListener)
581 _sessionIdListeners.remove(listener);
582 removeBean(listener);
583 }
584
585
586
587
588
589 @ManagedOperation(value="reset statistics", impact="ACTION")
590 public void statsReset()
591 {
592 _sessionsStats.reset(getSessions());
593 _sessionTimeStats.reset();
594 }
595
596
597
598
599
600
601 public void setHttpOnly(boolean httpOnly)
602 {
603 _httpOnly=httpOnly;
604 }
605
606
607
608
609
610 @Override
611 public void setSessionIdManager(SessionIdManager metaManager)
612 {
613 updateBean(_sessionIdManager, metaManager);
614 _sessionIdManager=metaManager;
615 }
616
617
618 @Override
619 public void setMaxInactiveInterval(int seconds)
620 {
621 _dftMaxIdleSecs=seconds;
622 }
623
624
625 public void setRefreshCookieAge(int ageInSeconds)
626 {
627 _refreshCookieAge=ageInSeconds;
628 }
629
630
631 public void setSessionCookie(String cookieName)
632 {
633 _sessionCookie=cookieName;
634 }
635
636
637
638
639
640
641 @Override
642 public void setSessionHandler(SessionHandler sessionHandler)
643 {
644 _sessionHandler=sessionHandler;
645 }
646
647
648
649 @Override
650 public void setSessionIdPathParameterName(String param)
651 {
652 _sessionIdPathParameterName =(param==null||"none".equals(param))?null:param;
653 _sessionIdPathParameterNamePrefix =(param==null||"none".equals(param))?null:(";"+ _sessionIdPathParameterName +"=");
654 }
655
656
657
658
659
660 public void setUsingCookies(boolean usingCookies)
661 {
662 _usingCookies=usingCookies;
663 }
664
665
666 protected abstract void addSession(AbstractSession session);
667
668
669
670
671
672
673
674
675 protected void addSession(AbstractSession session, boolean created)
676 {
677 synchronized (_sessionIdManager)
678 {
679 _sessionIdManager.addSession(session);
680 addSession(session);
681 }
682
683 if (created)
684 {
685 _sessionsStats.increment();
686 if (_sessionListeners!=null)
687 {
688 HttpSessionEvent event=new HttpSessionEvent(session);
689 for (HttpSessionListener listener : _sessionListeners)
690 listener.sessionCreated(event);
691 }
692 }
693 }
694
695
696
697
698
699
700
701 public abstract AbstractSession getSession(String idInCluster);
702
703
704
705
706
707
708 protected abstract void shutdownSessions() throws Exception;
709
710
711
712
713
714
715
716
717 protected abstract AbstractSession newSession(HttpServletRequest request);
718
719
720
721
722
723
724 public boolean isNodeIdInSessionId()
725 {
726 return _nodeIdInSessionId;
727 }
728
729
730
731
732
733 public void setNodeIdInSessionId(boolean nodeIdInSessionId)
734 {
735 _nodeIdInSessionId=nodeIdInSessionId;
736 }
737
738
739
740
741
742
743
744 public void removeSession(HttpSession session, boolean invalidate)
745 {
746 AbstractSession s = ((SessionIf)session).getSession();
747 removeSession(s,invalidate);
748 }
749
750
751
752
753
754
755
756
757
758 public boolean removeSession(AbstractSession session, boolean invalidate)
759 {
760
761 boolean removed = removeSession(session.getClusterId());
762
763 if (removed)
764 {
765 _sessionsStats.decrement();
766 _sessionTimeStats.set(round((System.currentTimeMillis() - session.getCreationTime())/1000.0));
767
768
769 _sessionIdManager.removeSession(session);
770 if (invalidate)
771 _sessionIdManager.invalidateAll(session.getClusterId());
772
773 if (invalidate && _sessionListeners!=null)
774 {
775 HttpSessionEvent event=new HttpSessionEvent(session);
776 for (int i = _sessionListeners.size()-1; i>=0; i--)
777 {
778 _sessionListeners.get(i).sessionDestroyed(event);
779 }
780 }
781 }
782
783 return removed;
784 }
785
786
787 protected abstract boolean removeSession(String idInCluster);
788
789
790
791
792
793 @ManagedAttribute("maximum amount of time sessions have remained active (in s)")
794 public long getSessionTimeMax()
795 {
796 return _sessionTimeStats.getMax();
797 }
798
799
800 @Override
801 public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
802 {
803 return __defaultSessionTrackingModes;
804 }
805
806
807 @Override
808 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
809 {
810 return Collections.unmodifiableSet(_sessionTrackingModes);
811 }
812
813
814 @Override
815 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
816 {
817 _sessionTrackingModes=new HashSet<SessionTrackingMode>(sessionTrackingModes);
818 _usingCookies=_sessionTrackingModes.contains(SessionTrackingMode.COOKIE);
819 _usingURLs=_sessionTrackingModes.contains(SessionTrackingMode.URL);
820 }
821
822
823 @Override
824 public boolean isUsingURLs()
825 {
826 return _usingURLs;
827 }
828
829
830 @Override
831 public SessionCookieConfig getSessionCookieConfig()
832 {
833 return _cookieConfig;
834 }
835
836
837 private SessionCookieConfig _cookieConfig =
838 new CookieConfig();
839
840
841
842
843
844
845 @ManagedAttribute("total time sessions have remained valid")
846 public long getSessionTimeTotal()
847 {
848 return _sessionTimeStats.getTotal();
849 }
850
851
852
853
854
855 @ManagedAttribute("mean time sessions remain valid (in s)")
856 public double getSessionTimeMean()
857 {
858 return _sessionTimeStats.getMean();
859 }
860
861
862
863
864
865 @ManagedAttribute("standard deviation a session remained valid (in s)")
866 public double getSessionTimeStdDev()
867 {
868 return _sessionTimeStats.getStdDev();
869 }
870
871
872
873
874
875 @Override
876 @ManagedAttribute("check remote session id encoding")
877 public boolean isCheckingRemoteSessionIdEncoding()
878 {
879 return _checkingRemoteSessionIdEncoding;
880 }
881
882
883
884
885
886 @Override
887 public void setCheckingRemoteSessionIdEncoding(boolean remote)
888 {
889 _checkingRemoteSessionIdEncoding=remote;
890 }
891
892
893
894
895
896
897
898
899
900 @Override
901 public void renewSessionId(String oldClusterId, String oldNodeId, String newClusterId, String newNodeId)
902 {
903 if (!_sessionIdListeners.isEmpty())
904 {
905 AbstractSession session = getSession(newClusterId);
906 HttpSessionEvent event = new HttpSessionEvent(session);
907 for (HttpSessionIdListener l:_sessionIdListeners)
908 {
909 l.sessionIdChanged(event, oldClusterId);
910 }
911 }
912
913 }
914
915
916
917
918
919
920 public final class CookieConfig implements SessionCookieConfig
921 {
922 @Override
923 public String getComment()
924 {
925 return _sessionComment;
926 }
927
928 @Override
929 public String getDomain()
930 {
931 return _sessionDomain;
932 }
933
934 @Override
935 public int getMaxAge()
936 {
937 return _maxCookieAge;
938 }
939
940 @Override
941 public String getName()
942 {
943 return _sessionCookie;
944 }
945
946 @Override
947 public String getPath()
948 {
949 return _sessionPath;
950 }
951
952 @Override
953 public boolean isHttpOnly()
954 {
955 return _httpOnly;
956 }
957
958 @Override
959 public boolean isSecure()
960 {
961 return _secureCookies;
962 }
963
964 @Override
965 public void setComment(String comment)
966 {
967 if (_context != null && _context.getContextHandler().isAvailable())
968 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
969 _sessionComment = comment;
970 }
971
972 @Override
973 public void setDomain(String domain)
974 {
975 if (_context != null && _context.getContextHandler().isAvailable())
976 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
977 _sessionDomain=domain;
978 }
979
980 @Override
981 public void setHttpOnly(boolean httpOnly)
982 {
983 if (_context != null && _context.getContextHandler().isAvailable())
984 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
985 _httpOnly=httpOnly;
986 }
987
988 @Override
989 public void setMaxAge(int maxAge)
990 {
991 if (_context != null && _context.getContextHandler().isAvailable())
992 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
993 _maxCookieAge=maxAge;
994 }
995
996 @Override
997 public void setName(String name)
998 {
999 if (_context != null && _context.getContextHandler().isAvailable())
1000 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
1001 _sessionCookie=name;
1002 }
1003
1004 @Override
1005 public void setPath(String path)
1006 {
1007 if (_context != null && _context.getContextHandler().isAvailable())
1008 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
1009 _sessionPath=path;
1010 }
1011
1012 @Override
1013 public void setSecure(boolean secure)
1014 {
1015 if (_context != null && _context.getContextHandler().isAvailable())
1016 throw new IllegalStateException("CookieConfig cannot be set after ServletContext is started");
1017 _secureCookies=secure;
1018 }
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029 public interface SessionIf extends HttpSession
1030 {
1031 public AbstractSession getSession();
1032 }
1033
1034 public void doSessionAttributeListeners(AbstractSession session, String name, Object old, Object value)
1035 {
1036 if (!_sessionAttributeListeners.isEmpty())
1037 {
1038 HttpSessionBindingEvent event=new HttpSessionBindingEvent(session,name,old==null?value:old);
1039
1040 for (HttpSessionAttributeListener l : _sessionAttributeListeners)
1041 {
1042 if (old==null)
1043 l.attributeAdded(event);
1044 else if (value==null)
1045 l.attributeRemoved(event);
1046 else
1047 l.attributeReplaced(event);
1048 }
1049 }
1050 }
1051
1052 @Override
1053 @Deprecated
1054 public SessionIdManager getMetaManager()
1055 {
1056 throw new UnsupportedOperationException();
1057 }
1058 }