/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Icy 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.system; import icy.file.FileUtil; import icy.main.Icy; import icy.type.collection.CollectionUtil; import icy.util.ReflectionUtil; import icy.util.StringUtil; import java.awt.BufferCapabilities; import java.awt.Desktop; import java.awt.Desktop.Action; import java.awt.DisplayMode; import java.awt.Event; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.ImageCapabilities; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Transparency; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.VolatileImage; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Properties; import com.sun.management.OperatingSystemMXBean; /** * @author stephane */ public class SystemUtil { public static final String SYSTEM_WINDOWS = "win"; public static final String SYSTEM_MAC_OS = "mac"; public static final String SYSTEM_UNIX = "unix"; /** * internals */ private static Properties props = System.getProperties(); private static long lastNano = 0; private static long lastCpu = 0; private static int lastCpuLoad = 0; /** * Launch specified jar file. * * @param jarPath * jar file path. * @param vmArgs * arguments for the java virtual machine. * @param appArgs * arguments for jar application. * @param workDir * working directory. */ public static Process execJAR(String jarPath, String vmArgs, String appArgs, String workDir) { return exec("java " + vmArgs + " -jar " + jarPath + " " + appArgs, workDir); } /** * Launch specified jar file. * * @param jarPath * jar file path. * @param vmArgs * arguments for the java virtual machine. * @param appArgs * arguments for jar application. */ public static Process execJAR(String jarPath, String vmArgs, String appArgs) { return exec("java " + vmArgs + " -jar " + jarPath + " " + appArgs); } /** * Launch specified jar file. * * @param jarPath * jar file path. * @param appArgs * arguments for jar application. */ public static Process execJAR(String jarPath, String appArgs) { return execJAR(jarPath, "", appArgs); } /** * Launch specified jar file. * * @param jarPath * jar file path. */ public static Process execJAR(String jarPath) { return execJAR(jarPath, "", ""); } /** * Execute a system command and return the attached process. * * @param cmd * system command to execute. */ public static Process exec(String cmd) { return exec(cmd, "."); } /** * Execute a system command and return the attached process. * * @param cmd * system command to execute. * @param dir * the working directory of the subprocess, or null if the subprocess should inherit the * working directory of the current process. */ public static Process exec(String cmd, String dir) { try { return Runtime.getRuntime().exec(cmd, null, new File(dir)); } catch (Exception e) { System.err.println("SystemUtil.exec(" + cmd + ") error :"); IcyExceptionHandler.showErrorMessage(e, false); return null; } } public static BufferedImage createCompatibleImage(int width, int height) { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); return defaultGC.createCompatibleImage(width, height); } public static BufferedImage createCompatibleImage(int width, int height, int transparency) { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) { if (transparency == Transparency.OPAQUE) return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } return defaultGC.createCompatibleImage(width, height, transparency); } public static VolatileImage createCompatibleVolatileImage(int width, int height) { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.createCompatibleVolatileImage(width, height); } public static VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.createCompatibleVolatileImage(width, height, transparency); } public static Desktop getDesktop() { if (Desktop.isDesktopSupported()) return Desktop.getDesktop(); return null; } /** * Launch the system file manager on specified folder (if supported) * * @throws IOException */ public static boolean openFolder(String folder) throws IOException { final Desktop desktop = getDesktop(); if ((desktop != null) && desktop.isSupported(Action.OPEN)) { desktop.open(new File(folder)); return true; } return false; } /** * @see System#getProperty(String) */ public static String getProperty(String name) { return props.getProperty(name); } /** * @see System#getProperty(String, String) */ public static String getProperty(String name, String defaultValue) { return props.getProperty(name, defaultValue); } /** * @see System#setProperty(String, String) */ public static String setProperty(String name, String value) { return (String) props.setProperty(name, value); } /** * @deprecated Use {@link #getMenuCtrlMask()} instead. */ @Deprecated public static int getCtrlMask() { return getMenuCtrlMask(); } /** * Return the CTRL key mask used for Menu shortcut. */ public static int getMenuCtrlMask() { try { return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); } catch (HeadlessException e) { // headless mode, use default Ctrl Mask return Event.CTRL_MASK; } } /** * @deprecated Use {@link #getMenuCtrlMask()} instead */ @Deprecated public static int getSystemCtrlMask() { return getMenuCtrlMask(); } public static GraphicsEnvironment getLocalGraphicsEnvironment() { return GraphicsEnvironment.getLocalGraphicsEnvironment(); } /** * Return the default screen device. */ public static GraphicsDevice getDefaultScreenDevice() { if (Icy.getMainInterface().isHeadLess()) return null; return getLocalGraphicsEnvironment().getDefaultScreenDevice(); } /** * Return the default graphics configuration. */ public static GraphicsConfiguration getDefaultGraphicsConfiguration() { final GraphicsDevice screenDevice = getDefaultScreenDevice(); if (screenDevice != null) return screenDevice.getDefaultConfiguration(); return null; } /** * @deprecated Use {@link #getDefaultGraphicsConfiguration()} instead. */ @Deprecated public static GraphicsConfiguration getSystemGraphicsConfiguration() { return getDefaultGraphicsConfiguration(); } /** * Return all available screen devices. */ public static List<GraphicsDevice> getScreenDevices() { final List<GraphicsDevice> result = new ArrayList<GraphicsDevice>(); if (Icy.getMainInterface().isHeadLess()) return result; try { return CollectionUtil.asList(getLocalGraphicsEnvironment().getScreenDevices()); } catch (HeadlessException e) { return result; } } /** * Return the number of screen device. */ public static int getScreenDeviceCount() { if (Icy.getMainInterface().isHeadLess()) return 0; try { return getLocalGraphicsEnvironment().getScreenDevices().length; } catch (HeadlessException e) { return 0; } } /** * Return the screen device corresponding to specified index. */ public static GraphicsDevice getScreenDevice(int index) { if (Icy.getMainInterface().isHeadLess()) return null; try { return getLocalGraphicsEnvironment().getScreenDevices()[index]; } catch (HeadlessException e) { return null; } } /** * Returns all screen device intersecting the given region.<br> * Can return an empty list if given region do not intersect any screen device. */ public static List<GraphicsDevice> getScreenDevices(Rectangle region) { final List<GraphicsDevice> result = new ArrayList<GraphicsDevice>(); if (Icy.getMainInterface().isHeadLess()) return result; for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices()) if (getScreenBounds(gd, true).intersects(region)) result.add(gd); return result; } /** * Returns the main screen device corresponding to the given region.<br> * If the given region intersect multiple screen, it return screen containing the largest area.<br> * Can return <code>null</code> if given region do not intersect any screen device. */ public static GraphicsDevice getScreenDevice(Rectangle region) { if (Icy.getMainInterface().isHeadLess()) return null; GraphicsDevice result = null; Rectangle2D largest = null; for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices()) { final Rectangle2D intersection = getScreenBounds(gd, true).createIntersection(region); if (!intersection.isEmpty()) { // bigger intersection ? if ((largest == null) || ((intersection.getWidth() * intersection.getHeight()) > (largest.getWidth() * largest .getHeight()))) { largest = intersection; result = gd; } } } return result; } /** * Returns the screen device corresponding to the given position.<br> * Can return <code>null</code> if given position is not located in any screen device. */ public static GraphicsDevice getScreenDevice(Point position) { if (Icy.getMainInterface().isHeadLess()) return null; for (GraphicsDevice gd : getLocalGraphicsEnvironment().getScreenDevices()) if (getScreenBounds(gd, false).contains(position)) return gd; return null; } /** * Returns true if current system is "head less" (no screen output device). */ public static boolean isHeadLess() { return GraphicsEnvironment.isHeadless(); } public static ClassLoader getContextClassLoader() { return Thread.currentThread().getContextClassLoader(); } public static ClassLoader getSystemClassLoader() { return ClassLoader.getSystemClassLoader(); } public static BufferCapabilities getSystemBufferCapabilities() { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.getBufferCapabilities(); } public static ImageCapabilities getSystemImageCapabilities() { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.getImageCapabilities(); } public static ColorModel getSystemColorModel() { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.getColorModel(); } public static ColorModel getSystemColorModel(int transparency) { final GraphicsConfiguration defaultGC = getDefaultGraphicsConfiguration(); if (defaultGC == null) return null; return defaultGC.getColorModel(transparency); } /** * Return bounds for specified screen. * * @param removeInsets * remove any existing taskbars and menubars from the result */ public static Rectangle getScreenBounds(GraphicsDevice graphicsDevice, boolean removeInsets) { if (graphicsDevice == null) return new Rectangle(); final GraphicsConfiguration graphicsConfiguration = graphicsDevice.getDefaultConfiguration(); final Rectangle bounds = graphicsConfiguration.getBounds(); final Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration); bounds.x += insets.left; bounds.y += insets.top; bounds.width -= (insets.left + insets.right); bounds.height -= (insets.top + insets.bottom); return bounds; } /** * Return the entire desktop bounds (take multi screens in account). * * @param removeInsets * remove any existing taskbars and menubars from the result */ public static Rectangle getDesktopBounds(boolean removeInsets) { Rectangle result = new Rectangle(); if (Icy.getMainInterface().isHeadLess()) return result; final GraphicsDevice[] gs = getLocalGraphicsEnvironment().getScreenDevices(); for (int j = 0; j < gs.length; j++) result = result.union(getScreenBounds(gs[j], removeInsets)); return result; } /** * Return the entire desktop bounds (take multi screens in account) * * @see #getDesktopBounds(boolean) */ public static Rectangle getDesktopBounds() { return getDesktopBounds(true); } /** * {@link GraphicsEnvironment#getMaximumWindowBounds()} */ public static Rectangle getMaximumWindowBounds() { if (Icy.getMainInterface().isHeadLess()) return new Rectangle(); return getLocalGraphicsEnvironment().getMaximumWindowBounds(); } /** * {@link GraphicsDevice#getDisplayMode()} */ public static DisplayMode getSystemDisplayMode() { final GraphicsDevice screenDevice = getDefaultScreenDevice(); if (screenDevice != null) return screenDevice.getDisplayMode(); return null; } /** * @deprecated Use {@link #getNumberOfCPUs()} instead */ @Deprecated public static int getAvailableProcessors() { return Runtime.getRuntime().availableProcessors(); } /** * Return total number of processors or cores available to the JVM (same as system) */ public static int getNumberOfCPUs() { return Runtime.getRuntime().availableProcessors(); } /** * Return total amount of free memory available to the JVM (in bytes) */ public static long getJavaFreeMemory() { return getJavaMaxMemory() - getJavaUsedMemory(); } /** * Return maximum amount of memory the JVM will attempt to use (in bytes) */ public static long getJavaMaxMemory() { return Runtime.getRuntime().maxMemory(); } /** * @deprecated Use {@link #getJavaAllocatedMemory()} instead. */ @Deprecated public static long getJavaTotalMemory() { return getJavaAllocatedMemory(); } /** * Return memory currently allocated by the JVM (in bytes) */ public static long getJavaAllocatedMemory() { return Runtime.getRuntime().totalMemory(); } /** * Return actual memory used by the JVM (in bytes) */ public static long getJavaUsedMemory() { return getJavaAllocatedMemory() - Runtime.getRuntime().freeMemory(); } private static OperatingSystemMXBean getOSMXBean() { final java.lang.management.OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean(); if (bean instanceof OperatingSystemMXBean) return (OperatingSystemMXBean) bean; // for (Method method : bean.getClass().getDeclaredMethods()) // { // final int modifiers=method.getModifiers(); // // method.setAccessible(true); // if (method.getName().startsWith("get") // && Modifier.isPublic(modifiers)) { // Object value; // try { // value = method.invoke(bean); // } catch (Exception e) { // value = e; // } // try // System.out.println(method.getName() + " = " + value); // } // if // } // for return null; } /** * Return total physic memory of system (in bytes) */ public static long getTotalMemory() { final OperatingSystemMXBean bean = getOSMXBean(); if (bean != null) return bean.getTotalPhysicalMemorySize(); return -1L; } /** * @deprecated Use {@link #getTotalMemory()} instead */ @Deprecated public static long getSystemTotalMemory() { return getTotalMemory(); } /** * Return free physic memory of system (in bytes) */ public static long getFreeMemory() { final OperatingSystemMXBean bean = getOSMXBean(); if (bean != null) return bean.getFreePhysicalMemorySize(); return -1L; } /** * @deprecated Use {@link #getFreeMemory()} instead */ @Deprecated public static long getSystemFreeMemory() { return getFreeMemory(); } /** * Return system process CPU time */ public static long getProcessCpuTime() { final OperatingSystemMXBean bean = getOSMXBean(); if (bean != null) return bean.getProcessCpuTime(); return -1L; } /** * @deprecated Use {@link #getProcessCpuTime()} instead */ @Deprecated public static long getSystemProcessCpuTime() { return getProcessCpuTime(); } /** * Return average CPU load of the application processes from the last call<br> * (-1 if no available) */ public static int getCpuLoad() { final OperatingSystemMXBean bean = getOSMXBean(); if (bean != null) { // first call if (lastNano == 0) { lastNano = System.nanoTime(); lastCpu = bean.getProcessCpuTime(); } else { final long nanoAfter = System.nanoTime(); final long cpuAfter = bean.getProcessCpuTime(); final long dNano = nanoAfter - lastNano; final long dCpu = cpuAfter - lastCpu; // below 0.5s the reported value isn't very significant if (dNano > 500000000L) { lastCpuLoad = (int) ((dCpu * 100L) / (dNano * getNumberOfCPUs())); lastNano = nanoAfter; lastCpu = cpuAfter; } } return lastCpuLoad; } return -1; } /** * @deprecated Use {@link #getCpuLoad()} instead */ @Deprecated public static int getSystemCpuLoad() { return getCpuLoad(); } /** * Returns the user name. */ public static String getUserName() { return getProperty("user.name"); } /** * Returns the JVM name. */ public static String getJavaName() { return getProperty("java.runtime.name"); } /** * Returns the JVM version. */ public static String getJavaVersion() { String result = getProperty("java.runtime.version"); if (result.equals("unknow")) result = getProperty("java.version"); return result; } /** * Returns the JVM version in number format (ex: 1.6091) */ public static double getJavaVersionAsNumber() { String version = getJavaVersion().replaceAll("[^\\d.]", ""); final int firstSepInd = version.indexOf('.'); if (firstSepInd >= 0) { int lastSepInd = version.lastIndexOf('.'); while (lastSepInd != firstSepInd) { version = version.substring(0, lastSepInd) + version.substring(lastSepInd + 1); lastSepInd = version.lastIndexOf('.'); } } return StringUtil.parseDouble(version, 0); } /** * Returns the JVM data architecture model. */ public static int getJavaArchDataModel() { return Integer.parseInt(getProperty("sun.arch.data.model")); } /** * Returns the Operating System name. */ public static String getOSName() { return getProperty("os.name"); } /** * Returns the Operating System architecture name. */ public static String getOSArch() { return getProperty("os.arch"); } /** * Returns the Operating System version. */ public static String getOSVersion() { return getProperty("os.version"); } /** * Return an id OS string :<br> * <br> * Windows system return <code>SystemUtil.SYSTEM_WINDOWS</code><br> * MAC OS return <code>SystemUtil.SYSTEM_MAC_OS</code><br> * Unix system return <code>SystemUtil.SYSTEM_UNIX</code><br> * <br> * An empty string is returned is OS is unknown. */ public static String getOSNameId() { if (isWindows()) return SYSTEM_WINDOWS; if (isMac()) return SYSTEM_MAC_OS; if (isUnix()) return SYSTEM_UNIX; return ""; } /** * Return an id OS architecture string<br> * example : "win32", "win64", "mac32", "mac64", "unix32"...<br> * The bits number depends only from current installed JVM (32 or 64 bit) * and not directly from host OS.<br> * An empty string is returned if OS is unknown. */ public static String getOSArchIdString() { final String javaBit = Integer.toString(getJavaArchDataModel()); if (isWindows()) return SYSTEM_WINDOWS + javaBit; if (isMac()) return SYSTEM_MAC_OS + javaBit; if (isUnix()) return SYSTEM_UNIX + javaBit; return ""; } /** * Returns true is the operating system support link (symbolic or not). */ public static boolean isLinkSupported() { return isMac() || isUnix(); } /** * Returns true is the JVM is 32 bits. */ public static boolean is32bits() { return getJavaArchDataModel() == 32; } /** * Returns true is the JVM is 64 bits. */ public static boolean is64bits() { return getJavaArchDataModel() == 64; } /** * @deprecated Use {@link #isWindows()} instead. */ @Deprecated public static boolean isWindow() { return isWindows(); } /** * Returns true is the Operating System is Windows based. */ public static boolean isWindows() { return (getOSName().toLowerCase().indexOf("win") >= 0); } /** * Returns true is the Operating System is Mac OS based. */ public static boolean isMac() { return (getOSName().toLowerCase().indexOf("mac") >= 0); } /** * Returns true is the Operating System is Unix / Linux based. */ public static boolean isUnix() { final String os = getOSName().toLowerCase(); return (os.indexOf("nix") >= 0) || (os.indexOf("nux") >= 0); } /** * Returns true is the Operating System is Windows 64 bits whatever is the JVM installed (32 or 64 bits). */ public static boolean isWindows64() { if (!isWindows()) return false; final String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432"); if ((wow64Arch != null) && wow64Arch.endsWith("64")) return true; final String arch = System.getenv("PROCESSOR_ARCHITECTURE"); if ((arch != null) && arch.endsWith("64")) return true; return false; } /** * Returns default temporary directory.<br> * ex:<br> * <code>c:/temp</code><br> * <code>/tmp</code><br> * Same as {@link FileUtil#getTempDirectory()} */ public static String getTempDirectory() { return FileUtil.getTempDirectory(); } /** * Returns temporary native library path (used to load native libraries from plugin) */ public static String getTempLibraryDirectory() { return FileUtil.getTempDirectory() + "/lib"; } public static boolean addToJavaLibraryPath(String directories[]) { try { final String path_separator = System.getProperty("path.separator"); // patch user library paths... final Field pathsField = ReflectionUtil.getField(ClassLoader.class, "usr_paths", true); // get current user paths final ArrayList<String> userPaths = CollectionUtil.asArrayList((String[]) pathsField.get(null)); // get current system paths String sysPaths = System.getProperty("java.library.path"); for (String dir : directories) { if (!userPaths.contains(dir)) userPaths.add(dir); if (!sysPaths.contains(dir)) sysPaths += path_separator + dir; } // set back user library path pathsField.set(null, userPaths.toArray(new String[userPaths.size()])); // set back system library path System.setProperty("java.library.path", sysPaths); return true; } catch (Exception e) { System.err.println(e.getMessage()); System.err.println("Cannot patch Java Library Path."); return false; } } /** * Load the specified native library. * * @param dir * directory from where we want to load the native library. * @param name * name of the library.<br/> * The filename of the library is automatically built depending the operating system. */ public static void loadLibrary(String dir, String name) { final File libPath = new File(dir, System.mapLibraryName(name)); if (libPath.exists()) System.load(libPath.getAbsolutePath()); else System.loadLibrary(name); } /** * Load the specified native library. * * @param pathname * complete path or name of the library we want to load */ public static void loadLibrary(String pathname) { final File file = new File(pathname); if (file.exists()) System.load(file.getAbsolutePath()); else System.loadLibrary(pathname); } }