diff --git a/pom.xml b/pom.xml index 60c17b0..8f2535e 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,7 @@ ${findbugs-maven-plugin.version} Max + Low true false @@ -86,6 +87,11 @@ 3.0.0 provided + + org.kohsuke + access-modifier-annotation + 1.7 + @@ -94,6 +100,13 @@ gitsite:git@github.com/kohsuke/${project.artifactId}.git + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + diff --git a/src/main/java/org/jvnet/winp/Main.java b/src/main/java/org/jvnet/winp/Main.java index 2de5f4d..1f6b046 100644 --- a/src/main/java/org/jvnet/winp/Main.java +++ b/src/main/java/org/jvnet/winp/Main.java @@ -1,10 +1,14 @@ package org.jvnet.winp; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + /** * Test driver class * * @author Kohsuke Kawaguchi */ +@Restricted(NoExternalUse.class) public class Main { public static void main(String[] args) { WinProcess.enableDebugPrivilege(); diff --git a/src/main/java/org/jvnet/winp/Native.java b/src/main/java/org/jvnet/winp/Native.java index 4f04dcf..7a57caf 100755 --- a/src/main/java/org/jvnet/winp/Native.java +++ b/src/main/java/org/jvnet/winp/Native.java @@ -10,6 +10,8 @@ import java.security.NoSuchAlgorithmException; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; /** * Functions defined in the DLL. @@ -55,13 +57,16 @@ class Native { 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"; + //TODO: usage of this field has been removed in https://github.com/kohsuke/winp/pull/27 + // Likely it needs to be fixed private static final String UNPACK_DLL_TO_PARENT_DIR = "winp.unpack.dll.to.parent.dir"; static { load(); } - private static String md5(URL res) { + @Nonnull + private static String md5(@Nonnull URL res) throws IOException { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); InputStream in = res.openStream(); @@ -75,13 +80,13 @@ private static String md5(URL res) { in.close(); } } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); + throw new IOException("Cannot find MD5 algorithm", e); } catch (IOException e) { - throw new Error("failed to checksum " + res + ": " + e, e); + throw new IOException("failed to checksum " + res + ": " + e, e); } } - private static void load() { + private static void load() throws UnsatisfiedLinkError { final URL res = Native.class.getClassLoader().getResource(DLL_NAME + ".dll"); @@ -100,7 +105,7 @@ private static void load() { } } - private static void loadByUrl(URL res) throws IOException { + private static void loadByUrl(@Nonnull URL res) throws IOException { String url = res.toExternalForm(); @@ -128,11 +133,12 @@ private static void loadByUrl(URL res) throws IOException { loadDll(dllFile); } - private static File extractToStaticLocation(URL url) throws IOException { + @Nonnull + private static File extractToStaticLocation(@Nonnull URL url) throws IOException { File jarFile = getJarFile(url); if (jarFile == null) { - throw new RuntimeException("Failed to locate JAR file by URL " + url); + throw new IOException("Failed to locate JAR file by URL " + url); } String preferred = System.getProperty(DLL_TARGET); @@ -143,7 +149,8 @@ private static File extractToStaticLocation(URL url) throws IOException { return destFile; } - private static File extractToTmpLocation(URL res) throws IOException { + @Nonnull + private static File extractToTmpLocation(@Nonnull URL res) throws IOException { File tmpFile = File.createTempFile(DLL_NAME, ".dll"); tmpFile.deleteOnExit(); @@ -151,7 +158,8 @@ private static File extractToTmpLocation(URL res) throws IOException { return tmpFile; } - private static File getJarFile(URL res) { + @CheckForNull + /**package*/ static File getJarFile(@Nonnull URL res) { String url = res.toExternalForm(); if (!(url.startsWith("jar:") || url.startsWith("wsjar:"))) { @@ -175,6 +183,7 @@ private static File getJarFile(URL res) { // this indicates file://host/path-in-host format // Windows maps UNC path to this. On Unix, there's no well defined // semantics for this. + LOGGER.log(Level.FINE, "file://PATH semantics is used. On Unix the behavior is undefined, hence the results may differ from the expectation."); } filePortion = URLDecoder.decode(filePortion); @@ -226,7 +235,8 @@ private static void copyStream(InputStream in, OutputStream out) throws IOExcept /** * Convert 128bit data into hex string. */ - private static String toHex32(byte[] b) { + @Nonnull + private static String toHex32(@Nonnull byte[] b) { return String.format("%032X",new BigInteger(1,b)); } } diff --git a/src/main/java/org/jvnet/winp/WinProcess.java b/src/main/java/org/jvnet/winp/WinProcess.java index 63a58f2..67c66f8 100755 --- a/src/main/java/org/jvnet/winp/WinProcess.java +++ b/src/main/java/org/jvnet/winp/WinProcess.java @@ -1,13 +1,17 @@ package org.jvnet.winp; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.lang.reflect.Field; import java.util.Comparator; import java.util.TreeMap; import java.util.Iterator; +import java.util.Locale; +import java.util.NoSuchElementException; import java.util.logging.Level; import java.util.logging.Logger; import static java.util.logging.Level.FINE; +import javax.annotation.Nonnull; /** * Represents a Windows process. @@ -36,8 +40,12 @@ public WinProcess(int pid) { /** * Wraps {@link Process} into {@link WinProcess}. + * + * @param proc Process to be wrapped */ - public WinProcess(Process proc) { + @SuppressFBWarnings(value = "DP_DO_INSIDE_DO_PRIVILEGED", + justification = "Enabled for now, the calling code is expected to have appropriate security permissions") + public WinProcess(@Nonnull Process proc) { try { Field f = proc.getClass().getDeclaredField("handle"); f.setAccessible(true); @@ -121,13 +129,15 @@ public synchronized String getCommandLine() { * If we fail to obtain the command line. For example, * maybe we didn't have enough security privileges. */ - public synchronized TreeMap getEnvironmentVariables() { - if(envVars==null) + @Nonnull + public synchronized TreeMap getEnvironmentVariables() { + if (envVars == null) { parseCmdLineAndEnvVars(); + } return envVars; } - private void parseCmdLineAndEnvVars() { + private void parseCmdLineAndEnvVars() throws WinpException { String s = Native.getCmdLineAndEnvVars(pid); if(s==null) throw new WinpException("Failed to obtain for PID="+pid); @@ -157,7 +167,9 @@ private void parseCmdLineAndEnvVars() { private static final Comparator CASE_INSENSITIVE_COMPARATOR = new Comparator() { public int compare(String o1, String o2) { - return o1.toUpperCase().compareTo(o2.toUpperCase()); + // Rely on the default system locale + Locale loc = Locale.getDefault(); + return o1.toUpperCase(loc).compareTo(o2.toUpperCase(loc)); } }; @@ -192,7 +204,10 @@ public boolean hasNext() { return pos