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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
package scala.reflect
package runtime
import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{
Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField,
Member => jMember, Type => jType, Array => jArray, GenericDeclaration}
trait ScalaToJava extends ConversionUtil { self: SymbolTable =>
import definitions._
/** Optionally, the Java package corresponding to a given Scala package, or None if no such Java package exists.
* @param pkg The Scala package
*/
def packageToJava(pkg: Symbol): Option[jPackage] = packageCache.toJavaOption(pkg) {
Option(jPackage.getPackage(pkg.fullName.toString))
}
/** The Java class corresponding to given Scala class.
* Note: This only works for
* - top-level classes
* - Scala classes that were generated via jclassToScala
* - classes that have a class owner that has a corresponding Java class
* @throws A `ClassNotFoundException` for all Scala classes not in one of these categories.
*/
@throws(classOf[ClassNotFoundException])
def classToJava(clazz: Symbol): jClass[_] = classCache.toJava(clazz) {
def noClass = throw new ClassNotFoundException("no Java class corresponding to "+clazz+" found")
//println("classToJava "+clazz+" "+clazz.owner+" "+clazz.owner.isPackageClass)//debug
if (clazz.isValueClass)
clazz match {
case UnitClass => java.lang.Void.TYPE
case ByteClass => java.lang.Byte.TYPE
case CharClass => java.lang.Character.TYPE
case ShortClass => java.lang.Short.TYPE
case IntClass => java.lang.Integer.TYPE
case LongClass => java.lang.Long.TYPE
case FloatClass => java.lang.Float.TYPE
case DoubleClass => java.lang.Double.TYPE
case BooleanClass => java.lang.Boolean.TYPE
}
else if (clazz == ArrayClass)
noClass
else if (clazz.owner.isPackageClass)
javaClass(clazz.javaClassName)
else if (clazz.owner.isClass)
classToJava(clazz.owner)
.getDeclaredClasses
.find(_.getSimpleName == clazz.name.toString)
.getOrElse(noClass)
else
noClass
}
private def expandedName(sym: Symbol): String =
if (sym.isPrivate) nme.expandedName(sym.name, sym.owner).toString
else sym.name.toString
def fieldToJava(fld: Symbol): jField = fieldCache.toJava(fld) {
val jclazz = classToJava(fld.owner)
try jclazz getDeclaredField fld.name.toString
catch {
case ex: NoSuchFieldException => jclazz getDeclaredField expandedName(fld)
}
}
def methodToJava(meth: Symbol): jMethod = methodCache.toJava(meth) {
val jclazz = classToJava(meth.owner)
val paramClasses = transformedType(meth).paramTypes map typeToJavaClass
try jclazz getDeclaredMethod (meth.name.toString, paramClasses: _*)
catch {
case ex: NoSuchMethodException =>
jclazz getDeclaredMethod (expandedName(meth), paramClasses: _*)
}
}
def constrToJava(constr: Symbol): jConstructor[_] = constructorCache.toJava(constr) {
val jclazz = classToJava(constr.owner)
val paramClasses = transformedType(constr).paramTypes map typeToJavaClass
jclazz getConstructor (paramClasses: _*)
}
private def jArrayClass(elemClazz: jClass[_]): jClass[_] = {
jArray.newInstance(elemClazz, 0).getClass
}
/** The Java class that corresponds to given Scala type.
* Pre: Scala type is already transformed to Java level.
*/
def typeToJavaClass(tpe: Type): jClass[_] = tpe match {
case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
case TypeRef(_, sym, _) => classToJava(sym)
case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
}
}
|