package com.tsystems.vla.services;

import java.util.Hashtable;
import java.io.*;

import org.apache.turbine.services.security.UserManager;
import org.apache.turbine.om.security.User;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.util.security.DataBackendException;
import org.apache.turbine.util.security.UnknownEntityException;
import org.apache.turbine.util.security.EntityExistsException;
import org.apache.turbine.util.security.PasswordMismatchException;
import org.apache.turbine.om.security.TurbineUser;
import org.apache.turbine.util.Log;
import org.apache.turbine.services.resources.TurbineResources;

import javax.naming.Context;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.DirContext;
import javax.naming.directory.Attributes;
import javax.naming.NamingException;
import javax.naming.AuthenticationException;


/**
 * Class ClassName is used to <enter description>
 *
 * @author Bernhard Hirschmann
 * @version $Revision: 1.1 $
 */
public class LDAPUserService implements UserManager
{
    /**
     * Authenticate an User with the specified password. If authentication
     * is successful the method returns nothing. If there are any problems,
     * exception was thrown.
     *
     * @param user an User object to authenticate.
     * @param password the user supplied password.
     * @exception PasswordMismatchException if the supplied password was
     *            incorrect.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
    public void authenticate(User user, String password)
        throws PasswordMismatchException, UnknownEntityException, DataBackendException
    {
		Log.note("authentificate "+user.getUserName()+ " password "+password);
        //if(!user.getPassword().equals(password)) {
        //		throw new PasswordMismatchException ("Bad Password!");
        //	}

        if (password == null || password.length() < 1)
        {
            throw new PasswordMismatchException("invalid password");
        }

        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, TurbineResources.getString("initial_context_factory"));
        env.put(Context.PROVIDER_URL, TurbineResources.getString("provider_url"));

        // authenticate
        env.put(Context.SECURITY_AUTHENTICATION, TurbineResources.getString("security_authentication"));
        env.put(Context.SECURITY_PRINCIPAL, "uid=" + user.getUserName() +
                                            ", o=" + TurbineResources.getString("security_principal_o_detail") +
                                            ", c=" + TurbineResources.getString("security_principal_c") +
                                            ", o=" + TurbineResources.getString("security_principal_o")
                                          );

        env.put(Context.SECURITY_CREDENTIALS, password);

        System.out.println("Checking user: "+user.getUserName());

        try
        {
            // Create the initial directory context
            DirContext ctx = new InitialDirContext(env);

            System.out.println("authentication for "+user.getUserName()+" successfull");

        } catch (AuthenticationException e) {
            System.out.println("AuthenticationException: "+e.getMessage());
            throw new PasswordMismatchException(e.getMessage());
        } catch (NamingException e) {
            System.out.println("NamingException: "+e.getMessage());
            throw new UnknownEntityException(e.getMessage());
        } catch ( Exception e ) {
            System.out.println("Exception: "+e.getMessage());
            throw new DataBackendException(e.getMessage());
        }
    }

    /**
     * Retrieve a user from persistent storage using username as the
     * key, and authenticate the user. The implementation may chose
     * to authenticate to the server as the user whose data is being
     * retrieved.
     *
     * @param username the name of the user.
     * @param password the user supplied password.
     * @return an User object.
     * @exception PasswordMismatchException if the supplied password was
     *            incorrect.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
    public User retrieve(String username, String password)
        throws PasswordMismatchException, UnknownEntityException, DataBackendException
    {
        User user = retrieve(username);
		if(user==null) {
			throw new UnknownEntityException ("User not found");
		}
		authenticate(user, password);
		return user;
    }

   /**
     * Retrieve a user from persistent storage using username as the
     * key.
     *
     * @param username the name of the user.
     * @return an User object.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
    public User retrieve(String username) throws UnknownEntityException, DataBackendException
    {
        TurbineUser user = null;
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, TurbineResources.getString("initial_context_factory"));
        env.put(Context.PROVIDER_URL, TurbineResources.getString("provider_url"));

        try
        {
            // Create the initial directory context
            DirContext ctx = new InitialDirContext(env);

            // Ask for all attributes of the object
            Attributes attrs = ctx.getAttributes( "uid="+username+
                                                  ", o=" + TurbineResources.getString("security_principal_o_detail") +
                                                  ", c=" + TurbineResources.getString("security_principal_c") +
                                                  ", o=" + TurbineResources.getString("security_principal_o")
                                                  );

            // create a new User
            user = new TurbineUser();
            user.setUserName(username);
            user.setPerm(user.CONFIRM_VALUE , user.CONFIRM_DATA);
            user.setPerm(user.FIRST_NAME , attrs.get("givenname").get());
            user.setPerm(user.LAST_NAME, attrs.get("sn").get());
            String str = (String) attrs.get("mailalternateaddress").get();
            if ( str != null && str.length() > 0)
            {
                user.setPerm(user.EMAIL, str);
            }
            else
            {
                str = (String) attrs.get("mail").get();
                if ( str != null && str.length() > 0)
                {
                    user.setPerm(user.EMAIL, str);
                }
            }

        } catch (NamingException e) {
            System.out.println("NamingException: "+e.getMessage());
            throw new UnknownEntityException(e.getMessage());
        } catch ( Exception e ) {
            System.out.println("Exception: "+e.getMessage());
            throw new DataBackendException(e.getMessage());
        }
        return user;
    }

    /**
     * Retrieve a set of users that meet the specified criteria.
     *
     * As the keys for the criteria, you should use the constants that
     * are defined in {@link User} interface, plus the names
     * of the custom attributes you added to your user representation
     * in the data storage. Use verbatim names of the attributes -
     * without table name prefix in case of DB implementation.
     *
     * @param criteria The criteria of selection.
     * @return a List of users meeting the criteria.
     * @throws DataBackendException if there is a problem accessing the
     *         storage.
     */
    public User[] retrieve(Criteria criteria) throws DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method retrieve() not yet implemented.");
    }

    /**
     * Check whether a specified user's account exists.
     *
     * The login name is used for looking up the account.
     *
     * @param user The user to be checked.
     * @return true if the specified account exists
     * @throws DataBackendException if there was an error accessing the data backend.
     */
    public boolean accountExists(User user) throws DataBackendException {
        return user!=null;
    }

    /**
     * Check whether a specified user's account exists.
     *
     * The login name is used for looking up the account.
     *
     * @param usename The name of the user to be checked.
     * @return true if the specified account exists
     * @throws DataBackendException if there was an error accessing the data backend.
     */
    public boolean accountExists(String username) throws DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method not yet implemented.");
    }

    /**
     * Save an User object to persistent storage. User's record is
     * required to exist in the storage.
     *
     * @param user an User object to store.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
  public void store(User user) throws UnknownEntityException, DataBackendException {
    // dont store - simply do nothing
  }

    /**
     * Creates new user account with specified attributes.
     *
     * @param user the object describing account to be created.
     * @throws DataBackendException if there was an error accessing the data backend.
     * @throws EntityExistsException if the user account already exists.
     */
    public void createAccount(User user, String initialPassword) throws EntityExistsException, DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method retrieve() not yet implemented.");
    }

    /**
     * Removes an user account from the system.
     *
     * @param user the object describing the account to be removed.
     * @throws DataBackendException if there was an error accessing the data backend.
     * @throws UnknownEntityException if the user account is not present.
     */
    public void removeAccount(User user) throws UnknownEntityException, DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method retrieve() not yet implemented.");
    }

    /**
     * Change the password for an User.
     *
     * @param user an User to change password for.
     * @param oldPassword the current password suplied by the user.
     * @param newPassword the current password requested by the user.
     * @exception PasswordMismatchException if the supplied password was
     *            incorrect.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
    public void changePassword(User user, String oldPassword, String newPassword)
        throws PasswordMismatchException, UnknownEntityException, DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method retrieve() not yet implemented.");
  }

    /**
     * Forcibly sets new password for an User.
     *
     * This is supposed by the administrator to change the forgotten or
     * compromised passwords. Certain implementatations of this feature
     * would require administrative level access to the authenticating
     * server / program.
     *
     * @param user an User to change password for.
     * @param password the new password.
     * @exception UnknownEntityException if the user's record does not
     *            exist in the database.
     * @exception DataBackendException if there is a problem accessing the
     *            storage.
     */
    public void forcePassword(User user, String password) throws UnknownEntityException, DataBackendException {
        /**@todo: Implement this org.apache.turbine.services.security.UserManager method*/
        throw new java.lang.UnsupportedOperationException("Method retrieve() not yet implemented.");
    }
}
//
// Configuration Management Information:
// -------------------------------------
// $Id: LDAPUserService.java,v 1.1 2001/07/26 14:49:00 wreissen Exp $
//
// Version History:
// ----------------
// $Log: LDAPUserService.java,v $
// Revision 1.1  2001/07/26 14:49:00  wreissen
// initial version of portal contents.
//
// Revision 1.4  2001/07/10 14:37:01  bhirschm
// empty password bug fixed
//
// Revision 1.3  2001/07/10 13:52:57  mgiebele
// store() simply does nothing
//
// Revision 1.2  2001/07/10 13:49:23  mgiebele
// accountExists() implemented
//
// Revision 1.1  2001/07/10 11:27:18  bhirschm
// no message
//
// Revision 1.1  2001/07/06 07:00:45  mgiebele
// simple User Service implemented
//
//
// ***********************************************************************************
