@@ -8,6 +8,7 @@ def extraProperties = project.extensions.extraProperties
88 ' jmeNativeMetadataAdditionalTargetTypes' ,
99 ' jmeNativeMetadataAdditionalTargetAnnotations' ,
1010 ' jmeNativeMetadataAdditionalProxyInterfaceSets' ,
11+ ' jmeNativeMetadataAdditionalCloneMethodTypes' ,
1112 ' jmeNativeMetadataAdditionalResourceGlobs' ,
1213 ' jmeNativeMetadataGraalToolchainLanguageVersion' ,
1314 ' jmeNativeImageIncludeResourcesPattern' ,
@@ -74,6 +75,29 @@ def defaultTargetAnnotations = [
7475 ' com.jme3.network.serializing.Serializable'
7576]
7677
78+ def defaultCloneMethodTypes = [
79+ ' java.util.ArrayList' ,
80+ ' java.util.BitSet' ,
81+ ' java.util.Date' ,
82+ ' java.util.EnumMap' ,
83+ ' java.util.EnumSet' ,
84+ ' java.util.HashMap' ,
85+ ' java.util.HashSet' ,
86+ ' java.util.Hashtable' ,
87+ ' java.util.IdentityHashMap' ,
88+ ' java.util.LinkedHashMap' ,
89+ ' java.util.LinkedHashSet' ,
90+ ' java.util.LinkedList' ,
91+ ' java.util.PriorityQueue' ,
92+ ' java.util.Stack' ,
93+ ' java.util.TreeMap' ,
94+ ' java.util.TreeSet' ,
95+ ' java.util.Vector' ,
96+ ' java.util.concurrent.CopyOnWriteArrayList' ,
97+ ' java.util.concurrent.CopyOnWriteArraySet' ,
98+ ' com.jme3.util.SafeArrayList'
99+ ]
100+
77101def defaultProxyInterfaceSets = [
78102 [
79103 ' com.jme3.renderer.opengl.GL' ,
@@ -163,6 +187,15 @@ def safeSuperclass = { Class<?> clazz ->
163187 }
164188}
165189
190+ def hasPublicNoArgCloneMethod = { Class<?> clazz ->
191+ try {
192+ clazz. getMethod(' clone' )
193+ return true
194+ } catch (Throwable ignored) {
195+ return false
196+ }
197+ }
198+
166199def binaryClassName = { File classesDir , File classFile ->
167200 String relativePath = classesDir. toPath(). relativize(classFile. toPath()). toString(). replace(File . separatorChar, (char ) ' /' )
168201 if (! relativePath. endsWith(' .class' )) {
@@ -272,6 +305,26 @@ project.afterEvaluate {
272305 entry. allPublicMethods = true
273306 }
274307 }
308+ def addMethodEntry = { String className , String methodName , List<String > parameterTypes ->
309+ Map<String , Object > entry = classEntries. computeIfAbsent(className) {
310+ [type : className] as LinkedHashMap<String , Object >
311+ }
312+ List<Map<String , Object > > methods = entry. methods as List<Map<String , Object > >
313+ if (methods == null ) {
314+ methods = []
315+ entry. methods = methods
316+ }
317+ List<String > orderedParameterTypes = parameterTypes == null ? [] : parameterTypes
318+ boolean exists = methods. any { method ->
319+ method. name == methodName && ((method. parameterTypes ?: []) == orderedParameterTypes)
320+ }
321+ if (! exists) {
322+ methods. add([
323+ name : methodName,
324+ parameterTypes : orderedParameterTypes
325+ ] as LinkedHashMap<String , Object > )
326+ }
327+ }
275328
276329 discoveredClassNames. each { className ->
277330 Class<?> clazz = loadClassSafely(scanLoader, className)
@@ -291,8 +344,27 @@ project.afterEvaluate {
291344 current = safeSuperclass(current)
292345 }
293346 }
347+
348+ if (targetTypeClasses. any { it == Cloneable . class || it. name == ' java.lang.Cloneable' }
349+ && safeAssignableFrom(Cloneable . class, clazz)
350+ && hasPublicNoArgCloneMethod(clazz)) {
351+ addMethodEntry(className, ' clone' , [])
352+ }
294353 }
295354
355+ (defaultCloneMethodTypes + asStringList(project. ext. jmeNativeMetadataAdditionalCloneMethodTypes))
356+ .findAll { ! it. isEmpty() }
357+ .unique()
358+ .sort()
359+ .each { className ->
360+ Class<?> clazz = loadClassSafely(scanLoader, className)
361+ if (clazz != null
362+ && safeAssignableFrom(Cloneable . class, clazz)
363+ && hasPublicNoArgCloneMethod(clazz)) {
364+ addMethodEntry(className, ' clone' , [])
365+ }
366+ }
367+
296368 List<Map<String , Object > > reflectionEntries = classEntries. values(). collect { entry ->
297369 Map<String , Object > orderedEntry = new LinkedHashMap<> ()
298370 orderedEntry. type = entry. type
@@ -308,6 +380,14 @@ project.afterEvaluate {
308380 if (entry. allPublicMethods == true ) {
309381 orderedEntry. allPublicMethods = true
310382 }
383+ if (entry. methods instanceof List && ! entry. methods. isEmpty()) {
384+ orderedEntry. methods = entry. methods. collect { method ->
385+ [
386+ name : method. name,
387+ parameterTypes : method. parameterTypes ?: []
388+ ] as LinkedHashMap<String , Object >
389+ }
390+ }
311391 return orderedEntry
312392 }
313393
@@ -370,6 +450,14 @@ project.afterEvaluate {
370450 if (entry. allPublicMethods == true ) {
371451 reflectEntry. allPublicMethods = true
372452 }
453+ if (entry. methods instanceof List && ! entry. methods. isEmpty()) {
454+ reflectEntry. methods = entry. methods. collect { method ->
455+ [
456+ name : method. name,
457+ parameterTypes : method. parameterTypes ?: []
458+ ] as LinkedHashMap<String , Object >
459+ }
460+ }
373461 return reflectEntry
374462 }
375463 reflectConfigFile. text = JsonOutput . prettyPrint(JsonOutput . toJson(reflectConfigEntries)) + System . lineSeparator()
@@ -476,4 +564,4 @@ project.afterEvaluate {
476564 if (checkTask != null ) {
477565 checkTask. dependsOn(validateTaskProvider)
478566 }
479- }
567+ }
0 commit comments