/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/urm/org/apache/slide/urm/authenticator/URMAuthenticator.java,v 1.4 2005/03/02 10:53:34 eckehard Exp $
 * $Revision: 1.4 $
 * $Date: 2005/03/02 10:53:34 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.slide.urm.authenticator;

import java.io.IOException;
import java.util.Properties;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.SAXException;

import org.apache.slide.urm.URMException;
import org.apache.slide.urm.common.URMCloseConnectionException;
import org.apache.slide.urm.common.URMConfigurator;
import org.apache.slide.urm.common.URMPrincipal;
import org.apache.slide.urm.common.URMConfigurationException;
import org.apache.slide.urm.common.impl.URMConfiguratorXML;
import org.apache.slide.urm.utils.URMClassInstantiator;
import org.apache.slide.urm.utils.messagelogger.MessageLogger;
import org.apache.slide.urm.accesscontroler.impl.URMAclAdministratorImpl;
import org.apache.slide.urm.authenticator.impl.URMGuestAdministratorImpl;
import org.apache.slide.urm.common.impl.URMPrincipalImpl;

/**
 * The user authentication in the URM module is possible only via this interface.
 * It can create a URMPrincipal object that represents an authenticated user or a URMAdministrator
 * with the permissions of the specified user.
 * It can be created using the URMAuthenticatorFactory.
 *
 * @author eckehard.hermann@softwareag.com
 * @author dieter.kessler@softwareag.com
 * @author zsolt.sasvarie@softwareag.com
 */
public abstract class URMAuthenticator {
    
    private static org.apache.log4j.Logger msLogger =
        org.apache.log4j.Logger.getLogger(URMAuthenticator.class.getName());
        
    private static final String AUTHENTICATOR_CONFIGURATOR = "Authenticator";
    protected URMConfigurator conf = null;
    protected static boolean sensitive = true;
    
    /**
     * Creates a new factory using the specified configuration.
     *
     * @param inConf that should be used to create the factory and
     *          will be used to create further object using the this factory
     *
     * @return URMAuthenticator object
     *
     * @throws URMConfigurationException if a wrong configuration was passed
     *
     * @throws URMException if an unpredictable internal error occurs
     */
    public static final URMAuthenticator newInstance(URMConfigurator inConf)
            throws URMConfigurationException, URMException {
        if (inConf == null)
            throw new URMConfigurationException(MessageLogger.getAndLogMessage(
                                msLogger, "URMCOC0017", AUTHENTICATOR_CONFIGURATOR));
            
        URMConfigurator conf = inConf;
        if (msLogger.isInfoEnabled())
            MessageLogger.logMessage(msLogger, "URMCOI0016", AUTHENTICATOR_CONFIGURATOR, conf.getName());
        if (!AUTHENTICATOR_CONFIGURATOR.equals(conf.getName()))
            conf = conf.getSubConfigurator(AUTHENTICATOR_CONFIGURATOR);
        Properties props = conf.getProperties();
        String class_name = null;
        if (props == null || ( class_name = props.getProperty("Class"))  == null) {
            throw new URMConfigurationException(MessageLogger.getAndLogMessage(
                                    msLogger, "URMCOC0002", "Class", AUTHENTICATOR_CONFIGURATOR));
        }
        
        Object params[] = {conf};
        try {
            URMAuthenticator ator = (URMAuthenticator)URMClassInstantiator.newInstance(class_name, params);
            if (msLogger.isInfoEnabled())
                MessageLogger.logMessage(msLogger, "URMCOI0018", AUTHENTICATOR_CONFIGURATOR);
            return ator;
        } catch (URMException e) {
            throw new URMConfigurationException(MessageLogger.getAndLogMessage(msLogger, "F", e));
        }
    }
    
    public static boolean isCaseSensitive() {
        return sensitive;
    }
    
    /**
     * Creates a new factory using the default XML configuration and
     * the java System property settings or the default config file,
     * if the paramerters are not defined.
     *
     * @return URMAuthenticator object
     *
     * @throws URMConfigurationException if a wrong configuration was passed
     *
     * @throws URMException if an unpredictable internal error occurs
     */
    public static final URMAuthenticator newInstance()
            throws URMConfigurationException, URMException {
                
        try {
            URMConfigurator conf = URMConfiguratorXML.newConfigfileConfigurator();
            return newInstance(conf);
        } catch (ParserConfigurationException e) {
            throw new URMConfigurationException(msLogger, "F", e);
        } catch (SAXException e) {
            throw new URMConfigurationException(msLogger, "F", e);
        } catch (IOException e) {
            throw new URMConfigurationException(msLogger, "F", e);
        }
    }
    
    /**
     * Tries to authenticate the specified user.
     *
     * @param user name of the user whose properties are searched
     * @param password the user's current password
     *
     * @return URMPrincipal the principal representing the user if the
     *                      authentication was successful
     *
     * @throws URMAuthenticationException if the authentication fails
     *
     * @throws URMException if an unpredictable internal error occurs.
     */
    public abstract URMPrincipal authenticateUser(String user, char[] password)
        throws URMAuthenticationFailsException, URMAuthenticatorException,
                URMConfigurationException, URMCloseConnectionException;
            
    /**
     * Tries to authenticate the specified user.
     *
     * @param user name of the user whose properties are searched
     * @param domain the domain against the operation is executed
     * @param password the user's current password
     *
     * @return URMPrincipal the principal representing the user if the
     *                      authentication was successful
     *
     * @throws URMAuthenticationException if the authentication fails
     *
     * @throws URMException if an unpredictable internal error occurs.
     */
    public abstract URMPrincipal authenticateUser(String user, char[] password, String domain)
        throws URMAuthenticationFailsException, URMAuthenticatorException,
                URMConfigurationException, URMCloseConnectionException;

    /**
     * Creates an URMPrincipal with URMGuest permission
     *
     * @throws URMException if an unpredictable internal error occurs.
     */
    public URMPrincipal authenticateUser()
        throws URMException, URMAuthenticatorException,
                URMConfigurationException, URMCloseConnectionException {
        Object owner = new Object();
        URMAclAdministratorImpl aclAdmin = new URMAclAdministratorImpl(conf.getSubConfigurator("/Authenticator/Administrator"), owner);
        URMGuestAdministratorImpl urmAdmin = new URMGuestAdministratorImpl(conf.getSubConfigurator("/Authenticator/Administrator"), owner);
        URMPrincipal guest = new URMPrincipalImpl(urmAdmin, aclAdmin);
        return guest;
    }
}

