1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.eclipse.jetty.server.session;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.sql.Connection;
29 import java.sql.PreparedStatement;
30 import java.sql.ResultSet;
31 import java.sql.SQLException;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.concurrent.atomic.AtomicReference;
38
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpSessionEvent;
41 import javax.servlet.http.HttpSessionListener;
42
43 import org.eclipse.jetty.server.SessionIdManager;
44 import org.eclipse.jetty.server.handler.ContextHandler;
45 import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
46 import org.eclipse.jetty.util.log.Log;
47 import org.eclipse.jetty.util.log.Logger;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public class JDBCSessionManager extends AbstractSessionManager
74 {
75 private static final Logger LOG = Log.getLogger(JDBCSessionManager.class);
76
77 private ConcurrentHashMap<String, AbstractSession> _sessions;
78 protected JDBCSessionIdManager _jdbcSessionIdMgr = null;
79 protected long _saveIntervalSec = 60;
80
81
82
83
84
85
86
87
88
89 public class Session extends AbstractSession
90 {
91 private static final long serialVersionUID = 5208464051134226143L;
92
93
94
95
96 private boolean _dirty=false;
97
98
99
100
101
102 private long _cookieSet;
103
104
105
106
107
108 private long _expiryTime;
109
110
111
112
113
114 private long _lastSaved;
115
116
117
118
119
120 private String _lastNode;
121
122
123
124
125
126 private String _virtualHost;
127
128
129
130
131
132 private String _rowId;
133
134
135
136
137
138 private String _canonicalContext;
139
140
141
142
143
144
145
146 protected Session (HttpServletRequest request)
147 {
148 super(JDBCSessionManager.this,request);
149 int maxInterval=getMaxInactiveInterval();
150 _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
151 _virtualHost = JDBCSessionManager.getVirtualHost(_context);
152 _canonicalContext = canonicalize(_context.getContextPath());
153 _lastNode = getSessionIdManager().getWorkerName();
154 }
155
156
157
158
159
160
161
162
163
164 protected Session (String sessionId, String rowId, long created, long accessed, long maxInterval)
165 {
166 super(JDBCSessionManager.this, created, accessed, sessionId);
167 _rowId = rowId;
168 super.setMaxInactiveInterval((int)maxInterval);
169 _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
170 }
171
172
173 protected synchronized String getRowId()
174 {
175 return _rowId;
176 }
177
178 protected synchronized void setRowId(String rowId)
179 {
180 _rowId = rowId;
181 }
182
183 public synchronized void setVirtualHost (String vhost)
184 {
185 _virtualHost=vhost;
186 }
187
188 public synchronized String getVirtualHost ()
189 {
190 return _virtualHost;
191 }
192
193 public synchronized long getLastSaved ()
194 {
195 return _lastSaved;
196 }
197
198 public synchronized void setLastSaved (long time)
199 {
200 _lastSaved=time;
201 }
202
203 public synchronized void setExpiryTime (long time)
204 {
205 _expiryTime=time;
206 }
207
208 public synchronized long getExpiryTime ()
209 {
210 return _expiryTime;
211 }
212
213
214 public synchronized void setCanonicalContext(String str)
215 {
216 _canonicalContext=str;
217 }
218
219 public synchronized String getCanonicalContext ()
220 {
221 return _canonicalContext;
222 }
223
224 public void setCookieSet (long ms)
225 {
226 _cookieSet = ms;
227 }
228
229 public synchronized long getCookieSet ()
230 {
231 return _cookieSet;
232 }
233
234 public synchronized void setLastNode (String node)
235 {
236 _lastNode=node;
237 }
238
239 public synchronized String getLastNode ()
240 {
241 return _lastNode;
242 }
243
244 @Override
245 public void setAttribute (String name, Object value)
246 {
247 _dirty=updateAttribute(name, value);
248 }
249
250 @Override
251 public void removeAttribute (String name)
252 {
253 super.removeAttribute(name);
254 _dirty=true;
255 }
256
257 @Override
258 protected void cookieSet()
259 {
260 _cookieSet = getAccessed();
261 }
262
263
264
265
266
267
268
269 @Override
270 protected boolean access(long time)
271 {
272 synchronized (this)
273 {
274 if (super.access(time))
275 {
276 int maxInterval=getMaxInactiveInterval();
277 _expiryTime = (maxInterval <= 0 ? 0 : (time + maxInterval*1000L));
278 return true;
279 }
280 return false;
281 }
282 }
283
284
285
286
287
288
289
290
291
292 @Override
293 public void setMaxInactiveInterval(int secs)
294 {
295 synchronized (this)
296 {
297 super.setMaxInactiveInterval(secs);
298 int maxInterval=getMaxInactiveInterval();
299 _expiryTime = (maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
300
301 try
302 {
303 updateSessionAccessTime(this);
304 }
305 catch (Exception e)
306 {
307 LOG.warn("Problem saving changed max idle time for session "+ this, e);
308 }
309 }
310 }
311
312
313
314
315
316
317 @Override
318 protected void complete()
319 {
320 synchronized (this)
321 {
322 super.complete();
323 try
324 {
325 if (isValid())
326 {
327 if (_dirty)
328 {
329
330
331 willPassivate();
332 updateSession(this);
333 didActivate();
334 }
335 else if ((getAccessed() - _lastSaved) >= (getSaveInterval() * 1000L))
336 {
337 updateSessionAccessTime(this);
338 }
339 }
340 }
341 catch (Exception e)
342 {
343 LOG.warn("Problem persisting changed session data id="+getId(), e);
344 }
345 finally
346 {
347 _dirty=false;
348 }
349 }
350 }
351
352 protected void save() throws Exception
353 {
354 synchronized (this)
355 {
356 try
357 {
358 updateSession(this);
359 }
360 finally
361 {
362 _dirty = false;
363 }
364 }
365 }
366
367 @Override
368 protected void timeout() throws IllegalStateException
369 {
370 if (LOG.isDebugEnabled())
371 LOG.debug("Timing out session id="+getClusterId());
372 super.timeout();
373 }
374
375
376 @Override
377 public String toString ()
378 {
379 return "Session rowId="+_rowId+",id="+getId()+",lastNode="+_lastNode+
380 ",created="+getCreationTime()+",accessed="+getAccessed()+
381 ",lastAccessed="+getLastAccessedTime()+",cookieSet="+_cookieSet+
382 ",maxInterval="+getMaxInactiveInterval()+",lastSaved="+_lastSaved+",expiry="+_expiryTime;
383 }
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407 public void setSaveInterval (long sec)
408 {
409 _saveIntervalSec=sec;
410 }
411
412 public long getSaveInterval ()
413 {
414 return _saveIntervalSec;
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 public void cacheInvalidate (Session session)
431 {
432
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452 @Override
453 public Session getSession(String idInCluster)
454 {
455 Session session = null;
456 Session memSession = (Session)_sessions.get(idInCluster);
457
458 synchronized (this)
459 {
460
461
462
463
464
465
466
467
468
469 long now = System.currentTimeMillis();
470 if (LOG.isDebugEnabled())
471 {
472 if (memSession==null)
473 LOG.debug("getSession("+idInCluster+"): not in session map,"+
474 " now="+now+
475 " lastSaved="+(memSession==null?0:memSession._lastSaved)+
476 " interval="+(_saveIntervalSec * 1000L));
477 else
478 LOG.debug("getSession("+idInCluster+"): in session map, "+
479 " now="+now+
480 " lastSaved="+(memSession==null?0:memSession._lastSaved)+
481 " interval="+(_saveIntervalSec * 1000L)+
482 " lastNode="+memSession._lastNode+
483 " thisNode="+getSessionIdManager().getWorkerName()+
484 " difference="+(now - memSession._lastSaved));
485 }
486
487 try
488 {
489 if (memSession==null)
490 {
491 LOG.debug("getSession("+idInCluster+"): no session in session map. Reloading session data from db.");
492 session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
493 }
494 else if ((now - memSession._lastSaved) >= (_saveIntervalSec * 1000L))
495 {
496 LOG.debug("getSession("+idInCluster+"): stale session. Reloading session data from db.");
497 session = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
498 }
499 else
500 {
501 LOG.debug("getSession("+idInCluster+"): session in session map");
502 session = memSession;
503 }
504 }
505 catch (Exception e)
506 {
507 LOG.warn("Unable to load session "+idInCluster, e);
508 return null;
509 }
510
511
512
513 if (session != null)
514 {
515
516 if (!session.getLastNode().equals(getSessionIdManager().getWorkerName()) || memSession==null)
517 {
518
519 if (session._expiryTime <= 0 || session._expiryTime > now)
520 {
521 if (LOG.isDebugEnabled())
522 LOG.debug("getSession("+idInCluster+"): lastNode="+session.getLastNode()+" thisNode="+getSessionIdManager().getWorkerName());
523
524 session.setLastNode(getSessionIdManager().getWorkerName());
525 _sessions.put(idInCluster, session);
526
527
528 try
529 {
530 updateSessionNode(session);
531 session.didActivate();
532 }
533 catch (Exception e)
534 {
535 LOG.warn("Unable to update freshly loaded session "+idInCluster, e);
536 return null;
537 }
538 }
539 else
540 {
541 LOG.debug("getSession ({}): Session has expired", idInCluster);
542
543
544 _jdbcSessionIdMgr.removeSession(idInCluster);
545 session=null;
546 }
547
548 }
549 else
550 LOG.debug("getSession({}): Session not stale {}", idInCluster,session);
551 }
552 else
553 {
554
555 LOG.debug("getSession({}): No session in database matching id={}",idInCluster,idInCluster);
556 }
557
558 return session;
559 }
560 }
561
562
563
564
565
566
567
568 @Override
569 public int getSessions()
570 {
571 int size = 0;
572 synchronized (this)
573 {
574 size = _sessions.size();
575 }
576 return size;
577 }
578
579
580
581
582
583
584
585 @Override
586 public void doStart() throws Exception
587 {
588 if (_sessionIdManager==null)
589 throw new IllegalStateException("No session id manager defined");
590
591 _jdbcSessionIdMgr = (JDBCSessionIdManager)_sessionIdManager;
592
593 _sessions = new ConcurrentHashMap<String, AbstractSession>();
594
595 super.doStart();
596 }
597
598
599
600
601
602
603
604 @Override
605 public void doStop() throws Exception
606 {
607 _sessions.clear();
608 _sessions = null;
609
610 super.doStop();
611 }
612
613 @Override
614 protected void invalidateSessions()
615 {
616
617
618
619
620
621
622 }
623
624
625
626
627
628
629 public void renewSessionId (String oldClusterId, String oldNodeId, String newClusterId, String newNodeId)
630 {
631 Session session = null;
632 synchronized (this)
633 {
634 try
635 {
636 session = (Session)_sessions.remove(oldClusterId);
637 if (session != null)
638 {
639 session.setClusterId(newClusterId);
640 session.setNodeId(newNodeId);
641 _sessions.put(newClusterId, session);
642 session.save();
643 }
644 }
645 catch (Exception e)
646 {
647 LOG.warn(e);
648 }
649 }
650
651 super.renewSessionId(oldClusterId, oldNodeId, newClusterId, newNodeId);
652 }
653
654
655
656
657
658
659
660
661 protected void invalidateSession (String idInCluster)
662 {
663 Session session = null;
664 synchronized (this)
665 {
666 session = (Session)_sessions.get(idInCluster);
667 }
668
669 if (session != null)
670 {
671 session.invalidate();
672 }
673 }
674
675
676
677
678
679
680
681 @Override
682 protected boolean removeSession(String idInCluster)
683 {
684 synchronized (this)
685 {
686 Session session = (Session)_sessions.remove(idInCluster);
687 try
688 {
689 if (session != null)
690 deleteSession(session);
691 }
692 catch (Exception e)
693 {
694 LOG.warn("Problem deleting session id="+idInCluster, e);
695 }
696 return session!=null;
697 }
698 }
699
700
701
702
703
704
705
706 @Override
707 protected void addSession(AbstractSession session)
708 {
709 if (session==null)
710 return;
711
712 synchronized (this)
713 {
714 _sessions.put(session.getClusterId(), session);
715 }
716
717
718
719 try
720 {
721 synchronized (session)
722 {
723 session.willPassivate();
724 storeSession(((JDBCSessionManager.Session)session));
725 session.didActivate();
726 }
727 }
728 catch (Exception e)
729 {
730 LOG.warn("Unable to store new session id="+session.getId() , e);
731 }
732 }
733
734
735
736
737
738
739
740 @Override
741 protected AbstractSession newSession(HttpServletRequest request)
742 {
743 return new Session(request);
744 }
745
746
747
748
749
750
751
752 @Override
753 public void removeSession(AbstractSession session, boolean invalidate)
754 {
755
756 boolean removed = false;
757
758 synchronized (this)
759 {
760
761 if (_sessions.containsKey(session.getClusterId()))
762 {
763 removed = true;
764 removeSession(session.getClusterId());
765 }
766 }
767
768 if (removed)
769 {
770
771 _sessionIdManager.removeSession(session);
772
773 if (invalidate)
774 _sessionIdManager.invalidateAll(session.getClusterId());
775
776 if (invalidate && !_sessionListeners.isEmpty())
777 {
778 HttpSessionEvent event=new HttpSessionEvent(session);
779 for (HttpSessionListener l : _sessionListeners)
780 l.sessionDestroyed(event);
781 }
782 if (!invalidate)
783 {
784 session.willPassivate();
785 }
786 }
787 }
788
789
790
791
792
793
794
795
796 protected Set<String> expire (Set<String> sessionIds)
797 {
798
799 if (isStopping() || isStopped())
800 return null;
801
802
803 Thread thread=Thread.currentThread();
804 ClassLoader old_loader=thread.getContextClassLoader();
805
806 Set<String> successfullyExpiredIds = new HashSet<String>();
807 try
808 {
809 Iterator<?> itor = sessionIds.iterator();
810 while (itor.hasNext())
811 {
812 String sessionId = (String)itor.next();
813 if (LOG.isDebugEnabled())
814 LOG.debug("Expiring session id "+sessionId);
815
816 Session session = (Session)_sessions.get(sessionId);
817
818
819 if (session == null)
820 {
821 if (LOG.isDebugEnabled())LOG.debug("Force loading session id "+sessionId);
822 session = loadSession(sessionId, canonicalize(_context.getContextPath()), getVirtualHost(_context));
823 if (session != null)
824 {
825
826
827 synchronized (this)
828 {
829 _sessions.put(session.getClusterId(), session);
830 }
831 }
832 else
833 {
834 if (LOG.isDebugEnabled())
835 LOG.debug("Unrecognized session id="+sessionId);
836 continue;
837 }
838 }
839
840 if (session != null)
841 {
842 session.timeout();
843 successfullyExpiredIds.add(session.getClusterId());
844 }
845 }
846 return successfullyExpiredIds;
847 }
848 catch (Throwable t)
849 {
850 LOG.warn("Problem expiring sessions", t);
851 return successfullyExpiredIds;
852 }
853 finally
854 {
855 thread.setContextClassLoader(old_loader);
856 }
857 }
858
859
860
861
862
863
864
865
866 protected Session loadSession (final String id, final String canonicalContextPath, final String vhost)
867 throws Exception
868 {
869 final AtomicReference<Session> _reference = new AtomicReference<Session>();
870 final AtomicReference<Exception> _exception = new AtomicReference<Exception>();
871 Runnable load = new Runnable()
872 {
873
874
875
876 @SuppressWarnings("unchecked")
877 public void run()
878 {
879 try (Connection connection = getConnection();
880 PreparedStatement statement = _jdbcSessionIdMgr._dbAdaptor.getLoadStatement(connection, id, canonicalContextPath, vhost);
881 ResultSet result = statement.executeQuery())
882 {
883 Session session = null;
884 if (result.next())
885 {
886 long maxInterval = result.getLong("maxInterval");
887 if (maxInterval == JDBCSessionIdManager.MAX_INTERVAL_NOT_SET)
888 {
889 maxInterval = getMaxInactiveInterval();
890 }
891 session = new Session(id, result.getString(_jdbcSessionIdMgr._sessionTableRowId),
892 result.getLong("createTime"),
893 result.getLong("accessTime"),
894 maxInterval);
895 session.setCookieSet(result.getLong("cookieTime"));
896 session.setLastAccessedTime(result.getLong("lastAccessTime"));
897 session.setLastNode(result.getString("lastNode"));
898 session.setLastSaved(result.getLong("lastSavedTime"));
899 session.setExpiryTime(result.getLong("expiryTime"));
900 session.setCanonicalContext(result.getString("contextPath"));
901 session.setVirtualHost(result.getString("virtualHost"));
902
903 try (InputStream is = ((JDBCSessionIdManager)getSessionIdManager())._dbAdaptor.getBlobInputStream(result, "map");
904 ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is))
905 {
906 Object o = ois.readObject();
907 session.addAttributes((Map<String,Object>)o);
908 }
909
910 if (LOG.isDebugEnabled())
911 LOG.debug("LOADED session "+session);
912 }
913 else
914 if (LOG.isDebugEnabled())
915 LOG.debug("Failed to load session "+id);
916 _reference.set(session);
917 }
918 catch (Exception e)
919 {
920 _exception.set(e);
921 }
922 }
923 };
924
925 if (_context==null)
926 load.run();
927 else
928 _context.getContextHandler().handle(load);
929
930 if (_exception.get()!=null)
931 {
932
933
934 _jdbcSessionIdMgr.removeSession(id);
935 throw _exception.get();
936 }
937
938 return _reference.get();
939 }
940
941
942
943
944
945
946
947 protected void storeSession (Session session)
948 throws Exception
949 {
950 if (session==null)
951 return;
952
953
954 try (Connection connection = getConnection();
955 PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._insertSession))
956 {
957 String rowId = calculateRowId(session);
958
959 long now = System.currentTimeMillis();
960 connection.setAutoCommit(true);
961 statement.setString(1, rowId);
962 statement.setString(2, session.getId());
963 statement.setString(3, session.getCanonicalContext());
964 statement.setString(4, session.getVirtualHost());
965 statement.setString(5, getSessionIdManager().getWorkerName());
966 statement.setLong(6, session.getAccessed());
967 statement.setLong(7, session.getLastAccessedTime());
968 statement.setLong(8, session.getCreationTime());
969 statement.setLong(9, session.getCookieSet());
970 statement.setLong(10, now);
971 statement.setLong(11, session.getExpiryTime());
972 statement.setLong(12, session.getMaxInactiveInterval());
973
974 ByteArrayOutputStream baos = new ByteArrayOutputStream();
975 ObjectOutputStream oos = new ObjectOutputStream(baos);
976 oos.writeObject(session.getAttributeMap());
977 oos.flush();
978 byte[] bytes = baos.toByteArray();
979
980 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
981 statement.setBinaryStream(13, bais, bytes.length);
982
983
984 statement.executeUpdate();
985 session.setRowId(rowId);
986 session.setLastSaved(now);
987 }
988 if (LOG.isDebugEnabled())
989 LOG.debug("Stored session "+session);
990 }
991
992
993
994
995
996
997
998
999 protected void updateSession (Session data)
1000 throws Exception
1001 {
1002 if (data==null)
1003 return;
1004
1005 try (Connection connection = getConnection();
1006 PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSession))
1007 {
1008 long now = System.currentTimeMillis();
1009 connection.setAutoCommit(true);
1010 statement.setString(1, data.getId());
1011 statement.setString(2, getSessionIdManager().getWorkerName());
1012 statement.setLong(3, data.getAccessed());
1013 statement.setLong(4, data.getLastAccessedTime());
1014 statement.setLong(5, now);
1015 statement.setLong(6, data.getExpiryTime());
1016 statement.setLong(7, data.getMaxInactiveInterval());
1017
1018 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1019 ObjectOutputStream oos = new ObjectOutputStream(baos);
1020 oos.writeObject(data.getAttributeMap());
1021 oos.flush();
1022 byte[] bytes = baos.toByteArray();
1023 ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
1024
1025 statement.setBinaryStream(8, bais, bytes.length);
1026 statement.setString(9, data.getRowId());
1027 statement.executeUpdate();
1028
1029 data.setLastSaved(now);
1030 }
1031 if (LOG.isDebugEnabled())
1032 LOG.debug("Updated session "+data);
1033 }
1034
1035
1036
1037
1038
1039
1040
1041
1042 protected void updateSessionNode (Session data)
1043 throws Exception
1044 {
1045 String nodeId = getSessionIdManager().getWorkerName();
1046 try (Connection connection = getConnection();
1047 PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSessionNode))
1048 {
1049 connection.setAutoCommit(true);
1050 statement.setString(1, nodeId);
1051 statement.setString(2, data.getRowId());
1052 statement.executeUpdate();
1053 }
1054 if (LOG.isDebugEnabled())
1055 LOG.debug("Updated last node for session id="+data.getId()+", lastNode = "+nodeId);
1056 }
1057
1058
1059
1060
1061
1062
1063
1064 private void updateSessionAccessTime (Session data)
1065 throws Exception
1066 {
1067 try (Connection connection = getConnection();
1068 PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._updateSessionAccessTime))
1069 {
1070 long now = System.currentTimeMillis();
1071 connection.setAutoCommit(true);
1072 statement.setString(1, getSessionIdManager().getWorkerName());
1073 statement.setLong(2, data.getAccessed());
1074 statement.setLong(3, data.getLastAccessedTime());
1075 statement.setLong(4, now);
1076 statement.setLong(5, data.getExpiryTime());
1077 statement.setLong(6, data.getMaxInactiveInterval());
1078 statement.setString(7, data.getRowId());
1079
1080 statement.executeUpdate();
1081 data.setLastSaved(now);
1082 }
1083 if (LOG.isDebugEnabled())
1084 LOG.debug("Updated access time session id="+data.getId());
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097 protected void deleteSession (Session data)
1098 throws Exception
1099 {
1100 try (Connection connection = getConnection();
1101 PreparedStatement statement = connection.prepareStatement(_jdbcSessionIdMgr._deleteSession))
1102 {
1103 connection.setAutoCommit(true);
1104 statement.setString(1, data.getRowId());
1105 statement.executeUpdate();
1106 if (LOG.isDebugEnabled())
1107 LOG.debug("Deleted Session "+data);
1108 }
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118 private Connection getConnection ()
1119 throws SQLException
1120 {
1121 return ((JDBCSessionIdManager)getSessionIdManager()).getConnection();
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131 private String calculateRowId (Session data)
1132 {
1133 String rowId = canonicalize(_context.getContextPath());
1134 rowId = rowId + "_" + getVirtualHost(_context);
1135 rowId = rowId+"_"+data.getId();
1136 return rowId;
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146 private static String getVirtualHost (ContextHandler.Context context)
1147 {
1148 String vhost = "0.0.0.0";
1149
1150 if (context==null)
1151 return vhost;
1152
1153 String [] vhosts = context.getContextHandler().getVirtualHosts();
1154 if (vhosts==null || vhosts.length==0 || vhosts[0]==null)
1155 return vhost;
1156
1157 return vhosts[0];
1158 }
1159
1160
1161
1162
1163
1164
1165
1166 private static String canonicalize (String path)
1167 {
1168 if (path==null)
1169 return "";
1170
1171 return path.replace('/', '_').replace('.','_').replace('\\','_');
1172 }
1173 }