1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package ch.jodersky.sbt.jni
package util
import java.io.{File, FileInputStream, Closeable}
import scala.collection.mutable.{HashSet}
import org.objectweb.asm.{ClassReader, ClassVisitor, MethodVisitor, Opcodes}
object ByteCode {
private class NativeFinder extends ClassVisitor(Opcodes.ASM5) {
//contains any classes found to contain at least one @native def
val _nativeClasses = new HashSet[String]
def nativeClasses = _nativeClasses.toSet
private var fullyQualifiedName: String = ""
override def visit(version: Int, access: Int, name: String, signature: String,
superName: String, interfaces: Array[String]): Unit = {
fullyQualifiedName = name.replaceAll("/", ".")
}
override def visitMethod(access: Int, name: String, desc: String,
signature: String, exceptions: Array[String]): MethodVisitor = {
val isNative = (access & Opcodes.ACC_NATIVE) != 0
if (isNative) {
_nativeClasses += fullyQualifiedName
}
null //return null, do not visit method further
}
}
private def using[A >: Null <: Closeable, R](mkStream: => A)(action: A => R): R = {
var stream: A = null
try {
stream = mkStream
action(stream)
} finally {
if (stream != null) {
stream.close()
}
}
}
def natives(classFile: File): Set[String] = using(new FileInputStream(classFile)) { in =>
val reader = new ClassReader(in)
val finder = new NativeFinder
reader.accept(finder, 0)
finder.nativeClasses
}
}
|