
.13.e.source-code.jailbreak.scala Maven / Gradle / Ivy
/*
Copyright 2010 Aaron J. Radke
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.drx
import scala.language.existentials
object JailBreak{
//--wrap objects with jailbreak configuration
def apply[A](obj:A):JailBreak[A] = JailBreak(obj,obj.getClass)
def apply[A](obj:A,className:String):JailBreak[A] = JailBreak(obj,forName(className))
//--construct new objection
def companion(className:String):JailBreak[_] = apply(className + "$")
def apply(className:String):JailBreak[_] =
apply(className,None)
def apply(className:String, constructorName:String):JailBreak[_] =
apply(className,Some(constructorName))
def apply(className:String, constructor:Option[String]=None):JailBreak[_] = {
val klass = forName(className)
val obj = if(className endsWith "$") klass.getField("MODULE$").get(())
else constructor match{
case None => klass.getConstructor().newInstance() //java8: klass.newInstance
case Some(name) => klass.getMethod(name).invoke(null)
}
JailBreak(obj,klass)
}
//TODO base JailBreak around a Class instead of an object
private def forName(className:String) = java.lang.Class.forName(className)
private def findClass(className:String):Option[java.lang.Class[_]] = //a type hole exists explictly becuase we don't reflectively know what it actually is
Try{forName(className)}.toOption
def field[A](name:String):Try[A] = Try{
val args = name.split('.')
val className = args.init.mkString(".")
val fieldName = args.last
val c = forName(className)
c.getField(fieldName).get(c).asInstanceOf[A]
}
}
/**Simple scala type inferencing wrapper around the java reflection api to break into protected fields
*
* */
case class JailBreak[A](obj:A,klass:Class[_]){
private def field(fieldName:String):java.lang.reflect.Field = {
val reflectedField = klass.getDeclaredField(fieldName)
reflectedField.setAccessible(true) //we need to be able to set this private method
reflectedField
}
private def method(name:String,numArgs:Int):java.lang.reflect.Method = {
val mopt = methods.filter(_.getName == name).find(_.getParameterTypes.size == numArgs)
// println(s"found method $mopt")
if(mopt.isEmpty) throw(new java.lang.RuntimeException(
s"method name '$name' with $numArgs arguments does not exist in $this"
))
val m = mopt.get
m.setAccessible(true) //we need to be able to set this private method
m
}
def fields = klass.getDeclaredFields
lazy val methods = klass.getDeclaredMethods
def update[B](fieldName:String,value:B):Unit = field(fieldName).set(obj,value)
def apply[B](fieldName:String):B = field(fieldName).get(obj).asInstanceOf[B]
// def /[B](fieldName:Symbol):B = field(fieldName.name).get(obj).asInstanceOf[B]
//supper simple access, assumes field exists and the first name found matches the arguments... warning this may causes some things to break badly if these assumptiosn are not met, but using jailbreak itself is a dangerous thing so if you decide to be dangerous lets make it easy
def invoke[B](methodName:String):B = method(methodName, 0).invoke(obj).asInstanceOf[B]
def invoke[B](methodName:String,arg0:AnyRef):B = method(methodName,1).invoke(obj,arg0).asInstanceOf[B] //scala.AnyRef => java.lang.Object
def invoke[B](methodName:String,arg0:AnyRef,arg1:AnyRef):B = method(methodName, 2).invoke(obj,arg0,arg1).asInstanceOf[B]
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy