head	1.52;
access;
symbols
	TIGRIS_1_1_0RC2:1.10.6.1
	TIGRIS_1_1_0RC1:1.10.6.1
	TIGRIS_1_1:1.10.6.1.0.2
	TIGRIS_1_0_8:1.10.6.1
	TIGRIS_1_0_8RC3:1.10.6.1
	TIGRIS_1_0_8RC2:1.10.6.1
	TIGRIS_1_0_8RC1:1.10.6.1
	TIGRIS_1_0_7:1.10.6.1
	TIGRIS_1_0_7RC3:1.10.6.1
	TIGRIS_1_0_7RC2:1.10.6.1
	TIGRIS_1_0_7RC1:1.10.6.1
	TIGRIS_1_0_6:1.10.6.1
	TIGRIS_1_0_6RC5:1.10.6.1
	TIGRIS_1_0_6RC4:1.10.6.1
	TIGRIS_1_0_6RC3:1.10.6.1
	TIGRIS_1_0_6RC2:1.10.6.1
	TIGRIS_1_0_6RC1:1.10.6.1
	TIGRIS_1_0_5:1.10.6.1
	TIGRIS_1_0_5RC6:1.10.6.1
	TIGRIS_1_0_5RC5:1.10.6.1
	TIGRIS_1_0_5RC4:1.10
	TIGRIS_1_0_5RC3:1.10
	TIGRIS_1_0_5RC2:1.10
	TIGRIS_1_0_5RC1:1.10
	TIGRIS_1_0_4:1.10
	TIGRIS_1_0_3:1.10
	TIGRIS_1_0_2:1.10
	TIGRIS_1_0_1:1.10
	TIGRIS_1_0:1.10.0.6
	TIGRIS_1_0_0:1.10
	TIGRIS_1_0_0_RC1:1.10.0.2;
locks; strict;
comment	@# @;


1.52
date	2001.08.11.09.08.04;	author dlr;	state Exp;
branches;
next	1.51;

1.51
date	2001.08.06.22.17.46;	author dlr;	state Exp;
branches;
next	1.50;

1.50
date	2001.07.27.17.05.19;	author leonardr;	state Exp;
branches;
next	1.49;

1.49
date	2001.07.20.19.51.36;	author dlr;	state Exp;
branches;
next	1.48;

1.48
date	2001.06.18.22.12.20;	author leonardr;	state Exp;
branches;
next	1.47;

1.47
date	2001.06.16.00.22.58;	author leonardr;	state Exp;
branches;
next	1.46;

1.46
date	2001.06.15.21.23.35;	author leonardr;	state Exp;
branches;
next	1.45;

1.45
date	2001.06.15.20.23.08;	author leonardr;	state Exp;
branches;
next	1.44;

1.44
date	2001.06.15.17.11.19;	author leonardr;	state Exp;
branches;
next	1.43;

1.43
date	2001.06.14.21.15.21;	author leonardr;	state Exp;
branches;
next	1.42;

1.42
date	2001.06.13.17.51.09;	author leonardr;	state Exp;
branches;
next	1.41;

1.41
date	2001.06.09.01.02.15;	author leonardr;	state Exp;
branches;
next	1.40;

1.40
date	2001.06.09.00.01.09;	author leonardr;	state Exp;
branches;
next	1.39;

1.39
date	2001.06.08.21.52.09;	author leonardr;	state Exp;
branches;
next	1.38;

1.38
date	2001.06.08.20.43.30;	author leonardr;	state Exp;
branches;
next	1.37;

1.37
date	2001.06.04.19.15.23;	author leonardr;	state Exp;
branches;
next	1.36;

1.36
date	2001.06.04.15.09.27;	author leonardr;	state Exp;
branches;
next	1.35;

1.35
date	2001.05.30.20.15.25;	author leonardr;	state Exp;
branches;
next	1.34;

1.34
date	2001.05.25.23.02.29;	author leonardr;	state Exp;
branches;
next	1.33;

1.33
date	2001.05.25.01.45.28;	author leonardr;	state Exp;
branches;
next	1.32;

1.32
date	2001.05.23.01.41.58;	author leonardr;	state Exp;
branches;
next	1.31;

1.31
date	2001.05.23.00.35.00;	author leonardr;	state Exp;
branches;
next	1.30;

1.30
date	2001.05.21.21.11.52;	author dlr;	state Exp;
branches;
next	1.29;

1.29
date	2001.05.21.21.06.01;	author leonardr;	state Exp;
branches;
next	1.28;

1.28
date	2001.05.18.21.56.26;	author leonardr;	state Exp;
branches;
next	1.27;

1.27
date	2001.04.20.21.19.40;	author leonardr;	state Exp;
branches;
next	1.26;

1.26
date	2001.04.20.18.56.29;	author leonardr;	state Exp;
branches;
next	1.25;

1.25
date	2001.04.20.15.30.21;	author dlr;	state Exp;
branches;
next	1.24;

1.24
date	2001.04.18.22.39.19;	author dlr;	state Exp;
branches;
next	1.23;

1.23
date	2001.04.12.02.21.02;	author dlr;	state Exp;
branches;
next	1.22;

1.22
date	2001.04.12.02.17.07;	author dlr;	state Exp;
branches;
next	1.21;

1.21
date	2001.04.12.02.09.59;	author dlr;	state Exp;
branches;
next	1.20;

1.20
date	2001.04.12.01.33.45;	author dlr;	state Exp;
branches;
next	1.19;

1.19
date	2001.04.12.00.56.30;	author leonardr;	state Exp;
branches;
next	1.18;

1.18
date	2001.04.12.00.17.39;	author dlr;	state Exp;
branches;
next	1.17;

