//OS.java //------------------------------------------- //(C) by Michael Peter Christen; mc@yacy.net //first published on http://www.anomic.de //Frankfurt, Germany, 2004 //last major change: 11.03.2004 // //This program 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 2 of the License, or //(at your option) any later version. // //This program 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 this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // this class was taken from the YaCy project package org.loklak.tools; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.eclipse.jetty.util.log.Log; public final class OS { // constants for system identification public enum System { MacOSX, // all Mac OS X Unix, // all Unix/Linux type systems Windows, // all Windows 95/98/NT/2K/XP Unknown; // any other system } // system-identification statics public static final System systemOS; public static final boolean isMacArchitecture; public static final boolean isUnixFS; public static final boolean canExecUnix; public static final boolean isWindows; public static final boolean isWin32; // calculated system constants public static int maxPathLength = 65535; // Macintosh-specific statics public static final Map<String, String> macFSTypeCache = new HashMap<String, String>(); public static final Map<String, String> macFSCreatorCache = new HashMap<String, String>(); private final static Set<PosixFilePermission> securePerm = new HashSet<PosixFilePermission>(); // system beans private static OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); // static initialization static { // check operation system type final Properties sysprop = java.lang.System.getProperties(); final String sysname = sysprop.getProperty("os.name","").toLowerCase(); if (sysname.startsWith("mac os x")) systemOS = System.MacOSX; else if (sysname.startsWith("windows")) systemOS = System.Windows; else if ((sysname.startsWith("linux")) || (sysname.startsWith("unix"))) systemOS = System.Unix; else systemOS = System.Unknown; isMacArchitecture = systemOS == System.MacOSX; isUnixFS = systemOS == System.MacOSX || systemOS == System.Unix; canExecUnix = isUnixFS || systemOS != System.Windows; isWindows = systemOS == System.Windows; isWin32 = isWindows && java.lang.System.getProperty("os.arch", "").contains("x86"); // set up maximum path length according to system if (isWindows) maxPathLength = 255; else maxPathLength = 65535; securePerm.add(PosixFilePermission.OWNER_READ); securePerm.add(PosixFilePermission.OWNER_WRITE); securePerm.add(PosixFilePermission.OWNER_EXECUTE); } public final static void protectPath(Path path) { try { Files.setPosixFilePermissions(path, securePerm); } catch (UnsupportedOperationException | IOException e) {} } private static long copy(final InputStream source, final OutputStream dest, final long count) throws IOException { assert count < 0 || count > 0 : "precondition violated: count == " + count + " (nothing to copy)"; if ( count == 0 ) { // no bytes to copy return 0; } final byte[] buffer = new byte[2048]; int chunkSize = (int) ((count > 0) ? Math.min(count, 2048) : 2048); int c; long total = 0; while ( (c = source.read(buffer, 0, chunkSize)) > 0 ) { dest.write(buffer, 0, c); dest.flush(); total += c; if ( count > 0 && count == total) { break; } } dest.flush(); return total; } private static void copy(final InputStream source, final File dest, final long count) throws IOException { final String path = dest.getParent(); if ( path != null && path.length() > 0 ) { new File(path).mkdirs(); } FileOutputStream fos = null; try { fos = new FileOutputStream(dest); copy(source, fos, count); } finally { if ( fos != null ) { try { fos.close(); } catch (final Exception e ) { Log.getLog().warn(e); } } } } private static void copy(final InputStream source, final File dest) throws IOException { copy(source, dest, -1); } private static void copy(final byte[] source, final File dest) throws IOException { copy(new ByteArrayInputStream(source), dest); } private static void deployScript(final File scriptFile, final String theScript) throws IOException { copy(UTF8.getBytes(theScript), scriptFile); if(!isWindows){ // set executable try { Runtime.getRuntime().exec("chmod 755 " + scriptFile.getAbsolutePath().replaceAll(" ", "\\ ")).waitFor(); } catch (final InterruptedException e) { Log.getLog().warn("DEPLOY of script file failed. file = " + scriptFile.getAbsolutePath(), e); throw new IOException(e.getMessage()); } } } /** * use a hack to get the current process PID * @return the PID of the current java process or -1 if the PID cannot be obtained */ public static int getPID() { final String pids = ManagementFactory.getRuntimeMXBean().getName(); final int p = pids.indexOf('@'); return p >= 0 ? parseIntDecSubstring(pids, 0, p) : -1; } private static final int parseIntDecSubstring(String s, int startPos, final int endPos) throws NumberFormatException { if (s == null || endPos > s.length() || endPos <= startPos) throw new NumberFormatException(s); int result = 0; boolean negative = false; int i = startPos; int limit = -Integer.MAX_VALUE; final int multmin; int digit; char c; char firstChar = s.charAt(i); if (firstChar < '0') { if (firstChar == '-') { negative = true; limit = Integer.MIN_VALUE; } else if (firstChar != '+') throw new NumberFormatException(s); i++; if (endPos == i) throw new NumberFormatException(s); } multmin = limit / 10; while (i < endPos) { c = s.charAt(i++); if (c == ' ') break; digit = c - '0'; if (digit < 0 || digit > 9 || result < multmin) throw new NumberFormatException(s); result *= 10; //result = (result << 3) + (result << 1); if (result < limit + digit) throw new NumberFormatException(s); result -= digit; } return negative ? result : -result; } private static final String LF_STRING = UTF8.String(new byte[]{10}); public static void execAsynchronous(final File scriptFile) throws IOException { // runs a script as separate thread String starterFileExtension = null; String script = null; if(isWindows){ starterFileExtension = ".starter.bat"; // use /K to debug, /C for release script = "start /MIN CMD /C \"" + scriptFile.getAbsolutePath() + "\""; } else { // unix/linux starterFileExtension = ".starter.sh"; script = "#!/bin/sh" + LF_STRING + scriptFile.getAbsolutePath().replaceAll(" ", "\\ ") + " &" + LF_STRING; } final File starterFile = new File(scriptFile.getAbsolutePath().replaceAll(" ", "\\ ") + starterFileExtension); deployScript(starterFile, script); try { Runtime.getRuntime().exec(starterFile.getAbsolutePath().replaceAll(" ", "\\ ")).waitFor(); } catch (final InterruptedException e) { throw new IOException(e.getMessage()); } starterFile.delete(); } public static List<String> execSynchronous(final String command) throws IOException { // runs a unix/linux command and returns output as Vector of Strings // this method blocks until the command is executed final Process p = Runtime.getRuntime().exec(command); return execSynchronousProcess(p); } private static List<String> execSynchronousProcess(Process p) throws IOException { String line; BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); final List<String> output = new ArrayList<String>(); while ((line = in.readLine()) != null) output.add(line); in.close(); in = new BufferedReader(new InputStreamReader(p.getErrorStream())); while ((line = in.readLine()) != null) output.add(line); in.close(); return output; } public static double getSystemLoadAverage() { return osBean.getSystemLoadAverage(); } public static double getSystemCpuLoad() { return getOSBean("getSystemCpuLoad"); } public static double getProcessCpuLoad() { return getOSBean("getProcessCpuLoad"); } private static double getOSBean(String name) { try { Method m = osBean.getClass().getMethod(name); m.setAccessible(true); Object o = m.invoke(osBean); if (o instanceof Double) return ((Double) o).doubleValue(); } catch (Throwable e) {} return 0.0d; } }