uncheckedCast crusade (#1667)

This commit is contained in:
Andrzej Cichocki
2017-09-27 12:58:48 +01:00
committed by GitHub
parent c6c4c13bee
commit 9874e1ff34
51 changed files with 172 additions and 231 deletions

View File

@ -5,6 +5,7 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigUtil
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.noneOrSingle
import net.corda.core.internal.uncheckedCast
import net.corda.core.utilities.NetworkHostAndPort
import org.slf4j.LoggerFactory
import java.net.Proxy
@ -25,7 +26,7 @@ import kotlin.reflect.jvm.jvmErasure
annotation class OldConfig(val value: String)
// TODO Move other config parsing to use parseAs and remove this
operator fun <T> Config.getValue(receiver: Any, metadata: KProperty<*>): T {
operator fun <T : Any> Config.getValue(receiver: Any, metadata: KProperty<*>): T {
return getValueInternal(metadata.name, metadata.returnType)
}
@ -52,9 +53,8 @@ fun Config.toProperties(): Properties {
{ it.value.unwrapped().toString() })
}
@Suppress("UNCHECKED_CAST")
private fun <T> Config.getValueInternal(path: String, type: KType): T {
return (if (type.arguments.isEmpty()) getSingleValue(path, type) else getCollectionValue(path, type)) as T
private fun <T : Any> Config.getValueInternal(path: String, type: KType): T {
return uncheckedCast(if (type.arguments.isEmpty()) getSingleValue(path, type) else getCollectionValue(path, type))
}
private fun Config.getSingleValue(path: String, type: KType): Any? {
@ -122,8 +122,7 @@ private fun Config.defaultToOldPath(property: KProperty<*>): String {
return property.name
}
@Suppress("UNCHECKED_CAST")
private fun parseEnum(enumType: Class<*>, name: String): Enum<*> = enumBridge(enumType as Class<Proxy.Type>, name) // Any enum will do
private fun parseEnum(enumType: Class<*>, name: String): Enum<*> = enumBridge<Proxy.Type>(uncheckedCast(enumType), name) // Any enum will do
private fun <T : Enum<T>> enumBridge(clazz: Class<T>, name: String): T = java.lang.Enum.valueOf(clazz, name)

View File

@ -14,6 +14,7 @@ import net.corda.core.crypto.CompositeKey
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.TransactionSignature
import net.corda.core.identity.Party
import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SerializedBytes
@ -245,9 +246,8 @@ object WireTransactionSerializer : Serializer<WireTransaction>() {
kryo.writeClassAndObject(output, obj.privacySalt)
}
@Suppress("UNCHECKED_CAST")
override fun read(kryo: Kryo, input: Input, type: Class<WireTransaction>): WireTransaction {
val componentGroups = kryo.readClassAndObject(input) as List<ComponentGroup>
val componentGroups: List<ComponentGroup> = uncheckedCast(kryo.readClassAndObject(input))
val privacySalt = kryo.readClassAndObject(input) as PrivacySalt
return WireTransaction(componentGroups, privacySalt)
}
@ -261,9 +261,8 @@ object NotaryChangeWireTransactionSerializer : Serializer<NotaryChangeWireTransa
kryo.writeClassAndObject(output, obj.newNotary)
}
@Suppress("UNCHECKED_CAST")
override fun read(kryo: Kryo, input: Input, type: Class<NotaryChangeWireTransaction>): NotaryChangeWireTransaction {
val inputs = kryo.readClassAndObject(input) as List<StateRef>
val inputs: List<StateRef> = uncheckedCast(kryo.readClassAndObject(input))
val notary = kryo.readClassAndObject(input) as Party
val newNotary = kryo.readClassAndObject(input) as Party
@ -278,11 +277,10 @@ object SignedTransactionSerializer : Serializer<SignedTransaction>() {
kryo.writeClassAndObject(output, obj.sigs)
}
@Suppress("UNCHECKED_CAST")
override fun read(kryo: Kryo, input: Input, type: Class<SignedTransaction>): SignedTransaction {
return SignedTransaction(
kryo.readClassAndObject(input) as SerializedBytes<CoreTransaction>,
kryo.readClassAndObject(input) as List<TransactionSignature>
uncheckedCast<Any?, SerializedBytes<CoreTransaction>>(kryo.readClassAndObject(input)),
uncheckedCast<Any?, List<TransactionSignature>>(kryo.readClassAndObject(input))
)
}
}
@ -600,8 +598,7 @@ class ThrowableSerializer<T>(kryo: Kryo, type: Class<T>) : Serializer<Throwable>
}
}
@Suppress("UNCHECKED_CAST")
private val delegate: Serializer<Throwable> = ReflectionSerializerFactory.makeSerializer(kryo, FieldSerializer::class.java, type) as Serializer<Throwable>
private val delegate: Serializer<Throwable> = uncheckedCast(ReflectionSerializerFactory.makeSerializer(kryo, FieldSerializer::class.java, type))
override fun write(kryo: Kryo, output: Output, throwable: Throwable) {
delegate.write(kryo, output, throwable)

View File

@ -14,6 +14,7 @@ import com.google.common.cache.CacheBuilder
import net.corda.core.contracts.Attachment
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.LazyPool
import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.*
import net.corda.core.utilities.ByteSequence
import net.corda.core.utilities.OpaqueBytes
@ -204,11 +205,10 @@ abstract class AbstractKryoSerializationScheme : SerializationScheme {
Input(byteSequence.bytes, byteSequence.offset + headerSize, byteSequence.size - headerSize).use { input ->
return pool.run { kryo ->
withContext(kryo, context) {
@Suppress("UNCHECKED_CAST")
if (context.objectReferencesEnabled) {
kryo.readClassAndObject(input) as T
uncheckedCast(kryo.readClassAndObject(input))
} else {
kryo.withoutReferences { kryo.readClassAndObject(input) as T }
kryo.withoutReferences { uncheckedCast<Any?, T>(kryo.readClassAndObject(input)) }
}
}
}

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
import net.corda.core.utilities.NonEmptySet
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
@ -36,8 +37,7 @@ class CollectionSerializer(val declaredType: ParameterizedType, factory: Seriali
fun deriveParameterizedType(declaredType: Type, declaredClass: Class<*>, actualClass: Class<*>?): ParameterizedType {
if(supportedTypes.containsKey(declaredClass)) {
// Simple case - it is already known to be a collection.
@Suppress("UNCHECKED_CAST")
return deriveParametrizedType(declaredType, declaredClass as Class<out Collection<*>>)
return deriveParametrizedType(declaredType, uncheckedCast(declaredClass))
}
else if (actualClass != null && Collection::class.java.isAssignableFrom(actualClass)) {
// Declared class is not collection, but [actualClass] is - represent it accordingly.

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory.Companion.nameForType
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
@ -9,7 +10,7 @@ import java.lang.reflect.Type
* Base class for serializers of core platform types that do not conform to the usual serialization rules and thus
* cannot be automatically serialized.
*/
abstract class CustomSerializer<T> : AMQPSerializer<T> {
abstract class CustomSerializer<T : Any> : AMQPSerializer<T> {
/**
* This is a collection of custom serializers that this custom serializer depends on. e.g. for proxy objects
* that refer to other custom types etc.
@ -36,8 +37,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) {
data.withDescribed(descriptor) {
@Suppress("UNCHECKED_CAST")
writeDescribedObject(obj as T, data, type, output)
writeDescribedObject(uncheckedCast(obj), data, type, output)
}
}
@ -49,7 +49,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* subclass in the schema, so that we can distinguish between subclasses.
*/
// TODO: should this be a custom serializer at all, or should it just be a plain AMQPSerializer?
class SubClass<T>(protected val clazz: Class<*>, protected val superClassSerializer: CustomSerializer<T>) : CustomSerializer<T>() {
class SubClass<T : Any>(protected val clazz: Class<*>, protected val superClassSerializer: CustomSerializer<T>) : CustomSerializer<T>() {
// TODO: should this be empty or contain the schema of the super?
override val schemaForDocumentation = Schema(emptyList())
@ -76,7 +76,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* Additional base features for a custom serializer for a particular class [withInheritance] is false
* or super class / interfaces [withInheritance] is true
*/
abstract class CustomSerializerImp<T>(protected val clazz: Class<T>, protected val withInheritance: Boolean) : CustomSerializer<T>() {
abstract class CustomSerializerImp<T : Any>(protected val clazz: Class<T>, protected val withInheritance: Boolean) : CustomSerializer<T>() {
override val type: Type get() = clazz
override val typeDescriptor = Symbol.valueOf("$DESCRIPTOR_DOMAIN:${nameForType(clazz)}")
override fun writeClassInfo(output: SerializationOutput) {}
@ -87,12 +87,12 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
/**
* Additional base features for a custom serializer for a particular class, that excludes subclasses.
*/
abstract class Is<T>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, false)
abstract class Is<T : Any>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, false)
/**
* Additional base features for a custom serializer for all implementations of a particular interface or super class.
*/
abstract class Implements<T>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, true)
abstract class Implements<T : Any>(clazz: Class<T>) : CustomSerializerImp<T>(clazz, true)
/**
* Additional base features over and above [Implements] or [Is] custom serializer for when the serialized form should be
@ -101,7 +101,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* The proxy class must use only types which are either native AMQP or other types for which there are pre-registered
* custom serializers.
*/
abstract class Proxy<T, P>(clazz: Class<T>,
abstract class Proxy<T : Any, P : Any>(clazz: Class<T>,
protected val proxyClass: Class<P>,
protected val factory: SerializerFactory,
withInheritance: Boolean = true) : CustomSerializerImp<T>(clazz, withInheritance) {
@ -134,8 +134,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
}
override fun readObject(obj: Any, schema: Schema, input: DeserializationInput): T {
@Suppress("UNCHECKED_CAST")
val proxy = proxySerializer.readObject(obj, schema, input) as P
val proxy: P = uncheckedCast(proxySerializer.readObject(obj, schema, input))
return fromProxy(proxy)
}
}
@ -151,7 +150,7 @@ abstract class CustomSerializer<T> : AMQPSerializer<T> {
* @param make A lambda for constructing an instance, that defaults to calling a constructor that expects a string.
* @param unmake A lambda that extracts the string value for an instance, that defaults to the [toString] method.
*/
abstract class ToString<T>(clazz: Class<T>, withInheritance: Boolean = false,
abstract class ToString<T : Any>(clazz: Class<T>, withInheritance: Boolean = false,
private val maker: (String) -> T = clazz.getConstructor(String::class.java).let {
`constructor` ->
{ string -> `constructor`.newInstance(string) }

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.amqp
import net.corda.core.internal.uncheckedCast
import org.apache.qpid.proton.amqp.Symbol
import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException
@ -31,8 +32,7 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
LinkedHashMap::class.java to { map -> LinkedHashMap(map) },
TreeMap::class.java to { map -> TreeMap(map) },
EnumMap::class.java to { map ->
@Suppress("UNCHECKED_CAST")
EnumMap(map as Map<EnumJustUsedForCasting, Any>)
EnumMap(uncheckedCast<Map<*, *>, Map<EnumJustUsedForCasting, Any>>(map))
}
))
@ -44,8 +44,7 @@ class MapSerializer(private val declaredType: ParameterizedType, factory: Serial
declaredClass.checkSupportedMapType()
if(supportedTypes.containsKey(declaredClass)) {
// Simple case - it is already known to be a map.
@Suppress("UNCHECKED_CAST")
return deriveParametrizedType(declaredType, declaredClass as Class<out Map<*, *>>)
return deriveParametrizedType(declaredType, uncheckedCast(declaredClass))
}
else if (actualClass != null && Map::class.java.isAssignableFrom(actualClass)) {
// Declared class is not map, but [actualClass] is - represent it accordingly.

View File

@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.hash.Hasher
import com.google.common.hash.Hashing
import net.corda.core.internal.uncheckedCast
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.toBase64
@ -94,8 +95,7 @@ data class Schema(val types: List<TypeNotation>) : DescribedType {
override fun newInstance(described: Any?): Schema {
val list = described as? List<*> ?: throw IllegalStateException("Was expecting a list")
@Suppress("UNCHECKED_CAST")
return Schema(list[0] as List<TypeNotation>)
return Schema(uncheckedCast(list[0]))
}
}
@ -162,8 +162,7 @@ data class Field(val name: String, val type: String, val requires: List<String>,
override fun newInstance(described: Any?): Field {
val list = described as? List<*> ?: throw IllegalStateException("Was expecting a list")
@Suppress("UNCHECKED_CAST")
return Field(list[0] as String, list[1] as String, list[2] as List<String>, list[3] as? String, list[4] as? String, list[5] as Boolean, list[6] as Boolean)
return Field(list[0] as String, list[1] as String, uncheckedCast(list[2]), list[3] as? String, list[4] as? String, list[5] as Boolean, list[6] as Boolean)
}
}
@ -223,8 +222,7 @@ data class CompositeType(override val name: String, override val label: String?,
override fun newInstance(described: Any?): CompositeType {
val list = described as? List<*> ?: throw IllegalStateException("Was expecting a list")
@Suppress("UNCHECKED_CAST")
return CompositeType(list[0] as String, list[1] as? String, list[2] as List<String>, list[3] as Descriptor, list[4] as List<Field>)
return CompositeType(list[0] as String, list[1] as? String, uncheckedCast(list[2]), list[3] as Descriptor, uncheckedCast(list[4]))
}
}
@ -273,8 +271,7 @@ data class RestrictedType(override val name: String,
override fun newInstance(described: Any?): RestrictedType {
val list = described as? List<*> ?: throw IllegalStateException("Was expecting a list")
@Suppress("UNCHECKED_CAST")
return RestrictedType(list[0] as String, list[1] as? String, list[2] as List<String>, list[3] as String, list[4] as Descriptor, list[5] as List<Choice>)
return RestrictedType(list[0] as String, list[1] as? String, uncheckedCast(list[2]), list[3] as String, list[4] as Descriptor, uncheckedCast(list[5]))
}
}

View File

@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.serialization.amqp
import com.google.common.primitives.Primitives
import com.google.common.reflect.TypeResolver
import net.corda.core.internal.uncheckedCast
import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable
import net.corda.nodeapi.internal.serialization.carpenter.*
@ -262,8 +263,7 @@ class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) {
return customSerializer
} else {
// Make a subclass serializer for the subclass and return that...
@Suppress("UNCHECKED_CAST")
return CustomSerializer.SubClass(clazz, customSerializer as CustomSerializer<Any>)
return CustomSerializer.SubClass(clazz, uncheckedCast(customSerializer))
}
}
}

View File

@ -1,11 +1,11 @@
package net.corda.nodeapi.internal.serialization.amqp.custom
import net.corda.core.internal.uncheckedCast
import net.corda.nodeapi.internal.serialization.amqp.CustomSerializer
import net.corda.nodeapi.internal.serialization.amqp.MapSerializer
import net.corda.nodeapi.internal.serialization.amqp.SerializerFactory
import java.util.*
@Suppress("UNCHECKED_CAST")
/**
* A serializer that writes out an [EnumSet] as a type, plus list of instances in the set.
*/
@ -16,7 +16,7 @@ class EnumSetSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Enu
private fun elementType(set: EnumSet<*>): Class<*> {
return if (set.isEmpty()) {
EnumSet.complementOf(set as EnumSet<MapSerializer.EnumJustUsedForCasting>).first().javaClass
EnumSet.complementOf(uncheckedCast<EnumSet<*>, EnumSet<MapSerializer.EnumJustUsedForCasting>>(set)).first().javaClass
} else {
set.first().javaClass
}
@ -24,9 +24,9 @@ class EnumSetSerializer(factory: SerializerFactory) : CustomSerializer.Proxy<Enu
override fun fromProxy(proxy: EnumSetProxy): EnumSet<*> {
return if (proxy.elements.isEmpty()) {
EnumSet.noneOf(proxy.clazz as Class<MapSerializer.EnumJustUsedForCasting>)
EnumSet.noneOf(uncheckedCast<Class<*>, Class<MapSerializer.EnumJustUsedForCasting>>(proxy.clazz))
} else {
EnumSet.copyOf(proxy.elements as List<MapSerializer.EnumJustUsedForCasting>)
EnumSet.copyOf(uncheckedCast<List<Any>, List<MapSerializer.EnumJustUsedForCasting>>(proxy.elements))
}
}

View File

@ -237,10 +237,9 @@ class ClassCarpenter(cl: ClassLoader = Thread.currentThread().contextClassLoader
}
private fun ClassWriter.generateGetters(schema: Schema) {
@Suppress("UNCHECKED_CAST")
for ((name, type) in (schema.fields as Map<String, ClassField>)) {
for ((name, type) in schema.fields) {
visitMethod(ACC_PUBLIC, "get" + name.capitalize(), "()" + type.descriptor, null, null).apply {
type.addNullabilityAnnotation(this)
(type as ClassField).addNullabilityAnnotation(this)
visitCode()
visitVarInsn(ALOAD, 0) // Load 'this'
visitFieldInsn(GETFIELD, schema.jvmName, name, type.descriptor)
@ -258,8 +257,7 @@ class ClassCarpenter(cl: ClassLoader = Thread.currentThread().contextClassLoader
}
private fun ClassWriter.generateAbstractGetters(schema: Schema) {
@Suppress("UNCHECKED_CAST")
for ((name, field) in (schema.fields as Map<String, ClassField>)) {
for ((name, field) in schema.fields) {
val opcodes = ACC_ABSTRACT + ACC_PUBLIC
// abstract method doesn't have any implementation so just end
visitMethod(opcodes, "get" + name.capitalize(), "()${field.descriptor}", null, null).visitEnd()
@ -363,9 +361,8 @@ class ClassCarpenter(cl: ClassLoader = Thread.currentThread().contextClassLoader
// Assign the fields from parameters.
var slot = 1 + superclassFields.size
@Suppress("UNCHECKED_CAST")
for ((name, field) in (schema.fields as Map<String, ClassField>)) {
field.nullTest(this, slot)
for ((name, field) in schema.fields) {
(field as ClassField).nullTest(this, slot)
visitVarInsn(ALOAD, 0) // Load 'this' onto the stack
slot += load(slot, field) // Load the contents of the parameter onto the stack.

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.serialization.carpenter
import net.corda.core.internal.uncheckedCast
import net.corda.nodeapi.internal.serialization.AllWhitelist
import org.junit.Test
import java.beans.Introspector
@ -323,7 +324,6 @@ class ClassCarpenterTest {
}
@Test
@Suppress("UNCHECKED_CAST")
fun `int array`() {
val className = "iEnjoyPotato"
val schema = ClassSchema(
@ -356,7 +356,6 @@ class ClassCarpenterTest {
}
@Test
@Suppress("UNCHECKED_CAST")
fun `integer array`() {
val className = "iEnjoyFlan"
val schema = ClassSchema(
@ -366,16 +365,15 @@ class ClassCarpenterTest {
val clazz = cc.build(schema)
val i = clazz.constructors[0].newInstance(arrayOf(1, 2, 3)) as SimpleFieldAccess
val arr = clazz.getMethod("getA").invoke(i)
val arr: Array<Int> = uncheckedCast(clazz.getMethod("getA").invoke(i))
assertEquals(1, (arr as Array<Int>)[0])
assertEquals(1, arr[0])
assertEquals(2, arr[1])
assertEquals(3, arr[2])
assertEquals("$className{a=[1, 2, 3]}", i.toString())
}
@Test
@Suppress("UNCHECKED_CAST")
fun `int array with ints`() {
val className = "iEnjoyCrumble"
val schema = ClassSchema(
@ -395,7 +393,6 @@ class ClassCarpenterTest {
}
@Test
@Suppress("UNCHECKED_CAST")
fun `multiple int arrays`() {
val className = "iEnjoyJam"
val schema = ClassSchema(
@ -417,7 +414,6 @@ class ClassCarpenterTest {
}
@Test
@Suppress("UNCHECKED_CAST")
fun `string array`() {
val className = "iEnjoyToast"
val schema = ClassSchema(
@ -427,7 +423,7 @@ class ClassCarpenterTest {
val clazz = cc.build(schema)
val i = clazz.constructors[0].newInstance(arrayOf("toast", "butter", "jam"))
val arr = clazz.getMethod("getA").invoke(i) as Array<String>
val arr: Array<String> = uncheckedCast(clazz.getMethod("getA").invoke(i))
assertEquals("toast", arr[0])
assertEquals("butter", arr[1])
@ -435,7 +431,6 @@ class ClassCarpenterTest {
}
@Test
@Suppress("UNCHECKED_CAST")
fun `string arrays`() {
val className = "iEnjoyToast"
val schema = ClassSchema(
@ -452,8 +447,8 @@ class ClassCarpenterTest {
"and on the side",
arrayOf("some pickles", "some fries"))
val arr1 = clazz.getMethod("getA").invoke(i) as Array<String>
val arr2 = clazz.getMethod("getC").invoke(i) as Array<String>
val arr1: Array<String> = uncheckedCast(clazz.getMethod("getA").invoke(i))
val arr2: Array<String> = uncheckedCast(clazz.getMethod("getC").invoke(i))
assertEquals("bread", arr1[0])
assertEquals("spread", arr1[1])