diff --git a/changelog.html b/changelog.html index 67fcc38739c5049cb772c3eba064de1df04fc4bf..b64e62fa9def0663fbff65956b403540a218e802 100644 --- a/changelog.html +++ b/changelog.html @@ -61,6 +61,9 @@ Upcoming changes
  • Optimizations in fingerprint recording. (issue 16301) +
  • + Using JNR-POSIX rather than JNA-POSIX for better platform support. + (issue 14351)
  • Errors searching build records when builds were misordered. (issue 15652) diff --git a/core/pom.xml b/core/pom.xml index 439073496b8a4b17e690fdaf00a2b702069e38c9..aee9a887c0d02b07378e29378b865983d8b3ca0e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -112,11 +112,16 @@ THE SOFTWARE. - + org.jruby.ext.posix jna-posix 1.0.3 + + com.github.jnr + jnr-posix + 3.0.0 + org.kohsuke trilead-putty-extension diff --git a/core/src/main/java/hudson/Util.java b/core/src/main/java/hudson/Util.java index 696bfe5f64e1c2fc4a2353031739907ffc249468..d91b85fa75ea0f64f28e6dea72da5d1c320a1bb6 100644 --- a/core/src/main/java/hudson/Util.java +++ b/core/src/main/java/hudson/Util.java @@ -40,8 +40,8 @@ import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.Chmod; import org.apache.tools.ant.taskdefs.Copy; import org.apache.tools.ant.types.FileSet; -import org.jruby.ext.posix.FileStat; -import org.jruby.ext.posix.POSIX; +import jnr.posix.FileStat; +import jnr.posix.POSIX; import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import javax.crypto.SecretKey; @@ -281,7 +281,7 @@ public class Util { } try {// try libc chmod - POSIX posix = PosixAPI.get(); + POSIX posix = PosixAPI.jnr(); String path = f.getAbsolutePath(); FileStat stat = posix.stat(path); posix.chmod(path, stat.mode()|0200); // u+w @@ -1073,13 +1073,16 @@ public class Util { } catch (LinkageError e) { // if JNA is unavailable, fall back. // we still prefer to try JNA first as PosixAPI supports even smaller platforms. - if (PosixAPI.supportsNative()) { - r = PosixAPI.get().symlink(targetPath,symlinkFile.getAbsolutePath()); + POSIX posix = PosixAPI.jnr(); + if (posix.isNative()) { + // XXX should we rethrow PosixException as IOException here? + r = posix.symlink(targetPath,symlinkFile.getAbsolutePath()); } } } if (r==null) { // if all else fail, fall back to the most expensive approach of forking a process + // XXX is this really necessary? JavaPOSIX should do this automatically r = new LocalProc(new String[]{ "ln","-s", targetPath, symlinkPath}, new String[0],listener.getLogger(), baseDir).join(); @@ -1221,7 +1224,7 @@ public class Util { } catch (LinkageError e) { // if JNA is unavailable, fall back. // we still prefer to try JNA first as PosixAPI supports even smaller platforms. - return PosixAPI.get().readlink(filename); + return PosixAPI.jnr().readlink(filename); } } diff --git a/core/src/main/java/hudson/cli/ClientAuthenticationCache.java b/core/src/main/java/hudson/cli/ClientAuthenticationCache.java index 25bc040d8b3bd97b294752daad100f14e0d917ed..3525599178a9372b5971a629df23f51a1202466e 100644 --- a/core/src/main/java/hudson/cli/ClientAuthenticationCache.java +++ b/core/src/main/java/hudson/cli/ClientAuthenticationCache.java @@ -118,7 +118,7 @@ public class ClientAuthenticationCache implements Serializable { } // try to protect this file from other users, if we can. - PosixAPI.get().chmod(f.getAbsolutePath(),0600); + PosixAPI.jnr().chmod(f.getAbsolutePath(),0600); return null; } }); diff --git a/core/src/main/java/hudson/os/PosixAPI.java b/core/src/main/java/hudson/os/PosixAPI.java index 1e893c1b903201f1a710072e1799efc69a55a798..2e69069c1c2e4a94e7dfbb782be4e12d9112cbc4 100644 --- a/core/src/main/java/hudson/os/PosixAPI.java +++ b/core/src/main/java/hudson/os/PosixAPI.java @@ -1,45 +1,74 @@ package hudson.os; -import org.jruby.ext.posix.JavaPOSIX; -import org.jruby.ext.posix.POSIX; -import org.jruby.ext.posix.POSIXFactory; -import org.jruby.ext.posix.POSIXHandler; -import org.jruby.ext.posix.POSIX.ERRORS; - import java.io.File; import java.io.InputStream; import java.io.PrintStream; import java.util.Map; import java.util.logging.Logger; +import jnr.constants.platform.Errno; +import jnr.posix.POSIX; +import jnr.posix.POSIXFactory; +import jnr.posix.util.DefaultPOSIXHandler; /** * POSIX API wrapper. - * + * Formerly used the jna-posix library, but this has been superseded by jnr-posix. * @author Kohsuke Kawaguchi */ public class PosixAPI { - public static POSIX get() { + + private static POSIX posix; + + /** + * Load the JNR implementation of the POSIX APIs for the current platform. + * Runtime exceptions will be of type {@link PosixException}. + * @return some implementation (even on Windows or unsupported Unix) + * @since 1.518 + */ + public static synchronized POSIX jnr() { + if (posix == null) { + posix = POSIXFactory.getPOSIX(new DefaultPOSIXHandler() { + @Override public void error(Errno error, String extraData) { + throw new PosixException("native error " + error.description() + " " + extraData, convert(error)); + } + @Override public void error(Errno error, String methodName, String extraData) { + throw new PosixException("native error calling " + methodName + ": " + error.description() + " " + extraData, convert(error)); + } + private org.jruby.ext.posix.POSIX.ERRORS convert(Errno error) { + try { + return org.jruby.ext.posix.POSIX.ERRORS.valueOf(error.name()); + } catch (IllegalArgumentException x) { + return org.jruby.ext.posix.POSIX.ERRORS.EIO; // PosixException.message has real error anyway + } + } + }, true); + } return posix; } /** - * @deprecated as of 1.448 - * Use {@link #supportsNative()}. + * @deprecated use {@link #jnr} and {@link POSIX#isNative} */ + @Deprecated public boolean isNative() { return supportsNative(); } /** - * Determine if the jna-posix library could not provide native support, and - * used a fallback java implementation which does not support many operations. + * @deprecated use {@link #jnr} and {@link POSIX#isNative} */ + @Deprecated public static boolean supportsNative() { - return !(posix instanceof JavaPOSIX); + return !(jnaPosix instanceof org.jruby.ext.posix.JavaPOSIX); } - - private static final POSIX posix = POSIXFactory.getPOSIX(new POSIXHandler() { - public void error(ERRORS errors, String s) { + + private static org.jruby.ext.posix.POSIX jnaPosix; + /** @deprecated Use {@link #jnr} instead. */ + @Deprecated + public static synchronized org.jruby.ext.posix.POSIX get() { + if (jnaPosix == null) { + jnaPosix = org.jruby.ext.posix.POSIXFactory.getPOSIX(new org.jruby.ext.posix.POSIXHandler() { + public void error(org.jruby.ext.posix.POSIX.ERRORS errors, String s) { throw new PosixException(s,errors); } @@ -87,6 +116,9 @@ public class PosixAPI { return System.err; } }, true); + } + return jnaPosix; + } private static final Logger LOGGER = Logger.getLogger(PosixAPI.class.getName()); } diff --git a/core/src/main/java/hudson/os/PosixException.java b/core/src/main/java/hudson/os/PosixException.java index 93e96ef5d0d1aec7a7ad23968ca62068741a9cec..03cdd50e38b8c176b7ecc5571d1c10c8a855f96d 100644 --- a/core/src/main/java/hudson/os/PosixException.java +++ b/core/src/main/java/hudson/os/PosixException.java @@ -4,7 +4,7 @@ import org.jruby.ext.posix.POSIX.ERRORS; /** * Indicates an error during POSIX API call. - * + * @see PosixAPI * @author Kohsuke Kawaguchi */ public class PosixException extends RuntimeException { @@ -15,6 +15,8 @@ public class PosixException extends RuntimeException { this.errors = errors; } + /** @deprecated Leaks reference to deprecated jna-posix API. */ + @Deprecated public ERRORS getErrorCode() { return errors; } diff --git a/core/src/main/java/hudson/tools/ZipExtractionInstaller.java b/core/src/main/java/hudson/tools/ZipExtractionInstaller.java index 1fa7adb8bd0fdcecc07a6be852359f98b7e9bd7f..48ef62b97cf053693b355bf239ce9b9cc7a09201 100644 --- a/core/src/main/java/hudson/tools/ZipExtractionInstaller.java +++ b/core/src/main/java/hudson/tools/ZipExtractionInstaller.java @@ -137,7 +137,7 @@ public class ZipExtractionInstaller extends ToolInstaller { } catch (LinkageError e) { // if JNA is unavailable, fall back. // we still prefer to try JNA first as PosixAPI supports even smaller platforms. - PosixAPI.get().chmod(f.getAbsolutePath(),0755); + PosixAPI.jnr().chmod(f.getAbsolutePath(),0755); } } } else { diff --git a/core/src/main/java/hudson/util/IOUtils.java b/core/src/main/java/hudson/util/IOUtils.java index 4d046b7541294c0dd3b6db3fc026a50dffe5443b..60faaaf032726d0029604c9f67c80af2c65a0419 100644 --- a/core/src/main/java/hudson/util/IOUtils.java +++ b/core/src/main/java/hudson/util/IOUtils.java @@ -122,7 +122,7 @@ public class IOUtils extends org.apache.commons.io.IOUtils { */ public static int mode(File f) throws PosixException { if(Functions.isWindows()) return -1; - return PosixAPI.get().stat(f.getPath()).mode(); + return PosixAPI.jnr().stat(f.getPath()).mode(); } /** diff --git a/core/src/main/java/hudson/util/jna/GNUCLibrary.java b/core/src/main/java/hudson/util/jna/GNUCLibrary.java index aa397b5b371e1a73406b6440a4ef778d439be7bb..8659089f52ab72ff25fd75d8d58c3ab67f7a996c 100644 --- a/core/src/main/java/hudson/util/jna/GNUCLibrary.java +++ b/core/src/main/java/hudson/util/jna/GNUCLibrary.java @@ -30,6 +30,8 @@ import com.sun.jna.Native; import com.sun.jna.Memory; import com.sun.jna.NativeLong; import com.sun.jna.ptr.IntByReference; +import hudson.os.PosixAPI; +import jnr.posix.POSIX; import org.jvnet.libpam.impl.CLibrary.passwd; /** @@ -38,7 +40,7 @@ import org.jvnet.libpam.impl.CLibrary.passwd; *

    * Not available on all platforms (such as Linux/PPC, IBM mainframe, etc.), so the caller should recover gracefully * in case of {@link LinkageError}. See HUDSON-4820. - * + *

    Consider deprecating all methods present also in {@link POSIX} (as obtained by {@link PosixAPI#jnr}). * @author Kohsuke Kawaguchi */ public interface GNUCLibrary extends Library {