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