Checker Framework integration (#126)

This commit is contained in:
Andrew Steinborn
2018-10-27 21:45:42 -04:00
committed by GitHub
parent dccf688da8
commit 32829c5637
106 changed files with 1170 additions and 708 deletions

View File

@@ -2,9 +2,13 @@ plugins {
id 'java'
}
apply from: '../gradle/checkerframework.gradle'
dependencies {
compile "com.google.guava:guava:${guavaVersion}"
compile "io.netty:netty-buffer:${nettyVersion}"
compile "org.checkerframework:checker-qual:${checkerFrameworkVersion}"
testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
testCompile "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
}

View File

@@ -1,88 +1,64 @@
package com.velocitypowered.natives.util;
import com.google.common.collect.ImmutableList;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
public class NativeCodeLoader<T> implements Supplier<T> {
private final List<Variant<T>> variants;
private volatile Variant<T> selected;
public final class NativeCodeLoader<T> implements Supplier<T> {
private final Variant<T> selected;
public NativeCodeLoader(List<Variant<T>> variants) {
this.variants = ImmutableList.copyOf(variants);
NativeCodeLoader(List<Variant<T>> variants) {
this.selected = getVariant(variants);
}
@Override
public T get() {
return tryLoad().object;
return selected.object;
}
private Variant<T> tryLoad() {
if (selected != null) {
return selected;
}
synchronized (this) {
if (selected != null) {
return selected;
private static <T> Variant<T> getVariant(List<Variant<T>> variants) {
for (Variant<T> variant : variants) {
T got = variant.get();
if (got == null) {
continue;
}
for (Variant<T> variant : variants) {
T got = variant.get();
if (got == null) {
continue;
}
selected = variant;
return selected;
}
throw new IllegalArgumentException("Can't find any suitable variants");
return variant;
}
throw new IllegalArgumentException("Can't find any suitable variants");
}
public String getLoadedVariant() {
return tryLoad().name;
return selected.name;
}
static class Variant<T> {
private volatile boolean available;
private Status status;
private final Runnable setup;
private final String name;
private final T object;
private volatile boolean hasBeenSetup = false;
Variant(BooleanSupplier available, Runnable setup, String name, T object) {
this.available = available.getAsBoolean();
Variant(BooleanSupplier possiblyAvailable, Runnable setup, String name, T object) {
this.status = possiblyAvailable.getAsBoolean() ? Status.POSSIBLY_AVAILABLE : Status.NOT_AVAILABLE;
this.setup = setup;
this.name = name;
this.object = object;
}
public T get() {
if (!available) {
public @Nullable T get() {
if (status == Status.NOT_AVAILABLE || status == Status.SETUP_FAILURE) {
return null;
}
// Make sure setup happens only once
if (!hasBeenSetup) {
synchronized (this) {
// We change availability if need be below, may as well check it again here for sanity.
if (!available) {
return null;
}
// Okay, now try the setup if we haven't done so yet.
if (!hasBeenSetup) {
try {
setup.run();
hasBeenSetup = true;
return object;
} catch (Exception e) {
available = false;
return null;
}
}
if (status == Status.POSSIBLY_AVAILABLE) {
try {
setup.run();
status = Status.SETUP;
} catch (Exception e) {
status = Status.SETUP_FAILURE;
return null;
}
}
@@ -90,9 +66,16 @@ public class NativeCodeLoader<T> implements Supplier<T> {
}
}
static final BooleanSupplier MACOS = () -> System.getProperty("os.name").equalsIgnoreCase("Mac OS X") &&
private enum Status {
NOT_AVAILABLE,
POSSIBLY_AVAILABLE,
SETUP,
SETUP_FAILURE
}
static final BooleanSupplier MACOS = () -> System.getProperty("os.name", "").equalsIgnoreCase("Mac OS X") &&
System.getProperty("os.arch").equals("x86_64");
static final BooleanSupplier LINUX = () -> System.getProperties().getProperty("os.name").equalsIgnoreCase("Linux") &&
static final BooleanSupplier LINUX = () -> System.getProperties().getProperty("os.name", "").equalsIgnoreCase("Linux") &&
System.getProperty("os.arch").equals("amd64");
static final BooleanSupplier ALWAYS = () -> true;
}

View File

@@ -8,6 +8,7 @@ import com.velocitypowered.natives.encryption.JavaVelocityCipher;
import com.velocitypowered.natives.encryption.VelocityCipherFactory;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -21,7 +22,12 @@ public class Natives {
return () -> {
try {
Path tempFile = Files.createTempFile("native-", path.substring(path.lastIndexOf('.')));
Files.copy(Natives.class.getResourceAsStream(path), tempFile, StandardCopyOption.REPLACE_EXISTING);
InputStream nativeLib = Natives.class.getResourceAsStream(path);
if (nativeLib == null) {
throw new IllegalStateException("Native library " + path + " not found.");
}
Files.copy(nativeLib, tempFile, StandardCopyOption.REPLACE_EXISTING);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
Files.deleteIfExists(tempFile);