GroupImpl.java
001 /*
002  *  GroupImpl.java
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Marin Dimitrov, 19/Sep/2001
013  *
014  *  $Id: GroupImpl.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015  */
016 
017 package gate.security;
018 
019 import java.sql.*;
020 import java.util.List;
021 import java.util.Vector;
022 
023 import junit.framework.Assert;
024 
025 import gate.Gate;
026 import gate.event.*;
027 import gate.persist.DBHelper;
028 import gate.persist.PersistenceException;
029 import gate.util.MethodNotImplementedException;
030 
031 
032 public class GroupImpl
033   implements Group, ObjectModificationListener {
034 
035   /** --- */
036   private Long    id;
037 
038   /** --- */
039   private String  name;
040 
041   /** --- */
042   private List    users;
043 
044   /** --- */
045   private Connection conn;
046   /** --- */
047   private int dbType;
048 
049   /** --- */
050   private AccessControllerImpl ac;
051 
052   /** --- */
053   private Vector omModificationListeners;
054   /** --- */
055   private Vector omCreationListeners;
056   /** --- */
057   private Vector omDeletionListeners;
058 
059 
060 
061   public GroupImpl(Long id, String name, List users,AccessControllerImpl ac,Connection conn) {
062 
063     this.id = id;
064     this.name = name;
065     this.users = users;
066     this.ac = ac;
067     this.conn = conn;
068 
069     try {
070       String jdbcURL = conn.getMetaData().getURL();
071       this.dbType = DBHelper.getDatabaseType(jdbcURL);
072       Assert.assertTrue(this.dbType == DBHelper.ORACLE_DB ||
073                         this.dbType == DBHelper.POSTGRES_DB);
074     }
075     catch(SQLException sqex) {
076       sqex.printStackTrace();
077     }
078 
079     this.omModificationListeners = new Vector();
080     this.omCreationListeners = new Vector();
081     this.omDeletionListeners = new Vector();
082 
083     //register self as listener for the security factory events
084     //of type OBJECT_DELETED (users)
085     //don't forget that only AC can delete users, so he's the only
086     //source of such events
087     this.ac.registerObjectModificationListener(
088                                 this,
089                                 ObjectModificationEvent.OBJECT_DELETED);
090 
091   }
092 
093   /** --- */
094   public Long getID() {
095 
096     return id;
097   }
098 
099   /** --- */
100   public String getName() {
101 
102     return name;
103   }
104 
105   /** --- */
106   public List getUsers() {
107 
108     /** NOTE that we're returning a copy of the actuall collection of users
109      *  so that someone would not accidentaly modify it */
110     Vector copy = new Vector();
111     copy.addAll(this.users);
112     return copy;
113 
114   }
115 
116 
117   /** --- */
118   public void setName(String newName, Session s)
119     throws PersistenceException,SecurityException {
120 
121     //first check the session and then check whether the user is member of the group
122     if (this.ac.isValidSession(s== false) {
123       throw new SecurityException("invalid session supplied");
124     }
125 
126     //2.1 check if the user is privileged
127     if (false == s.isPrivilegedSession() ) {
128       throw new SecurityException("insufficient privileges to change group name");
129     }
130 
131     CallableStatement stmt = null;
132     PreparedStatement pstmt = null;
133 
134     //Oracle / Postgres ?
135 
136     if (this.dbType == DBHelper.ORACLE_DB) {
137 
138       //1. update database
139       try {
140 
141         stmt = this.conn.prepareCall(
142                 "{ call "+Gate.DB_OWNER+".security.set_group_name(?,?)} ");
143         stmt.setLong(1,this.id.longValue());
144         stmt.setString(2,newName);
145         stmt.execute();
146         //release stmt???
147       }
148       catch(SQLException sqle) {
149         throw new PersistenceException("can't change group name in DB: ["+ sqle.getMessage()+"]");
150       }
151       finally {
152         DBHelper.cleanup(stmt);
153       }
154     }
155 
156     else if (this.dbType == DBHelper.POSTGRES_DB) {
157 
158       try {
159 
160         String sql = "select security_set_group_name(?,?) ";
161         pstmt = this.conn.prepareStatement(sql);
162         pstmt.setLong(1,this.id.longValue());
163         pstmt.setString(2,newName);
164         pstmt.execute();
165         //release stmt???
166       }
167       catch(SQLException sqle) {
168         throw new PersistenceException("can't change group name in DB: ["+ sqle.getMessage()+"]");
169       }
170       finally {
171         DBHelper.cleanup(pstmt);
172       }
173 
174     }
175 
176     else {
177       throw new IllegalArgumentException();
178     }
179 
180     //2. update memebr variable
181     this.name = newName;
182 
183     //3. create ObjectModificationEvent
184     ObjectModificationEvent e = new ObjectModificationEvent(
185                                           this,
186                                           ObjectModificationEvent.OBJECT_MODIFIED,
187                                           Group.OBJECT_CHANGE_NAME);
188 
189 
190     //4. fire ObjectModificationEvent for all who care
191     this.fireObjectModifiedEvent(e);
192 
193   }
194 
195 
196   /** --- */
197   public void addUser(Long userID, Session s)
198     throws PersistenceException,SecurityException{
199 
200     User usr = this.ac.findUser(userID);
201     addUser(usr,s);
202   }
203 
204   /** --- */
205   public void addUser(User usr, Session s)
206     throws PersistenceException,SecurityException{
207 
208     //1. check if the user is not already in group
209     if (this.users.contains(usr)) {
210       throw new SecurityException("User id=["+usr.getID()+"] is alredy member of group");
211     }
212 
213     //2. check the session
214     if (false == this.ac.isValidSession(s)) {
215       throw new SecurityException("invalid session provided");
216     }
217 
218     //2.1 check if the user is privileged
219     if (false == s.isPrivilegedSession() ) {
220       throw new SecurityException("insufficient privileges to add users");
221     }
222 
223     //3. update DB
224     CallableStatement stmt = null;
225     PreparedStatement pstmt = null;
226 
227     //Oracle / Postgres ?
228 
229     if (this.dbType == DBHelper.ORACLE_DB) {
230 
231       try {
232         stmt = this.conn.prepareCall(
233                   "{ call "+Gate.DB_OWNER+".security.add_user_to_group(?,?)} ");
234         stmt.setLong(1,this.id.longValue());
235         stmt.setLong(2,usr.getID().longValue());
236         stmt.execute();
237         //release stmt???
238       }
239       catch(SQLException sqle) {
240         throw new PersistenceException("can't add user to group in DB: ["+ sqle.getMessage()+"]");
241       }
242       finally {
243         DBHelper.cleanup(stmt);
244       }
245     }
246 
247     else if (this.dbType == DBHelper.POSTGRES_DB) {
248 
249       try {
250         String sql = "select security_add_user_to_group(?,?) ";
251         pstmt = this.conn.prepareStatement(sql);
252         pstmt.setLong(1,this.id.longValue());
253         pstmt.setLong(2,usr.getID().longValue());
254         pstmt.execute();
255         //release stmt???
256       }
257       catch(SQLException sqle) {
258         throw new PersistenceException("can't add user to group in DB: ["+ sqle.getMessage()+"]");
259       }
260       finally {
261         DBHelper.cleanup(pstmt);
262       }
263 
264     }
265 
266     else {
267       throw new IllegalArgumentException();
268     }
269 
270 
271     //4. create ObjectModificationEvent
272     ObjectModificationEvent e = new ObjectModificationEvent(
273                                           this,
274                                           ObjectModificationEvent.OBJECT_MODIFIED,
275                                           Group.OBJECT_CHANGE_ADDUSER);
276 
277     //5. update usr collection
278     this.users.add(usr);
279 
280     //6. notify user about the change
281     ((ObjectModificationListener)usr).objectModified(e);
282 
283     //7. fire ObjectModificationEvent for all other who care
284     fireObjectModifiedEvent(e);
285   }
286 
287 
288   /** --- */
289   public void removeUser(Long userID, Session s)
290     throws PersistenceException,SecurityException {
291 
292 
293     User usr = this.ac.findUser(userID);
294     removeUser(usr,s);
295   }
296 
297 
298   /** --- */
299   public void removeUser(User usr, Session s)
300     throws PersistenceException,SecurityException{
301 
302     //1. check if the user member of group
303     if (this.users.contains(usr== false) {
304       throw new SecurityException("User id=["+usr.getID()+"] is NOT a member of group");
305     }
306 
307     //2. check the session
308     if (this.ac.isValidSession(s== false) {
309       throw new SecurityException("invalid session provided");
310     }
311 
312     //2.1 check if the user is privileged
313     if (false == s.isPrivilegedSession() ) {
314       throw new SecurityException("insufficient privileges to remove users");
315     }
316 
317     //3. update DB
318     CallableStatement stmt = null;
319     PreparedStatement pstmt = null;
320 
321     //Oracle / Postgres ?
322 
323     if (this.dbType == DBHelper.ORACLE_DB) {
324       try {
325         stmt = this.conn.prepareCall(
326                   "{ call "+Gate.DB_OWNER+".security.remove_user_from_group(?,?)} ");
327         stmt.setLong(1,this.id.longValue());
328         stmt.setLong(2,usr.getID().longValue());
329         stmt.execute();
330         //release stmt???
331       }
332       catch(SQLException sqle) {
333         throw new PersistenceException("can't remove user from group in DB: ["+ sqle.getMessage()+"]");
334       }
335       finally {
336         DBHelper.cleanup(stmt);
337       }
338     }
339 
340     else if (this.dbType == DBHelper.POSTGRES_DB) {
341       try {
342         String sql = "select security_remove_user_from_group(?,?) ";
343         pstmt = this.conn.prepareStatement(sql);
344         pstmt.setLong(1,this.id.longValue());
345         pstmt.setLong(2,usr.getID().longValue());
346         pstmt.execute();
347         //release stmt???
348       }
349       catch(SQLException sqle) {
350         throw new PersistenceException("can't remove user from group in DB: ["+ sqle.getMessage()+"]");
351       }
352       finally {
353         DBHelper.cleanup(pstmt);
354       }
355     }
356 
357     else {
358       throw new IllegalArgumentException();
359     }
360 
361     //4. create ObjectModificationEvent
362     ObjectModificationEvent e = new ObjectModificationEvent(
363                                           this,
364                                           ObjectModificationEvent.OBJECT_MODIFIED,
365                                           Group.OBJECT_CHANGE_REMOVEUSER);
366 
367     //5. update usr collection
368     this.users.remove(usr);
369 
370     //6. notify user about the change
371     ((ObjectModificationListener)usr).objectModified(e);
372 
373     //7. fire ObjectModificationEvent for all other who care
374     fireObjectModifiedEvent(e);
375   }
376 
377 
378   //ObjectModificationListener interface
379   public void objectCreated(ObjectModificationEvent e) {
380 
381     //ignore, we don't care about creations
382     return;
383   }
384 
385   public void objectModified(ObjectModificationEvent e) {
386 
387     //ignore, we don't care about modifications
388     return;
389   }
390 
391   public void objectDeleted(ObjectModificationEvent e) {
392 
393     if (e.getSource() instanceof User) {
394 
395       User usr = (User)e.getSource();
396       //check if the user being deleted is one we contain
397       if (true == this.users.contains(usr)) {
398         this.users.remove(usr);
399       }
400 
401     }
402   }
403 
404   public void processGateEvent(GateEvent e){
405     throw new MethodNotImplementedException();
406   }
407 
408 
409   /**
410    *
411    *  this one is necessary for the contains() operations in Lists
412    *  It is possible that two users have two different GroupImpl that refer
413    *  to the very same GATE group in the DB, because they got it from the security
414    *  factory at different times. So we assume that two instances refer the same
415    *  GATE group if NAME1==NAME2
416    *
417    *  */
418   public boolean equals(Object obj)
419   {
420     Assert.assertTrue(obj instanceof Group);
421 
422     Group group2 = (Group)obj;
423 
424     return (this.id.equals(group2.getID()));
425   }
426 
427 
428   public void registerObjectModificationListener(ObjectModificationListener l,
429                                                  int eventType) {
430 
431     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
432         eventType != ObjectModificationEvent.OBJECT_DELETED &&
433         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
434 
435         throw new IllegalArgumentException();
436     }
437 
438     switch(eventType) {
439       case ObjectModificationEvent.OBJECT_CREATED :
440         //we never generate such events
441         Assert.fail();
442 //        this.omCreationListeners.add(l);
443         break;
444       case ObjectModificationEvent.OBJECT_DELETED :
445         //we never generate such events
446         Assert.fail();
447 //        this.omDeletionListeners.add(l);
448         break;
449       case ObjectModificationEvent.OBJECT_MODIFIED :
450         this.omModificationListeners.add(l);
451         break;
452       default:
453         Assert.fail();
454     }
455 
456   }
457 
458   private void fireObjectModifiedEvent(ObjectModificationEvent e) {
459 
460     //sanity check
461     if (e.getType() != ObjectModificationEvent.OBJECT_MODIFIED) {
462       throw new IllegalArgumentException();
463     }
464 
465     for (int i=0; i< this.omModificationListeners.size(); i++) {
466       ((ObjectModificationListener)omModificationListeners.elementAt(i)).objectModified(e);
467     }
468   }
469 
470   public void unregisterObjectModificationListener(ObjectModificationListener l,
471                                                    int eventType) {
472 
473     if (eventType != ObjectModificationEvent.OBJECT_CREATED &&
474         eventType != ObjectModificationEvent.OBJECT_DELETED &&
475         eventType != ObjectModificationEvent.OBJECT_MODIFIED) {
476 
477         throw new IllegalArgumentException();
478     }
479 
480     switch(eventType) {
481       case ObjectModificationEvent.OBJECT_CREATED :
482         this.omCreationListeners.remove(l);
483         break;
484       case ObjectModificationEvent.OBJECT_DELETED :
485         this.omDeletionListeners.remove(l);
486         break;
487       case ObjectModificationEvent.OBJECT_MODIFIED :
488         this.omModificationListeners.remove(l);
489         break;
490       default:
491         Assert.fail();
492     }
493   }
494 
495   /*package*/ void setUsers(Vector userIDs) {
496 
497     for (int i=0; i< userIDs.size(); i++) {
498       Long usr_id = (Long)userIDs.elementAt(i);
499       User usr = null;
500 
501       try {
502         usr = (User)this.ac.findUser(usr_id);
503       }
504       catch(SecurityException se) {
505         Assert.fail();
506       }
507       catch(PersistenceException se) {
508         Assert.fail();
509       }
510 
511       //is valid?
512       Assert.assertNotNull(usr);
513       Assert.assertTrue(usr instanceof User);
514       //add to our collection, which was empty so far
515       this.users.add(usr);
516     }
517 
518 
519   }
520 
521 }