Catch IllegalAccessException in KFunction.call

Rename IllegalPropertyAccessException -> IllegalCallableAccessException
This commit is contained in:
Alexander Udalov
2015-07-24 19:32:10 +03:00
parent 262099c899
commit ef4a5e78ed
12 changed files with 96 additions and 73 deletions
@@ -0,0 +1,22 @@
import kotlin.reflect.*
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
class A {
private fun foo() = "A"
}
fun box(): String {
val f = A::class.declaredFunctions.single() as KFunction<String>
try {
f.call(A())
return "Fail: no exception was thrown"
} catch (e: IllegalCallableAccessException) {}
f.isAccessible = true
assertEquals("A", f.call(A()))
return "OK"
}
@@ -9,7 +9,7 @@ fun box(): String {
try { try {
return p.get(K("Fail: private property should not be accessible by default")) return p.get(K("Fail: private property should not be accessible by default"))
} }
catch (e: IllegalPropertyAccessException) { catch (e: IllegalCallableAccessException) {
// OK // OK
} }
@@ -12,7 +12,7 @@ fun box(): String {
try { try {
p.get(Result()) p.get(Result())
return "Fail: private property is accessible by default" return "Fail: private property is accessible by default"
} catch(e: IllegalPropertyAccessException) { } } catch(e: IllegalCallableAccessException) { }
p.isAccessible = true p.isAccessible = true
@@ -22,7 +22,7 @@ fun box(): String {
try { try {
p.get(Result()) p.get(Result())
return "Fail: setAccessible(false) had no effect" return "Fail: setAccessible(false) had no effect"
} catch(e: IllegalPropertyAccessException) { } } catch(e: IllegalCallableAccessException) { }
return r return r
} }
@@ -13,7 +13,7 @@ fun box(): String {
try { try {
p.set(a, 1) p.set(a, 1)
return "Fail: private property is accessible by default" return "Fail: private property is accessible by default"
} catch(e: IllegalPropertyAccessException) { } } catch(e: IllegalCallableAccessException) { }
p.isAccessible = true p.isAccessible = true
@@ -24,7 +24,7 @@ fun box(): String {
try { try {
p.set(a, 3) p.set(a, 3)
return "Fail: setAccessible(false) had no effect" return "Fail: setAccessible(false) had no effect"
} catch(e: IllegalPropertyAccessException) { } } catch(e: IllegalCallableAccessException) { }
return "OK" return "OK"
} }
@@ -14,12 +14,12 @@ fun box(): String {
try { try {
f.get(a) f.get(a)
return "Fail: protected property getter is accessible by default" return "Fail: protected property getter is accessible by default"
} catch (e: IllegalPropertyAccessException) { } } catch (e: IllegalCallableAccessException) { }
try { try {
f.set(a, ":D") f.set(a, ":D")
return "Fail: protected property setter is accessible by default" return "Fail: protected property setter is accessible by default"
} catch (e: IllegalPropertyAccessException) { } } catch (e: IllegalCallableAccessException) { }
f.isAccessible = true f.isAccessible = true
@@ -3126,6 +3126,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName); doTestWithStdlib(fileName);
} }
@TestMetadata("privateMemberFunction.kt")
public void testPrivateMemberFunction() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/privateMemberFunction.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("simpleGetFunctions.kt") @TestMetadata("simpleGetFunctions.kt")
public void testSimpleGetFunctions() throws Exception { public void testSimpleGetFunctions() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleGetFunctions.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleGetFunctions.kt");
@@ -17,14 +17,14 @@
package kotlin.reflect package kotlin.reflect
/** /**
* An exception that is thrown when `get` or `set` is called on a property * An exception that is thrown when `call` is invoked on a callable or `get` or `set` is invoked on a property
* and that property is not accessible (in JVM terms) from the calling method. * and that callable is not accessible (in JVM terms) from the calling method.
* *
* @param cause the original exception thrown by the JVM. * @param cause the original exception thrown by the JVM.
* *
* @see [kotlin.reflect.jvm.isAccessible] * @see [kotlin.reflect.jvm.isAccessible]
*/ */
public class IllegalPropertyAccessException(cause: IllegalAccessException) : Exception(cause.getMessage()) { public class IllegalCallableAccessException(cause: IllegalAccessException) : Exception(cause.getMessage()) {
init { init {
@suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") @suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
(this as java.lang.Throwable).initCause(cause) (this as java.lang.Throwable).initCause(cause)
@@ -74,7 +74,9 @@ open class KFunctionImpl protected constructor(
} }
} }
override fun call(vararg args: Any?): Any? = caller.call(args) override fun call(vararg args: Any?): Any? = reflectionCall {
caller.call(args)
}
override fun getArity(): Int { override fun getArity(): Int {
return descriptor.valueParameters.size() + return descriptor.valueParameters.size() +
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Method import java.lang.reflect.Method
import kotlin.jvm.internal.MutablePropertyReference0 import kotlin.jvm.internal.MutablePropertyReference0
import kotlin.jvm.internal.PropertyReference0 import kotlin.jvm.internal.PropertyReference0
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty0 import kotlin.reflect.KProperty0
@@ -35,14 +34,9 @@ open class KProperty0Impl<out R> : DescriptorBasedProperty<R>, KProperty0<R>, KP
override val javaGetter: Method get() = super.javaGetter!! override val javaGetter: Method get() = super.javaGetter!!
override fun get(): R { @suppress("UNCHECKED_CAST")
try { override fun get(): R = reflectionCall {
@suppress("UNCHECKED_CAST") return javaGetter.invoke(null) as R
return javaGetter.invoke(null) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
} }
override fun call(vararg args: Any?): R { override fun call(vararg args: Any?): R {
@@ -65,12 +59,9 @@ open class KMutableProperty0Impl<R> : KProperty0Impl<R>, KMutableProperty0<R>, K
override val javaSetter: Method get() = super.javaSetter!! override val javaSetter: Method get() = super.javaSetter!!
override fun set(value: R) { override fun set(value: R) {
try { reflectionCall {
javaSetter.invoke(null, value) javaSetter.invoke(null, value)
} }
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
} }
class Setter<R>(override val property: KMutableProperty0Impl<R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty0.Setter<R> { class Setter<R>(override val property: KMutableProperty0Impl<R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty0.Setter<R> {
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import kotlin.jvm.internal.MutablePropertyReference1 import kotlin.jvm.internal.MutablePropertyReference1
import kotlin.jvm.internal.PropertyReference1 import kotlin.jvm.internal.PropertyReference1
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
@@ -34,26 +33,18 @@ open class KProperty1Impl<T, out R> : DescriptorBasedProperty<R>, KProperty1<T,
override val getter by ReflectProperties.lazy { Getter(this) } override val getter by ReflectProperties.lazy { Getter(this) }
// TODO: consider optimizing this, not to do complex checks on every access // TODO: consider optimizing this, not to do complex checks on every access
@suppress("UNCHECKED_CAST") @suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_UNIT_OR_ANY" /* KT-8619 */)
override fun get(receiver: T): R { override fun get(receiver: T): R = reflectionCall {
try { val getter = javaGetter
val getter = javaGetter ?: return when {
return javaField!!.get(receiver) as R getter == null -> javaField!!.get(receiver)
Modifier.isStatic(getter.modifiers) -> {
if (Modifier.isStatic(getter.getModifiers())) {
// Workaround the case of platformStatic property in object, getter of which doesn't take a receiver // Workaround the case of platformStatic property in object, getter of which doesn't take a receiver
if (getter.getParameterTypes().isEmpty()) { if (getter.parameterTypes.isEmpty()) getter.invoke(null)
return getter.invoke(null) as R else getter.invoke(null, receiver)
}
return getter.invoke(null, receiver) as R
} }
else -> getter.invoke(receiver)
return getter.invoke(receiver) as R } as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
} }
@suppress("UNCHECKED_CAST") @suppress("UNCHECKED_CAST")
@@ -76,25 +67,17 @@ open class KMutableProperty1Impl<T, R> : KProperty1Impl<T, R>, KMutableProperty1
override val setter by ReflectProperties.lazy { Setter(this) } override val setter by ReflectProperties.lazy { Setter(this) }
override fun set(receiver: T, value: R) { override fun set(receiver: T, value: R) {
try { reflectionCall {
val setter = javaSetter ?: val setter = javaSetter
return javaField!!.set(receiver, value) when {
setter == null -> javaField!!.set(receiver, value)
if (Modifier.isStatic(setter.getModifiers())) { Modifier.isStatic(setter.modifiers) -> {
// Workaround the case of platformStatic property in object, setter of which doesn't take a receiver // Workaround the case of platformStatic property in object, setter of which doesn't take a receiver
if (setter.getParameterTypes().size() == 1) { if (setter.parameterTypes.size() == 1) setter.invoke(null, value)
setter.invoke(null, value) else setter.invoke(null, receiver, value)
}
else {
setter.invoke(null, receiver, value)
} }
else -> setter.invoke(receiver, value)
} }
else {
setter.invoke(receiver, value)
}
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
} }
} }
@@ -19,7 +19,6 @@ package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Field import java.lang.reflect.Field
import java.lang.reflect.Method import java.lang.reflect.Method
import kotlin.reflect.IllegalPropertyAccessException
import kotlin.reflect.KMutableProperty2 import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KProperty2 import kotlin.reflect.KProperty2
@@ -36,14 +35,9 @@ open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty<R>, KProperty2<
override val javaField: Field? get() = null override val javaField: Field? get() = null
override fun get(receiver1: D, receiver2: E): R { @suppress("UNCHECKED_CAST")
try { override fun get(receiver1: D, receiver2: E): R = reflectionCall {
@suppress("UNCHECKED_CAST") return javaGetter.invoke(receiver1, receiver2) as R
return javaGetter.invoke(receiver1, receiver2) as R
}
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
} }
@suppress("UNCHECKED_CAST") @suppress("UNCHECKED_CAST")
@@ -68,12 +62,9 @@ class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty
override val javaSetter: Method get() = super.javaSetter!! override val javaSetter: Method get() = super.javaSetter!!
override fun set(receiver1: D, receiver2: E, value: R) { override fun set(receiver1: D, receiver2: E, value: R) {
try { reflectionCall {
javaSetter.invoke(receiver1, receiver2, value) javaSetter.invoke(receiver1, receiver2, value)
} }
catch (e: IllegalAccessException) {
throw IllegalPropertyAccessException(e)
}
} }
class Setter<D, E, R>(override val property: KMutableProperty2Impl<D, E, R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty2.Setter<D, E, R> { class Setter<D, E, R>(override val property: KMutableProperty2Impl<D, E, R>) : KMutablePropertyImpl.Setter<R>(), KMutableProperty2.Setter<D, E, R> {
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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 kotlin.reflect.jvm.internal
import kotlin.reflect.IllegalCallableAccessException
// TODO: wrap other exceptions
internal inline fun <R> reflectionCall(block: () -> R): R =
try {
block()
}
catch (e: IllegalAccessException) {
throw IllegalCallableAccessException(e)
}