|
UserImpl |
|
1 /* 2 * UserImpl.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: UserImpl.java,v 1.17 2001/10/30 12:45:40 valyt Exp $ 14 */ 15 16 package gate.security; 17 18 import java.util.*; 19 import java.sql.*; 20 import junit.framework.*; 21 22 import gate.*; 23 import gate.event.*; 24 import gate.persist.*; 25 import gate.util.*; 26 27 28 public class UserImpl 29 implements User, ObjectModificationListener { 30 31 /** user ID (must be unique) */ 32 private Long id; 33 34 /** user name (must be unique) */ 35 private String name; 36 37 /** list of groups the user belongs to */ 38 private List groups; 39 40 /** Connection to the data store 41 * used for updates */ 42 private Connection conn; 43 44 /** reference to the security factory */ 45 private AccessControllerImpl ac; 46 47 /** list of objects that should be modified when the state 48 * of this object is changed */ 49 private Vector omModificationListeners; 50 51 /** list of objects that should be modified when 52 * this object is created */ 53 private Vector omCreationListeners; 54 55 /** list of objects that should be modified when 56 * this object is deleted */ 57 private Vector omDeletionListeners; 58 59 60 /** --- */ 61 public UserImpl(Long id, String name, List groups,AccessControllerImpl ac,Connection conn) { 62 63 this.id = id; 64 this.name = name; 65 this.groups = groups; 66 this.ac = ac; 67 this.conn = conn; 68 69 this.omModificationListeners = new Vector(); 70 this.omCreationListeners = new Vector(); 71 this.omDeletionListeners = new Vector(); 72 73 //register self as listener for the security factory events 74 //of type OBJECT_DELETED (groups) 75 //don't forget that only AC can delete groups, so he's the only 76 //source of such events 77 this.ac.registerObjectModificationListener( 78 this, 79 ObjectModificationEvent.OBJECT_DELETED); 80 81 } 82 83 84 /* Interface USER */ 85 86 /** returns the ID of the user 87 * user IDs are uniques in the same 88 * data store 89 * */ 90 91 public Long getID() { 92 93 return id; 94 } 95 96 /** returns the name of the user 97 * user names are unique in the 98 * same data store */ 99 public String getName() { 100 101 return name; 102 } 103 104 /** returns a list with the groups that the 105 * user is member of */ 106 public List getGroups() { 107 108 /** NOTE that we're returning a copy of the actuall collection of groups 109 * so that someone would not accidentaly modify it */ 110 Vector copy = new Vector(); 111 copy.addAll(this.groups); 112 return copy; 113 } 114 115 /** changes user name 116 * Only members of the ADMIN group have sufficient privileges. 117 * fires ObjectModificationEvent 118 * @see gate.events.ObjectModificationEvent 119 * */ 120 public void setName(String newName, Session s) 121 throws PersistenceException,SecurityException { 122 123 CallableStatement stmt = null; 124 125 try { 126 //1. check the session 127 if (this.ac.isValidSession(s) == false) { 128 throw new SecurityException("invalid session supplied"); 129 } 130 131 //1.5 check if user has right to change name 132 if (s.getID() != this.id && false == s.isPrivilegedSession()) { 133 throw new SecurityException("insufficient privileges"); 134 } 135 136 137 //2. update database 138 139 stmt = this.conn.prepareCall( 140 "{ call "+Gate.DB_OWNER+".security.set_user_name(?,?)} "); 141 stmt.setLong(1,this.id.longValue()); 142 stmt.setString(2,newName); 143 stmt.execute(); 144 } 145 catch(SQLException sqle) { 146 throw new PersistenceException("can't change user name in DB: ["+ sqle.getMessage()+"]"); 147 } 148 finally { 149 DBHelper.cleanup(stmt); 150 } 151 152 //4. create ObjectModificationEvent 153 ObjectModificationEvent e = new ObjectModificationEvent( 154 this, 155 ObjectModificationEvent.OBJECT_MODIFIED, 156 this.OBJECT_CHANGE_NAME); 157 158 //5. update member variable 159 this.name = newName; 160 161 //6. fire ObjectModificationEvent for all who care 162 fireObjectModifiedEvent(e); 163 } 164 165 166 /** changes user password 167 * Only members of the ADMIN group and the user himself 168 * have sufficient privileges */ 169 public void setPassword(String newPass, Session s) 170 throws PersistenceException,SecurityException { 171 172 CallableStatement stmt = null; 173 174 try { 175 //1. first check the session 176 if (this.ac.isValidSession(s) == false) { 177 throw new SecurityException("invalid session supplied"); 178 } 179 180 //2. check privileges 181 if (false == s.isPrivilegedSession() && s.getID() != this.id) { 182 throw new SecurityException("insuffieicent privileges"); 183 } 184 185 186 stmt = this.conn.prepareCall( 187 "{ call "+Gate.DB_OWNER+".security.set_user_password(?,?)} "); 188 stmt.setLong(1,this.id.longValue()); 189 stmt.setString(2,newPass); 190 stmt.execute(); 191 //release stmt??? 192 } 193 catch(SQLException sqle) { 194 throw new PersistenceException("can't change user password in DB: ["+ sqle.getMessage()+"]"); 195 } 196 197 } 198 199 /** 200 * 201 * this one is necessary for the contains() operations in Lists 202 * It is possible that two users have two different UserImpl that refer 203 * to the very same user in the DB, because they got it fromt he security 204 * factory at different times. So we assume that two instances refer the same 205 * GATE user if ID1==ID2 && NAME1==NAME2 206 * 207 * */ 208 public boolean equals(Object obj) 209 { 210 Assert.assertTrue(obj instanceof User); 211 212 User usr2 = (User)obj; 213 214 return (this.id.equals(usr2.getID())); 215 } 216 217 /** registers an object fore receiving ObjectModificationEvent-s 218 * send by this object 219 * the only types of events sent by a user object are 220 * OBJECT_DELETED and OBJECT_MODIFIED, so any attempt for 221 * registering for other events is invalid */ 222 public void registerObjectModificationListener(ObjectModificationListener l, 223 int eventType) { 224 225 if (eventType != ObjectModificationEvent.OBJECT_DELETED && 226 eventType != ObjectModificationEvent.OBJECT_MODIFIED) { 227 228 throw new IllegalArgumentException(); 229 } 230 231 switch(eventType) { 232 case ObjectModificationEvent.OBJECT_CREATED : 233 this.omCreationListeners.add(l); 234 break; 235 case ObjectModificationEvent.OBJECT_DELETED : 236 this.omDeletionListeners.add(l); 237 break; 238 case ObjectModificationEvent.OBJECT_MODIFIED : 239 this.omModificationListeners.add(l); 240 break; 241 default: 242 Assert.fail(); 243 } 244 245 } 246 247 /** unregisters an object fore receiving ObjectModificationEvent-s 248 * send by this object 249 * the only types of events sent by a user object are 250 * OBJECT_DELETED and OBJECT_MODIFIED, so any attempt for 251 * unregistering for other events is invalid */ 252 public void unregisterObjectModificationListener(ObjectModificationListener l, 253 int eventType) { 254 255 if (eventType != ObjectModificationEvent.OBJECT_DELETED && 256 eventType != ObjectModificationEvent.OBJECT_MODIFIED) { 257 258 throw new IllegalArgumentException(); 259 } 260 261 switch(eventType) { 262 case ObjectModificationEvent.OBJECT_CREATED : 263 this.omCreationListeners.remove(l); 264 break; 265 case ObjectModificationEvent.OBJECT_DELETED : 266 this.omDeletionListeners.remove(l); 267 break; 268 case ObjectModificationEvent.OBJECT_MODIFIED : 269 this.omModificationListeners.remove(l); 270 break; 271 default: 272 Assert.fail(); 273 } 274 } 275 276 /** sends ObjectModificationEvent of type OBJECT_MODIFIED to all 277 * who have already registered */ 278 private void fireObjectModifiedEvent(ObjectModificationEvent e) { 279 280 //sanity check 281 if (e.getType() != ObjectModificationEvent.OBJECT_MODIFIED) { 282 throw new IllegalArgumentException(); 283 } 284 285 for (int i=0; i< this.omModificationListeners.size(); i++) { 286 ((ObjectModificationListener)omModificationListeners.elementAt(i)).objectModified(e); 287 } 288 } 289 290 //ObjectModificationListener interface 291 292 /** callback that is invoked from objects that were <b>created</b> 293 * and this user object is interested in 294 * <b>NOTE</b> that this events are just ignored*/ 295 public void objectCreated(ObjectModificationEvent e) { 296 //ignore, we don't care about creations 297 return; 298 } 299 300 /** callback that is invoked from objects that were <b>modified</b> 301 * and this user object is interested in 302 * Useful when a group drops the user as member and 303 * this user should be notified so that it will remove the 304 * reference to the group from its internal collections 305 * (the user is no longer member of the group) 306 * */ 307 public void objectModified(ObjectModificationEvent e) { 308 309 //only groups can disturb the user 310 Assert.assertTrue(e.getSubType() == Group.OBJECT_CHANGE_ADDUSER || 311 e.getSubType() == Group.OBJECT_CHANGE_REMOVEUSER || 312 e.getSubType() == Group.OBJECT_CHANGE_NAME); 313 314 //we get this event only if a group adds/removes user to it 315 Group grp = (Group)e.getSource(); 316 317 switch(e.getSubType()) { 318 319 case Group.OBJECT_CHANGE_ADDUSER: 320 321 //1.check that the groupis not already in collection 322 Assert.assertTrue(false == this.groups.contains(grp)); 323 //1.1 verify grp 324 Assert.assertTrue(grp instanceof Group); 325 //2.add group to collection 326 this.groups.add(grp); 327 //3. the group has laredy registered 328 //the user as listener for this group 329 ; 330 break; 331 332 case Group.OBJECT_CHANGE_REMOVEUSER: 333 //1.check that the group is in collection 334 Assert.assertTrue(true == this.groups.contains(grp)); 335 //2.remove group from collection 336 this.groups.remove(grp); 337 //3. the group has laredy UNregistered 338 //the user as listener for this group 339 ; 340 break; 341 342 case Group.OBJECT_CHANGE_NAME: 343 //do nothing 344 break; 345 346 default: 347 throw new IllegalArgumentException(); 348 } 349 350 351 } 352 353 /** callback that is invoked from objects that were <b>deleted</b> 354 * and this user object is interested in 355 * Useful when a group is deleted from the security factory and 356 * this user should be notified so that it will remove the 357 * reference to the group from its internal collections 358 * (the user is no longer member of the group) 359 * */ 360 public void objectDeleted(ObjectModificationEvent e) { 361 362 if (e.getSource() instanceof Group) { 363 364 Group grp = (Group)e.getSource(); 365 //check if the Group being deleted is one we belong to 366 if (true == this.groups.contains(grp)) { 367 this.groups.remove(grp); 368 } 369 370 } 371 } 372 373 /** huh? */ 374 public void processGateEvent(GateEvent e){ 375 throw new MethodNotImplementedException(); 376 } 377 378 379 /*package*/ void setGroups(Vector groupIDs) { 380 381 for (int i=0; i< groupIDs.size(); i++) { 382 Long grp_id = (Long)groupIDs.elementAt(i); 383 Group grp = null; 384 385 try { 386 grp = (Group)this.ac.findGroup(grp_id); 387 } 388 catch(SecurityException se) { 389 Assert.fail(); 390 } 391 catch(PersistenceException se) { 392 Assert.fail(); 393 } 394 395 //is valid? 396 Assert.assertNotNull(grp); 397 Assert.assertTrue(grp instanceof Group); 398 //add to our collection, which was empty so far 399 this.groups.add(grp); 400 } 401 } 402 403 404 } 405
|
UserImpl |
|