
package uk.co.wingpath.util;

import java.io.*;
import java.util.*;
import javax.swing.*;
import java.net.*;
import java.lang.reflect.*;

/**
* This class, together with {@link JarLoader}, provides methods for installing
* resources (such as serial libraries) from a product JAR file.
* <p>In order to load the resources, the product should have a top-level
* class that looks like:
* <p><blockquote><pre>
class Bootstrap
{
    public static void main (String [] args)
    {
        List<String> paths = new ArrayList<String> ();

        paths.add ("xresource/lib/jserial");

        JarLoader loader = JarLoader.create (paths);

        Installer.runMain (loader, "uk.co.wingpath.modsak.Modsak", args);
    }
}
* </pre></blockquote>
* <p>where <code>"uk.co.wingpath.modsak.Modsak"</code> is the name of the
* "real" top-level class, which should also contain a main method.
* <p>If you want to load other jars or native libraries, you can add them
* to 'paths' before creating the {@link JarLoader}.
*/
public final class Installer
{
    private Installer ()
    {
    }

    /**
    * Tests whether we are running under Windows.
    * <p>This test is crude (it simply tests whether the "os.name" system
    * property contains the string "Windows"), but it seems to work.
    * @return {@code true} if we running under Windows.
    */
    public static boolean isWindows ()
    {
        return System.getProperty ("os.name").contains ("Windows");
    }

    /**
    * Tests whether we are running under Linux.
    * <p>This test is crude (it simply tests whether the "os.name" system
    * property contains the string "Linux"), but it seems to work.
    * @return {@code true} if we running under Windows.
    */
    public static boolean isLinux ()
    {
        return System.getProperty ("os.name").contains ("Linux");
    }

    /**
    * Tests whether we are running under a 64-bit JVM.
    * This works for Sun and IBM JVM's only - for other JVM's it will
    * return false.
    * @return true if the JVM is known to be 64-bit, otherwise false.
    */
    public static boolean isJvm64 ()
    {
        String dataModel = System.getProperty ("sun.arch.data.model");
        if (dataModel == null)
            dataModel = System.getProperty ("com.ibm.vm.bitmode");
        if (dataModel == null)
            return false;
        return dataModel.equals ("64");
    }

    /**
    * Tests whether we are running under a 32-bit JVM.
    * This works for Sun and IBM JVM's only - for other JVM's it will
    * return false.
    * @return true if the JVM is known to be 32-bit, otherwise false.
    */
    public static boolean isJvm32 ()
    {
        String dataModel = System.getProperty ("sun.arch.data.model");
        if (dataModel == null)
            dataModel = System.getProperty ("com.ibm.vm.bitmode");
        if (dataModel == null)
            return false;
        return dataModel.equals ("32");
    }

    /**
    * Gets Java version as an integer.
    * Any leading "1." in the version is removed.
    * @return Java version number.
    */
    public static int getJavaVersion ()
    {
        String version = System.getProperty ("java.specification.version");
        if (version == null)
        {
            return 0;
        }
        else
        {
            version = version.trim ();
            if (version.startsWith ("1."))
                version = version.substring (2);
            try
            {
                int n = Integer.parseInt (version);
                return n;
            }
            catch (NumberFormatException e)
            {
                return 0;
            }
        }
    }

    /**
    * Loads a class using the specifed loader, and then calls the 'main'
    * method of the class.
    * @param loader loader to be used to load the class.
    * @param mainClass the class to be loaded.
    * @param args arguments to be passed to the 'main' method.
    * @throws RuntimeException if anything goes wrong.
    */
    public static void runMain (ClassLoader loader, String mainClass,
        String [] args)
    {
        try
        {
            Class<?> c = loader.loadClass (mainClass);
// System.out.println ("runMain: mainClass loader " + c.getClassLoader ());
            Method m = c.getMethod ("main", new Class [] { String [].class });
            m.invoke (null, new Object [] { args });
        }
        catch (Exception e)
        {
            Throwable cause = e.getCause ();
            if (cause instanceof InternalError &&
                (cause.getMessage ().contains ("DISPLAY variable") ||
                 cause.getMessage ().contains ("X11Graphics")))
            {
                System.err.println (cause.getMessage ());
                System.err.println ("You need to have an X-server running.");
                System.exit (23);
            }
            throw new RuntimeException ("Can't call " + mainClass + ".main", e);
        }
    }
}

