/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007,2008 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.client.boot;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

import org.ow2.jonas.lib.bootstrap.loader.JClassLoader;

/**
 * Client Bootstrap class that launch given class using client.jar file.
 * @author Guillaume Sauthier
 */
public final class Bootstrap {

    /**
     * Empty private constructir for main only class.
     */
    private Bootstrap() {}

    /**
     * Execute the Client class within the client.jar ClassLoader.
     * @param args Program arguments.
     * @throws Exception if unable to create the {@link ClassLoader} or if
     *         the executed class is failing
     */
    public static void main(final String[] args) throws Exception {

        // Init the directories
        String jroot = System.getProperty("jonas.root");
        if (jroot == null) {
            throw new Exception("JONAS_ROOT is not set.");
        }
        File root = new File(jroot);
        File lib = new File(root, "lib");

        URL clientDotJarURL = null;
        try {
            clientDotJarURL = new File(lib, "client.jar").toURI().toURL();
        } catch (MalformedURLException e) {
            e.printStackTrace();
            System.exit(2);
        }

        ClassLoader loader = new JClassLoader("ClientClassLoader",
                                              new URL[] {clientDotJarURL});

        // First argument should be the Java class to execute
        Method main = null;
        // Do nothing if there is no arg
        if (args == null || args.length == 0) {
            return;
        }

        String classname = args[0];
        try {
            Class<?> clazz = loader.loadClass(classname);
            main = clazz.getDeclaredMethod("main", new Class[] {String[].class});
        } catch (ClassNotFoundException e) {
            System.err.println("Cannot load class: '" + classname + "': " + e.getMessage());
            throw e;
        } catch (SecurityException e) {
            System.err.println("Permission denied on: '" + classname + "': " + e.getMessage());
            throw e;
        } catch (NoSuchMethodException e) {
            System.err.println("No main(String[]) method on: '" + classname + "': " + e.getMessage());
            throw e;
        }

        // Remove first element now
        String[] newArgs = new String[args.length - 1];
        System.arraycopy(args, 1, newArgs, 0, args.length - 1);

        // Invoke the main
        ClassLoader old = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(loader);
            main.invoke(null, new Object[] {newArgs});
        } catch (InvocationTargetException e) {
            if (e.getCause() != null) {
                throw e;
            }
        } catch (Exception e) {
            System.err.println("Cannot execute main(String[]) method on: '" + classname + "': " + e.getMessage());
            throw e;
        } finally {
            Thread.currentThread().setContextClassLoader(old);
        }

    }


}
