1   /*
2    *  GroupImpl.java
3    *
4    *  Copyright (c) 1998-2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Marin Dimitrov, 19/Sep/2001
12   *
13   *  $Id: GroupImpl.java,v 1.20 2002/04/01 13:48:50 marin Exp $
14   */
15  
16  package gate.security;
17  
18  import java.util.*;
19  import java.sql.*;
20  
21  import junit.framework.*;
22  
23  import gate.*;
24  import gate.event.*;
25  import gate.persist.*;
26  import gate.util.MethodNotImplementedException;
27  
28  
29  public class GroupImpl
30    implements Group, ObjectModificationListener {
31  
32    /** --- */
33    private Long    id;
34  
35    /** --- */
36    private String  name;
37  
38    /** --- */
39    private List    users;
40  
41    /** --- */
42    private Connection conn;
43    /** --- */
44    private int dbType;
45  
46    /** --- */
47    private AccessControllerImpl ac;
48  
49    /** --- */
50    private Vector omModificationListeners;
51    /** --- */
52    private Vector omCreationListeners;
53    /** --- */
54    private Vector omDeletionListeners;
55  
56  
57  
58    public GroupImpl(Long id, String name, List users,AccessControllerImpl ac,Connection conn) {
59  
60      this.id = id;
61      this.name = name;
62      this.users = users;
63      this.ac = ac;
64      this.conn = conn;
65  
66      try {
67        String jdbcURL = conn.getMetaData().getURL();
68        this.dbType = DBHelper.getDatabaseType(jdbcURL);
69        Assert.assertTrue(this.dbType == DBHelper.ORACLE_DB ||
70                          this.dbType == DBHelper.POSTGRES_DB);
71      }
72      catch(SQLException sqex) {
73        sqex.printStackTrace();
74      }
75  
76      this.omModificationListeners = new Vector();
77      this.omCreationListeners = new Vector();
78      this.omDeletionListeners = new Vector();
79  
80      //register self as listener for the security factory events
81      //of type OBJECT_DELETED (users)
82      //don't forget that only AC can delete users, so he's the only
83      //source of such events
84      this.ac.registerObjectModificationListener(
85                                  this,
86                                  ObjectModificationEvent.OBJECT_DELETED);
87  
88    }
89  
90    /** --- */
91    public Long getID() {
92  
93      return id;
94    }
95  
96    /** --- */
97    public String getName() {
98  
99      return name;
100   }
101 
102   /** --- */
103   public List getUsers() {
104 
105     /** NOTE that we're returning a copy of the actuall collection of users
106      *  so that someone would not accidentaly modify it */
107     Vector copy = new Vector();
108     copy.addAll(this.users);
109     return copy;
110 
111   }
112 
113 
114   /** --- */
115   public void setName(String newName, Session s)
116     throws PersistenceException,SecurityException {
117 
118     //first check the session and then check whether the user is member of the group
119     if (this.ac.isValidSession(s) == false) {
120       throw new SecurityException("invalid session supplied");
121     }
122 
123     //2.1 check if the user is privileged
124     if (false == s.isPrivilegedSession() ) {
125       throw new SecurityException("insufficient privileges to change group name");
126     }
127 
128     CallableStatement stmt = null;
129     PreparedStatement pstmt = null;
130 
131     //Oracle / Postgres ?
132 
133     if (this.dbType == DBHelper.ORACLE_DB) {
134 
135       //1. update database
136       try {
137 
138         stmt = this.conn.prepareCall(
139                 "{ call "+Gate.DB_OWNER+".security.set_group_name(?,?)} ");
140         stmt.setLong(1,this.id.longValue());
141         stmt.setString(2,newName);
142         stmt.execute();
143         //release stmt???
144       }
145       catch(SQLException sqle) {
146         throw new PersistenceException("can't change group name in DB: ["+ sqle.getMessage()+"]");
147       }
148       finally {
149         DBHelper.cleanup(stmt);
150       }
151     }
152 
153     else if (this.dbType == DBHelper.POSTGRES_DB) {
154 
155       try {
156 
157         String sql = "select security_set_group_name(?,?) ";
158         pstmt = this.conn.prepareStatement(sql);
159         pstmt.setLong(1,this.id.longValue());
160         pstmt.setString(2,newName);
161         pstmt.execute();
162         //release stmt???
163       }
164       catch(SQLException sqle) {
165         throw new PersistenceException("can't change group name in DB: ["+ sqle.getMessage()+"]");
166       }
167       finally {
168         DBHelper.cleanup(pstmt);
169       }
170 
171     }
172 
173     else {
174       throw new IllegalArgumentException();
175     }
176 
177     //2. update memebr variable
178     this.name = newName;
179 
180     //3. create ObjectModificationEvent
181     ObjectModificationEvent e = new ObjectModificationEvent(
182                                           this,
183                                           ObjectModificationEvent.OBJECT_MODIFIED,
184                                           this.OBJECT_CHANGE_NAME);
185 
186 
187     //4. fire ObjectModificationEvent for all who care
188     this.fireObjectModifiedEvent(e);
189 
190   }
191 
192 
193   /** --- */
194   public void addUser(Long userID, Session s)
195     throws PersistenceException,SecurityException{
196 
197     User usr = this.ac.findUser(userID);
198     addUser(usr,s);
199   }
200 
201   /** --- */
202   public void addUser(User usr, Session s)
203     throws PersistenceException,SecurityException{
204 
205     //1. check if the user is not already in group
206     if (this.users.contains(usr)) {
207       throw new SecurityException("User id=["+usr.getID()+"] is alredy member of group");
208     }
209 
210     //2. check the session
211     if (false == this.ac.isValidSession(s)) {
212       throw new SecurityException("invalid session provided");
213     }
214 
215     //2.1 check if the user is privileged
216     if (false == s.isPrivilegedSession() ) {
217       throw new SecurityException("insufficient privileges to add users");
218     }
219 
220     //3. update DB
221     CallableStatement stmt = null;
222     PreparedStatement pstmt = null;
223 
224     //Oracle / Postgres ?
225 
226     if (this.dbType == DBHelper.ORACLE_DB) {
227 
228       try {
229         stmt = this.conn.prepareCall(
230                   "{ call "+Gate.DB_OWNER+".security.add_user_to_group(?,?)} ");
231         stmt.setLong(1,this.id.longValue());
232         stmt.setLong(2,usr.getID().longValue());
233         stmt.execute();
234         //release stmt???
235       }
236       catch(SQLException sqle) {
237         throw new PersistenceException("can't add user to group in DB: ["+ sqle.getMessage()+"]");
238       }
239       finally {
240         DBHelper.cleanup(stmt);
241       }
242     }
243 
244     else if (this.dbType == DBHelper.POSTGRES_DB) {
245 
246       try {
247         String sql = "select security_add_user_to_group(?,?) ";
248         pstmt = this.conn.prepareStatement(sql);
249         pstmt.setLong(1,this.id.longValue());
250         pstmt.setLong(2,usr.getID().longValue());
251         pstmt.execute();
252         //release stmt???
253       }
254       catch(SQLException sqle) {
255         throw new PersistenceException("can't add user to group in DB: ["+ sqle.getMessage()+"]");
256       }
257       finally {
258         DBHelper.cleanup(pstmt);
259       }
260 
261     }
262 
263     else {
264       throw new IllegalArgumentException();
265     }
266 
267 
268     //4. create ObjectModificationEvent
269     ObjectModificationEvent e = new ObjectModificationEvent(
270                                           this,
271                                           ObjectModificationEvent.OBJECT_MODIFIED,
272                                           this.OBJECT_CHANGE_ADDUSER);
273 
274     //5. update usr collection
275     this.users.add(usr);
276 
277     //6. notify user about the change
278     ((ObjectModificationListener)usr).objectModified(e);
279 
280     //7. fire ObjectModificationEvent for all other who care
281     fireObjectModifiedEvent(e);
282   }
283 
284 
285   /** --- */
286   public void removeUser(Long userID, Session s)
287     throws PersistenceException,SecurityException {
288 
289 
290     User usr = this.ac.findUser(userID);
291     removeUser(usr,s);
292   }
293 
294 
295   /** --- */
296   public void removeUser(User usr, Session s)
297     throws PersistenceException,SecurityException{
298 
299     //1. check if the user member of group
300     if (this.users.contains(usr) == false) {
301       throw new SecurityException("User id=["+usr.getID()+"] is NOT a member of group");
302     }
303 
304     //2. check the session
305     if (this.ac.isValidSession(s) == false) {
306       throw new SecurityException("invalid session provided");
307     }
308 
309     //2.1 check if the user is privileged
310     if (false == s.isPrivilegedSession() ) {
311       throw new SecurityException("insufficient privileges to remove users");
312     }
313 
314     //3. update DB
315     CallableStatement stmt = null;
316     PreparedStatement pstmt = null;
317 
318     //Oracle / Postgres ?
319 
320     if (this.dbType == DBHelper.ORACLE_DB) {
321       try {
322         stmt = this.conn.prepareCall(
323                   "{ call "+Gate.DB_OWNER+".security.remove_user_from_group(?,?)} ");
324         stmt.setLong(1,this.id.longValue());
325         stmt.setLong(2,usr.getID().longValue());
326         stmt.execute();
327         //release stmt???
328       }
329       catch(SQLException sqle) {
330         throw new PersistenceException("can't remove user from group in DB: ["+ sqle.getMessage()+"]");
331       }
332       finally {
333         DBHelper.cleanup(stmt);
334       }
335     }
336 
337     else if (this.dbType == DBHelper.POSTGRES_DB) {
338       try {
339         String sql = "select security_remove_user_from_group(?,?) ";
340         pstmt = this.conn.prepareStatement(sql);
341         pstmt.setLong(1,this.id.longValue());
342         pstmt.setLong(2,usr.getID().longValue());
343         pstmt.execute();
344         //release stmt???
345       }
346       catch(SQLException sqle) {
347         throw new PersistenceException("can't remove user from group in DB: ["+ sqle.getMessage()+"]");
348       }
349       finally {
350         DBHelper.cleanup(pstmt);
351       }
352     }
353 
354     else {
355       throw new IllegalArgumentException();
356     }
357 
358     //4. create ObjectModificationEvent
359     ObjectModificationEvent e = new ObjectModificationEvent(
360                                           this,
361                                           ObjectModificationEvent.OBJECT_MODIFIED,
362                                           this.OBJECT_CHANGE_REMOVEUSER);
363 
364     //5. update usr collection
365     this.users.remove(usr);
366 
367     //6. notify user about the change
368     ((ObjectModificationListener)usr).objectModified(e);
369 
370     //7. fire ObjectModificationEvent for all other who care
371     fireObjectModifiedEvent(e);
372   }
373 
374 
375   //ObjectModificationListener interface
376   public void objectCreated(ObjectModificationEvent e) {
377 
378     //ignore, we don't care about creations
379     return;
380   }
381 
382   public void objectModified(ObjectModificationEvent e) {
383 
384     //ignore, we don't care about modifications
385     return;
386   }
387 
388   public void objectDeleted(ObjectModificationEvent e) {
389 
390     if (e.getSource() instanceof User) {
391 
392       User usr = (User)e.getSource();
393       //check if the user being deleted is one we contain
394       if (true == this.users.contains(usr)) {
395         this.users.remove(usr);
396       }
397 
398     }
399   }
400 
401   public void processGateEvent(GateEvent e){
402     throw new MethodNotImplementedException();
403   }
404 
405 
406   /**
407    *
408    *  this one is necessary for the contains() operations in Lists
409    *  It is possible that two users have two different GroupImpl that refer
410    *  to the very same GATE group in the DB, because they got it from the security
411    *  factory at different times. So we assume that two instances refer the same
412    *  GATE group if NAME1==NAME2
413    *
414    *  */
415   public boolean equals(Object obj)
416   {
417     Assert.assertTrue(obj instanceof Group);
418 
419     Group group2 = (Group)obj;
420 
421     return (this.id.equals(group2.getID()));
422   }
423 
424 
425   public void registerObjectModificationListener(ObjectModificationListener l,
426                                                  int eventType) {
427 
428     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
429         eventType != ObjectModificationEvent.OBJECT_DELETED &&
430         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
431 
432         throw new IllegalArgumentException();
433     }
434 
435     switch(eventType) {
436       case ObjectModificationEvent.OBJECT_CREATED :
437         //we never generate such events
438         Assert.fail();
439 //        this.omCreationListeners.add(l);
440         break;
441       case ObjectModificationEvent.OBJECT_DELETED :
442         //we never generate such events
443         Assert.fail();
444 //        this.omDeletionListeners.add(l);
445         break;
446       case ObjectModificationEvent.OBJECT_MODIFIED :
447         this.omModificationListeners.add(l);
448         break;
449       default:
450         Assert.fail();
451     }
452 
453   }
454 
455   private void fireObjectModifiedEvent(ObjectModificationEvent e) {
456 
457     //sanity check
458     if (e.getType() != ObjectModificationEvent.OBJECT_MODIFIED) {
459       throw new IllegalArgumentException();
460     }
461 
462     for (int i=0; i< this.omModificationListeners.size(); i++) {
463       ((ObjectModificationListener)omModificationListeners.elementAt(i)).objectModified(e);
464     }
465   }
466 
467   public void unregisterObjectModificationListener(ObjectModificationListener l,
468                                                    int eventType) {
469 
470     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
471         eventType != ObjectModificationEvent.OBJECT_DELETED &&
472         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
473 
474         throw new IllegalArgumentException();
475     }
476 
477     switch(eventType) {
478       case ObjectModificationEvent.OBJECT_CREATED :
479         this.omCreationListeners.remove(l);
480         break;
481       case ObjectModificationEvent.OBJECT_DELETED :
482         this.omDeletionListeners.remove(l);
483         break;
484       case ObjectModificationEvent.OBJECT_MODIFIED :
485         this.omModificationListeners.remove(l);
486         break;
487       default:
488         Assert.fail();
489     }
490   }
491 
492   /*package*/ void setUsers(Vector userIDs) {
493 
494     for (int i=0; i< userIDs.size(); i++) {
495       Long usr_id = (Long)userIDs.elementAt(i);
496       User usr = null;
497 
498       try {
499         usr = (User)this.ac.findUser(usr_id);
500       }
501       catch(SecurityException se) {
502         Assert.fail();
503       }
504       catch(PersistenceException se) {
505         Assert.fail();
506       }
507 
508       //is valid?
509       Assert.assertNotNull(usr);
510       Assert.assertTrue(usr instanceof User);
511       //add to our collection, which was empty so far
512       this.users.add(usr);
513     }
514 
515 
516   }
517 
518 }
519