1.17
date	2001.04.09.17.48.13;	author dlr;	state Exp;
branches;
next	1.16;

1.16
date	2001.04.09.17.10.43;	author dlr;	state Exp;
branches;
next	1.15;

1.15
date	2001.04.09.07.01.08;	author dlr;	state Exp;
branches;
next	1.14;

1.14
date	2001.04.09.06.54.27;	author dlr;	state Exp;
branches;
next	1.13;

1.13
date	2001.04.07.07.33.47;	author dlr;	state Exp;
branches;
next	1.12;

1.12
date	2001.04.07.07.30.27;	author dlr;	state Exp;
branches;
next	1.11;

1.11
date	2001.04.07.07.12.52;	author dlr;	state Exp;
branches;
next	1.10;

1.10
date	2001.03.26.19.05.25;	author dlr;	state Exp;
branches
	1.10.6.1;
next	1.9;

1.9
date	2001.03.21.18.38.12;	author leonardr;	state Exp;
branches;
next	1.8;

1.8
date	2001.03.15.18.34.50;	author dlr;	state Exp;
branches;
next	1.7;

1.7
date	2001.03.15.18.16.10;	author dlr;	state Exp;
branches;
next	1.6;

1.6
date	2001.03.13.03.52.24;	author dlr;	state Exp;
branches;
next	1.5;

1.5
date	2001.03.13.03.47.31;	author dlr;	state Exp;
branches;
next	1.4;

1.4
date	2001.03.13.03.15.20;	author leonardr;	state Exp;
branches;
next	1.3;

1.3
date	2001.03.13.03.15.03;	author leonardr;	state Exp;
branches;
next	1.2;

1.2
date	2001.03.07.01.53.22;	author lucas;	state Exp;
branches;
next	1.1;

1.1
date	2001.03.07.01.13.15;	author lucas;	state Exp;
branches;
next	;

1.10.6.1
date	2001.05.18.20.45.47;	author leonardr;	state Exp;
branches;
next	;


desc
@@


1.52
log
@Upgrading to Turbine 3.0-dev, Fulcrum 1.0, and Torque 1.0.
@
text
@/* ================================================================
 * Copyright (c) 2000-2001 CollabNet.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if
 * any, must include the following acknowlegement: "This product includes
 * software developed by CollabNet (http://www.collab.net/)."
 * Alternately, this acknowlegement may appear in the software itself, if
 * and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The hosted project names must not be used to endorse or promote
 * products derived from this software without prior written
 * permission. For written permission, please contact info@@collab.net.
 * 
 * 5. Products derived from this software may not use the "Tigris" name
 * nor may "Tigris" appear in their names without prior written
 * permission of CollabNet.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL COLLABNET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 * 
 * This software consists of voluntary contributions made by many
 * individuals on behalf of CollabNet.
 */

package org.tigris.helm.om;

import java.util.*;
import java.sql.*;

import org.apache.torque.util.Criteria;
import org.apache.commons.util.BufferCache;
import org.apache.turbine.util.Log;
import org.apache.commons.util.exception.NestableException;

import org.tigris.madcow.MySQLPassword;

import org.tigris.helm.om.map.UserMapBuilder;
import org.tigris.helm.*;
import org.tigris.helm.tool.*;
import org.tigris.helm.tool.cache.*;

/**
 * Extension of generated Peer BaseUserPeer.
 *
 * @@author <a href="mailto:leonardr@@collab.net">Leonard Richardson</a>
 * @@author <a href="mailto:dlr@@collab.net">Daniel Rall</a>
 */
public class UserPeer extends BaseUserPeer
{
    /**
     * Flag indicating whether in debug mode.
     */
    private static final boolean DEBUG = true;

    /**
     * The cache.
     */
    private static UserCache cache;

    //
    // Special data structures and methods for paginating lists of users.
    //     

    public static Map filterableFields = new HashMap();
    
    /**
     * How objects of this type should be ordered in lists.
     */
    public static final String DEFAULT_ORDER_BY = LOGIN_NAME;

    //
    // Special users.
    // 
    public static final String NOBODY_USER_LOGIN_NAME = "**Nobody";
    public static final String DOMAIN_USERS_LOGIN_NAME = "*All users in domain";

    /**
     * The login name of the super user.
     */
    protected static final String ROOT_LOGIN_NAME = "root";

    /**
     * The login name of the anonymous user (previously the guest user).
     */
    protected static final String ANONYMOUS_LOGIN_NAME = "guest";

    /**
     * Setup and initialize various class variables.
     */
    static
    { 
        filterableFields.put("Real Name", REAL_NAME);
        filterableFields.put("Login Name", LOGIN_NAME);
        filterableFields.put("Email", EMAIL);
        filterableFields.put("Organization", ORGANIZATION);

        try
        {
            cache = new UserCache();
        }
        catch (Exception e)
        {
            throw new RuntimeException("Unable to create user cache: " +
                                       e.getMessage());
        }

        // Cache some user objects.
        getSuperUser();
        getAnonymousUser();
        getNobodyUser();
    }
    
    /**
     * Macro to throw an {@@link java.lang.Error} when a cached user is missing.
     */
    private static final void missingUserError(Exception e, String userDescrip)
    {
        Log.error("Could not get " + userDescrip + " user", e);
        throw new Error("Could not get " + userDescrip + " user");
    }

