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

org.jvnet.winp.Native Maven / Gradle / Ivy

There is a newer version: 1.28
Show newest version
package org.jvnet.winp;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URISyntaxException;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Functions defined in the DLL.
 * 
 * @author Kohsuke Kawaguchi
 */
class Native {

    public static final String DLL_NAME = "64".equals(System.getProperty("sun.arch.data.model")) ? "winp.x64" : "winp";

    native static boolean kill(int pid, boolean recursive);
    native static boolean isCriticalProcess(int pid);
    native static int setPriority(int pid, int value);
    native static int getProcessId(int handle);
    native static boolean exitWindowsEx(int flags,int reasonCode);

    /**
     * Gets the command line and environment variables of the process
     * identified by the process ID.
     * If the environment variables are not required, consider using {@link #getCmdLine(int)}.
     *
     * 

* To simplify the JNI side, the resulting string is structured to * "cmdlineargs\0env1=val1\0env2=val2\0..." */ native static String getCmdLineAndEnvVars(int pid); /** * Gets the command line of the process identified by the process ID. * @param pid Process ID * @return Command line or {@code null} if it cannot be retrieved * @throws WinpException Operation failure */ native static String getCmdLine(int pid) throws WinpException; /** * Enumerate all processes. * * @param result * Receives process IDs. * @return * The number of processes obtained. If this is the same * as result.length, a bigger buffer was necessary. * In case of error, 0. */ native static int enumProcesses(int[] result); native static void enableDebugPrivilege(); native static void noop(); private static final Logger LOGGER = Logger.getLogger(Native.class.getName()); // system property holding the preferred folder for copying the dll file to. private static final String DLL_TARGET = "winp.folder.preferred"; private static final String UNPACK_DLL_TO_PARENT_DIR = "winp.unpack.dll.to.parent.dir"; static { load(); } private static String md5(URL res) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); InputStream in = res.openStream(); try { byte[] buf = new byte[8192]; int len; while((len=in.read(buf))>=0) md5.update(buf, 0, len); return toHex32(md5.digest()); } finally { in.close(); } } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); } catch (IOException e) { throw new Error("failed to checksum " + res + ": " + e, e); } } private static void load() { final URL res = Native.class.getClassLoader().getResource(DLL_NAME + ".dll"); try { if (res != null) { loadByUrl(res); } else { // we don't know where winp.dll is, so let's just hope the user put it somewhere System.loadLibrary(DLL_NAME); } } catch (Throwable cause) { UnsatisfiedLinkError error = new UnsatisfiedLinkError("Unable to load " + DLL_NAME + ".dll"); error.initCause(cause); throw error; } } private static void loadByUrl(URL res) throws IOException { String url = res.toExternalForm(); if (url.startsWith("file:")) { // during debug File f; try { f = new File(res.toURI()); } catch (URISyntaxException e) { f = new File(res.getPath()); } loadDll(f); return; } try { File dllFile = extractToStaticLocation(res); loadDll(dllFile); return; } catch (Throwable e) { LOGGER.log(Level.WARNING, "Failed to load DLL from static location", e); } File dllFile = extractToTmpLocation(res); loadDll(dllFile); } private static File extractToStaticLocation(URL url) throws IOException { File jarFile = getJarFile(url); if (jarFile == null) { throw new RuntimeException("Failed to locate JAR file by URL " + url); } String preferred = System.getProperty(DLL_TARGET); File destFile = new File(preferred != null ? new File(preferred) : jarFile.getParentFile(), DLL_NAME + '.' + md5(url) + ".dll"); if (!destFile.exists()) { copyStream(url.openStream(), new FileOutputStream(destFile)); } return destFile; } private static File extractToTmpLocation(URL res) throws IOException { File tmpFile = File.createTempFile(DLL_NAME, ".dll"); tmpFile.deleteOnExit(); copyStream(res.openStream(), new FileOutputStream(tmpFile)); return tmpFile; } private static File getJarFile(URL res) { String url = res.toExternalForm(); if (!(url.startsWith("jar:") || url.startsWith("wsjar:"))) { return null; } int idx = url.lastIndexOf('!'); String filePortion = url.substring(url.indexOf(':') + 1, idx); while (filePortion.startsWith("/")) filePortion = filePortion.substring(1); if (!filePortion.startsWith("file:")) { return null; } filePortion = filePortion.substring(5); if (filePortion.startsWith("///")) { // JDK on Unix uses file:/home/kohsuke/abc, whereas // I believe RFC says file:///home/kohsuke/abc/... is correct. filePortion = filePortion.substring(2); } else if (filePortion.startsWith("//")) { // this indicates file://host/path-in-host format // Windows maps UNC path to this. On Unix, there's no well defined // semantics for this. } filePortion = URLDecoder.decode(filePortion); return new File(filePortion.replace('/', File.separatorChar)); } /** * Loads a DLL with a precaution for multi-classloader situation. */ @SuppressFBWarnings(value = "DM_GC", justification = "Fallback in the case of linkage errors, see details in the code") private static void loadDll(File dllFile) { try { System.load(dllFile.getPath()); } catch (LinkageError e) { // see http://forum.java.sun.com/thread.jspa?threadID=618431&messageID=3462466 // if another ClassLoader loaded winp, loading may fail // even if the classloader is no longer in use, due to GC delay. // this is a poor attempt to see if we can force GC early on. for( int i=0; i<5; i++ ) { try { System.gc(); System.gc(); Thread.sleep(1000); System.load(dllFile.getPath()); return; } catch (InterruptedException x) { throw e; // throw the original exception } catch (LinkageError x) { // retry } } // still failing after retry. throw e; } } private static void copyStream(InputStream in, OutputStream out) throws IOException { try { byte[] buf = new byte[8192]; int len; while((len=in.read(buf))>=0) out.write(buf,0,len); } finally { in.close(); out.close(); } } /** * Convert 128bit data into hex string. */ private static String toHex32(byte[] b) { return String.format("%032X",new BigInteger(1,b)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy