@@ -49,6 +49,19 @@ public protocol AnyJavaObject {
4949 var javaHolder : JavaObjectHolder { get }
5050}
5151
52+ /// Protocol that allows Swift types to specify a custom Java class loader on
53+ /// initialization. This is useful for platforms (e.g. Android) where the default
54+ /// class loader does not make all application classes visible.
55+ public protocol CustomJavaClassLoaderConstructible : AnyJavaObject {
56+ static func getJavaClassLoader( in environment: JNIEnvironment ) throws -> JavaClassLoader !
57+ }
58+
59+ /// Add getClassLoader() to JavaObject as it is otherwise recursively defined
60+ extension JavaObject {
61+ @JavaMethod
62+ public func getClassLoader( ) throws -> JavaClassLoader !
63+ }
64+
5265extension AnyJavaObject {
5366 /// Retrieve the underlying Java object.
5467 public var javaThis : jobject {
@@ -81,13 +94,40 @@ extension AnyJavaObject {
8194 JavaClass ( javaThis: jniClass!, environment: javaEnvironment)
8295 }
8396
84- /// Retrieve the Java class for this type.
85- public static func getJNIClass( in environment: JNIEnvironment ) throws -> jclass {
86- try environment. translatingJNIExceptions {
97+ /// Retrieve the Java class for this type using the default class loader.
98+ private static func _withJNIClassFromDefaultClassLoader< T> (
99+ in environment: JNIEnvironment ,
100+ _ body: ( jclass ) throws -> T
101+ ) throws -> T {
102+ let resolvedClass = try environment. translatingJNIExceptions {
87103 environment. interface. FindClass (
88104 environment,
89105 fullJavaClassNameWithSlashes
90106 )
91107 } !
108+ return try body ( resolvedClass)
109+ }
110+
111+ /// Retrieve the Java class for this type using a specific class loader.
112+ private static func _withJNIClassFromCustomClassLoader< T> (
113+ _ classLoader: JavaClassLoader ,
114+ in environment: JNIEnvironment ,
115+ _ body: ( jclass ) throws -> T
116+ ) throws -> T {
117+ let resolvedClass = try classLoader. findClass ( fullJavaClassName)
118+ return try body ( resolvedClass!. javaThis)
119+ }
120+
121+ /// Retrieve the Java class for this type and execute body().
122+ internal static func withJNIClass< T> (
123+ in environment: JNIEnvironment ,
124+ _ body: ( jclass ) throws -> T
125+ ) throws -> T {
126+ if let customConstructible = self as? CustomJavaClassLoaderConstructible . Type ,
127+ let customClassLoader = try customConstructible. getJavaClassLoader ( in: environment) {
128+ try _withJNIClassFromCustomClassLoader ( customClassLoader, in: environment, body)
129+ } else {
130+ try _withJNIClassFromDefaultClassLoader ( in: environment, body)
131+ }
92132 }
93133}
0 commit comments