    /**
     * Asserts that the provided login/password token is valid in the given
     * domain.
     *
     * @@param domain    The domain to check the login name in.
     * @@param loginName The login name to check the password of.
     * @@param password  The password to check.
     * @@return          The valid user.
     *
     * @@exception NestableException Invalid login.
     * @@exception Exception        Error condition, probably database related.
     */
    public static User assertValidLogin(Domain domain, String loginName,
                                        String password)
        throws NestableException, Exception
    {
        String failString = "Invalid login";
        User user = null;
        try 
        {
            user = getInstanceByIdentifier(domain, loginName);
        }
        catch (DoesNotExist e)
        {
            throw new NestableException(failString);
        }

        if (!user.validPassword(password))
        {
            throw new NestableException(failString);
        }
        return user;
    }

    /**
     * Returns true iff the given login is valid.
     */
    public static boolean isValidLogin(Domain domain, String loginName,
                                       String password)
        throws NestableException, Exception
    {
        boolean ok = true;
        User user = null;
        try 
        {
            user = getInstanceByIdentifier(domain, loginName);
        }
        catch (DoesNotExist e)
        {
            ok = false;
        }

        if (!user.validPassword(password))
        {
            ok = false;
        }
        return ok;
    }

    /**
     * Asserts that the provided user key/password token is valid.
     *
     * @@param userID   The primary key of the user to check the password of.
     * @@param password The password to check.
     * @@return         The valid user.
     *
     * @@exception NestableException Invalid login.
     * @@exception Exception        Error condition, probably database related.
     */
    public static User assertValidLogin(String userID, String password)
        throws NestableException, Exception
    {
        String failString = "Password invalid";
        User user = null;
        try 
        {
            user = getInstance(userID);
        }
        catch (DoesNotExist e)
        {
            throw new NestableException(failString);
        }

        if (!user.validPassword(password))
        {
            throw new NestableException(failString);
        }
        return user;
    }

    /**
     * Checks whether the specified user exists.
     */
    public static boolean exists(Domain domain, String loginName)
        throws Exception
    {
        try {
            getInstanceByLoginName(domain, loginName);
            return true;
        }
        catch (DoesNotExist e) {
            return false;
        }
    }

    /**
     * Gets the database key associated with the special user that represents 
     * the "all users in domain" user group for the specified domain.
     *
     * @@param domain The domain to retrieve the special user for.
     */
    public static UserGroup getDomainUser(Domain domain)
        throws Exception
    {
        Criteria c = new Criteria()
            .add(UserPeer.DOMAIN_ID, domain.getID())
            .add(UserPeer.TYPE, User.DOMAIN_TYPE);
        UserGroup g = null;
        try 
        {
            g = (UserGroup)UserPeer.doSelect(c).get(0);
        }
        catch (DoesNotExist e) 
        {
            throw new Error("Could not locate special domain user for " +
                            domain.getName());
        }
        return g;
    }

    /**
     * Gets the database key associated with the special user that
     * represents the group of all users in the host domain.
     */
    public static UserGroup getHostUser()
        throws Exception
    {
        Criteria c = new Criteria()
            .add(UserPeer.TYPE, User.HOST_TYPE);
        UserGroup g = null;
        try 
        {
            g = (UserGroup)UserPeer.doSelect(c).get(0);
        }
        catch (DoesNotExist e) 
        {
            throw new Error("Could not locate special host user!");
        }
        return g;
    }
    
    //
    // Ways of retrieving User objects.
    //

    /**
     * Returns a list of users corresponding to the specified list of IDs.
     *
     * @@param userIDs A list of primary keys of the users to retrieve.
     * @@return       The requested users.
     */
    public static List getInstances(List userIDs)
        throws Exception
    {
        List users = new ArrayList(userIDs.size());
        for (Iterator i = userIDs.iterator(); i.hasNext();)
        {
            String userID = (String)i.next();
            users.add(getInstance(userID));
        }
        return users;
    }

    /**
     * Returns the user with the specified ID.
     *
     * @@param userID The primary key of the user to retrieve.
     * @@return       The requested user.
     */
    public static User getInstance(String userID)
        throws Exception
    {
        User user = (User) cache.users.get(userID);
        if (user == null)
        {
            synchronized (cache.users)
            {
                user = (User) cache.users.get(userID);
                if (user == null)
                {
                    Criteria c = new Criteria(1).add(USER_ID, userID);
                    user = (User)PeerTool.getFirstBO
                        (UserPeer.doSelect(c), "User with ID " + userID);
                    cache.users.put(userID, user);
                }
            }
        }
        return user;
    }

    /**
     * Tries to get a user by login name, email address, and real name.
     * If all of these fail, throws an exception.
     *
     * @@param domain     The domain to look in.
     * @@param identifier The identifier of the user to retrieve.
     * @@return           The first matching user.
     *
     * @@exception DoesNotExist No matches for the provided identifier.
     */
    public static User getInstanceByIdentifier(Domain domain,
                                               String identifier)
        throws DoesNotExist, Exception
    {
        User u = null;
        try
        {
            u =  getInstanceByLoginName(domain, identifier);
        }
        catch (DoesNotExist loginNameEx)
        {
            try 
            {
                u = getInstanceByEmail(domain, identifier);
            }
            catch (DoesNotExist emailEx) 
            {
                try 
                {
                    u = getInstanceByRealName(domain, identifier);
                }
                catch (DoesNotExist realNameEx)
                {
                    throw new DoesNotExist("User identified by " + 
                                           identifier, "domain named " +
                                           domain.getName());
                }
            }
        }
        return u;
    }

    /**
     * Returns the user for a specified domain and login name.
     */
    public static User getInstanceByLoginName(Domain domain, String name)
        throws DoesNotExist, Exception
    {
        Criteria c = new Criteria()
            .add(UserPeer.LOGIN_NAME, name);
        checkThisAndHostDomain(c, domain);
        return (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                         "User with login name of " + name,
                                         domain);
    }

