/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.kernel.security;

import com.arsdigita.kernel.UserAuthentication;
import com.arsdigita.domain.DataObjectNotFoundException;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
import org.apache.log4j.Logger;

/**
 * Checks a username and password in the database using
 * <code>com.arsdigita.kernel.UserAuthentication</code>.
 *
 * @author Sameer Ajmani
 **/
public class LocalLoginModule extends PasswordLoginModule {

    public static final String versionId = "$Id: //core-platform/dev/src/com/arsdigita/kernel/security/LocalLoginModule.java#9 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";
    private static final Logger s_log =
        Logger.getLogger(LocalLoginModule.class.getName());

    // fields set by initialize()
    private Subject m_subject;
    private CallbackHandler m_handler;
    private Map m_shared;
    private Map m_options;

    // implements LoginModule
    public void initialize(Subject subject,
                           CallbackHandler handler,
                           Map shared,
                           Map options) {
        super.initialize(subject, handler, shared, options);
        m_handler = handler;
        m_subject = subject;
        m_shared  = shared;
        m_options = options;
        // TODO: support "debug" option
    }

    /**
     * Retrieves the user account from the database and checks the password
     * against the saved value.
     *
     * @throws AccountNotFoundException if the account does not exist.
     * @throws FailedLoginException if the password is invalid.
     * @throws LoginException if an error occurs.
     **/
    protected void checkPassword(String username, char[] password)
        throws LoginException {

        s_log.debug("START checkPassword");
        UserAuthentication auth;
        try {
            s_log.debug("retreiving UserAuthentication");
            auth = UserAuthentication.retrieveForLoginName(username);
        } catch (DataObjectNotFoundException e) {
            throw new AccountNotFoundException("no such user: "+username, e);
        }
        // FIXME: do not create string from password, since cannot clear
        // from memory!  Replace below param with char[] and create a string
        // of the password hash for the database
        s_log.debug("checking password");
        if (!auth.isValidPassword(new String(password))) {
            s_log.debug("FAILURE checkPassword: bad password");
            throw new FailedLoginException("bad username/password");
        }

        s_log.debug("SUCCESS checkPassword");
    }

    /**
     * Trivial implementation; does nothing.
     *
     * @return <code>true</code>.
     **/
    public boolean commit() throws LoginException {
        s_log.debug("commit");
        return true;
    }

    /**
     * Trivial implementation; does nothing.
     *
     * @return <code>true</code>.
     **/
    public boolean abort() throws LoginException {
        s_log.debug("abort");
        return true;
    }

    /**
     * Trivial implementation; does nothing.
     *
     * @return <code>true</code>.
     **/
    public boolean logout() throws LoginException {
        s_log.debug("logout");
        return true;
    }
}
