octavian-nita
2/19/2014 - 10:38 AM

Runtime environment-related utilities (e.g. getting the user name)

Runtime environment-related utilities (e.g. getting the user name)

import java.lang.reflect.Method;

/**
 * Runtime environment-related utilities.
 */
public class OS {

    private static Object userInfoProvider;

    private static Method userNameGetter;

    static {
        String userInfoProviderClassName = null;
        String userNameGetterName = "getUsername";

        // Detect the current operating system, based on the os.name Java system property:
        String osName = System.getProperty("os.name", "unknown").toLowerCase();
        if (osName.indexOf("windows") >= 0) {
            userInfoProviderClassName = "com.sun.security.auth.module.NTSystem";
            userNameGetterName = "getName";
        } else if (osName.indexOf("sunos") >= 0) {
            userInfoProviderClassName = "com.sun.security.auth.module.SolarisSystem";
        } else if (osName.indexOf("linux") >= 0) {
            userInfoProviderClassName = "com.sun.security.auth.module.UnixSystem";
        }

        // 'Cache' the objects obtained through reflection:
        if (userInfoProviderClassName != null) {
            try {
                Class<?> userInfoProviderClass = Class.forName(userInfoProviderClassName);
                userInfoProvider = userInfoProviderClass.newInstance();
                userNameGetter = userInfoProviderClass.getMethod(userNameGetterName);
            } catch (Throwable e) {
                System.err.println("cannot reliably obtain user-related information from the operating system");
                e.printStackTrace();
                userInfoProvider = null;
                userNameGetter = null;
            }
        }
    }

    /**
     * Safer choice than {@link System#getProperty(String) System.getProperty("user.name")}. For example, on Windows
     * systems, if the USERNAME environment variable is not empty, its value is returned when calling
     * System.getProperty("user.name"); a privileged user can thus set it to whatever value s/he wants and the change
     * would be reflected when the Java program restarts.
     *
     * @return the current user name, as retrieved by operating system calls; in case of any errors, they are logged and
     * the value of <code>{@link System#getProperty(String, String) System.getProperty("user.name", "unknown")}</code>
     * is retrieved
     */
    public static String getUsername() {
        if (userInfoProvider == null) {
            logger.error("cannot reliably obtain the current user name from the operating system "
                + "(could not instantiate a user information provider)");
            return System.getProperty("user.name", "unknown");
        }
        try { // ... to call 'userInfoProvider'.'userNameGetter'() and cast the result to a String...
            return (String) userNameGetter.invoke(userInfoProvider);
        } catch (Throwable e) {
            System.err.println("cannot reliably obtain the current user name from the operating system");
            e.printStackTrace();
            return System.getProperty("user.name", "unknown");
        }
    }

    public static void main(String[] args) {
        System.out.println("  os.name: " + System.getProperty("os.name"));
        System.out.println("user name: " + OS.getUsername());
    }
}