All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dorkbox.util.OS Maven / Gradle / Ivy

There is a newer version: 1.48
Show newest version
/*
 * Copyright 2010 dorkbox, llc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dorkbox.util;

import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.TimeZone;

public
class OS {
    public static final String LINE_SEPARATOR = getProperty("line.separator", "\n"); // make the default unix
    public static final String LINE_SEPARATOR_UNIX = "\n";
    public static final String LINE_SEPARATOR_WINDOWS = "\r\n";

    public static final Charset US_ASCII = Charset.forName("US-ASCII");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    public static final Charset UTF_16LE = Charset.forName("UTF-16LE");

    public static final File TEMP_DIR = new File(getProperty("java.io.tmpdir", "temp"));

    /**
     * The currently running MAJOR java version as a NUMBER. For example, "Java version 1.7u45", and converts it into 7, uses JEP 223 for java > 9
     */
    public static final int javaVersion = _getJavaVersion();


    private static final OSType osType;
    private static final String originalTimeZone = TimeZone.getDefault().getID();

    static {
        if (!TEMP_DIR.isDirectory()) {
            // create the temp dir if necessary because the TEMP dir doesn't exist.
            TEMP_DIR.mkdirs();
        }

        /**
         * By default, the timer resolution in some operating systems are not particularly high-resolution (ie: 'Thread.sleep(1)' will not
         * really sleep for 1ms, but will really sleep for 16ms). This forces the JVM to use high resolution timers. This is USUALLY
         * necessary on Windows.
         */
        Thread timerAccuracyThread = new Thread(new Runnable() {
            @Override
            public
            void run() {
                //noinspection InfiniteLoopStatement
                while (true) {
                    try {
                        Thread.sleep(Long.MAX_VALUE);
                    } catch (Exception ignored) {
                    }
                }
            }
        }, "ForceHighResTimer");
        timerAccuracyThread.setDaemon(true);
        timerAccuracyThread.start();


        String osName = getProperty("os.name", "");
        String osArch = getProperty("os.arch", "");

        if (osName != null && osArch != null) {
            osName = osName.toLowerCase(Locale.US);
            osArch = osArch.toLowerCase(Locale.US);

            if (osName.startsWith("linux")) {
                // best way to determine if it's android.
                // Sometimes java binaries include Android classes on the classpath, even if it isn't actually Android, so we check the VM


                String value = getProperty("java.vm.name", "");
                boolean isAndroid = "Dalvik".equals(value);
                if (isAndroid) {
                    // android check from https://stackoverflow.com/questions/14859954/android-os-arch-output-for-arm-mips-x86
                    if (osArch.equals("armeabi")) {
                        // really old/low-end non-hf 32bit cpu
                        osType = OSType.AndroidArm56;
                    }
                    else if (osArch.equals("armeabi-v7a")) {
                        // 32bit hf cpu
                        osType = OSType.AndroidArm7;
                    }
                    else if (osArch.equals("arm64-v8a")) {
                        // 64bit hf cpu
                        osType = OSType.AndroidArm8;
                    }
                    else if (osArch.equals("x86")) {
                        // 32bit x86 (usually emulator)
                        osType = OSType.AndroidX86;
                    }
                    else if (osArch.equals("x86_64")) {
                        // 64bit x86 (usually emulator)
                        osType = OSType.AndroidX86_64;
                    }
                    else if (osArch.equals("mips")) {
                        // 32bit mips
                        osType = OSType.AndroidMips;
                    }
                    else if (osArch.equals("mips64")) {
                        // 64bit mips
                        osType = OSType.AndroidMips64;
                    } else {
                        // who knows?
                        osType = null;
                    }
                }
                else {
                    // normal linux 32/64/arm32/arm64
                    if ("amd64".equals(osArch)) {
                        osType = OSType.Linux64;
                    }
                    else {
                        if (osArch.startsWith("arm")) {
                            if (osArch.contains("v8")) {
                                osType = OSType.LinuxArm64;
                            }
                            else {
                                osType = OSType.LinuxArm32;
                            }
                        }
                        else {
                            osType = OSType.Linux32;
                        }
                    }
                }
            }
            else if (osName.startsWith("windows")) {
                if ("amd64".equals(osArch)) {
                    osType = OSType.Windows64;
                }
                else {
                    osType = OSType.Windows32;
                }
            }
            else if (osName.startsWith("mac") || osName.startsWith("darwin")) {
                if ("x86_64".equals(osArch)) {
                    osType = OSType.MacOsX64;
                }
                else {
                    osType = OSType.MacOsX32;
                }
            }
            else if (osName.startsWith("freebsd") || osName.contains("nix") || osName.contains("nux") || osName.startsWith("aix")) {
                if ("x86".equals(osArch) || "i386".equals(osArch)) {
                    osType = OSType.Unix32;
                }
                else if ("arm".equals(osArch)) {
                    osType = OSType.UnixArm;
                }
                else {
                    osType = OSType.Unix64;
                }
            }
            else if (osName.startsWith("solaris") || osName.startsWith("sunos")) {
                osType = OSType.Solaris;
            }
            else {
                osType = null;
            }
        }
        else {
            osType = null;
        }
    }

    /**
     * @return the System Property in a safe way for a given key, or null if it does not exist.
     */
    public static
    String getProperty(final String key) {
        return getProperty(key, null);
    }

    /**
     * @return the System Property in a safe way for a given key, and if null - returns the specified default value.
     */
    public static
    String getProperty(final String key, final String defaultValue) {
        try {
            if (System.getSecurityManager() == null) {
                return System.getProperty(key, defaultValue);
            } else {
                return AccessController.doPrivileged(new PrivilegedAction() {
                    @Override
                    public String run() {
                        return System.getProperty(key, defaultValue);
                    }
                });
            }
        } catch (Exception ignored) {
            return defaultValue;
        }
    }

    public static
    OSType get() {
        return osType;
    }

    public static
    boolean is64bit() {
        return osType.is64bit();
    }

    public static
    boolean is32bit() {
        return osType.is32bit();
    }

    /**
     * @return true if this is a "standard" x86/x64 architecture (intel/amd/etc) processor.
     */
    public static
    boolean isX86() {
        return osType.isX86();
    }

    public static
    boolean isMips() {
        return osType.isMips();
    }

    public static
    boolean isArm() {
        return osType.isArm();
    }

    public static
    boolean isLinux() {
        return osType.isLinux();
    }

    public static
    boolean isUnix() {
        return osType.isUnix();
    }

    public static
    boolean isSolaris() {
        return osType.isSolaris();
    }

    public static
    boolean isWindows() {
        return osType.isWindows();
    }

    public static
    boolean isMacOsX() {
        return osType.isMacOsX();
    }

    public static
    boolean isAndroid() {
        return osType.isAndroid();
    }


    /**
     * Gets the currently running MAJOR java version as a NUMBER. For example, "Java version 1.7u45", and converts it into 7, uses JEP 223 for java > 9
     */
    private static
    int _getJavaVersion() {
        // this should never be a problem, but just in case
        String fullJavaVersion = getProperty("java.version", "");


        if (fullJavaVersion.startsWith("1.")) {
            switch (fullJavaVersion.charAt(2)) {
                case '4':
                    return 4;
                case '5':
                    return 5;
                case '6':
                    return 6;
                case '7':
                    return 7;
                case '8':
                    return 8;
                case '9':
                    return 9;
            }
        }
        else {
            // We are >= java 10, use JEP 223 to get the version (early releases of 9 might not have JEP 223, so 10 is guaranteed to have it)
            fullJavaVersion = getProperty("java.specification.version", "10");

            try {
                // it will ALWAYS be the major release version as an integer. See http://openjdk.java.net/jeps/223
                return Integer.parseInt(fullJavaVersion);
            } catch (Exception ignored) {
            }
        }

        // the last valid guess we have, since the current Java implementation, whatever it is, decided not to cooperate with JEP 223.
        return 10;
    }

    /**
     * Set our system to UTC time zone. Retrieve the original time zone via {@link #getOriginalTimeZone()}
     */
    public static
    void setUTC() {
        // have to set our default timezone to UTC. EVERYTHING will be UTC, and if we want local, we must explicitly ask for it.
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    }

    /**
     * Returns the *ORIGINAL* system time zone, before (*IF*) it was changed to UTC
     */
    public static
    String getOriginalTimeZone() {
        return originalTimeZone;
    }

    /**
     * @return the optimum number of threads for a given task. Makes certain not to take ALL the threads, always returns at least one
     * thread.
     */
    public static
    int getOptimumNumberOfThreads() {
        return Math.max(Runtime.getRuntime()
                               .availableProcessors() - 2, 1);
    }


    /**
     * @return the first line of the exception message from 'throwable', or the type if there was no message.
     */
    public static
    String getExceptionMessage(final Throwable throwable) {
        String message = throwable.getMessage();
        if (message != null) {
            int index = message.indexOf(OS.LINE_SEPARATOR);
            if (index > -1) {
                message = message.substring(0, index);
            }
        } else {
            message = throwable.getClass()
                               .getSimpleName();
        }

        return message;
    }

    @Override
    public final
    Object clone() throws java.lang.CloneNotSupportedException {
        throw new java.lang.CloneNotSupportedException();
    }

    public final
    void writeObject(ObjectOutputStream out) throws java.io.IOException {
        throw new java.io.NotSerializableException();
    }

    public final
    void readObject(ObjectInputStream in) throws java.io.IOException {
        throw new java.io.NotSerializableException();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy