All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.app.cash.paparazzi.Reflections.kt Maven / Gradle / Ivy

Go to download

An Android library to render your application screens without a physical device or emulator

The newest version!
package app.cash.paparazzi

import sun.misc.Unsafe
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.security.AccessController
import java.security.PrivilegedAction

/**
 * Inspired by and ported from:
 * https://github.com/powermock/powermock/commit/fc092c5d7e339d01e079184a2a0e88b5c46fc0e8
 * https://github.com/powermock/powermock/commit/bd92bcc5329c4981cf09dece5c3eafcf92fe49ff
 */
internal fun Class<*>.getFieldReflectively(fieldName: String): Field =
  try {
    this.getDeclaredField(fieldName).also { it.isAccessible = true }
  } catch (e: NoSuchFieldException) {
    throw RuntimeException("Field '$fieldName' was not found in class $name.")
  }

internal fun Field.setStaticValue(value: Any) {
  try {
    this.isAccessible = true
    val isFinalModifierPresent = this.modifiers and Modifier.FINAL == Modifier.FINAL
    if (isFinalModifierPresent) {
      AccessController.doPrivileged(
        PrivilegedAction {
          try {
            val unsafe = Unsafe::class.java.getFieldReflectively("theUnsafe").get(null) as Unsafe
            val offset = unsafe.staticFieldOffset(this)
            val base = unsafe.staticFieldBase(this)
            unsafe.setFieldValue(this, base, offset, value)
            null
          } catch (t: Throwable) {
            throw RuntimeException(t)
          }
        }
      )
    } else {
      this.set(null, value)
    }
  } catch (ex: SecurityException) {
    throw RuntimeException(ex)
  } catch (ex: IllegalAccessException) {
    throw RuntimeException(ex)
  } catch (ex: IllegalArgumentException) {
    throw RuntimeException(ex)
  }
}

internal fun Unsafe.setFieldValue(field: Field, base: Any, offset: Long, value: Any) =
  when (field.type) {
    Integer.TYPE -> this.putInt(base, offset, (value as Int))
    java.lang.Short.TYPE -> this.putShort(base, offset, (value as Short))
    java.lang.Long.TYPE -> this.putLong(base, offset, (value as Long))
    java.lang.Byte.TYPE -> this.putByte(base, offset, (value as Byte))
    java.lang.Boolean.TYPE -> this.putBoolean(base, offset, (value as Boolean))
    java.lang.Float.TYPE -> this.putFloat(base, offset, (value as Float))
    java.lang.Double.TYPE -> this.putDouble(base, offset, (value as Double))
    Character.TYPE -> this.putChar(base, offset, (value as Char))
    else -> this.putObject(base, offset, value)
  }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy