Subversion Repositories general

Rev

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