/********************************************************************
 * Copyright © 2004 VHA. All rights reserved
 ********************************************************************/
package gov.va.med.fw.security.jaas;

import java.lang.reflect.Constructor;
import java.util.Properties;

import javax.security.auth.login.LoginException;

import org.acegisecurity.AcegiSecurityException;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationServiceException;
import org.acegisecurity.providers.jaas.LoginExceptionResolver;

/**
 * LoginExceptionMapper implements LoginExceptionResolver, an interface from
 * AcegiSecurity, that maps the JAAS LoginException's to AcegiSecurityException's.
 * 
 * JAAS throws LoginException where as Acegi authentication Manager throws
 * Authentication exception. So, this class provides a mapping and returns
 * a AcegiSecurityException that is mapped to a given LoginException.
 * 
 * @author DNS   MANSOG
 * @date Apr 27, 2005 5:47:48 PM
 */
public class LoginExceptionMapper implements LoginExceptionResolver {
    Properties exceptionMap = new Properties();

    /**
     * Returns a exception map properties.
     * Properties key values are fully qualified name of LoginException
     * Values of the properties are fully qualified name of AcegiSecurityException
     * that is mapped to a key.
     */
    public Properties getExceptionMap() {
        return exceptionMap;
    }

    /**
     * Setter method to set a exception map as properties.
     * Keys of the properties Object should be the fully qualified 
     * name of a specific LoginException, where as values are the 
     * fully qualified name of the AcegiSecurityException that is mapped 
     * to the LoginException provided in the key.
     * 
     * @param exceptionMap - exception map as properties.
     */
    public void setExceptionMap(Properties exceptionMap) {
        this.exceptionMap = exceptionMap;
    }

    /*
     * (non-Javadoc)
     * 
     * @see net.sf.acegisecurity.providers.jaas.LoginExceptionResolver#resolveException(javax.security.auth.login.LoginException)
     */
    public AcegiSecurityException resolveException(LoginException le) {
        AuthenticationException acegiEx = new AuthenticationServiceException(le.getMessage(), le);
        String acegiExceptionName = exceptionMap.getProperty(le.getClass().getName(), AuthenticationException.class.getName());
        try {
            Class acegiExceptionClass = Class.forName(acegiExceptionName);
            if (AuthenticationException.class.isAssignableFrom(acegiExceptionClass)) {
                 Constructor exConst;
                 Object[] params;
                try {
                    Class[] consType = new Class[] {
                            String.class, Throwable.class };
                   exConst = acegiExceptionClass.getConstructor(consType);
                   params = new Object[] {
                           le.getMessage(), le.getCause() };
                } catch (NoSuchMethodException ce) {
                    Class[] consType = new Class[] {
                            String.class};
                   exConst = acegiExceptionClass.getConstructor(consType);
                   params = new Object[] {le.getMessage()};
                }
                acegiEx = (AuthenticationException) exConst.newInstance(params);
            }
        } catch (Exception e) {
            return acegiEx;
        }
        return acegiEx;
    }
}