Rev 1072 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package ak.hostadmiral.core.model;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.Comparator;
import java.util.Date;
import ak.hostadmiral.util.ConfigInit;
import ak.hostadmiral.util.CollectionInfo;
import ak.hostadmiral.util.ModelException;
import ak.hostadmiral.util.ModelSecurityException;
import ak.hostadmiral.core.model.store.UserStore;
public class UserManager
implements
ConfigInit,
UserBeforeDeleteListener,
UserDeletingListener
{
private UserStore store;
private Class[] passwordStores;
private Collection validateListeners = new ArrayList();
private Collection createdListeners = new ArrayList();
private Collection modifiedListeners = new ArrayList();
private Collection beforeDeleteListeners = new ArrayList();
private Collection deletingListeners = new ArrayList();
private Collection deletedListeners = new ArrayList();
// FIXME: check that it works
private Map loggedinUsers = new WeakHashMap();
public UserManager()
throws ModelException
{
addBeforeDeleteListener(this);
addDeletingListener(this);
}
public User create(User editor)
throws ModelException
{
if(!allowedToCreate(editor)) throw new ModelSecurityException();
User user = new User();
if(!user.mayChangeBoss(editor)) // ordinal user can create only own "subusers"
user.setBoss(editor);
setUserPasswordStores(user);
return user;
}
public boolean allowedToCreate(User editor)
throws ModelException
{
return User.allowedToCreate(this, editor);
}
public User get(User editor, Long id)
throws ModelException
{
User user = store.get(id);
if(!user.viewableBy(editor))
throw new ModelSecurityException();
return user;
}
public User get(Long id)
throws ModelException
{
return store.get(id);
}
public boolean loginExists(User editor, User user, String login)
throws ModelException
{
return store.loginExists(user, login);
}
public User findForLogin(User editor, String login)
throws ModelException
{
User user = store.findForLogin(login);
if(user != null && !user.viewableBy(editor))
throw new ModelSecurityException();
return user;
}
public void save(User editor, User user)
throws ModelException
{
// security check
if(!user.editableBy(editor) && !user.partEditableBy(editor)
&& !user.mayChangeSuperuser(editor))
{
throw new ModelSecurityException();
}
//user.setModUser(editor); // FIXME: disabled because hb throws exception
// if user edits itself
boolean isNew = user.isNew();
User oldUser = user.getOrigin();
if(oldUser == null) oldUser = user;
// validate
for(Iterator i = validateListeners.iterator(); i.hasNext(); ) {
UserValidateListener listener = (UserValidateListener)i.next();
listener.userValidate(editor, user, oldUser);
}
store.save(user);
// update user if he is logged in
for(Iterator i = loggedinUsers.keySet().iterator(); i.hasNext(); ) {
User u = (User)i.next();
if(u.equals(user))
u.update(user);
}
// inform listeners
if(isNew) {
for(Iterator i = createdListeners.iterator(); i.hasNext(); ) {
UserCreatedListener listener = (UserCreatedListener)i.next();
listener.userCreated(editor, user);
}
}
else {
for(Iterator i = modifiedListeners.iterator(); i.hasNext(); ) {
UserModifiedListener listener = (UserModifiedListener)i.next();
listener.userModified(editor, user, oldUser);
}
}
// reset backup
user.resetOrigin();
}
public void addValidateListener(UserValidateListener listener)
{
validateListeners.add(listener);
}
public void removeValidateListener(UserValidateListener listener)
{
validateListeners.remove(listener);
}
public void addCreatedListener(UserCreatedListener listener)
{
createdListeners.add(listener);
}
public void removeCreatedListener(UserCreatedListener listener)
{
createdListeners.remove(listener);
}
public void addModifiedListener(UserModifiedListener listener)
{
modifiedListeners.add(listener);
}
public void removeModifiedListener(UserModifiedListener listener)
{
modifiedListeners.remove(listener);
}
public void addBeforeDeleteListener(UserBeforeDeleteListener listener)
{
beforeDeleteListeners.add(listener);
}
public void removeBeforeDeleteListener(UserBeforeDeleteListener listener)
{
beforeDeleteListeners.remove(listener);
}
public void addDeletedListener(UserDeletedListener listener)
{
deletedListeners.add(listener);
}
public void removeDeletedListener(UserDeletedListener listener)
{
deletedListeners.remove(listener);
}
public void addDeletingListener(UserDeletingListener listener)
{
deletingListeners.add(listener);
}
public void removeDeletingListener(UserDeletingListener listener)
{
deletingListeners.remove(listener);
}
public Collection beforeDelete(User editor, User user, Collection known)
throws ModelException
{
Collection cascade = new ArrayList();
for(Iterator i = beforeDeleteListeners.iterator(); i.hasNext(); ) {
UserBeforeDeleteListener listener = (UserBeforeDeleteListener)i.next();
Collection subcascade = listener.userBeforeDelete(editor, user, known);
if(subcascade != null)
cascade.addAll(subcascade);
}
return cascade;
}
public void delete(User editor, User user)
throws ModelException
{
// check rights
if(!user.deleteableBy(editor))
throw new ModelSecurityException();
// inform deleting listeners
for(Iterator i = deletingListeners.iterator(); i.hasNext(); ) {
UserDeletingListener listener = (UserDeletingListener)i.next();
listener.userDeleting(editor, user);
}
// backup copy
User oldUser = new User(user);
// delete it
store.delete(user);
// inform delete listeners
for(Iterator i = deletedListeners.iterator(); i.hasNext(); ) {
UserDeletedListener listener = (UserDeletedListener)i.next();
listener.userDeleted(editor, oldUser);
}
}
public Collection listUsers(User editor)
throws ModelException
{
return listUsers(null, 0, 0, null, editor);
}
public Collection listUsers(CollectionInfo info, int rowsPerPage, int pageNumber,
Integer[] sortingKeys, User editor)
throws ModelException
{
if(editor.isSuperuser())
return store.listAllUsers(info, rowsPerPage, pageNumber, sortingKeys);
else
return store.listUsers(info, rowsPerPage, pageNumber, sortingKeys, editor);
}
public boolean areUsersAvailable(User editor)
throws ModelException
{
return true;
}
public User loginUser(String login, String password, String ip)
throws ModelException
{
User user = (login == null || password == null)
? null : store.findForLogin(login);
boolean success = (user == null) ? false : user.checkPassword(password);
UserLogin userLogin = new UserLogin(user, login, new Date(), Boolean.valueOf(success), ip);
// save login information
store.saveUserLogin(userLogin);
if(success) {
user = new User(user); // unbind the user from store
loggedinUsers.put(user, Boolean.TRUE);
return user;
}
else {
return null; // wrong login or password
}
}
public Collection listFailedLogins(User editor)
throws ModelException
{
if(!editor.mayViewAllLogins())
throw new ModelSecurityException();
return store.listFailedLogins();
}
public Collection userBeforeDelete(User editor, User user, Collection known)
throws ModelException
{
Collection subusers = store.listSubusers(user);
Collection cascade = new ArrayList();
for(Iterator i = subusers.iterator(); i.hasNext(); ) {
User u = (User)i.next();
if(known.contains(u)) continue;
known.add(u);
if(u.viewableBy(editor)) {
if(u.deleteableBy(editor))
cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.DELETE,
this.beforeDelete(editor, u, known)));
else
cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.FORBIDDEN, null));
}
else {
cascade.add(new CascadeDeleteElement(User.createLimitedCopy(u),
CascadeDeleteElement.FORBIDDEN, null));
}
}
return cascade;
}
public void userDeleting(User editor, User user)
throws ModelException
{
Collection subusers = store.listSubusers(user);
for(Iterator i = subusers.iterator(); i.hasNext(); ) {
delete(editor, (User)i.next());
}
}
protected void setUserPasswordStores(User user)
throws ModelException
{
if(passwordStores == null) return;
try {
for(int i = 0; i < passwordStores.length; i++)
user.addPasswordStore((PasswordStore)passwordStores[i].newInstance());
}
catch(Exception ex) {
throw new ModelException(ex);
}
}
public Collection listUserLogins(CollectionInfo info, int rowsPerPage, int pageNumber,
Integer[] sortingKeys, User editor, User user)
throws ModelException
{
return store.listUserLogins(info, rowsPerPage, pageNumber, sortingKeys, user);
}
public static final Integer SORT_LOGIN = new Integer(1);
public static final Integer SORT_LOGINS_TIME = new Integer(2);
public static final Integer SORT_LOGINS_TIME_REVERSE = new Integer(3);
public static final Comparator LOGIN_COMPARATOR = new LoginComparator();
public static final Comparator LOGINS_TIME_COMPARATOR = new LoginsTimeComparator();
private static class LoginComparator
implements Comparator
{
public int compare(Object o1, Object o2)
{
if(!(o1 instanceof User) || !(o2 instanceof User))
throw new ClassCastException("not a User");
User a1 = (User)o1;
User a2 = (User)o2;
if(a1 == null && a2 == null)
return 0;
else if(a1 == null && a2 != null)
return -1;
else if(a1 != null && a2 == null)
return 1;
else
return a1.getLogin().compareToIgnoreCase(a2.getLogin());
}
public boolean equals(Object obj)
{
return (obj instanceof LoginComparator);
}
}
private static class LoginsTimeComparator
implements Comparator
{
public int compare(Object o1, Object o2)
{
if(!(o1 instanceof UserLogin) || !(o2 instanceof UserLogin))
throw new ClassCastException("not a UserLogin");
UserLogin a1 = (UserLogin)o1;
UserLogin a2 = (UserLogin)o2;
if(a1 == null && a2 == null)
return 0;
else if(a1 == null && a2 != null)
return -1;
else if(a1 != null && a2 == null)
return 1;
else
return a1.getLoginTime().compareTo(a2.getLoginTime());
}
public boolean equals(Object obj)
{
return (obj instanceof LoginComparator);
}
}
public void init(Map params)
throws ModelException
{
try {
userManager = this;
Class c = Class.forName(((String[])params.get("store"))[0]);
store = (UserStore)c.newInstance();
String[] passwordStoreNames = (String[])params.get("passwordStore");
if(passwordStoreNames != null) {
passwordStores = new Class[passwordStoreNames.length];
for(int i = 0; i < passwordStoreNames.length; i++) {
passwordStores[i] = Class.forName(passwordStoreNames[i]);
}
}
}
catch(Exception ex) {
throw new ModelException(ex);
}
}
private static UserManager userManager = null;
public static UserManager getInstance()
{
return userManager;
}
}