    /**
     * Returns the user for a specified domain and real name.
     */
    public static User getInstanceByRealName(Domain domain, String name)
        throws DoesNotExist, Exception
    {
        Criteria c = new Criteria()
            .add(UserPeer.REAL_NAME, name);
        checkThisAndHostDomain(c, domain);
        return (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                         "User named " + name, domain);
    }

    /**
     * Returns the user for a specified domain and email address.
     */
    public static User getInstanceByEmail(Domain domain, String email)
        throws DoesNotExist, Exception
    {
        Criteria c = new Criteria()
            .add(UserPeer.EMAIL, email);
        checkThisAndHostDomain(c, domain);
        return (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                         "User with email " + email, domain);
    }
    
    public static Criteria checkThisAndHostDomain(Criteria c, Domain domain)
        throws Exception
    {
        String[] domainIDs = 
        { 
            domain.getID(),
            ProjectPeer.getHost().getID() 
        };
        c.addIn(UserPeer.DOMAIN_ID, domainIDs);
        return c;
    }

    /**
     * Turns a string containing tokenized member designants into a list
     * of the corresponding users.
     */
    public static List parseDesignantList(String designantString,
                                          Domain domain, List errors)
        throws Exception
    {
        List designants = new ArrayList();
        StringTokenizer tok = new StringTokenizer(designantString);
        while (tok.hasMoreTokens())
        {
            String element = (String)tok.nextToken();

            //Get a record for the supposed user any way we can think
            //of--by login ID, email, and name. If all these fail,
            //add the nonexistant user to the validation errors.
            try
            {
                designants.add(UserPeer.getInstanceByIdentifier
                               (domain, element));
            }
            catch (DoesNotExist e)
            {
                errors.add(e.getMessage());
            }
        }

        return designants;
    }

    /**
     * Gets the special user for a given domain.
     */
    public static User getNobodyUser()
    {
        if (cache.nobodyUser == null)
        {
            try
            {
                Criteria c = new Criteria()
                    .add(TYPE, User.NOBODY_TYPE);
                cache.nobodyUser = (User) PeerTool.getFirstBO
                    (UserPeer.doSelect(c), "Nobody user");
            }
            catch (Exception e)
            {
                missingUserError(e, "nobody");
            }
        }
        return cache.nobodyUser;
    }

    /**
     * Gets the special super user.
     */
    public static User getSuperUser()
    {
        if (cache.superUser == null)
        {
            try
            {
                Criteria c = new Criteria()
                    .add(LOGIN_NAME, UserPeer.ROOT_LOGIN_NAME)
                    .add(DOMAIN_ID, ProjectPeer.getHost().getID());
                cache.superUser = (User) PeerTool.getFirstBO
                    (UserPeer.doSelect(c), "Root user");
            }
            catch (Exception e)
            {
                missingUserError(e, "super");
            }
        }
        return cache.superUser;
    }

    /**
     * Gets the special guest user.
     */
    public static User getAnonymousUser()
    {
        if (cache.anonymousUser == null)
        {
            try 
            {
                Criteria c = new Criteria()
                    .add(LOGIN_NAME, ANONYMOUS_LOGIN_NAME)
                    .add(DOMAIN_ID, ProjectPeer.getHost().getID());
                cache.anonymousUser = (User) PeerTool.getFirstBO
                    (UserPeer.doSelect(c), "Guest user");
            }
            catch (Exception e)
            {
                missingUserError(e, "anonymous");
            }
        }
        return cache.anonymousUser;
    }

    ////////////////////////////////////////////////////////////////
    // Mutator methods.
    ////////////////////////////////////////////////////////////////

    /**
     * Uses the database to encrypt the provided clear text password.
     *
     * @@param passwd The clear text password to encrypt.
     * @@return       The encrypted password.
     */
    public static final String encryptPassword(String passwd)
    {
        return MySQLPassword.makeScrambledPassword(passwd);
    }

    static class UserCache extends RegisterableCache
    {
        /**
         * Registered name of this cache.
         */
        private static final String NAME = "User cache";

        /**
         * Cache of users keyed by ID.
         */
        TableTrackingBufferCache users;

        /**
         * The super user (root).
         */
        User superUser;

        /**
         * The anonymous guest user.
         */
        User anonymousUser;

        /**
         * The nobody user.
         */
        User nobodyUser;

        /**
         * Minimum size of a cache.
         */
        private static final int MINIMUM_CACHE_SIZE = 50;

        /**
         * Registers with the {@@link org.tigris.helm.tool.cache.CacheRegistry}.
         */
        public UserCache()
            throws Exception
        {
            super("User cache", User.class);
            users = new TableTrackingBufferCache
                (TABLE_NAME, Attribute.FRACTIONAL_USER_CACHE_SIZE, 
                 MINIMUM_CACHE_SIZE);
        }

        public String describeContents()
        {
            StringBuffer buf = new StringBuffer("\n ");
            buf.append(users.describeParameters());
            if (superUser == null)
            {
                buf.append("No superuser cached.");
            }
            else
            {
                buf.append("Superuser: ").append(superUser.getLoginName());
            }
            buf.append("\n");

            if (anonymousUser == null)
            {
                buf.append(" No anonymous user cached.");
            }
            else
            {
                buf.append(" Anonymous user: ")
                    .append(anonymousUser.getLoginName());
            }
            buf.append("\n");

            if (superUser == null)
            {
                buf.append(" 'Nobody' user not cached.");
            }
            else
            {
                buf.append(" 'Nobody' user: ")
                    .append(nobodyUser.getLoginName());
            }
            buf.append("\n\n");
            buf.append(" Currently cached users by ID:\n");
            Object[] userKeys = users.keySet().toArray();
            for (int i = 0; i < userKeys.length; i++)
            {
                String key = (String) userKeys[i];
                buf.append("  ").append(key).append('\n');
            }
            return buf.toString();
        }

