/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2005 C.Marchand - christophe.marchand@axyus.com
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package fr.gouv.finances.cp.xemelios.auth;

import fr.gouv.finances.cp.xemelios.common.Constants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import fr.gouv.finances.cp.utils.PropertiesExpansion;
import fr.gouv.finances.cp.xemelios.ui.MainWindow;

/**
 * This class looks for authentication configuration and instanciates
 * the right manager
 * @author chm
 *
 */
public class AuthenticationFactory {
	public static final transient String PROP_CONFIG_FILE_NAME = Constants.SYS_PROP_AUTH_CONFIG_FILE_NAME;
	public static final transient String PROP_MANAGER_CLASS_NAME = "authentication.manager";
	private static AuthenticationManager manager = null;
	
	public static AuthenticationManager getManager(MainWindow mw) throws AuthenticationConfigurationException, AuthenticationCancelationException {
		if(manager==null) {
			String authConfigFileName = System.getProperty(PROP_CONFIG_FILE_NAME);
			if(authConfigFileName==null || authConfigFileName.length()==0)
				throw new AuthenticationConfigurationException("property "+PROP_CONFIG_FILE_NAME+" is not defined");
			
			PropertiesExpansion pe = new PropertiesExpansion();
			pe.putAll(System.getProperties());
			try {
				pe.load(new FileInputStream(authConfigFileName));
				String managerClassName = pe.getProperty(PROP_MANAGER_CLASS_NAME);
				if(managerClassName==null || managerClassName.length()==0)
					throw new AuthenticationConfigurationException("property "+PROP_MANAGER_CLASS_NAME+" is not defined in "+authConfigFileName);
				Class clazz = Class.forName(managerClassName);
				Class[] parametersTypes = new Class[1];
				parametersTypes[0]=MainWindow.class;
				Constructor constructor = clazz.getConstructor(parametersTypes);
				Object[] parameters = new Object[1];
				parameters[0]=mw;
				Object o = constructor.newInstance(parameters);
				if(!(o instanceof AuthenticationManager))
					throw new AuthenticationConfigurationException(managerClassName+" does not implements "+AuthenticationManager.class.getName());
				manager = (AuthenticationManager)o;
				manager.setProperties(pe);
			} catch (FileNotFoundException fnfEx) {
				throw new AuthenticationConfigurationException(authConfigFileName+" not found",fnfEx);
			} catch (IOException ioEx) {
				throw new AuthenticationConfigurationException(ioEx);
			} catch (ClassNotFoundException cnfEx) {
				throw new AuthenticationConfigurationException("class not found",cnfEx);
			} catch (InstantiationException iEx) {
				throw new AuthenticationConfigurationException(iEx);
			} catch (IllegalAccessException iaEx) {
				throw new AuthenticationConfigurationException(iaEx);
			} catch(NoSuchMethodException nsmEx) {
				throw new AuthenticationConfigurationException(pe.getProperty(PROP_MANAGER_CLASS_NAME)+" does not provide the required constructor.",nsmEx);
			} catch(InvocationTargetException itEx) {
				if(itEx.getCause()!=null && (itEx.getCause() instanceof AuthenticationCancelationException)) throw (AuthenticationCancelationException)itEx.getCause();
				throw new AuthenticationConfigurationException(pe.getProperty(PROP_MANAGER_CLASS_NAME)+".<init>(MainWindow)",itEx);
			}
		}
		return manager;
	}

}
