Skip to content

Commit

Permalink
Merge pull request #3 from alexarchambault/develop
Browse files Browse the repository at this point in the history
Tweak things for when the library is proguarded
  • Loading branch information
alexarchambault authored Apr 27, 2021
2 parents 4ce8c97 + 790f869 commit d78ad8f
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 23 deletions.
10 changes: 3 additions & 7 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import mill._, scalalib._
import scala.concurrent.duration._


object `windows-jni-utils` extends WindowsUtils with HasCSources with JniUtilsPublishModule {
object `windows-jni-utils` extends WindowsUtils with HasCSources with JniUtilsPublishModule with WithDllNameJava {
def linkingLibs = Seq("ole32")

def compile = T{
Expand Down Expand Up @@ -50,7 +50,7 @@ object `windows-jni-utils-tests` extends ScalaModule with JniUtilsPublishModule

// compile these projects to generate or update JNI header files
object headers extends Module {
object `windows-jni-utils` extends WindowsUtils with GenerateHeaders
object `windows-jni-utils` extends WindowsUtils with GenerateHeaders with WithDllNameJava
object `windows-jni-utils-bootstrap` extends WindowsUtils with GenerateHeaders {
def moduleDeps = Seq(`windows-jni-utils`)
def cDirectory = `windows-jni-utils`.cDirectory()
Expand All @@ -68,12 +68,8 @@ object headers extends Module {
define.BasePath(super.millModuleBasePath.value / os.up)
}

trait WindowsUtils extends MavenModule with JniUtilsPublishVersion with WithDllNameJava {
trait WindowsUtils extends MavenModule with JniUtilsPublishVersion {
def compileIvyDeps = Agg(Deps.svm)
def dllName = T{
val ver = publishVersion()
s"csjniutils-$ver"
}
}

def windowsJvmArchive = T.persistent {
Expand Down
7 changes: 6 additions & 1 deletion settings.sc
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,6 @@ def publishSonatype(
}

trait WithDllNameJava extends JavaModule {
def dllName: T[String]
def generatedSources = T{
val f = T.ctx().dest / "coursier" / "jniutils" / "DllName.java"
val dllName0 = dllName()
Expand All @@ -296,4 +295,10 @@ trait WithDllNameJava extends JavaModule {
os.write(f, content, createFolders = true)
Seq(PathRef(f))
}

def publishVersion: T[String]
def dllName = T{
val ver = publishVersion()
s"csjniutils-$ver"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ jstring _Java_coursier_jniutils_NativeCalls_Terminal_lastError
DWORD err = GetLastError();
char dummy[1];
const int len = snprintf(dummy, 1, "error:%s error %lu", origin, err);
char *buf = malloc(len);
snprintf(buf, len, "error:%s error %lu", origin, err);
char *buf = malloc(len + 1);
snprintf(buf, len + 1, "error:%s error %lu", origin, err);
const jstring result = (*env)->NewStringUTF(env, buf);
free(buf);
return result;
Expand All @@ -23,9 +23,9 @@ jstring _Java_coursier_jniutils_NativeCalls_Terminal_format
va_start(ap, format);
const int len = vsnprintf(dummy, 1, format, ap);
va_end(ap);
char *buf = malloc(len);
char *buf = malloc(len + 1);
va_start(ap, format);
vsnprintf(buf, len, format, ap);
vsnprintf(buf, len + 1, format, ap);
va_end(ap);
const jstring result = (*env)->NewStringUTF(env, buf);
free(buf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_SetUserEnvironmentVariableNative
(JNIEnv *env, jclass class, jbyteArray key, jbyteArray value) {

const jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
const jbyte *valueStr = (*env)->GetByteArrayElements(env, value, NULL);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
jbyte *valueStr = (*env)->GetByteArrayElements(env, value, NULL);
const size_t valueLen = (*env)->GetArrayLength(env, value);

LSTATUS status = RegSetKeyValueA(
Expand Down Expand Up @@ -40,7 +40,7 @@ JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_SetUserEnvironme
JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_GetUserEnvironmentVariableNative
(JNIEnv *env, jclass class, jbyteArray key) {

const jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);

DWORD type = 0;

Expand Down Expand Up @@ -100,7 +100,7 @@ JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_GetUserEnvironme
JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_DeleteUserEnvironmentVariableNative
(JNIEnv *env, jclass class, jbyteArray key) {

const jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);
jbyte *keyStr = (*env)->GetByteArrayElements(env, key, NULL);

LSTATUS status = RegDeleteKeyValueA(
HKEY_CURRENT_USER,
Expand All @@ -109,11 +109,11 @@ JNIEXPORT jbyteArray JNICALL Java_coursier_jniutils_NativeCalls_DeleteUserEnviro
);
(*env)->ReleaseByteArrayElements(env, key, keyStr, JNI_ABORT);
if (status != ERROR_SUCCESS && status != ERROR_FILE_NOT_FOUND) {
size_t size = 256;
jbyteArray arr = (*env)->NewByteArray(env, size);
char dummy = 0;
int len = snprintf(&dummy, 1, "E%lu", status);
jbyteArray arr = (*env)->NewByteArray(env, len + 1);
jbyte *data = (*env)->GetByteArrayElements(env, arr, NULL);
snprintf(data, size, "E%lu", status);
data[size - 1] = '\0';
snprintf(data, len + 1, "E%lu", status);
(*env)->ReleaseByteArrayElements(env, arr, data, 0);
return arr;
}
Expand Down
26 changes: 25 additions & 1 deletion windows-jni-utils/src/main/java/coursier/jniutils/NativeApi.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package coursier.jniutils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public abstract class NativeApi {

public abstract String terminalSize();
Expand All @@ -16,8 +19,29 @@ public abstract class NativeApi {
private static NativeApi instance = null;
public static NativeApi get() {
if (instance == null) {
instance = NativeCalls.nativeApi();
// Equivalent to
// instance = NativeCalls.nativeApi();
// but without referencing coursier.jniutils.NativeCalls from here, so
// that if this code gets proguarded, the JVM doesn't try (and fail) to link the
// native methods of coursier.jniutils.NativeCalls. Users need setup a different
// NativeCalls instance themselves in that case (from one of the other modules).
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String className = "coursier";
className = className + ".";
className = className + "jniutils";
className = className + ".";
className = className + "NativeCalls";
try {
Class<?> cls = cl.loadClass(className);
Method m = cls.getMethod("nativeApi");
Object v = m.invoke(null);
instance = (NativeApi) v;
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException("No NativeApi instance available. Set up one with coursier.jniutils.NativeCalls.setup()", e);
}
}
if (instance == null)
throw new RuntimeException("No NativeApi instance available. Set up one with coursier.jniutils.NativeCalls.setup()");
return instance;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package coursier.jniutils;

final class NativeCalls {
public final class NativeCalls {

static native String terminalSizeNative();

Expand All @@ -12,7 +12,7 @@ final class NativeCalls {

static native String GetKnownFolderPathNative(String rfid);

static NativeApi nativeApi() {
public static NativeApi nativeApi() {
LoadWindowsLibrary.ensureInitialized();
return new NativeApi() {
public String terminalSize() {
Expand All @@ -39,4 +39,9 @@ public String GetKnownFolderPath(String rfid) {
};
}

public static void setup() {
LoadWindowsLibrary.ensureInitialized();
NativeApi nativeApi0 = nativeApi();
NativeApi.set(nativeApi0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"name" : "coursier.jniutils.NativeCalls",
"allDeclaredConstructors" : true,
"allPublicConstructors" : true,
"allDeclaredMethods" : true,
"allPublicMethods" : true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
}
]

0 comments on commit d78ad8f

Please sign in to comment.