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

com.github.hypfvieh.util.SystemUtil Maven / Gradle / Ivy

Go to download

A collection of utils commonly used in my projects. Feel free to use it (or parts of it) in your own projects.

The newest version!
package com.github.hypfvieh.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility-Class with various operating system related helper methods.
 *
 * @author hypfvieh
 * @since v0.0.5 - 2015-08-05
 */
public final class SystemUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(SystemUtil.class);

    /** List of known terminal emulators on linux/unix systems. */
    private static final String[] TERMINAL_EMULATORS = new String[]
            {"x-terminal-emulator", "gnome-terminal", "mate-terminal",
                    "konsole", "xterm", "rxvt", "xdg-terminal", "lxterminal", "pterm",
                    "aterm", "eterm", "roxterm", "qterminal", "terminator",
                    "tmux", "screen"};

    /** Character that separates components of a file path. This is "/" on UNIX and "\" on Windows. */
    public static final String FILE_SEPARATOR = System.getProperty("file.separator");
    /** Sequence used by operating system to separate lines in text files. */
    public static final String LINE_SEPARATOR = System.getProperty("line.separator");
    /** The system's temporary-file directory. */
    public static final String TMP_DIR        = normalizePath(System.getProperty("java.io.tmpdir"));

    private SystemUtil() {

    }

    /**
     * Determines the operating system's type and version.
     * @return the OS type and version as a string
     */
    public static String getOs() {
        return (System.getProperty("os.name") + " " + System.getProperty("os.version"));
    }


    /**
     * Gets the host name of the local machine.
     * @return host name
     */
    public static String getHostName() {
        try {
            return java.net.InetAddress.getLocalHost().getHostName();
        } catch (java.net.UnknownHostException _ex) {
            return null;
        }
    }

    /**
     * Returns the current working directory.
     * @return current working dir
     */
    public static String getWorkingDirectory() {
        return System.getProperty("user.dir");
    }

    /**
     * Returns the running class path.
     * @return String with classpath
     */
    public static String getRunningClassPath() {
        return ClassLoader.getSystemClassLoader().getResource(".").getPath();
    }

    /**
     * Returns the temp directory of this platform.
     * @return temp directory
     */
    public static String getTempDir() {
        return TMP_DIR;
    }

    /**
     * Determines the Java version of the executing JVM.
     * @return Java version
     */
    public static String getJavaVersion() {
        String[] sysPropParms = new String[] {"java.runtime.version", "java.version"};
        for (int i = 0; i < sysPropParms.length; i++) {
            String val = System.getProperty(sysPropParms[i]);
            if (!StringUtil.isEmpty(val)) {
                return val;
            }
        }
        return null;
    }

    /**
     * Determines the current logged on user.
     * @return logged on user
     */
    public static String getCurrentUser() {
        String[] sysPropParms = new String[] {"user.name", "USER", "USERNAME"};
        for (int i = 0; i < sysPropParms.length; i++) {
            String val = System.getProperty(sysPropParms[i]);
            if (!StringUtil.isEmpty(val)) {
                return val;
            }
        }
        return null;
    }

    /**
     * Concats a path from all given parts, using the path delimiter for the currently used platform.
     * @param _includeTrailingDelimiter include delimiter after last token
     * @param _parts parts to concat
     * @return concatinated string
     */
    public static String concatFilePath(boolean _includeTrailingDelimiter, String..._parts) {
        String concatStrings = StringUtil.concatStrings(false, File.separator, _parts);

        if (_includeTrailingDelimiter && concatStrings.length() > 0) {
            return concatStrings + File.separator;
        }

        return concatStrings;
    }
    /**
     * Concats a path from all given parts, using the path delimiter for the currently used platform.
     * Does not include trailing delimiter.
     * @param _parts parts to concat
     * @return concatinated string
     */
    public static String concatFilePath(String... _parts) {
        return concatFilePath(false, _parts);
    }

    /**
     * Append a suffix to the string (e.g. filename) if it doesn't have it already.
     * @param _str string to check
     * @param _suffix suffix to append
     * @return string with suffix or original if no suffix was appended
     */
    public static String appendSuffixIfMissing(String _str, String _suffix) {
        if (_str == null) {
            return null;
        }
        if (!_str.endsWith(_suffix)) {
            _str += _suffix;
        }
        return _str;
    }

    /**
     * Appends the OS specific path delimiter to the end of the String, if it is missing.
     * @param _filePath file path
     * @return String
     */
    public static String appendTrailingDelimiter(String _filePath) {
        if (_filePath == null) {
            return null;
        }
        if (!_filePath.endsWith(File.separator)) {
            _filePath += File.separator;
        }
        return _filePath;
    }

    /**
     * Creates a new temporary directory in the given path.
     * @param _path path
     * @param _name directory name
     * @param _deleteOnExit delete directory on jvm shutdown
     * @return created Directory, null if directory/file was already existing
     */
    public static File createTempDirectory(String _path, String _name, boolean _deleteOnExit) {

        File outputDir = new File(concatFilePath(_path, _name));
        if (!outputDir.exists()) {
            try {
                Files.createDirectory(Paths.get(outputDir.toString()));
            } catch (IOException _ex) {
                LOGGER.error("Error while creating temp directory", _ex);
            }
        } else {
            return null;
        }
        if (_deleteOnExit) {
            outputDir.deleteOnExit();
        }
        return outputDir;
    }

    /**
     * Creates a temporary directory in the given path.
     * You can  specify certain files to get a random unique name.
     * @param _path where to place the temp folder
     * @param _prefix prefix of the folder
     * @param _length length of random chars
     * @param _timestamp add timestamp (yyyyMMdd_HHmmss-SSS) to directory name
     * @param _deleteOnExit mark directory for deletion on jvm termination
     * @return file
     */
    public static File createTempDirectory(String _path, String _prefix, int _length, boolean _timestamp, boolean _deleteOnExit) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss-SSS");
        String randomStr = StringUtil.randomString(_length);

        StringBuilder fileName = new StringBuilder();

        if (_prefix != null) {
            fileName.append(_prefix);
        }
        fileName.append(randomStr);

        if (_timestamp) {
            fileName.append("_").append(formatter.format(new Date()));
        }
        File result = createTempDirectory(_path, fileName.toString(), _deleteOnExit);
        while (result == null) {
            result = createTempDirectory(_path, _prefix, _length, _timestamp, _deleteOnExit);
        }
        return result;
    }

    /**
     * Examines some system properties to determine whether the process is likely being debugged
     * in an IDE or remotely.
     * @return true if being debugged, false otherwise
     */
    public static boolean isDebuggingEnabled() {
        boolean debuggingEnabled = false;
        if (ManagementFactory.getRuntimeMXBean().getInputArguments().toString().indexOf("-agentlib:jdwp") > 0) {
            debuggingEnabled = true;
        } else if (ManagementFactory.getRuntimeMXBean().getInputArguments().contains("-Xdebug")) {
            debuggingEnabled = true;
        } else if (System.getProperty("debug", "").equals("true")) {
            debuggingEnabled = true;
        }
        return debuggingEnabled;
    }

    /**
     * Extracts the file extension (part behind last dot of a filename).
     * Only returns the extension, without the leading dot.
     *
     * @param _fileName filename
     * @return extension, empty string if no dot was found in filename or null if given String was null
     */
    public static String getFileExtension(String _fileName) {
        if (_fileName == null) {
            return null;
        }
        int lastDot = _fileName.lastIndexOf('.');
        if (lastDot == -1) {
            return "";
        }
        return _fileName.substring(lastDot + 1);
    }

    /**
     * Extracts the file extension (part behind last dot of a filename).
     * Only returns the extension, without the leading dot.
     *
     * @param _file file
     * @return extension, empty string if no dot was found in filename or null if given String was null
     */
    public static String getFileExtension(File _file) {
        return getFileExtension(_file.getAbsolutePath());
    }

    /**
     * Checks if given String is a valid file, e.g. file exists, is really a file and can be read.
     *
     * Throws IOException or Subclass of it, if file is either non-existing, not a file or unreadable.
     *
     * @param _file filename
     * @return file object, never null
     * @throws IOException if file could not be read
     */
    public static File getFileIfReadable(String _file) throws IOException {
        if (StringUtil.isBlank(_file)) {
            throw new IOException("Empty or null string is not a valid file");
        }

        File file = new File(_file);

        if (!file.exists()) {
            throw new FileNotFoundException("No such file: " + _file);
        } else if (!file.isFile()) {
            throw new IOException("Not a file: " + _file);
        } else if (!file.canRead()) {
            throw new AccessDeniedException("File not readable: " + _file);
        }

        return file;
    }

    /**
     * Formats a file size given in byte to something human readable.
     *
     * @param _bytes size in bytes
     * @param _use1000BytesPerMb use 1000 bytes per MByte instead of 1024
     * @return String
     */
    public static String formatBytesHumanReadable(long _bytes, boolean _use1000BytesPerMb) {
        int unit = _use1000BytesPerMb ? 1000 : 1024;
        if (_bytes < unit)  {
            return _bytes + " B";
        }
        int exp = (int) (Math.log(_bytes) / Math.log(unit));
        String pre = (_use1000BytesPerMb ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (_use1000BytesPerMb ? "" : "i");
        return String.format("%.1f %sB", _bytes / Math.pow(unit, exp), pre);
    }

    /**
     * Read the JARs manifest and try to get the current program version from it.
     * @param _class class to use as entry point
     * @param _default default string to use if version could not be found
     * @return version or null
     */
    public static String getApplicationVersionFromJar(Class _class, String _default) {
        try {
            Enumeration resources = _class.getClassLoader().getResources("META-INF/MANIFEST.MF");
            while (resources.hasMoreElements()) {

                Manifest manifest = new Manifest(resources.nextElement().openStream());
                Attributes attribs = manifest.getMainAttributes();
                String ver = attribs.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
                if (ver == null) {
                	return _default;
                }

                String rev = attribs.getValue("Implementation-Revision");
                if (rev != null) {
                    ver += "-r" + rev;
                }
                return ver;

            }
        } catch (IOException _ex) {
        }

        return _default;
    }

    /**
     * Tries to find the "default" terminal emulator.
     * This will be cmd.exe on windows and may vary on linux/unix systems depending on installed terminal programs.
     * On linux/unix there is no generic way to find the default terminal,
     * so all known terminal programs will be tried until any of them is found.
     * @return String with terminal name or null if terminal could not be determined
     */
    public static String guessDefaultTerminal() {
        if (System.getProperty("os.name", "").equalsIgnoreCase("windows")) {
            return "cmd.exe";
        }

        String envPath = System.getenv("PATH");
        if (envPath == null) {
            throw new RuntimeException("Could not find enviroment PATH setting.");
        }
        String[] pathes = envPath.split(":");

        for (String term : TERMINAL_EMULATORS) {
            for (String path : pathes) {
                File terminalExe = new File(concatFilePath(path, term));
                if (terminalExe.exists() && terminalExe.canExecute()) {
                    return terminalExe.getAbsolutePath();
                }
            }
        }

        return null;
    }

    /**
     * Normalize a file system path expression for the current OS.
     * Replaces path separators by this OS's path separator.
     * Appends a final path separator if parameter is set
     * and if not yet present.
     * @param _path path
     * @param _appendFinalSeparator controls appendix of separator at the end
     * @return normalized path
     */
    public static String normalizePath(String _path, boolean _appendFinalSeparator) {
        if (_path == null) {
            return _path;
        }

        String path = _path
            .replace("\\", FILE_SEPARATOR)
            .replace("/", FILE_SEPARATOR);
        if (_appendFinalSeparator && !path.endsWith(FILE_SEPARATOR)) {
            path += FILE_SEPARATOR;
        }
        return path;
    }

    /**
     * Normalize a file system path expression for the current OS.
     * Replaces path separators by this OS's path separator.
     * Appends a final path separator unless present.
     * @param _path path
     * @return normalized path
     */
    public static String normalizePath(String _path) {
        return normalizePath(_path, true);
    }

    /**
     * Checks if the running OS is a MacOS/MacOS X.
     * @return true if MacOS (or MacOS X), false otherwise
     */
    public static boolean isMacOs() {
        String osName = System.getProperty("os.name");
        return osName == null ? false : osName.toLowerCase().startsWith("mac");
    }

    /**
     * Tries to get the current version of MacOS/MacOS X.
     * The version usually looks like '10.13.4', where the part behind the last dot represents the patchlevel.
     * The major version in this case would be '10.13'.
     * @return version without patchlevel or null
     */
    public static String getMacOsMajorVersion() {
        if (!isMacOs()) {
            return null;
        }

        String osVersion = System.getProperty("os.version");

        if (osVersion != null) {
            String[] split = osVersion.split("\\.");
            if (split.length >= 2) {
                return split[0] + "." + split[1];
            } else {
                return osVersion;
            }
        }

        return null;
    }

    /**
     * Delete all files and directories in the given path recursively.
     *
     * @param _fileOrDirectoryPath path to delete
     * @param _stopOnError if true throw an exception and exit on any error
     * @throws IOException if error occurs during deletion
     */
    public static void deleteRecursively(String _fileOrDirectoryPath, boolean _stopOnError) throws IOException {

        if (_fileOrDirectoryPath == null || _fileOrDirectoryPath.isEmpty()) {
            return;
        }

        File path = new File(_fileOrDirectoryPath);
        if (!path.exists()) {
            return;
        }

        List filesToDelete = new ArrayList<>();
        List foldersToDelete = new ArrayList<>();

        try (Stream walk = Files.walk(path.toPath())) {

            walk.forEach(e -> {
                if (e.toFile().isDirectory()) {
                    foldersToDelete.add(e.toFile());
                } else {
                    filesToDelete.add(e.toFile());
                }
            });
        } catch (IOException _ex) {
            if (_stopOnError) {
                throw _ex;
            }
        }

        List couldNotRemove = new ArrayList<>();
        for (File file : filesToDelete) {
            if (!file.delete()) {
                if (_stopOnError) {
                    throw new IOException("Could not delete file: " + file);
                }
                couldNotRemove.add(file.getAbsoluteFile().getParent());
            }
        }

        for (File file : foldersToDelete) {
            if (couldNotRemove.contains(file.getAbsoluteFile().getName())) {
                continue;
            } else {
                if (!file.delete()) {
                    if (_stopOnError) {
                        throw new IOException("Could not delete directory: " + file);
                    }
                }
            }
        }
    }

    /**
     * Delete all files and directories in the given path recursively and without throwing any exception.
     * @param _fileOrDirectoryPath file or directory to delete
     */
    public static void deleteRecursivelyQuiet(String _fileOrDirectoryPath) {
        try {
            deleteRecursively(_fileOrDirectoryPath, false);
        } catch (IOException _ex) {
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy