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

com.gojek.courier.messageadapter.protobuf.ProtobufMessageAdapter.kt Maven / Gradle / Ivy

The newest version!
package com.gojek.courier.messageadapter.protobuf

import com.gojek.courier.Message
import com.gojek.courier.MessageAdapter
import com.google.protobuf.ExtensionRegistryLite
import com.google.protobuf.InvalidProtocolBufferException
import com.google.protobuf.MessageLite
import com.google.protobuf.Parser
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Type

/**
 * A [message adapter][MessageAdapter] that uses Protobuf.
 */
private class ProtobufMessageAdapter constructor(
    private val parser: Parser,
    private val registry: ExtensionRegistryLite?
) : MessageAdapter {

    override fun fromMessage(topic: String, message: Message): T {
        val bytesValue = when (message) {
            is Message.Bytes -> message.value
        }
        try {
            return when (registry) {
                null -> parser.parseFrom(bytesValue)
                else -> parser.parseFrom(bytesValue, registry)
            }
        } catch (e: InvalidProtocolBufferException) {
            throw RuntimeException(e) // Despite extending IOException, this is data mismatch.
        }
    }

    override fun toMessage(topic: String, data: T): Message = Message.Bytes(data.toByteArray())

    override fun contentType() = "application/x-protobuf"
}

class ProtobufMessageAdapterFactory(
    private val registry: ExtensionRegistryLite? = null
) : MessageAdapter.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun create(type: Type, annotations: Array): MessageAdapter<*> {
        require(type is Class<*>)
        val clazz = type as Class<*>
        require(MessageLite::class.java.isAssignableFrom(type))

        var parser: Parser
        try {
            val method = clazz.getDeclaredMethod("parser")
            parser = method.invoke(null) as Parser
        } catch (e: InvocationTargetException) {
            throw RuntimeException(e.cause)
        } catch (ignored: NoSuchMethodException) {
            // If the method is missing, fall back to original static field for pre-3.0 support.
            try {
                val field = clazz.getDeclaredField("PARSER")
                parser = field.get(null) as Parser
            } catch (e: NoSuchFieldException) {
                throw ParserNotFoundException(clazz)
            } catch (e: IllegalAccessException) {
                throw ParserNotFoundException(clazz)
            }
        } catch (ignored: IllegalAccessException) {
            try {
                val field = clazz.getDeclaredField("PARSER")
                parser = field.get(null) as Parser
            } catch (e: NoSuchFieldException) {
                throw ParserNotFoundException(clazz)
            } catch (e: IllegalAccessException) {
                throw ParserNotFoundException(clazz)
            }
        }
        return ProtobufMessageAdapter(parser, registry)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy