diff --git a/console/src/main/scala/com/github/zhongl/housemd/Reflections.scala b/console/src/main/scala/com/github/zhongl/housemd/Reflections.scala index cbd0ccc..d492039 100644 --- a/console/src/main/scala/com/github/zhongl/housemd/Reflections.scala +++ b/console/src/main/scala/com/github/zhongl/housemd/Reflections.scala @@ -39,6 +39,23 @@ object Reflections { private val D = classOf[Double] private val d = Double.TYPE + // FIXME this is ugly, because i don't know how to get class of byte[] + private lazy val defineClassMethod = { + val m = classOf[ClassLoader].getDeclaredMethods.find { m => + m.getName == "defineClass" && (m.getParameterTypes match { + case Array(S, _, `i`, `i`) => true + case _ => false + }) + }.get + m.setAccessible(true) + m + } + + def is(m: java.lang.reflect.Method) = (m.getParameterTypes match { + case Array(S, _, `i`, `i`) => true + case _ => false + }) + def convert(c: Class[_], s: String): AnyRef = { c match { case B | `b` => Boolean.valueOf(s) @@ -53,7 +70,7 @@ object Reflections { def nativeToStringOf(instance: AnyRef) = instance.getClass.getName + "@" + Integer .toHexString(identityHashCode(instance)) - /** see https://github.com/zhongl/HouseMD/issues/17 */ + /**see https://github.com/zhongl/HouseMD/issues/17 */ def loadOrDefine(clazz: Class[_], inClassLoader: ClassLoader) = { val name = clazz.getName try { @@ -62,17 +79,13 @@ object Reflections { case _: ClassNotFoundException => import Utils._ - val parameterTypes = Array(classOf[String], classOf[Array[Byte]], Integer.TYPE, Integer.TYPE) - - val defineClass = inClassLoader.getClass.getDeclaredMethod("defineClass", parameterTypes: _*) - defineClass.setAccessible(true) - - val bytes = toBytes(clazz.getResourceAsStream(name)) + val bytes = toBytes(clazz.getResourceAsStream("/" + name.replace('.', '/') + ".class")) val zero: java.lang.Integer = 0 val length: java.lang.Integer = bytes.length - defineClass.invoke(inClassLoader, name, bytes, zero, length).asInstanceOf[Class[_]] + defineClassMethod.invoke(inClassLoader, name, bytes, zero, length).asInstanceOf[Class[_]] } } + } diff --git a/console/src/test/scala/com/github/zhongl/housemd/ReflectionsSpec.scala b/console/src/test/scala/com/github/zhongl/housemd/ReflectionsSpec.scala new file mode 100644 index 0000000..1014689 --- /dev/null +++ b/console/src/test/scala/com/github/zhongl/housemd/ReflectionsSpec.scala @@ -0,0 +1,24 @@ +package com.github.zhongl.housemd + +import org.scalatest.FunSpec +import org.scalatest.matchers.ShouldMatchers + +/** + * @author zhongl + */ +class ReflectionsSpec extends FunSpec with ShouldMatchers { + describe("Reflection") { + it("should load Advice") { + Reflections.loadOrDefine(classOf[Advice], new ClassLoader(getClass.getClassLoader) {}) should be(classOf[Advice]) + } + it("should define Advice") { + Reflections.loadOrDefine(classOf[Advice], new ClassLoader() { + override def loadClass(name: String) = { + if (name == classOf[Advice].getName) throw new ClassNotFoundException() + else super.loadClass(name) + } + }) + } + } + +}