/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2005 L.Meckert - lmeckert@club-internet.fr
 *
 * 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.starter;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Properties;

import fr.gouv.finances.cp.utils.PropertiesExpansion;
import fr.gouv.finances.cp.xemelios.updater.starter.Updater;

public class Bootstrap {
    private static final Class[] parameters = new Class[] { URL.class };

    public static void addFile(String s) throws IOException {
        File f = new File(s);
        addFile(f);
    }

    public static void addFile(File f) throws IOException {
        addURL(f.toURL());
    }

    // bitonio trouvé sur le net
    public static void addURL(URL u) throws IOException {
//System.out.println("adding to classpath "+u.toExternalForm());
        URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
        Class sysclass = URLClassLoader.class;

        try {
            Method method = sysclass.getDeclaredMethod("addURL", parameters);
            method.setAccessible(true); // voyou
            method.invoke(sysloader, new Object[] { u });
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IOException("Error, could not add URL to system classloader");
        }

    }

    static void restoreProperties() {
        Properties properties = new PropertiesExpansion();
        String propsFileName = System.getProperty("xemelios.properties");
        if (propsFileName == null) {
            propsFileName = "xemelios.properties";
        } // fichier de ce nom dans rep courant
        File propsFile = new File(propsFileName);
        try {
            if (propsFile.isFile() && propsFile.canRead()) {
            } else {
                System.err.println("Impossible d'accéder à " + propsFileName);
            }
        }
        catch (SecurityException se) {
            System.err.println("Problème d'accès au fichier " + propsFileName);
        }
        if (propsFile != null) {
            try {
                FileInputStream in = new FileInputStream(propsFile);
                properties.load(in);
            } catch (IOException ioe) {
                System.err.println("Cannot load properties " + ioe);
                return;
            }
        }
        for (Enumeration en = properties.keys(); en.hasMoreElements();) {
            String k = (String)en.nextElement();
            Object v = properties.get(k);
            if (v instanceof String) {
                System.setProperty(k, (String)v);
            }
        }
    }

    public static void main(String[] args) throws Exception {

        restoreProperties();
        // is there some updates to perform ?
        new Updater();
        System.out.println("user.dir=".concat(System.getProperty("user.dir")));

        String classdirs = System.getProperty("classdirs");
        String startclass = System.getProperty("startclass");
        String[] classdirsArray = classdirs.split(";");

        for (int dir = 0; dir < classdirsArray.length; ++dir) {
            try {
                File jarsdir = new File(classdirsArray[dir]);
                addURL(new URL("file:" + jarsdir.getAbsolutePath()));// Le
                                                                        // directory
                                                                        // itself
                File[] listJars = jarsdir.listFiles(new FileFilter() {
                    public boolean accept(File pathname) {
                        String s = pathname.getPath();
                        return s.endsWith(".jar");
                    }
                });
                for (int i = 0; i < listJars.length; ++i) // Chacun des jars
                {

                    addURL(new URL("file:" + listJars[i].getAbsolutePath()));
                }
            }
            catch (NullPointerException n) {
                System.err.println("Impossible de trouver le repertoire " + classdirsArray[dir]);
            }
        }

        String SnewInstance = System.getProperty("startclass.newInstance");
        boolean newInstance = (new Boolean(SnewInstance)).booleanValue();
        String SinstanceMethod = System.getProperty("startclass.instanceMethod");
        String SclassMethod = System.getProperty("startclass.classMethod");
        String SclassMethodArgs = null;
        if("main".equals(SclassMethod)) {
            if(args!=null && args.length>0) {
                for(String arg:args) SclassMethodArgs = arg+",";
            } else SclassMethodArgs = "/xxx";	// voila un nom de fichier xui a peu de chance dexister dans le repertoire racine
        } else {
            SclassMethodArgs= System.getProperty("startclass.classMethod.Args");
        }
//System.out.println("loading class ".concat(startclass));
        Class startClass = Class.forName(startclass);
        if (SclassMethod != null) {
            if (SclassMethodArgs != null) {
                // Que des Strings
                //System.out.println(SclassMethodArgs);
                String[] classMethodArgsArray = SclassMethodArgs.split(",");
                Class[] params = new Class[] { String[].class };
                Method classMethod = startClass.getDeclaredMethod(SclassMethod, params);
                //System.out.println(classMethod.toGenericString());
                Object[] parametersValues = new Object[] {classMethodArgsArray};
//System.out.println("invoking "+startclass+"."+classMethod.getName()+"("+parametersValues+")");
                classMethod.invoke(null, parametersValues);

            } else {
                // methode sans parametre
                Method classMethod = startClass.getDeclaredMethod(SclassMethod);
                classMethod.invoke(null);
            }
        }
        if (SinstanceMethod != null) {
            newInstance = true;
        }
        if (newInstance) {
            Object instance = startClass.newInstance();
            if (SinstanceMethod != null) {
                // idem methode sans parametre
                Method instanceMethod = startClass.getDeclaredMethod(SinstanceMethod);
                instanceMethod.invoke(instance);
            }
        }
    }

}