        /**
         * Invalidates the cache.
         *
         */
        public void invalidate()
            throws Exception
        {            
            if (DEBUG)
            {
                Log.debug("About to invalidate " + NAME + ":");
                Log.debug(describeContents());
            }
            super.invalidate();
            superUser = null;
            anonymousUser = null;
            nobodyUser = null;
            users.invalidate();
        }
    }

    /**
     * Overridden BasePeer method to do a delete and then to send out
     * an appropriate CacheInvalidationEvent.
     */
    public static void doDelete(Criteria c)
        throws Exception
    {
        BaseUserPeer.doDelete(c);
        uncache(User.class);
    }
}
@


1.51
log
@Corrected exception string and JavaDoc.
@
text
@d52 2
a53 3
import org.apache.turbine.om.*;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.util.BufferCache;
d55 1
a55 1
import org.apache.turbine.util.TurbineException;
d153 1
a153 1
     * @@exception TurbineException Invalid login.
d158 1
a158 1
        throws TurbineException, Exception
d168 1
a168 1
            throw new TurbineException(failString);
d173 1
a173 1
            throw new TurbineException(failString);
d183 1
a183 1
        throws TurbineException, Exception
d210 1
a210 1
     * @@exception TurbineException Invalid login.
d214 1
a214 1
        throws TurbineException, Exception
d224 1
a224 1
            throw new TurbineException(failString);
d229 1
a229 1
            throw new TurbineException(failString);
@


1.50
log
@Additions to permission server API for CVS-style checks.
@
text
@d217 1
a217 1
        String failString = "Invalid login";
a546 2
     *
     * @@exception Exception Database error occurred.
@


1.49
log
@Added MadCow library for Oracle support.
@
text
@d180 25
@


1.48
log
@Huge patch of the day: Got rid of redundant HELM_DOMAIN table. The project representation of the domain and the host is now the canonical one. Host and Domain now subclass ProjectGroup. The canonical representation of a project's membership in a domain group is now the corresponding mapping in HELM_PROJECT_PROJECTGROUP. Schema changes: No more HELM_DOMAIN table (obviously); no more DOMAIN_ID in HELM_PROJECT; HELM_USER and HELM_VC_VIEW now have foreign keys in HELM_PROJECT instead of HELM_DOMAIN.
@
text
@a53 1
import org.apache.turbine.util.db.pool.DBConnection;
d57 2
a58 1
import org.apache.turbine.services.db.TurbineDB;
d525 1
a525 2
    public static String encryptPassword(String passwd)
        throws Exception
d527 1
a527 26
        String encrypted = null;
        DBConnection dbc = null;
        try 
        {
            dbc = TurbineDB.getConnection();
            PreparedStatement stmt =
                dbc.getConnection().prepareStatement("select password(?)");
            stmt.setString(1, passwd);
            try 
            {
                ResultSet rset = stmt.executeQuery();
                if (rset.next()) 
                {
                    encrypted = rset.getString(1);
                }
            }
            finally 
            {
                if (stmt != null) stmt.close();
            }
        }
        finally 
        {
            TurbineDB.releaseConnection(dbc);
        }
        return encrypted;
@


1.47
log
@TTBC-bearing RegisterableCaches now describe the behavior of their TTBCs.
@
text
@d405 5
a409 2
        String[] domainIDs = { domain.getID(),
                               DomainPeer.getHostDomain().getID() };
d478 1
a478 1
                    .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
d501 1
a501 1
                    .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
@


1.46
log
@TableTrackingBufferCache now watches the attribute containing its fractional size, rather than the fractional size itself.
@
text
@d600 1
@


1.45
log
@Rearranged attribute constants and added generic host attribute-editing interface to AdminUtils.
@
text
@a585 6
         * Size of a cache as a percentage of the size of the table
         * it's tracking.  
         */
        private double fractionalCacheSize;

        /**
a591 4
            fractionalCacheSize = Double.parseDouble
                (AttributePeer.getHostAttribute
                 (Attribute.FRACTIONAL_USER_CACHE_SIZE));

d593 2
a594 11
                (TABLE_NAME, fractionalCacheSize, MINIMUM_CACHE_SIZE);
        }

        /**
         * Sets the fractional size of the caches.
         */
        public void setFractionalSize(double newSize)
            throws Exception
        {
            fractionalCacheSize = newSize;
            users.setFractionalSize(fractionalCacheSize);
@


1.44
log
@Added code to handle the default fractional size of TableTrackingBufferCaches as host attributes.
@
text
@d600 1
a600 1
                 (AttributePeer.FRACTIONAL_USER_CACHE_SIZE));
@


1.43
log
@Put TableTrackingBufferCache into practice; hopefully I can soon replace it with something smarter.
@
text
@d589 1
a589 1
        private static final double FRACTIONAL_CACHE_SIZE = .3;
d598 4
d603 11
a613 2
                (UserPeer.TABLE_NAME, FRACTIONAL_CACHE_SIZE, 
                 MINIMUM_CACHE_SIZE);
@


1.42
log
@Uncache with the BO class as descriptor, not the Peer class.
@
text
@a50 1
import java.rmi.RemoteException;
a122 1
            cache.users = new BufferCache(50);
d563 1
a563 1
        Map users;
d581 11
d595 1
a595 1
            throws RemoteException
d598 3
d663 1
a663 1
            users.clear();
@


