1
15
16 package gate.security;
17
18 import java.sql.*;
19 import java.util.*;
20
21 import junit.framework.Assert;
22
23 import gate.Gate;
24 import gate.event.*;
25 import gate.persist.DBHelper;
26 import gate.persist.PersistenceException;
27 import gate.util.MethodNotImplementedException;
28
29
30 public class AccessControllerImpl
31 implements AccessController, ObjectModificationListener {
32
33 public static final int DEFAULT_SESSION_TIMEOUT_MIN = 4*60;
34
35 public static final int LOGIN_OK = 1;
36 public static final int LOGIN_FAILED = 2;
37
38 private static long MY_VERY_SECRET_CONSTANT;
39 private static final int RANDOM_MAX = 1024;
40
41 private HashMap sessions;
42 private HashMap sessionLastUsed;
43 private HashMap sessionTimeouts;
44
45 private Connection jdbcConn;
46 private String jdbcURL;
47 private String jdbcSchema;
48 protected int dbType;
49
50 private HashMap usersByID;
51 private HashMap usersByName;
52
53 private HashMap groupsByID;
54 private HashMap groupsByName;
55
56 private static Random r;
57 private boolean isPooled;
58
59 private int refCnt;
60
61
62 private Vector omModificationListeners;
63
64 private Vector omCreationListeners;
65
66 private Vector omDeletionListeners;
67
68
69 static {
70 r = new Random();
71 MY_VERY_SECRET_CONSTANT = r.nextInt(RANDOM_MAX) * r.nextInt(RANDOM_MAX)
72 + Math.round(Math.PI * Math.E);
73 }
74
75
76 public AccessControllerImpl(String jdbcURL) {
77
78 Assert.assertNotNull(jdbcURL);
79
80 this.refCnt = 0;
81 this.jdbcURL = jdbcURL;
82 this.jdbcSchema = DBHelper.getSchemaPrefix(this.jdbcURL);
83 this.dbType = DBHelper.getDatabaseType(this.jdbcURL);
84
85 Assert.assertNotNull(this.jdbcSchema);
86 Assert.assertTrue(this.dbType == DBHelper.ORACLE_DB ||
87 this.dbType == DBHelper.POSTGRES_DB);
88
89 sessions = new HashMap();
90 sessionLastUsed = new HashMap();
91 sessionTimeouts = new HashMap();
92
93 usersByID = new HashMap();
94 usersByName= new HashMap();
95
96 groupsByID = new HashMap();
97 groupsByName = new HashMap();
98
99 this.omModificationListeners = new Vector();
100 this.omCreationListeners = new Vector();
101 this.omDeletionListeners = new Vector();
102 }
103
104
105 public void open()
106 throws PersistenceException{
107
108 synchronized(this) {
109 if (refCnt++ == 0) {
110 try {
112 jdbcConn = DBHelper.connect(this.jdbcURL);
114
115 Assert.assertNotNull(jdbcConn);
116
117 init();
120 }
121 catch(SQLException sqle) {
122 throw new PersistenceException("could not get DB connection ["+ sqle.getMessage() +"]");
123 }
124 catch(ClassNotFoundException clse) {
125 throw new PersistenceException("cannot locate JDBC driver ["+ clse.getMessage() +"]");
126 }
127 }
128 }
129
130
131 }
132
133
134 public void close()
135 throws PersistenceException{
136
137 if (--this.refCnt == 0) {
138
139 this.sessions.clear();
141 this.sessionLastUsed.clear();
142 this.sessionTimeouts.clear();
143
144 Set groupMappings = this.groupsByName.entrySet();
146 Iterator itGroups = groupMappings.iterator();
147
148 while (itGroups.hasNext()) {
149 Map.Entry mapEntry = (Map.Entry)itGroups.next();
150 GroupImpl grp = (GroupImpl)mapEntry.getValue();
151 grp.unregisterObjectModificationListener(this,
152 ObjectModificationEvent.OBJECT_MODIFIED);
153 }
154
155 Set userMappings = this.usersByName.entrySet();
157 Iterator itUsers = userMappings.iterator();
158
159 while (itUsers.hasNext()) {
160 Map.Entry mapEntry = (Map.Entry)itUsers.next();
161 UserImpl usr = (UserImpl)mapEntry.getValue();
162 usr.unregisterObjectModificationListener(this,
163 ObjectModificationEvent.OBJECT_MODIFIED);
164 }
165
166 this.omCreationListeners.removeAllElements();
168 this.omDeletionListeners.removeAllElements();
169 this.omModificationListeners.removeAllElements();
170
171 this.groupsByID.clear();
173 this.groupsByName.clear();
174 this.usersByID.clear();
175 this.groupsByName.clear();
176
177 try {
179 if (false == this.isPooled) {
180 this.jdbcConn.close();
181 }
182 }
183 catch(SQLException sqle) {
184 throw new PersistenceException("can't close connection to DB:["+
185 sqle.getMessage()+"]");
186 }
187 }
188 }
189
190
191 public Group findGroup(String name)
192 throws PersistenceException,SecurityException{
193
194 Group grp = (Group)this.groupsByName.get(name);
195
196 if (null == grp) {
197 throw new SecurityException("No such group");
198 }
199
200 return grp;
201 }
202
203
204 public Group findGroup(Long id)
205 throws PersistenceException,SecurityException {
206
207 Group grp = (Group)this.groupsByID.get(id);
208
209 if (null == grp) {
210 throw new SecurityException("No such group");
211 }
212
213 return grp;
214 }
215
216
217 public User findUser(String name)
218 throws PersistenceException,SecurityException {
219
220 User usr = (User)this.usersByName.get(name);
221
222 if (null == usr) {
223 throw new SecurityException("No such user (" + name + ")");
224 }
225
226 return usr;
227 }
228
229
230 public User findUser(Long id)
231 throws PersistenceException,SecurityException {
232
233 User usr = (User)this.usersByID.get(id);
234
235 if (null == usr) {
236 throw new SecurityException("No such user");
237 }
238
239 return usr;
240 }
241
242
243 public Session findSession(Long id)
244 throws SecurityException {
245
246 Session s = (Session)this.sessions.get(id);
247
248 if (null==s) {
249 throw new SecurityException("No such session ID!");
250 }
251
252 return s;
253 }
254
255
256 public Group createGroup(String name,Session s)
257 throws PersistenceException, SecurityException {
258
259 Assert.assertNotNull(name);
260
261 if (false == isValidSession(s)) {
263 throw new SecurityException("invalid session supplied");
264 }
265
266 if (false == s.isPrivilegedSession()) {
268 throw new SecurityException("insufficient privileges");
269 }
270
271
272 CallableStatement stmt = null;
274 PreparedStatement pstmt = null;
275 ResultSet rs = null;
276 Long new_id;
277
278
280 if (this.dbType == DBHelper.ORACLE_DB) {
281
282 try {
283 stmt = this.jdbcConn.prepareCall(
284 "{ call "+Gate.DB_OWNER+".security.create_group(?,?)} ");
285 stmt.setString(1,name);
286 stmt.registerOutParameter(2,java.sql.Types.BIGINT);
288 stmt.execute();
289 new_id = new Long(stmt.getLong(2));
290 }
291 catch(SQLException sqle) {
292
293 switch(sqle.getErrorCode()) {
295
296 case DBHelper.X_ORACLE_DUPLICATE_GROUP_NAME:
297 throw new PersistenceException(
298 "can't create a group in DB, name is not unique: ["
299 + sqle.getMessage()+"]");
300
301 default:
302 throw new PersistenceException(
303 "can't create a group in DB: ["+ sqle.getMessage()+"]");
304 }
305 }
306 finally {
307 DBHelper.cleanup(stmt);
308 }
309 }
310 else if (this.dbType == DBHelper.POSTGRES_DB) {
311 try {
312 String sql = "select security_create_group(?) ";
313 pstmt = this.jdbcConn.prepareStatement(sql);
314 pstmt.setString(1,name);
315 pstmt.execute();
316 rs = pstmt.getResultSet();
317
318 if (false == rs.next()) {
319 throw new PersistenceException("empty resultset");
320 }
321
322 new_id = new Long(rs.getLong(1));
323 }
324 catch(SQLException sqle) {
325
326 switch(sqle.getErrorCode()) {
328
329 case DBHelper.X_ORACLE_DUPLICATE_GROUP_NAME:
330 throw new PersistenceException(
331 "can't create a group in DB, name is not unique: ["
332 + sqle.getMessage()+"]");
333
334 default:
335 throw new PersistenceException(
336 "can't create a group in DB: ["+ sqle.getMessage()+"]");
337 }
338 }
339 finally {
340 DBHelper.cleanup(rs);
341 DBHelper.cleanup(pstmt);
342 }
343
344 }
345 else {
346 throw new IllegalArgumentException();
347 }
348
349 GroupImpl grp = new GroupImpl(new_id,name,new Vector(),this,this.jdbcConn);
352
353 grp.registerObjectModificationListener(this,ObjectModificationEvent.OBJECT_MODIFIED);
356
357 this.groupsByID.put(new_id,grp);
359 this.groupsByName.put(name,grp);
360
361 return grp;
362 }
363
364
365 public void deleteGroup(Long id, Session s)
366 throws PersistenceException,SecurityException {
367
368 Group grp = (Group)this.groupsByID.get(id);
369 if (null == grp) {
370 throw new SecurityException("incorrect group id supplied ( id = ["+id+"])");
371 }
372
373 deleteGroup(grp,s);
375 }
376
377
378 public void deleteGroup(Group grp, Session s)
379 throws PersistenceException,SecurityException {
380
381 if (false == isValidSession(s)) {
383 throw new SecurityException("invalid session supplied");
384 }
385
386 if (false == s.isPrivilegedSession()) {
388 throw new SecurityException("insufficient privileges");
389 }
390
391 CallableStatement stmt = null;
393 PreparedStatement pstmt = null;
394
395 if (this.dbType == DBHelper.ORACLE_DB) {
397
398 try {
399 stmt = this.jdbcConn.prepareCall(
400 "{ call "+Gate.DB_OWNER+".security.delete_group(?) } ");
401 stmt.setLong(1,grp.getID().longValue());
402 stmt.execute();
403 }
404 catch(SQLException sqle) {
405 switch(sqle.getErrorCode()) {
407
408 case DBHelper.X_ORACLE_GROUP_OWNS_RESOURCES:
409 throw new PersistenceException(
410 "can't delete a group from DB, the group owns LR(s): ["
411 + sqle.getMessage()+"]");
412
413 default:
414 throw new PersistenceException(
415 "can't delete a group from DB: ["+ sqle.getMessage()+"]");
416 }
417 }
418 finally {
419 DBHelper.cleanup(stmt);
420 }
421 }
422
423 else if (this.dbType == DBHelper.POSTGRES_DB) {
424
425 try {
426 String sql = "select security_delete_group(?)";
427 pstmt = this.jdbcConn.prepareStatement(sql);
428 pstmt.setLong(1,grp.getID().longValue());
429 pstmt.execute();
430 }
431 catch(SQLException sqle) {
432 switch(sqle.getErrorCode()) {
434
435 case DBHelper.X_ORACLE_GROUP_OWNS_RESOURCES:
436 throw new PersistenceException(
437 "can't delete a group from DB, the group owns LR(s): ["
438 + sqle.getMessage()+"]");
439
440 default:
441 throw new PersistenceException(
442 "can't delete a group from DB: ["+ sqle.getMessage()+"]");
443 }
444 }
445 finally {
446 DBHelper.cleanup(pstmt);
447 }
448
449 }
450 else {
451 throw new IllegalArgumentException();
452 }
453
454
455 this.groupsByID.remove(grp.getID());
457 this.groupsByName.remove(grp.getName());
458
459 ObjectModificationEvent e = new ObjectModificationEvent(
463 grp,
464 ObjectModificationEvent.OBJECT_DELETED,
465 0);
466
467 fireObjectDeletedEvent(e);
468
469 Set sessionMappings = this.sessions.entrySet();
472 Iterator itSessions = sessionMappings.iterator();
473
474 Vector sessionsToDelete = new Vector();
477 while (itSessions.hasNext()) {
478 Map.Entry mapEntry = (Map.Entry)itSessions.next();
479 SessionImpl ses = (SessionImpl)mapEntry.getValue();
480 if (ses.getGroup().equals(grp)) {
481 sessionsToDelete.add(ses);
483 }
484 }
485 for (int i=0; i< sessionsToDelete.size(); i++) {
487 Session ses = (Session)sessionsToDelete.elementAt(i);
488 logout(ses);
489 }
490
491 }
492
493
494 public User createUser(String name, String passwd,Session s)
495 throws PersistenceException,SecurityException {
496
497 Assert.assertNotNull(name);
498
499 if (false == isValidSession(s)) {
501 throw new SecurityException("invalid session supplied");
502 }
503
504 if (false == s.isPrivilegedSession()) {
506 throw new SecurityException("insufficient privileges");
507 }
508
509 CallableStatement stmt = null;
511 PreparedStatement pstmt = null;
512 ResultSet rs = null;
513
514 Long new_id;
515
516 if (this.dbType == DBHelper.ORACLE_DB) {
517
518 try {
519 stmt = this.jdbcConn.prepareCall(
520 "{ call "+Gate.DB_OWNER+".security.create_user(?,?,?)} ");
521 stmt.setString(1,name);
522 stmt.setString(2,passwd);
523 stmt.registerOutParameter(3,java.sql.Types.BIGINT);
525 stmt.execute();
526 new_id = new Long(stmt.getLong(3));
527 }
528 catch(SQLException sqle) {
529 switch(sqle.getErrorCode()) {
531
532 case DBHelper.X_ORACLE_DUPLICATE_USER_NAME:
533 throw new PersistenceException(
534 "can't create a user in DB, name is not unique: ["
535 + sqle.getMessage()+"]");
536 default:
537 throw new PersistenceException(
538 "can't create a user in DB: ["+ sqle.getMessage()+"]");
539 }
540 }
541 finally {
542 DBHelper.cleanup(stmt);
543 }
544 }
545
546 else if (this.dbType == DBHelper.POSTGRES_DB) {
547
548 try {
549 String sql = "select security_create_user(?,?) ";
550 pstmt = this.jdbcConn.prepareStatement(sql);
551 pstmt.setString(1,name);
552 pstmt.setString(2,passwd);
553 pstmt.execute();
554 rs = pstmt.getResultSet();
555
556 if (false == rs.next()) {
557 throw new PersistenceException("empty resultset");
558 }
559
560 new_id = new Long(rs.getLong(1));
561 }
562 catch(SQLException sqle) {
563 switch(sqle.getErrorCode()) {
565
566 case DBHelper.X_ORACLE_DUPLICATE_USER_NAME:
567 throw new PersistenceException(
568 "can't create a user in DB, name is not unique: ["
569 + sqle.getMessage()+"]");
570 default:
571 throw new PersistenceException(
572 "can't create a user in DB: ["+ sqle.getMessage()+"]");
573 }
574 }
575 finally {
576 DBHelper.cleanup(rs);
577 DBHelper.cleanup(pstmt);
578 }
579
580 }
581
582 else {
583 throw new IllegalArgumentException();
584 }
585
586 UserImpl usr = new UserImpl(new_id,name,new Vector(),this,this.jdbcConn);
589
590 usr.registerObjectModificationListener(this,ObjectModificationEvent.OBJECT_MODIFIED);
593
594 this.usersByID.put(new_id,usr);
596 this.usersByName.put(name,usr);
597
598 return usr;
599 }
600
601
602 public void deleteUser(User usr, Session s)
603 throws PersistenceException,SecurityException {
604
605 if (false == isValidSession(s)) {
607 throw new SecurityException("invalid session supplied");
608 }
609
610 if (false == s.isPrivilegedSession()) {
612 throw new SecurityException("insufficient privileges");
613 }
614
615 CallableStatement cstmt = null;
617 PreparedStatement pstmt = null;
618
619 if (this.dbType == DBHelper.ORACLE_DB) {
620
621 try {
622 cstmt = this.jdbcConn.prepareCall(
623 "{ call "+Gate.DB_OWNER+".security.delete_user(?) } ");
624 cstmt.setLong(1,usr.getID().longValue());
625 cstmt.execute();
626 }
627 catch(SQLException sqle) {
628 switch(sqle.getErrorCode()) {
629
630 case DBHelper.X_ORACLE_USER_OWNS_RESOURCES:
631 throw new PersistenceException(
632 "can't delete user from DB, the user owns LR(s): ["
633 + sqle.getMessage()+"]");
634 default:
635 throw new PersistenceException(
636 "can't delete user from DB: ["+ sqle.getMessage()+"]");
637 }
638 }
639 finally {
640 DBHelper.cleanup(cstmt);
641 }
642 }
643
644 else if (this.dbType == DBHelper.POSTGRES_DB) {
645
646 try {
647 String sql = "select security_delete_user(?) ";
648 pstmt = this.jdbcConn.prepareStatement(sql);
649 pstmt.setLong(1,usr.getID().longValue());
650 pstmt.execute();
651 }
652 catch(SQLException sqle) {
653 switch(sqle.getErrorCode()) {
654
655 case DBHelper.X_ORACLE_USER_OWNS_RESOURCES:
656 throw new PersistenceException(
657 "can't delete user from DB, the user owns LR(s): ["
658 + sqle.getMessage()+"]");
659 default:
660 throw new PersistenceException(
661 "can't delete user from DB: ["+ sqle.getMessage()+"]");
662 }
663 }
664 finally {
665 DBHelper.cleanup(pstmt);
666 }
667
668 }
669
670 else {
671 throw new IllegalArgumentException();
672 }
673
674
675 this.usersByID.remove(usr.getID());
677 this.usersByName.remove(usr.getName());
678
679 ObjectModificationEvent e = new ObjectModificationEvent(
683 usr,
684 ObjectModificationEvent.OBJECT_DELETED,
685 0);
686
687 fireObjectDeletedEvent(e);
688
689 Set sessionMappings = this.sessions.entrySet();
691 Iterator itSessions = sessionMappings.iterator();
692
693 Vector sessionsToDelete = new Vector();
696 while (itSessions.hasNext()) {
697 Map.Entry mapEntry = (Map.Entry)itSessions.next();
698 SessionImpl ses = (SessionImpl)mapEntry.getValue();
699 if (ses.getUser().equals(usr)) {
700 sessionsToDelete.add(ses);
702 }
703 }
704 for (int i=0; i< sessionsToDelete.size(); i++) {
706 Session ses = (Session)sessionsToDelete.elementAt(i);
707 logout(ses);
708 }
709
710 }
711
712
713
714 public void deleteUser(Long id, Session s)
715 throws PersistenceException,SecurityException {
716
717 User usr = (User)usersByID.get(id);
718 if (null == usr) {
719 throw new SecurityException("incorrect user id supplied ( id = ["+id+"])");
720 }
721
722 deleteUser(usr,s);
724 }
725
726
727 public Session login(String usr_name, String passwd,Long prefGroupID)
728 throws PersistenceException,SecurityException {
729
730 User usr = (User)this.usersByName.get(usr_name);
732 if (null == usr) {
733 throw new SecurityException("no such user (username=["+usr_name+"])");
734 }
735
736 Group grp = (Group)this.groupsByID.get(prefGroupID);
738 if (null == grp) {
739 throw new SecurityException("no such group (id=["+prefGroupID+"])");
740 }
741
742 CallableStatement cstmt = null;
744 PreparedStatement pstmt = null;
745 ResultSet rs = null;
746
747 boolean isPrivilegedUser = false;
748
749 if (this.dbType == DBHelper.ORACLE_DB) {
750
751 try {
752 cstmt = this.jdbcConn.prepareCall(
753 "{ call "+Gate.DB_OWNER+".security.login(?,?,?,?)} ");
754 cstmt.setString(1,usr_name);
755 cstmt.setString(2,passwd);
756 cstmt.setLong(3,prefGroupID.longValue());
757 cstmt.registerOutParameter(4,java.sql.Types.NUMERIC);
758 cstmt.execute();
759 isPrivilegedUser = (cstmt.getInt(4) == DBHelper.FALSE ? false : true );
760 }
761 catch(SQLException sqle) {
762 switch(sqle.getErrorCode())
763 {
764 case DBHelper.X_ORACLE_INVALID_USER_NAME :
765 throw new SecurityException("Login failed: incorrect user");
766 case DBHelper.X_ORACLE_INVALID_USER_PASS :
767 throw new SecurityException("Login failed: incorrect password");
768 case DBHelper.X_ORACLE_INVALID_USER_GROUP :
769 throw new SecurityException("Login failed: incorrect group");
770 default:
771 throw new PersistenceException("can't login user, DB error is: ["+
772 sqle.getMessage()+"]");
773 }
774 }
775 finally {
776 DBHelper.cleanup(cstmt);
777 }
778 }
779
780 else if (this.dbType == DBHelper.POSTGRES_DB) {
781
782 try {
783 String sql = "select security_login(?,?,?) ";
784 pstmt = this.jdbcConn.prepareStatement(sql);
785 pstmt.setString(1,usr_name);
786 pstmt.setString(2,passwd);
787 pstmt.setLong(3,prefGroupID.longValue());
788 pstmt.execute();
789 rs = pstmt.getResultSet();
790
791 if (false == rs.next()) {
792 throw new PersistenceException("empty resultset");
793 }
794
795 isPrivilegedUser = rs.getBoolean(1);
796 }
797 catch(SQLException sqle) {
798 switch(sqle.getErrorCode())
799 {
800 case DBHelper.X_ORACLE_INVALID_USER_NAME :
801 throw new SecurityException("Login failed: incorrect user");
802 case DBHelper.X_ORACLE_INVALID_USER_PASS :
803 throw new SecurityException("Login failed: incorrect password");
804 case DBHelper.X_ORACLE_INVALID_USER_GROUP :
805 throw new SecurityException("Login failed: incorrect group");
806 default:
807 throw new PersistenceException("can't login user, DB error is: ["+
808 sqle.getMessage()+"]");
809 }
810 }
811 finally {
812 DBHelper.cleanup(rs);
813 DBHelper.cleanup(pstmt);
814 }
815 }
816
817 else {
818 throw new IllegalArgumentException();
819 }
820
821 Long sessionID = createSessionID();
823 while (this.sessions.containsKey(sessionID)) {
824 sessionID = createSessionID();
825 }
826
827 SessionImpl s = new SessionImpl(sessionID,
828 usr,
829 grp,
830 DEFAULT_SESSION_TIMEOUT_MIN,
831 isPrivilegedUser);
832
833 this.sessions.put(s.getID(),s);
835
836 this.sessionTimeouts.put(sessionID,new Long(DEFAULT_SESSION_TIMEOUT_MIN));
838 touchSession(s);
840 return s;
841 }
842
843
844 public void logout(Session s)
845 throws SecurityException {
846
847 Assert.assertNotNull(s);
848 Long SID = s.getID();
849
850 Session removedSession = (Session)this.sessions.remove(SID);
852 Assert.assertNotNull(removedSession);
853
854 Object lastUsed = this.sessionLastUsed.remove(SID);
856 Assert.assertNotNull(lastUsed);
857
858 Object timeout = this.sessionTimeouts.remove(SID);
860 Assert.assertNotNull(timeout);
861 }
862
863
864 public void setSessionTimeout(Session s, int timeoutMins)
865 throws SecurityException {
866
867 this.sessionTimeouts.put(s.getID(),new Long(timeoutMins));
868 }
869
870
871 public boolean isValidSession(Session s) {
872
873 if (false == this.sessions.containsKey(s.getID())) {
875 return false;
876 }
877
878 Assert.assertNotNull(this.sessionLastUsed.get(s.getID()));
880
881 long lastUsedMS = ((Long)this.sessionLastUsed.get(s.getID())).longValue();
882 long sessTimeoutMin = ((Long)this.sessionTimeouts.get(s.getID())).longValue();
883 long currTimeMS = System.currentTimeMillis();
884 long lastUsedMin = (currTimeMS-lastUsedMS)/(1000*60);
886
887 if (lastUsedMin > sessTimeoutMin) {
888 try {
891 logout(s);
892 }
893 catch(SecurityException se) {
894 ;
898 }
899
900 return false;
901 }
902
903 touchSession(s);
906
907 return true;
908 }
909
910
911 public List listGroups()
912 throws PersistenceException {
913
914 Statement stmt = null;
916 ResultSet rs = null;
917 String sql;
918 Vector result = new Vector();
919
920 try {
921 stmt = this.jdbcConn.createStatement();
922
923 sql = " SELECT grp_name "+
925 " FROM "+this.jdbcSchema+"t_group "+
926 " ORDER BY grp_name ASC";
927 rs = stmt.executeQuery(sql);
928
929 while (rs.next()) {
930 String grp_name = rs.getString(1);
933 result.add(grp_name);
934 }
935
936 return result;
937 }
938 catch (SQLException sqle) {
939 throw new PersistenceException("cannot read groups from DB :["+
940 sqle.getMessage() +"]");
941 }
942 finally {
943 DBHelper.cleanup(rs);
944 DBHelper.cleanup(stmt);
945 }
946 }
947
948
949 public List listUsers()
950 throws PersistenceException {
951
952 Statement stmt = null;
954 ResultSet rs = null;
955 String sql;
956 Vector result = new Vector();
957
958 try {
959 stmt = this.jdbcConn.createStatement();
960
961 sql = " SELECT usr_login "+
963 " FROM "+this.jdbcSchema+"t_user "+
964 " ORDER BY usr_login DESC";
965 rs = stmt.executeQuery(sql);
966
967 while (rs.next()) {
968 String usr_name = rs.getString(1);
971 result.add(usr_name);
972 }
973
974 return result;
975 }
976 catch (SQLException sqle) {
977 throw new PersistenceException("cannot read groups from DB :["+
978 sqle.getMessage() +"]");
979 }
980 finally {
981 DBHelper.cleanup(rs);
982 DBHelper.cleanup(stmt);
983 }
984 }
985
986
987
988
989
990 private void touchSession(Session s) {
991
992 this.sessionLastUsed.put(s.getID(), new Long(System.currentTimeMillis()));
993 }
994
995
996 private Long createSessionID() {
997
998 return new Long(((System.currentTimeMillis() << 16) >> 16)*
1000 (r.nextInt(RANDOM_MAX))*
1001 Runtime.getRuntime().freeMemory()*
1002 MY_VERY_SECRET_CONSTANT);
1003 }
1004
1005
1006 private boolean canDeleteGroup(Group grp)
1007 throws PersistenceException, SecurityException{
1008
1009 if (false == this.groupsByID.containsValue(grp)) {
1011 throw new SecurityException("no such group (id=["+grp.getID()+"])");
1012 }
1013
1014 CallableStatement stmt = null;
1016 PreparedStatement pstmt = null;
1017 ResultSet rs = null;
1018
1019 if (this.dbType == DBHelper.ORACLE_DB) {
1020
1021 try {
1022 stmt = this.jdbcConn.prepareCall(
1023 "{ ? = call "+Gate.DB_OWNER+".security.can_delete_group(?) }");
1024 stmt.registerOutParameter(1,java.sql.Types.INTEGER);
1025 stmt.setLong(2,grp.getID().longValue());
1026 stmt.execute();
1027 boolean res = stmt.getBoolean(1);
1028
1029 return res;
1030 }
1031 catch(SQLException sqle) {
1032 throw new PersistenceException("can't perform document checks, DB error is: ["+
1033 sqle.getMessage()+"]");
1034 }
1035 finally {
1036 DBHelper.cleanup(stmt);
1037 }
1038 }
1039
1040 else if (this.dbType == DBHelper.POSTGRES_DB) {
1041
1042 try {
1043 String sql = "select security_can_delete_group(?)";
1044 pstmt = this.jdbcConn.prepareCall(sql);
1045 pstmt.setLong(1,grp.getID().longValue());
1046 pstmt.execute();
1047 rs = pstmt.getResultSet();
1048
1049 if (false == rs.next()) {
1050 throw new PersistenceException("empty resultset");
1051 }
1052
1053 boolean res = rs.getBoolean(1);
1054
1055 return res;
1056 }
1057 catch(SQLException sqle) {
1058 throw new PersistenceException("can't perform document checks, DB error is: ["+
1059 sqle.getMessage()+"]");
1060 }
1061 finally {
1062 DBHelper.cleanup(rs);
1063 DBHelper.cleanup(pstmt);
1064 }
1065
1066 }
1067
1068 else {
1069 throw new IllegalArgumentException();
1070 }
1071 }
1072
1073
1074 private boolean canDeleteUser(User usr)
1075 throws PersistenceException, SecurityException{
1076
1077 if (false == this.usersByID.containsValue(usr)) {
1079 throw new SecurityException("no such user (id=["+usr.getID()+"])");
1080 }
1081
1082 CallableStatement stmt = null;
1084 PreparedStatement pstmt = null;
1085 ResultSet rs = null;
1086
1087 if (this.dbType == DBHelper.ORACLE_DB) {
1088
1089 try {
1090 stmt = this.jdbcConn.prepareCall(
1091 "{ ? = call "+Gate.DB_OWNER+".security.can_delete_user(?) }");
1092
1093 stmt.registerOutParameter(1,java.sql.Types.INTEGER);
1094 stmt.setLong(2,usr.getID().longValue());
1095 stmt.execute();
1096 boolean res = stmt.getBoolean(1);
1097
1098 return res;
1099 }
1100 catch(SQLException sqle) {
1101 throw new PersistenceException("can't perform document checks, DB error is: ["+
1102 sqle.getMessage()+"]");
1103 }
1104 finally {
1105 DBHelper.cleanup(stmt);
1106 }
1107 }
1108
1109 else if (this.dbType == DBHelper.POSTGRES_DB) {
1110
1111 try {
1112 String sql = "select security_can_delete_user(?) ";
1113 pstmt = this.jdbcConn.prepareCall(sql);
1114 pstmt.setLong(1,usr.getID().longValue());
1115 pstmt.execute();
1116 boolean res = rs.getBoolean(1);
1117
1118 return res;
1119 }
1120 catch(SQLException sqle) {
1121 throw new PersistenceException("can't perform document checks, DB error is: ["+
1122 sqle.getMessage()+"]");
1123 }
1124 finally {
1125 DBHelper.cleanup(rs);
1126 DBHelper.cleanup(pstmt);
1127 }
1128
1129 }
1130
1131 else {
1132 throw new IllegalArgumentException();
1133 }
1134
1135 }
1136
1137 private void init()
1138 throws PersistenceException {
1139
1140 Statement stmt = null;
1142 ResultSet rs = null;
1143 String sql;
1144 Hashtable groupNames = new Hashtable();
1145 Hashtable groupMembers= new Hashtable();
1146 Hashtable userNames= new Hashtable();
1147 Hashtable userGroups= new Hashtable();
1148
1149 try {
1150 stmt = this.jdbcConn.createStatement();
1151
1152 sql = " SELECT grp_id, " +
1154 " grp_name "+
1155 " FROM "+this.jdbcSchema+"t_group";
1156 rs = stmt.executeQuery(sql);
1157
1158
1159
1160 while (rs.next()) {
1161 long grp_id = rs.getLong(1);
1164 String grp_name = rs.getString(2);
1165 groupNames.put(new Long(grp_id),grp_name);
1166 groupMembers.put(new Long(grp_id),new Vector());
1167 }
1168 DBHelper.cleanup(rs);
1169
1170
1171 sql = " SELECT usr_id, " +
1173 " usr_login "+
1174 " FROM "+this.jdbcSchema+"t_user";
1175 rs = stmt.executeQuery(sql);
1176
1177 while (rs.next()) {
1178 long usr_id = rs.getLong(1);
1181 String usr_name = rs.getString(2);
1182 userNames.put(new Long(usr_id),usr_name);
1183 userGroups.put(new Long(usr_id),new Vector());
1184 }
1185 DBHelper.cleanup(rs);
1186
1187
1188 sql = " SELECT UGRP_GROUP_ID, " +
1190 " UGRP_USER_ID "+
1191 " FROM "+this.jdbcSchema+"t_user_group " +
1192 " ORDER BY UGRP_GROUP_ID asc";
1193 rs = stmt.executeQuery(sql);
1194
1195 while (rs.next()) {
1196 Long grp_id = new Long(rs.getLong(1));
1199 Long usr_id = new Long(rs.getLong(2));
1200
1201 Vector currMembers = (Vector)groupMembers.get(grp_id);
1203 currMembers.add(usr_id);
1204
1205 Vector currGroups = (Vector)userGroups.get(usr_id);
1206 currGroups.add(grp_id);
1207 }
1208 DBHelper.cleanup(rs);
1209 }
1210 catch(SQLException sqle) {
1211 throw new PersistenceException("DB error is: ["+
1212 sqle.getMessage()+"]");
1213 }
1214 finally {
1215 DBHelper.cleanup(rs);
1216 DBHelper.cleanup(stmt);
1217 }
1218
1219
1221 Vector toBeInitializedGroups = new Vector();
1223
1224 Enumeration enGroups = groupNames.keys();
1225 while (enGroups.hasMoreElements()) {
1226 Long grpId = (Long)enGroups.nextElement();
1227 String grpName = (String)groupNames.get(grpId);
1229
1230 GroupImpl grp = new GroupImpl(grpId,grpName,new Vector(),this,this.jdbcConn);
1233 grp.registerObjectModificationListener(this,ObjectModificationEvent.OBJECT_MODIFIED);
1236
1237 this.groupsByID.put(grp.getID(),grp);
1239 this.groupsByName.put(grp.getName(),grp);
1240
1241 toBeInitializedGroups.add(grp);
1243 }
1244
1245 Vector toBeInitializedUsers = new Vector();
1247
1248 Enumeration enUsers = userNames.keys();
1249 while (enUsers.hasMoreElements()) {
1250 Long usrId = (Long)enUsers.nextElement();
1251 String usrName = (String)userNames.get(usrId);
1253
1254 UserImpl usr = new UserImpl(usrId,usrName,new Vector(),this,this.jdbcConn);
1257 usr.registerObjectModificationListener(this,ObjectModificationEvent.OBJECT_MODIFIED);
1260
1261 this.usersByID.put(usr.getID(),usr);
1263 this.usersByName.put(usr.getName(),usr);
1264
1265 toBeInitializedUsers.add(usr);
1267 }
1268
1269
1274 for (int i=0; i< toBeInitializedGroups.size(); i++) {
1276 GroupImpl grp = (GroupImpl)toBeInitializedGroups.elementAt(i);
1277 grp.setUsers((Vector)groupMembers.get(grp.getID()));
1278 }
1279
1280 for (int i=0; i< toBeInitializedUsers.size(); i++) {
1282 UserImpl usr = (UserImpl)toBeInitializedUsers.elementAt(i);
1283 usr.setGroups((Vector)userGroups.get(usr.getID()));
1284 }
1285
1286 }
1287
1288
1289 private void fireObjectCreatedEvent(ObjectModificationEvent e) {
1290
1291 if (e.getType() != ObjectModificationEvent.OBJECT_CREATED) {
1293 throw new IllegalArgumentException();
1294 }
1295
1296 for (int i=0; i< this.omCreationListeners.size(); i++) {
1297 ((ObjectModificationListener)this.omCreationListeners.elementAt(i)).objectCreated(e);
1298 }
1299 }
1300
1301
1302 private void fireObjectDeletedEvent(ObjectModificationEvent e) {
1303
1304 if (e.getType() != ObjectModificationEvent.OBJECT_DELETED) {
1306 throw new IllegalArgumentException();
1307 }
1308
1309 for (int i=0; i< this.omDeletionListeners.size(); i++) {
1310 ((ObjectModificationListener)this.omDeletionListeners.elementAt(i)).objectDeleted(e);
1311 }
1312 }
1313
1314
1315 private void fireObjectModifiedEvent(ObjectModificationEvent e) {
1316
1317 if (e.getType() != ObjectModificationEvent.OBJECT_MODIFIED) {
1319 throw new IllegalArgumentException();
1320 }
1321
1322 for (int i=0; i< this.omModificationListeners.size(); i++) {
1323 ((ObjectModificationListener)omModificationListeners.elementAt(i)).objectModified(e);
1324 }
1325 }
1326
1327
1328
1329
1330 public void registerObjectModificationListener(ObjectModificationListener l,
1331 int eventType) {
1332
1333 if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
1334 eventType != ObjectModificationEvent.OBJECT_DELETED &&
1335 eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
1336
1337 throw new IllegalArgumentException();
1338 }
1339
1340 switch(eventType) {
1341 case ObjectModificationEvent.OBJECT_CREATED :
1342 this.omCreationListeners.add(l);
1343 break;
1344 case ObjectModificationEvent.OBJECT_DELETED :
1345 this.omDeletionListeners.add(l);
1346 break;
1347 case ObjectModificationEvent.OBJECT_MODIFIED :
1348 this.omModificationListeners.add(l);
1349 break;
1350 default:
1351 Assert.fail();
1352 }
1353
1354 }
1355
1356 public void unregisterObjectModificationListener(ObjectModificationListener l,
1357 int eventType) {
1358
1359 if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
1360 eventType != ObjectModificationEvent.OBJECT_DELETED &&
1361 eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
1362
1363 throw new IllegalArgumentException();
1364 }
1365
1366 switch(eventType) {
1367 case ObjectModificationEvent.OBJECT_CREATED :
1368 this.omCreationListeners.remove(l);
1369 break;
1370 case ObjectModificationEvent.OBJECT_DELETED :
1371 this.omDeletionListeners.remove(l);
1372 break;
1373 case ObjectModificationEvent.OBJECT_MODIFIED :
1374 this.omModificationListeners.remove(l);
1375 break;
1376 default:
1377 Assert.fail();
1378 }
1379
1380 }
1381
1382
1383
1384
1385
1386
1387 public void objectCreated(ObjectModificationEvent e) {
1388 Assert.fail();
1390 }
1391
1392 public void objectModified(ObjectModificationEvent e) {
1393
1394 Object source = e.getSource();
1395 int type = e.getType();
1396 int subtype = e.getSubType();
1397
1398 if (type != ObjectModificationEvent.OBJECT_MODIFIED) {
1400 throw new IllegalArgumentException();
1401 }
1402
1403 if (false == source instanceof Group &&
1405 false == source instanceof User) {
1406
1407 throw new IllegalArgumentException();
1408 }
1409
1410
1411 if (source instanceof Group) {
1412
1413 Assert.assertTrue(subtype == Group.OBJECT_CHANGE_ADDUSER ||
1414 subtype == Group.OBJECT_CHANGE_NAME ||
1415 subtype == Group.OBJECT_CHANGE_REMOVEUSER);
1416
1417 if (subtype == Group.OBJECT_CHANGE_NAME) {
1419 Set mappings = this.groupsByName.entrySet();
1422 Iterator it = mappings.iterator();
1423
1424 boolean found = false;
1425 while (it.hasNext()) {
1426 Map.Entry mapEntry = (Map.Entry)it.next();
1427 String key = (String)mapEntry.getKey();
1428 Group grp = (Group)mapEntry.getValue();
1429
1430 if (false == key.equals(grp.getName())) {
1431 this.groupsByName.remove(key);
1433 this.groupsByName.put(grp.getName(),grp);
1434 found = true;
1435 break;
1436 }
1437 }
1438
1439 Assert.assertTrue(found);
1440 }
1441 }
1442 else {
1443
1444 Assert.assertTrue(source instanceof User);
1445
1446
1448 Assert.assertTrue(subtype == User.OBJECT_CHANGE_NAME);
1449
1450 if (subtype == User.OBJECT_CHANGE_NAME) {
1452 Set mappings = this.usersByName.entrySet();
1455 Iterator it = mappings.iterator();
1456
1457 boolean found = false;
1458 while (it.hasNext()) {
1459 Map.Entry mapEntry = (Map.Entry)it.next();
1460 String key = (String)mapEntry.getKey();
1461 User usr = (User)mapEntry.getValue();
1462
1463 if (false == key.equals(usr.getName())) {
1464 this.usersByName.remove(key);
1466 this.usersByName.put(usr.getName(),usr);
1467 found = true;
1468 break;
1469 }
1470 }
1471
1472 Assert.assertTrue(found);
1473 }
1474 }
1475
1476
1477 }
1478
1479 public void objectDeleted(ObjectModificationEvent e) {
1480 Assert.fail();
1482 }
1483
1484 public void processGateEvent(GateEvent e){
1485 throw new MethodNotImplementedException();
1486 }
1487
1488
1489 public boolean isValidSecurityInfo(SecurityInfo si) {
1490
1491 switch(si.getAccessMode()) {
1492
1493 case SecurityInfo.ACCESS_WR_GW:
1494 case SecurityInfo.ACCESS_GR_GW:
1495 return (null != si.getGroup());
1496
1497 case SecurityInfo.ACCESS_GR_OW:
1498 return (null != si.getGroup() &&
1499 null != si.getUser());
1500
1501 case SecurityInfo.ACCESS_OR_OW:
1502 return (null != si.getUser());
1503
1504 default:
1505 throw new IllegalArgumentException();
1506 }
1507 }
1508
1509 public void finalize() {
1510 try {
1512 this.jdbcConn.close();
1513 }
1514 catch(SQLException sqle) {}
1515
1516 }
1517
1518}
1519