| 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 |