1.41
log
@Got rid of the ugly and unneccessary asGroup() and getGroupInstance() methods.
@
text
@d663 1
a663 1
        uncache(UserPeer.class);
@


1.40
log
@use PeerTool to get better message when user does not exist.
@
text
@d240 3
a242 2
        try {
            g = ((User)UserPeer.doSelect(c).get(0)).asGroup();
d244 2
a245 1
        catch (DoesNotExist e) {
d262 3
a264 2
        try {
            g = ((User)UserPeer.doSelect(c).get(0)).asGroup();
d266 2
a267 1
        catch (DoesNotExist e) {
a441 32
    }

    //
    // Ways of retrieving UserGroup objects. These suck.
    //
    public static UserGroup getGroupInstance(String userID)
        throws Exception
    {
        int uid = Integer.parseInt(userID);
        Criteria criteria = new Criteria();
        if (uid > 0) {
            criteria.add(UserPeer.USER_ID, uid);
        }
        return getFirstUserGroup(criteria);
    }

    public static UserGroup getGroupInstanceByName(Domain domain, String name)
        throws Exception
    {
        int domainID = Integer.parseInt(domain.getDomainId().toString());
        Criteria criteria = new Criteria();
        criteria.add(UserPeer.LOGIN_NAME, name);
        if (domainID > 0)
            criteria.add( UserPeer.DOMAIN_ID, domainID );
        return getFirstUserGroup(criteria);
    }

    private static final UserGroup getFirstUserGroup(Criteria criteria)
        throws DoesNotExist, Exception
    {
        return (UserGroup)PeerTool.getFirstBO(doSelect(criteria),
                                              "User group");
@


1.39
log
@Added ability for caches to keep track of number of invalidations.
@
text
@d308 3
a310 1
                    user = retrieveByPK(new NumberKey(userID));
@


1.38
log
@Sanified the exception handling.
@
text
@d584 5
d667 1
a667 1
        {
d670 1
a670 1
                Log.debug("About to invalidate user cache.");
d673 1
@


1.37
log
@Added convenience method for turning lists of userIDs into lists of users.
@
text
@d64 1
a64 1
import org.tigris.helm.tool.cache.RegisterableCache;
d124 1
d126 1
a126 1
        catch (RemoteException e)
a130 1
        cache.users = new BufferCache(50);
d661 1
@


1.36
log
@Factored out code for turning strings into lists of users.
@
text
@d274 18
@


1.35
log
@Big cleanup of cache self-descriptions. Also added an admin tool to do manual selective cache invalidation.
@
text
@d389 31
@


1.34
log
@Invalidate user cache on user deletion.
@
text
@d560 1
a560 1
            super("User peer", User.class);
d565 1
a565 1
            StringBuffer buf = new StringBuffer();
d572 1
a572 1
                buf.append("Superuser: " + superUser.getLoginName());
d578 1
a578 1
                buf.append("No anonymous user cached.");
d582 2
a583 1
                buf.append("Anonymous user: " + anonymousUser.getLoginName());
d589 1
a589 1
                buf.append("Nobody user not cached.");
d593 2
a594 1
                buf.append("Nobody user: " + nobodyUser.getLoginName());
d596 2
a597 2
            buf.append("\n");
            buf.append("Currently cached users: ");
d602 1
a602 2
                if (i > 0) buf.append(", ");
                buf.append(key);
@


1.33
log
@Finally got rid of REQUESTABLE and DENOTES_OWNER fields in HELM_ROLE.
@
text
@d623 11
@


1.32
log
@Display the correct users. Also display login name when avaliable.
@
text
@a136 11

    /**
     * Overridden BasePeer method to do a delete and then to send out
     * an appropriate CacheInvalidationEvent.
     */
    public static void doDelete(Criteria c)
        throws Exception
    {
        BaseUserPeer.doDelete(c);
        uncache(User.class);
    }
@


1.31
log
@Cleanup of caching and cache invalidation.
@
text
@d583 1
a583 1
                buf.append("Superuser: " + superUser.getID());
d593 1
a593 1
                buf.append("Anonymous user: " + superUser.getID());
d603 1
a603 1
                buf.append("Nobody user: " + nobodyUser.getID());
d605 1
a605 1
            buf.append("\n\n");
@


1.30
log
@Repositioned import of TurbineException.
@
text
@d146 1
a146 1
        uncache(UserPeer.class);
d571 44
a614 1
            super(User.class);
d625 2
a626 15
                StringBuffer buf =
                    new StringBuffer("UserPeer invalidating cache: ");
                Object[] userKeys = users.keySet().toArray();
                for (int i = 0; i < userKeys.length; i++)
                {
                    String key = (String) userKeys[i];
                    if (i > 0) buf.append(", ");
                    buf.append(key);
                    users.remove(key);
                }
                Log.debug(buf.toString());
            }
            else
            {
                users.clear();
d631 1
@


1.29
log
@Moved clustering features out of RMI and into the database.
@
text
@a55 1
import org.apache.turbine.util.TurbineException;
d58 1
@


1.28
log
@Fixed up cluster singleton interface and made the task runner into a cluster singleton.
@
text
@d571 1
a571 1
            super(UserPeer.class);
a573 2


d575 1
a575 1
         * Invalidates some portion of the cache.
a576 3
         * @@param invalidationDescriptor Description of the invalidation that 
         *                               should occur, or <code>null</code> for
         *                               complete invalidation.
d578 1
a578 1
        public void invalidate(Object invalidationDescriptor)
d580 1
a580 1
            if (affectedByInvalidation(invalidationDescriptor))
d582 4
a585 15
                if (DEBUG)
                {
                    StringBuffer buf =
                        new StringBuffer("UserPeer invalidating cache: ");
                    Object[] userKeys = users.keySet().toArray();
                    for (int i = 0; i < userKeys.length; i++)
                    {
                        String key = (String) userKeys[i];
                        if (i > 0) buf.append(", ");
                        buf.append(key);
                        users.remove(key);
                    }
                    Log.debug(buf.toString());
                }
                else
d587 4
a590 1
                    users.clear();
d592 1
a592 3
                superUser = null;
                anonymousUser = null;
                nobodyUser = null;
d594 1
a594 14
        }

        /**
         * This cache is invalidated whenever a User is changed.
         */
        protected final boolean affectedByInvalidation
            (Object invalidationDescriptor)
        {
            boolean affects = false;
            if (invalidationDescriptor == null)
            {
                affects = true;
            }
            else if (invalidationDescriptor instanceof String)
d596 1
a596 5
                String objectClassName = (String)invalidationDescriptor;
                if (objectClassName.equals(User.class.getName()))
                {
                    affects = true;
                }
d598 3
a600 1
            return affects;
@


1.27
log
@Send CacheInvalidationEvents on deletes, and on saves of objects which are not themselves cached but which invalidate other caches when they are changed.
@
text
@a499 1

@


1.26
log
@Old uncache() begone!
@
text
@d139 11
@


1.25
log
@Added semi-selective cache invalidation which invalidates particular caches on a write instead of all the caches.
@
text
@a147 24
     * Removes a user from the cache.
     */
    public static void uncache(User user)
    {
        if (user.equals(cache.superUser))
        {
            cache.superUser = null;
        }
        else if (user.equals(cache.anonymousUser))
        {
            cache.anonymousUser = null;
        }
        else if (user.equals(cache.nobodyUser))
        {
            cache.nobodyUser = null;
        }

        if (cache.users.containsKey(user.getID()))
        {
            cache.users.remove(user.getID());
        }
    }

    /**
@


1.24
log
@SequencedHashtable, BufferCache, and BaseUnicastRemoteService have been moved into Turbine.  Changed references accordingly.
@
text
@d588 2
d599 1
a599 1
            if (invalidationDescriptor == null)
d623 10
a632 1
            else
d634 9
a642 3
                throw new UnsupportedOperationException
                    ("UserCache.invalidate() does not " + 
                     "currently support a descriptor");
d644 1
@


1.23
log
@Removed extraneous DEBUG.
@
text
@d50 1
a52 2
import java.sql.*;

d57 1
@


1.22
log
@Corrected error message.
@
text
@a596 1
            Log.debug("Invalidate!");
@


1.21
log
@Leveraged new RegisterableCache ctor.
@
text
@d127 1
a127 1
            throw new RuntimeException("Unable to create user cache" +
@


1.20
log
@Use a key other than Class.
@
text
@d123 1
a123 1
            cache = new UserCache(UserPeer.class.getName());
d582 1
a582 1
        public UserCache(String key)
d585 1
a585 1
            super(key);
@


1.19
log
@Make CacheRegistry a Turbine service.
@
text
@d123 1
a123 1
            cache = new UserCache(UserPeer.class);
d582 1
a582 1
        public UserCache(Class key)
@


1.18
log
@Added DEBUG logging of cache invalidation.
@
text
@d597 1
@


1.17
log
@Corrected UnsupportedOperationException error message.
@
text
@d75 5
d599 18
a616 1
                users.clear();
@


1.16
log
@Switched to Leonard's suggested method of invalidation.
@
text
@d602 1
a602 1
                    ("SimpleRegisterableCache.invalidate() does not " + 
@


1.15
log
@JavaDoc corrections.
@
text
@d594 1
a594 5
                Iterator keys = users.keySet().iterator();
                while (keys.hasNext())
                {
                    users.remove(keys.next());
                }
@


1.14
log
@Changed to less retard...I mean, "more descriptive" class name.
@
text
@d555 1
a555 1
         * Cache of users.
d575 1
a575 1
         * Registers with the {@@link org.tigris.helm.tool.CacheRegistry}.
@


1.13
log
@* Fixed compile time errors in uncache(User user).

* Removed unnecessary local var in MyRegisterableCache.invalidate().
@
text
@d77 1
a77 1
    private static MyRegisterableCache cache;
d118 1
a118 1
            cache = new MyRegisterableCache(UserPeer.class);
d552 1
a552 1
    static class MyRegisterableCache extends RegisterableCache
d577 1
a577 1
        public MyRegisterableCache(Class key)
@


1.12
log
@* Moved known User object retrieval down into accessor methods.  Still
performing retrieval on class loading.

* Enhanced uncache(User) to check the User object to uncache against
the known Users in addition to BufferCache of users.

* Dropped Exception from known User accessor methods in favor of
missingUserError() method.
@
text
@d147 1
a147 1
        if (user.equals(superUser))
d149 1
a149 1
            superUser = null;
d151 1
a151 1
        else if (user.equals(anonymousUser))
d153 1
a153 1
            anonymousUser = null;
d155 1
a155 1
        else if (user.equals(nobodyUser))
d157 1
a157 1
            nobodyUser = null;
d594 2
a595 2
                Iterator iter = users.keySet().iterator();
                while (iter.hasNext())
d597 1
a597 2
                    Object key = iter.next();
                    users.remove(key);
@


1.11
log
@First pass at a per-Peer cache registerable with a singleton used to
communicate with other JVMs.
@
text
@d128 3
a130 39
        Criteria c;

        try
        {
            c = new Criteria()
                .add(LOGIN_NAME, UserPeer.ROOT_LOGIN_NAME)
                .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
            cache.superUser = (User)PeerTool.getFirstBO(UserPeer.doSelect(c), 
                                                        "Root user");
        }
        catch (Exception e)
        {
            missingUserError(e, "super");
        }

        try 
        {
            c = new Criteria()
                .add(LOGIN_NAME, ANONYMOUS_LOGIN_NAME)
                .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
            cache.anonymousUser =
                (User)PeerTool.getFirstBO(UserPeer.doSelect(c), "Guest user");
        }
        catch (Exception e)
        {
            missingUserError(e, "anonymous");
        }

        try
        {
            c = new Criteria()
                .add(TYPE, User.NOBODY_TYPE);
            cache.nobodyUser = (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                                         "Nobody user");
        }
        catch (Exception e)
        {
            missingUserError(e, "nobody");
        }
d147 13
a443 1
        throws Exception
d445 14
a465 1
        throws Exception
d467 15
a488 1
        throws Exception
d490 15
@


1.10
log
@Cache other special users like we cache the anonymous/guest user.
@
text
@d50 1
d64 1
d75 1
a75 1
     * Cache of users.
d77 1
a77 16
    private static Map users = new BufferCache(50);

    /**
     * The super user (root).
     */
    private static User superUser;

    /**
     * The anonymous guest user.
     */
    private static User anonymousUser;

    /**
     * The nobody user.
     */
    private static User nobodyUser;
d116 11
d135 2
a136 2
            superUser = (User)PeerTool.getFirstBO(UserPeer.doSelect(c), 
                                                  "Root user");
d148 2
a149 2
            anonymousUser = (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                                      "Guest user");
d160 2
a161 2
            nobodyUser = (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                                   "Nobody user");
d183 1
a183 1
        if (users.containsKey(user.getID()))
d185 1
a185 1
            users.remove(user.getID());
d324 1
a324 1
        User user = (User) users.get(userID);
d327 1
a327 1
            synchronized (users)
d329 1
a329 1
                user = (User) users.get(userID);
d333 1
a333 1
                    users.put(userID, user);
d469 1
a469 1
        return nobodyUser;
d478 1
a478 1
        return superUser;
d487 1
a487 1
        return anonymousUser;
d532 61
@


1.10.6.1
log
@Made getDomainUser work for the host domain.
@
text
@a279 4
        if (domain.isHost())
        {
            return getHostUser();
        }
d284 1
a284 2
        try 
        {
d287 1
a287 2
        catch (Exception e) 
        {
@


1.9
log
@Cache the anonymous user.
@
text
@d78 5
d87 5
d120 1
a120 1
     * Static initializer; initializes the filterableFields data structure.
d128 17
d147 1
a147 1
            Criteria c = new Criteria()
a149 1

d153 6
a158 1
        catch (Exception e) 
d160 4
a163 1
            throw new Error("Could not get anonymous user!");
d165 13
d471 1
a471 10
        Criteria c = new Criteria()
            .add(TYPE, User.NOBODY_TYPE);
        User u = null;
        try {
            u = (User)PeerTool.getFirstBO(UserPeer.doSelect(c), "Nobody user");
        }
        catch (DoesNotExist e) {
            throw new Error("Could not locate special 'nobody' user!");
        }
        return u;
a475 2
     * <p>
     * TODO: Remove db hit via caching.
d480 1
a480 9
        Criteria c = new Criteria()
            .add(LOGIN_NAME, UserPeer.ROOT_LOGIN_NAME)
            .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
        try {
            return (User)PeerTool.getFirstBO(UserPeer.doSelect(c), "Root user");
        }
        catch (DoesNotExist e) {
            throw new Error("Super user cannot be found!");
        }
a484 2
     * <p>
     * TODO: Remove db hit via caching.
@


1.8
log
@Added new assertValidLogin() overload for Manoj.
@
text
@d77 5
d118 13
d463 1
a463 10
        Criteria c = new Criteria()
            .add(LOGIN_NAME, UserPeer.ANONYMOUS_LOGIN_NAME)
            .add(DOMAIN_ID, DomainPeer.getHostDomain().getID());
        try {
            return (User)PeerTool.getFirstBO(UserPeer.doSelect(c),
                                             "Guest user");
        }
        catch (DoesNotExist e) {
            throw new Error("Guest user cannot be found!");
        }
@


1.7
log
@Corrected JavaDoc.
@
text
@d133 1
d147 34
a180 1
        } catch (DoesNotExist e) {
@


1.6
log
@Renamed uncacheUser() to uncache().
@
text
@d248 1
a248 1
     * @@param identifier The primary key of the user to retrieve.
@


1.5
log
@Corrected handling of critical section in getInstance().
@
text
@d118 1
a118 1
    public static void uncacheUser(User user)
@


1.4
log
@Got rid of debug comment.
@
text
@a60 1
import org.tigris.helm.om.*;
a71 1

d113 1
a113 1
    };    
d227 2
a228 2
        User user = null;
        synchronized (users)
d230 1
a230 1
            if (users.containsKey(userID))
d232 6
a237 1
                user = (User)users.get(userID);
a238 5
            else
            {
                user = retrieveByPK(new NumberKey(userID));
                users.put(userID, user);
            }        
@


1.3
log
@Implemented caching of users.
@
text
@a234 1
                Log.debug("User " + user.getLoginName() + " is cached.");
@


1.2
log
@Corrected regex madness for Torque upgrade.  -dlr
@
text
@d57 1
d63 1
a63 1
import org.tigris.helm.tool.PeerTool;
d74 5
d118 11
d229 15
a243 1
        return UserPeer.retrieveByPK(new NumberKey(userID));
@


1.1
log
@Moved in from peer package to handle Torque changes. -dlr
@
text
@a59 1

@

