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.19 2001/10/30 12:45:40 valyt 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    /** --- */
45    private AccessControllerImpl ac;
46  
47    /** --- */
48    private Vector omModificationListeners;
49    /** --- */
50    private Vector omCreationListeners;
51    /** --- */
52    private Vector omDeletionListeners;
53  
54  
55  
56    public GroupImpl(Long id, String name, List users,AccessControllerImpl ac,Connection conn) {
57  
58      this.id = id;
59      this.name = name;
60      this.users = users;
61      this.ac = ac;
62      this.conn = conn;
63  
64      this.omModificationListeners = new Vector();
65      this.omCreationListeners = new Vector();
66      this.omDeletionListeners = new Vector();
67  
68      //register self as listener for the security factory events
69      //of type OBJECT_DELETED (users)
70      //don't forget that only AC can delete users, so he's the only
71      //source of such events
72      this.ac.registerObjectModificationListener(
73                                  this,
74                                  ObjectModificationEvent.OBJECT_DELETED);
75  
76    }
77  
78    /** --- */
79    public Long getID() {
80  
81      return id;
82    }
83  
84    /** --- */
85    public String getName() {
86  
87      return name;
88    }
89  
90    /** --- */
91    public List getUsers() {
92  
93      /** NOTE that we're returning a copy of the actuall collection of users
94       *  so that someone would not accidentaly modify it */
95      Vector copy = new Vector();
96      copy.addAll(this.users);
97      return copy;
98  
99    }
100 
101 
102   /** --- */
103   public void setName(String newName, Session s)
104     throws PersistenceException,SecurityException {
105 
106     CallableStatement stmt = null;
107 
108     //1. update database
109     try {
110       //first check the session and then check whether the user is member of the group
111       if (this.ac.isValidSession(s) == false) {
112         throw new SecurityException("invalid session supplied");
113       }
114 
115       //2.1 check if the user is privileged
116       if (false == s.isPrivilegedSession() ) {
117         throw new SecurityException("insufficient privileges to change group name");
118       }
119 
120       stmt = this.conn.prepareCall(
121               "{ call "+Gate.DB_OWNER+".security.set_group_name(?,?)} ");
122       stmt.setLong(1,this.id.longValue());
123       stmt.setString(2,newName);
124       stmt.execute();
125       //release stmt???
126     }
127     catch(SQLException sqle) {
128       throw new PersistenceException("can't change group name in DB: ["+ sqle.getMessage()+"]");
129     }
130     finally {
131       DBHelper.cleanup(stmt);
132     }
133 
134     //2. update memebr variable
135     this.name = newName;
136 
137     //3. create ObjectModificationEvent
138     ObjectModificationEvent e = new ObjectModificationEvent(
139                                           this,
140                                           ObjectModificationEvent.OBJECT_MODIFIED,
141                                           this.OBJECT_CHANGE_NAME);
142 
143 
144     //4. fire ObjectModificationEvent for all who care
145     this.fireObjectModifiedEvent(e);
146 
147   }
148 
149 
150   /** --- */
151   public void addUser(Long userID, Session s)
152     throws PersistenceException,SecurityException{
153 
154     User usr = this.ac.findUser(userID);
155     addUser(usr,s);
156   }
157 
158   /** --- */
159   public void addUser(User usr, Session s)
160     throws PersistenceException,SecurityException{
161 
162     //1. check if the user is not already in group
163     if (this.users.contains(usr)) {
164       throw new SecurityException("User id=["+usr.getID()+"] is alredy member of group");
165     }
166 
167     //2. check the session
168     if (false == this.ac.isValidSession(s)) {
169       throw new SecurityException("invalid session provided");
170     }
171 
172     //2.1 check if the user is privileged
173     if (false == s.isPrivilegedSession() ) {
174       throw new SecurityException("insufficient privileges to add users");
175     }
176 
177     //3. update DB
178     CallableStatement stmt = null;
179 
180     try {
181       stmt = this.conn.prepareCall(
182                 "{ call "+Gate.DB_OWNER+".security.add_user_to_group(?,?)} ");
183       stmt.setLong(1,this.id.longValue());
184       stmt.setLong(2,usr.getID().longValue());
185       stmt.execute();
186       //release stmt???
187     }
188     catch(SQLException sqle) {
189       throw new PersistenceException("can't add user to group in DB: ["+ sqle.getMessage()+"]");
190     }
191 
192     //4. create ObjectModificationEvent
193     ObjectModificationEvent e = new ObjectModificationEvent(
194                                           this,
195                                           ObjectModificationEvent.OBJECT_MODIFIED,
196                                           this.OBJECT_CHANGE_ADDUSER);
197 
198     //5. update usr collection
199     this.users.add(usr);
200 
201     //6. notify user about the change
202     ((ObjectModificationListener)usr).objectModified(e);
203 
204     //7. fire ObjectModificationEvent for all other who care
205     fireObjectModifiedEvent(e);
206   }
207 
208 
209   /** --- */
210   public void removeUser(Long userID, Session s)
211     throws PersistenceException,SecurityException {
212 
213 
214     User usr = this.ac.findUser(userID);
215     removeUser(usr,s);
216   }
217 
218 
219   /** --- */
220   public void removeUser(User usr, Session s)
221     throws PersistenceException,SecurityException{
222 
223     //1. check if the user member of group
224     if (this.users.contains(usr) == false) {
225       throw new SecurityException("User id=["+usr.getID()+"] is NOT a member of group");
226     }
227 
228     //2. check the session
229     if (this.ac.isValidSession(s) == false) {
230       throw new SecurityException("invalid session provided");
231     }
232 
233     //2.1 check if the user is privileged
234     if (false == s.isPrivilegedSession() ) {
235       throw new SecurityException("insufficient privileges to remove users");
236     }
237 
238     //3. update DB
239     CallableStatement stmt = null;
240 
241     try {
242       stmt = this.conn.prepareCall(
243                 "{ call "+Gate.DB_OWNER+".security.remove_user_from_group(?,?)} ");
244       stmt.setLong(1,this.id.longValue());
245       stmt.setLong(2,usr.getID().longValue());
246       stmt.execute();
247       //release stmt???
248     }
249     catch(SQLException sqle) {
250       throw new PersistenceException("can't remove user from group in DB: ["+ sqle.getMessage()+"]");
251     }
252 
253     //4. create ObjectModificationEvent
254     ObjectModificationEvent e = new ObjectModificationEvent(
255                                           this,
256                                           ObjectModificationEvent.OBJECT_MODIFIED,
257                                           this.OBJECT_CHANGE_REMOVEUSER);
258 
259     //5. update usr collection
260     this.users.remove(usr);
261 
262     //6. notify user about the change
263     ((ObjectModificationListener)usr).objectModified(e);
264 
265     //7. fire ObjectModificationEvent for all other who care
266     fireObjectModifiedEvent(e);
267   }
268 
269 
270   //ObjectModificationListener interface
271   public void objectCreated(ObjectModificationEvent e) {
272 
273     //ignore, we don't care about creations
274     return;
275   }
276 
277   public void objectModified(ObjectModificationEvent e) {
278 
279     //ignore, we don't care about modifications
280     return;
281   }
282 
283   public void objectDeleted(ObjectModificationEvent e) {
284 
285     if (e.getSource() instanceof User) {
286 
287       User usr = (User)e.getSource();
288       //check if the user being deleted is one we contain
289       if (true == this.users.contains(usr)) {
290         this.users.remove(usr);
291       }
292 
293     }
294   }
295 
296   public void processGateEvent(GateEvent e){
297     throw new MethodNotImplementedException();
298   }
299 
300 
301   /**
302    *
303    *  this one is necessary for the contains() operations in Lists
304    *  It is possible that two users have two different GroupImpl that refer
305    *  to the very same GATE group in the DB, because they got it from the security
306    *  factory at different times. So we assume that two instances refer the same
307    *  GATE group if NAME1==NAME2
308    *
309    *  */
310   public boolean equals(Object obj)
311   {
312     Assert.assertTrue(obj instanceof Group);
313 
314     Group group2 = (Group)obj;
315 
316     return (this.id.equals(group2.getID()));
317   }
318 
319 
320   public void registerObjectModificationListener(ObjectModificationListener l,
321                                                  int eventType) {
322 
323     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
324         eventType != ObjectModificationEvent.OBJECT_DELETED &&
325         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
326 
327         throw new IllegalArgumentException();
328     }
329 
330     switch(eventType) {
331       case ObjectModificationEvent.OBJECT_CREATED :
332         //we never generate such events
333         Assert.fail();
334 //        this.omCreationListeners.add(l);
335         break;
336       case ObjectModificationEvent.OBJECT_DELETED :
337         //we never generate such events
338         Assert.fail();
339 //        this.omDeletionListeners.add(l);
340         break;
341       case ObjectModificationEvent.OBJECT_MODIFIED :
342         this.omModificationListeners.add(l);
343         break;
344       default:
345         Assert.fail();
346     }
347 
348   }
349 
350   private void fireObjectModifiedEvent(ObjectModificationEvent e) {
351 
352     //sanity check
353     if (e.getType() != ObjectModificationEvent.OBJECT_MODIFIED) {
354       throw new IllegalArgumentException();
355     }
356 
357     for (int i=0; i< this.omModificationListeners.size(); i++) {
358       ((ObjectModificationListener)omModificationListeners.elementAt(i)).objectModified(e);
359     }
360   }
361 
362   public void unregisterObjectModificationListener(ObjectModificationListener l,
363                                                    int eventType) {
364 
365     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
366         eventType != ObjectModificationEvent.OBJECT_DELETED &&
367         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
368 
369         throw new IllegalArgumentException();
370     }
371 
372     switch(eventType) {
373       case ObjectModificationEvent.OBJECT_CREATED :
374         this.omCreationListeners.remove(l);
375         break;
376       case ObjectModificationEvent.OBJECT_DELETED :
377         this.omDeletionListeners.remove(l);
378         break;
379       case ObjectModificationEvent.OBJECT_MODIFIED :
380         this.omModificationListeners.remove(l);
381         break;
382       default:
383         Assert.fail();
384     }
385   }
386 
387   /*package*/ void setUsers(Vector userIDs) {
388 
389     for (int i=0; i< userIDs.size(); i++) {
390       Long usr_id = (Long)userIDs.elementAt(i);
391       User usr = null;
392 
393       try {
394         usr = (User)this.ac.findUser(usr_id);
395       }
396       catch(SecurityException se) {
397         Assert.fail();
398       }
399       catch(PersistenceException se) {
400         Assert.fail();
401       }
402 
403       //is valid?
404       Assert.assertNotNull(usr);
405       Assert.assertTrue(usr instanceof User);
406       //add to our collection, which was empty so far
407       this.users.add(usr);
408     }
409 
410 
411   }
412 
413 }
414