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