io.netty.buffer.Unpooled Scala Examples

The following examples show how to use io.netty.buffer.Unpooled. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Packet.scala    From finagle-postgres   with Apache License 2.0 6 votes vote down vote up
package com.twitter.finagle.postgres.messages

import com.twitter.finagle.postgres.values.Charsets

import io.netty.buffer.{ByteBuf, Unpooled}

object Packet {
  val INT_SIZE = 4
}


class PacketBuilder(val code: Option[Char]) {
  private val underlying = Unpooled.buffer()

  def writeByte(byte: Byte) = {
    underlying.writeByte(byte)
    this
  }

  def writeBytes(bytes: Array[Byte]) = {
	  underlying.writeBytes(bytes)
	  this
  }

  def writeBuf(bytes: ByteBuf) = {
	  underlying.writeBytes(bytes)
	  this
  }

  def writeChar(char: Char) = {
    underlying.writeByte(char)
    this
  }
  def writeInt(int: Int) = {
    underlying.writeInt(int)
    this
  }

  def writeShort(short: Short) = {
    underlying.writeShort(short)
    this
  }

  def writeCString(str: String) = {
    underlying.writeBytes(str.getBytes(Charsets.Utf8))
    underlying.writeByte(0)
    this
  }

  def toPacket = new Packet(code, underlying.writerIndex(), underlying)
}

object PacketBuilder {
  def apply(): PacketBuilder = new PacketBuilder(None)

  def apply(code: Char): PacketBuilder = new PacketBuilder(Some(code))
} 
Example 2
Source File: EchoServerHandler.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter2.echoserver

import io.netty.buffer.{ ByteBuf, Unpooled }
import io.netty.channel.ChannelHandler.Sharable
import io.netty.channel.{ ChannelFutureListener, ChannelHandlerContext, ChannelInboundHandlerAdapter }
import io.netty.util.CharsetUtil

@Sharable
class EchoServerHandler extends ChannelInboundHandlerAdapter {
  override def channelRead(ctx: ChannelHandlerContext, msg: Any): Unit = {
    val in = msg.asInstanceOf[ByteBuf]
    //将消息记录到控制台
    System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8))
    //将接收到的消息写给发送者,而不冲刷出站消息
    ctx.write(in)
  }

  @throws[Exception]
  override def channelReadComplete(ctx: ChannelHandlerContext): Unit = {
    //将未决消息冲刷到远程节点,并且关闭该 Channel
    ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE)
  }

  override def exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable): Unit = {
    //打印异常栈跟踪
    cause.printStackTrace()
    //关闭该Channel
    ctx.close()
  }
} 
Example 3
Source File: HandshakeInitSpec.scala    From asyncdb   with Apache License 2.0 5 votes vote down vote up
package io.asyncdb
package netty
package mysql
package protocol
package server

import cats.effect._
import io.netty.buffer.Unpooled
import java.nio.charset.Charset

class HandshakeInitSpec extends Spec {

  val CS = Charset.defaultCharset()

  "HandshakeInit" - {
    "decode init packet" - {
      "MariaDB10" in {
        Decoder.decode[HandshakeInit](Bytes.MariaDB10, CS) should be('right)
      }
      "MySQL56" in {
        Decoder.decode[HandshakeInit](Bytes.MySQL56, CS) should be('right)
      }
    }
  }

  object Bytes {

    val MariaDB10Bytes = HexDump.decode(
      """0a352e352e352d31302e312e33312d4d617269614442002500000026712d277d614c3a00fff7e002003fa015000000000000000000007b2335234c376f4859687e61006d7973716c5f6e61746976655f70617373776f726400"""
    )
    val MySQL56Bytes = HexDump.decode(
      """0a352e372e31332d6c6f6700160c0000533f5d042025172900ffff210200ffc1150000000000000000000027105a290c1f3a71111b5b68006d7973716c5f6e61746976655f70617373776f726400"""
    )

    val MariaDB10 = Unpooled.wrappedBuffer(MariaDB10Bytes)
    val MySQL56   = Unpooled.wrappedBuffer(MySQL56Bytes)
  }
} 
Example 4
Source File: example.scala    From aloha   with Apache License 2.0 5 votes vote down vote up
package me.jrwang.aloha.example

import com.google.common.base.Charsets
import io.netty.buffer.{ByteBuf, Unpooled}
import me.jrwang.aloha.common.{AlohaConf, Logging}
import me.jrwang.aloha.transport.client.{RpcResponseCallback, TransportClient}
import me.jrwang.aloha.transport.server.RpcHandler
import me.jrwang.aloha.transport.{AlohaTransportConf, TransportContext}

object SimpleAlohaServer extends Logging {
  def main(args: Array[String]): Unit = {
    val transportConf = AlohaTransportConf.fromAlohaConf(new AlohaConf(), "rpc")
    val rpcHandler = new RpcHandler {
      override def receive(client: TransportClient, message: ByteBuf, callback: RpcResponseCallback): Unit = {
        logInfo(s"server receive ${message.toString(Charsets.UTF_8)}")
        callback.onSuccess(Unpooled.wrappedBuffer("hello".getBytes))
      }

      override def channelActive(client: TransportClient): Unit = {
        logInfo("server channel active")
      }

      override def channelInactive(client: TransportClient): Unit = {
        logInfo("server channel inactive")
      }

      override def exceptionCaught(cause: Throwable, client: TransportClient): Unit = {
        logInfo(s"server exception$cause")
      }
    }

    new TransportContext(transportConf, rpcHandler)
      .createServer("localhost", 9999)
      .awaitTermination()
  }
}

object SimpleAlohaClient extends Logging {
  def main(args: Array[String]): Unit = {
    val transportConf = AlohaTransportConf.fromAlohaConf(new AlohaConf(), "rpc")
    val rpcHandler = new RpcHandler {
      override def receive(client: TransportClient, message: ByteBuf, callback: RpcResponseCallback): Unit = {
        logInfo(s"client receive ${message.toString(Charsets.UTF_8)}")
        callback.onSuccess(Unpooled.wrappedBuffer("hello".getBytes))
      }

      override def channelActive(client: TransportClient): Unit = {
        logInfo("client channel active")
      }

      override def channelInactive(client: TransportClient): Unit = {
        logInfo("client channel inactive")
      }

      override def exceptionCaught(cause: Throwable, client: TransportClient): Unit = {
        logInfo(s"client exception$cause")
      }
    }

    val client = new TransportContext(transportConf, rpcHandler).createClientFactory()
      .createClient("localhost", 9999)

    client.sendRpc(Unpooled.wrappedBuffer("hello world.".getBytes), new RpcResponseCallback {
      override def onSuccess(response: ByteBuf): Unit = {
        logInfo(s"rpc request success with ${response.toString(Charsets.UTF_8)}")
      }

      override def onFailure(e: Throwable): Unit = {
        logInfo(s"rpc request failed $e")
      }
    })

    client.channel.closeFuture().sync()
  }
} 
Example 5
Source File: NettyRpcCallContext.scala    From aloha   with Apache License 2.0 5 votes vote down vote up
package me.jrwang.aloha.rpc.netty

import scala.concurrent.Promise

import io.netty.buffer.Unpooled
import me.jrwang.aloha.rpc.{RpcAddress, RpcCallContext}
import me.jrwang.aloha.transport.client.RpcResponseCallback

abstract class NettyRpcCallContext(override val senderAddress: RpcAddress)
  extends RpcCallContext {

  protected def send(message: Any): Unit

  override def reply(response: Any): Unit = {
    send(response)
  }

  override def sendFailure(e: Throwable): Unit = {
    send(RpcFailure(e))
  }
}


class RemoteNettyRpcCallContext(
  nettyEnv: NettyRpcEnv,
  callback: RpcResponseCallback,
  senderAddress: RpcAddress)
  extends NettyRpcCallContext(senderAddress) {

  override protected def send(message: Any): Unit = {
    val reply = nettyEnv.serialize(message)
    callback.onSuccess(Unpooled.wrappedBuffer(reply))
  }
} 
Example 6
Source File: HandshakeDecoderSpec.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.network

import java.nio.charset.StandardCharsets

import com.google.common.primitives.{Ints, Longs}
import com.wavesplatform.{NoShrink, TransactionGen}
import io.netty.buffer.Unpooled
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.channel.{ChannelHandlerContext, ChannelInboundHandlerAdapter}
import org.scalacheck.{Arbitrary, Gen}
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FreeSpec, Matchers}
import org.scalatestplus.scalacheck.{ScalaCheckPropertyChecks => PropertyChecks}

class HandshakeDecoderSpec extends FreeSpec with Matchers with MockFactory with PropertyChecks with TransactionGen with NoShrink {

  "should read a handshake and remove itself from the pipeline" in {
    var mayBeDecodedHandshake: Option[Handshake] = None

    val channel = new EmbeddedChannel(
      new HandshakeDecoder(PeerDatabase.NoOp),
      new ChannelInboundHandlerAdapter {
        override def channelRead(ctx: ChannelHandlerContext, msg: Any): Unit = msg match {
          case x: Handshake => mayBeDecodedHandshake = Some(x)
          case _            =>
        }
      }
    )

    val origHandshake = new Handshake(
      applicationName = "wavesI",
      applicationVersion = (1, 2, 3),
      nodeName = "test",
      nodeNonce = 4,
      declaredAddress = None
    )

    val buff = Unpooled.buffer
    origHandshake.encode(buff)
    buff.writeCharSequence("foo", StandardCharsets.UTF_8)

    channel.writeInbound(buff)

    mayBeDecodedHandshake should contain(origHandshake)
  }

  private val invalidHandshakeBytes: Gen[Array[Byte]] = {
    // To bypass situations where the appNameLength > whole buffer and HandshakeDecoder waits for next bytes
    val appName  = "x" * Byte.MaxValue
    val nodeName = "y" * Byte.MaxValue

    val appNameBytes   = appName.getBytes(StandardCharsets.UTF_8)
    val versionBytes   = Array(1, 2, 3).flatMap(Ints.toByteArray)
    val nodeNameBytes  = nodeName.getBytes(StandardCharsets.UTF_8)
    val nonceBytes     = Longs.toByteArray(1)
    val timestampBytes = Longs.toByteArray(System.currentTimeMillis() / 1000)

    val validDeclaredAddressLen = Set(0, 8, 20)
    val invalidBytesGen = Gen.listOfN(3, Arbitrary.arbByte.arbitrary).filter {
      case List(appNameLen, nodeNameLen, declaredAddressLen) =>
        !(appNameLen == appNameBytes.size || nodeNameLen == nodeNameBytes.size ||
          validDeclaredAddressLen.contains(declaredAddressLen))
      case _ =>
        false
    }

    invalidBytesGen.map {
      case List(appNameLen, nodeNameLen, declaredAddressLen) =>
        Array(appNameLen) ++
          appNameBytes ++
          versionBytes ++
          Array(nodeNameLen) ++
          nodeNameBytes ++
          nonceBytes ++
          Array(declaredAddressLen) ++
          timestampBytes
    }
  }

  "should blacklist a node sends an invalid handshake" in forAll(invalidHandshakeBytes) { bytes: Array[Byte] =>
    val decoder = new SpiedHandshakeDecoder
    val channel = new EmbeddedChannel(decoder)

    val buff = Unpooled.buffer
    buff.writeBytes(bytes)

    channel.writeInbound(buff)
    decoder.blockCalls shouldBe >(0)
  }

  private class SpiedHandshakeDecoder extends HandshakeDecoder(PeerDatabase.NoOp) {
    var blockCalls = 0

    override protected def block(ctx: ChannelHandlerContext, e: Throwable): Unit = {
      blockCalls += 1
    }
  }

} 
Example 7
Source File: ClientSpec.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.network

import java.util.concurrent.ConcurrentHashMap

import com.wavesplatform.{TransactionGen, Version}
import io.netty.buffer.{ByteBuf, Unpooled}
import io.netty.channel.Channel
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.channel.group.ChannelGroup
import org.scalamock.scalatest.MockFactory
import org.scalatest.{FreeSpec, Matchers}

import scala.concurrent.duration.DurationInt
import scala.util.Random

class ClientSpec extends FreeSpec with Matchers with MockFactory with TransactionGen {

  private val clientHandshake = new Handshake(
    applicationName = "wavesI",
    applicationVersion = Version.VersionTuple,
    nodeName = "test",
    nodeNonce = Random.nextInt(),
    declaredAddress = None
  )

  private val serverHandshake = clientHandshake.copy(nodeNonce = Random.nextInt())

  "should send only a local handshake on connection" in {
    val channel = createEmbeddedChannel(mock[ChannelGroup])

    val sentClientHandshakeBuff = channel.readOutbound[ByteBuf]()
    Handshake.decode(sentClientHandshakeBuff) shouldBe clientHandshake
    channel.outboundMessages() shouldBe empty
  }

  "should add a server's channel to all channels after the handshake only" in {
    var channelWasAdded = false
    val allChannels     = mock[ChannelGroup]
    (allChannels.add _).expects(*).onCall { _: Channel =>
      channelWasAdded = true
      true
    }

    val channel = createEmbeddedChannel(allChannels)

    // skip the client's handshake
    channel.readOutbound[ByteBuf]()
    channelWasAdded shouldBe false

    val replyServerHandshakeBuff = Unpooled.buffer()
    serverHandshake.encode(replyServerHandshakeBuff)
    channel.writeInbound(replyServerHandshakeBuff)
    channelWasAdded shouldBe true
  }

  private def createEmbeddedChannel(allChannels: ChannelGroup) = new EmbeddedChannel(
    new HandshakeDecoder(PeerDatabase.NoOp),
    new HandshakeTimeoutHandler(1.minute),
    new HandshakeHandler.Client(
      handshake = clientHandshake,
      establishedConnections = new ConcurrentHashMap(),
      peerConnections = new ConcurrentHashMap(),
      peerDatabase = PeerDatabase.NoOp,
      allChannels = allChannels
    )
  )

} 
Example 8
Source File: AsyncHttpClientFs2Backend.scala    From sttp   with Apache License 2.0 5 votes vote down vote up
package sttp.client.asynchttpclient.fs2

import java.io.File
import java.nio.ByteBuffer

import cats.effect._
import cats.effect.implicits._
import cats.implicits._
import fs2.{Chunk, Stream}
import fs2.interop.reactivestreams._
import io.netty.buffer.{ByteBuf, Unpooled}
import org.asynchttpclient.{Request => _, Response => _, _}
import org.reactivestreams.Publisher
import sttp.client.asynchttpclient.{AsyncHttpClientBackend, WebSocketHandler}
import sttp.client.impl.cats.CatsMonadAsyncError
import sttp.client.internal._
import sttp.client.testing.SttpBackendStub
import sttp.client.ws.WebSocketResponse
import sttp.client.{FollowRedirectsBackend, SttpBackend, SttpBackendOptions, _}

import scala.concurrent.ExecutionContext
import scala.language.higherKinds

class AsyncHttpClientFs2Backend[F[_]: ConcurrentEffect: ContextShift] private (
    asyncHttpClient: AsyncHttpClient,
    closeClient: Boolean,
    customizeRequest: BoundRequestBuilder => BoundRequestBuilder
) extends AsyncHttpClientBackend[F, Stream[F, Byte]](
      asyncHttpClient,
      new CatsMonadAsyncError,
      closeClient,
      customizeRequest
    ) {
  override def send[T](r: Request[T, Stream[F, Byte]]): F[Response[T]] = {
    super.send(r).guarantee(implicitly[ContextShift[F]].shift)
  }

  override def openWebsocket[T, WS_RESULT](
      r: Request[T, Stream[F, Byte]],
      handler: WebSocketHandler[WS_RESULT]
  ): F[WebSocketResponse[WS_RESULT]] = super.openWebsocket(r, handler).guarantee(ContextShift[F].shift)

  override protected def streamBodyToPublisher(s: Stream[F, Byte]): Publisher[ByteBuf] =
    s.chunks.map(c => Unpooled.wrappedBuffer(c.toArray)).toUnicastPublisher

  override protected def publisherToStreamBody(p: Publisher[ByteBuffer]): Stream[F, Byte] =
    p.toStream[F].flatMap(buf => Stream.chunk(Chunk.byteBuffer(buf)))

  override protected def publisherToBytes(p: Publisher[ByteBuffer]): F[Array[Byte]] = {
    p.toStream[F]
      .compile
      .fold(ByteBuffer.allocate(0))(concatByteBuffers)
      .map(_.array())
  }

  override protected def publisherToFile(p: Publisher[ByteBuffer], f: File): F[Unit] = {
    p.toStream[F]
      .flatMap(b => Stream.emits(b.array()))
      .through(fs2.io.file.writeAll(f.toPath, Blocker.liftExecutionContext(ExecutionContext.global)))
      .compile
      .drain
  }
}

object AsyncHttpClientFs2Backend {
  private def apply[F[_]: ConcurrentEffect: ContextShift](
      asyncHttpClient: AsyncHttpClient,
      closeClient: Boolean,
      customizeRequest: BoundRequestBuilder => BoundRequestBuilder
  ): SttpBackend[F, Stream[F, Byte], WebSocketHandler] =
    new FollowRedirectsBackend(new AsyncHttpClientFs2Backend(asyncHttpClient, closeClient, customizeRequest))

  def apply[F[_]: ConcurrentEffect: ContextShift](
      options: SttpBackendOptions = SttpBackendOptions.Default,
      customizeRequest: BoundRequestBuilder => BoundRequestBuilder = identity
  ): F[SttpBackend[F, Stream[F, Byte], WebSocketHandler]] =
    implicitly[Sync[F]]
      .delay(apply[F](AsyncHttpClientBackend.defaultClient(options), closeClient = true, customizeRequest))

  
  def stub[F[_]: Concurrent]: SttpBackendStub[F, Stream[F, ByteBuffer], WebSocketHandler] =
    SttpBackendStub(new CatsMonadAsyncError())
} 
Example 9
Source File: ExampleCloseHandler.scala    From Neutrino   with Apache License 2.0 5 votes vote down vote up
package com.ebay.neutrino.handler

import com.ebay.neutrino.NeutrinoRequest
import com.typesafe.scalalogging.slf4j.StrictLogging
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelHandler.Sharable
import io.netty.channel.{ChannelFutureListener, ChannelHandlerContext, ChannelInboundHandlerAdapter}
import io.netty.handler.codec.http._
import io.netty.util.CharsetUtil


@Sharable
class ExampleCloseHandler extends ChannelInboundHandlerAdapter with StrictLogging {


  override def channelRead(ctx: ChannelHandlerContext, msg: AnyRef): Unit =
    msg match {
      case request: NeutrinoRequest if request.uri.startsWith("/close") =>
        // Handle a 'close' request
        val status = HttpResponseStatus.OK
        val buffer = Unpooled.copiedBuffer(s"Handling /close request by closing connection.\r\n", CharsetUtil.UTF_8)
        val response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buffer)

        // Set the content-type
        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8")

        // Close the connection as soon as the error message is sent.
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE)


      case _ =>
        // Fall through
        ctx.fireChannelRead(msg)
    }
} 
Example 10
Source File: HttpUtils.scala    From Neutrino   with Apache License 2.0 5 votes vote down vote up
package com.ebay.neutrino.util

import java.net.URI

import com.ebay.neutrino.config.Host
import com.typesafe.scalalogging.slf4j.StrictLogging
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.http.HttpHeaders.{Names, Values}
import io.netty.handler.codec.http._
import io.netty.util.CharsetUtil



object HttpResponseUtils {
  import io.netty.handler.codec.http.HttpHeaderNames._
  import io.netty.handler.codec.http.HttpVersion._


  def error(status: HttpResponseStatus) = {
    // Allocate some memory for this
    val buffer = Unpooled.copiedBuffer(s"Failure: $status\r\n", CharsetUtil.UTF_8)

    // Package a response
    val response = new DefaultFullHttpResponse(HTTP_1_1, status, buffer)
    response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8")
    response
  }
} 
Example 11
Source File: JavaInvalidCharacterEscapingTest.scala    From guardrail   with MIT License 5 votes vote down vote up
package core.Dropwizard

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper
import invalidCharacters.client.dropwizard.invalidCharacters.InvalidCharactersClient
import invalidCharacters.server.dropwizard.definitions.{InvalidCharacters, InvalidCharactersEnum}
import io.netty.buffer.Unpooled
import java.net.{SocketAddress, URI, URLDecoder}
import java.util.concurrent.{CompletableFuture, CompletionStage}
import java.util.function
import org.asynchttpclient.Response.ResponseBuilder
import org.asynchttpclient.netty.EagerResponseBodyPart
import org.asynchttpclient.uri.Uri
import org.asynchttpclient.{HttpResponseStatus, Request, Response}
import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.must.Matchers
import scala.collection.JavaConverters._

object JavaInvalidCharacterEscapingTest {
  private implicit class RichString(private val s: String) extends AnyVal {
    def dec: String = URLDecoder.decode(s, "UTF-8")
  }

  private object OkStatus extends HttpResponseStatus(Uri.create("http://localhost:1234/foo?foo^bar=query-param")) {
    override def getStatusCode = 200
    override def getStatusText = "OK"
    override def getProtocolName = "HTTP"
    override def getProtocolMajorVersion = 1
    override def getProtocolMinorVersion = 1
    override def getProtocolText = "HTTP/1.1"
    override def getRemoteAddress: SocketAddress = ???
    override def getLocalAddress: SocketAddress = ???
  }
}

class JavaInvalidCharacterEscapingTest extends AnyFreeSpec with Matchers {
  import JavaInvalidCharacterEscapingTest._

  "Invalid characters in Java enums should be escaped" in {
    InvalidCharactersEnum.NORMAL.getName mustBe "normal"
    InvalidCharactersEnum.BANG_MOO_COLON_COW_SEMICOLON.getName mustBe "!moo:cow;"
    InvalidCharactersEnum.POUND_YEAH.getName mustBe "#yeah"
    InvalidCharactersEnum.WEIRD_AT.getName mustBe "weird@"
  }

  "Invalid characters in Java POJO properties should be escaped" in {
    val invChar = new InvalidCharacters.Builder("stuff", InvalidCharactersEnum.POUND_YEAH).build()
    invChar.getCloseSquareBraceMoo mustBe "stuff"
    invChar.getSomeEnumAsteriskCaret mustBe InvalidCharactersEnum.POUND_YEAH

    classOf[InvalidCharacters].getDeclaredField("closeSquareBraceMoo").getAnnotation(classOf[JsonProperty]).value mustBe "]moo"
    classOf[InvalidCharacters].getDeclaredField("someEnumAsteriskCaret").getAnnotation(classOf[JsonProperty]).value mustBe "some-enum*^"
  }

  "Invalid characters in Java operation param names should be escaped" in {
    val httpClient = new function.Function[Request, CompletionStage[Response]] {
      override def apply(request: Request): CompletionStage[Response] = {
        println(request.getUri)
        println(request.getQueryParams.asScala.map(_.getName))
        val qps = request.getQueryParams.asScala.map(p => (p.getName.dec, p.getValue.dec))
        val fps = request.getFormParams.asScala.map(p => (p.getName.dec, p.getValue.dec))
        qps.find(_._1 == "foo^bar").map(_._2) mustBe Some("firstarg")
        fps.find(_._1 == "a*b").map(_._2) mustBe Some("secondarg")
        fps.find(_._1 == "bc?").map(_._2) mustBe Some("thirdarg")
        fps.find(_._1 == "d/c").map(_._2) mustBe Some("fourtharg")
        val response = new ResponseBuilder()
        response.accumulate(OkStatus)
        response.accumulate(new EagerResponseBodyPart(
          Unpooled.copiedBuffer(new ObjectMapper().writeValueAsBytes(new InvalidCharacters.Builder("foo", InvalidCharactersEnum.WEIRD_AT).build())),
          true
        ))
        CompletableFuture.completedFuture(response.build())
      }
    }

    val client = new InvalidCharactersClient.Builder(new URI("http://localhost:1234")).withHttpClient(httpClient).build()
    val response = client.getFoo("firstarg", "secondarg", "thirdarg", "fourtharg").call().toCompletableFuture.get()
    response.fold(
      { invChar =>
        invChar.getCloseSquareBraceMoo mustBe "foo"
        invChar.getSomeEnumAsteriskCaret mustBe invalidCharacters.client.dropwizard.definitions.InvalidCharactersEnum.WEIRD_AT
      }
    )
  }
} 
Example 12
Source File: package.scala    From grpcgateway   with MIT License 5 votes vote down vote up
package grpcgateway

import java.nio.charset.StandardCharsets

import scalapb.json4s.JsonFormatException
import io.grpc.Status.Code
import io.netty.buffer.Unpooled
import io.netty.handler.codec.http._

import scala.util.{Failure, Try}
import handlers._

package object handlers {

  val GRPC_HTTP_CODE_MAP: Map[Int, HttpResponseStatus] = Map(
    Code.OK.value()                  -> HttpResponseStatus.OK,
    Code.CANCELLED.value()           -> HttpResponseStatus.GONE,
    Code.UNKNOWN.value()             -> HttpResponseStatus.NOT_FOUND,
    Code.INVALID_ARGUMENT.value()    -> HttpResponseStatus.BAD_REQUEST,
    Code.DEADLINE_EXCEEDED.value()   -> HttpResponseStatus.GATEWAY_TIMEOUT,
    Code.NOT_FOUND.value()           -> HttpResponseStatus.NOT_FOUND,
    Code.ALREADY_EXISTS.value()      -> HttpResponseStatus.CONFLICT,
    Code.PERMISSION_DENIED.value()   -> HttpResponseStatus.FORBIDDEN,
    Code.RESOURCE_EXHAUSTED.value()  -> HttpResponseStatus.INSUFFICIENT_STORAGE,
    Code.FAILED_PRECONDITION.value() -> HttpResponseStatus.PRECONDITION_FAILED,
    Code.ABORTED.value()             -> HttpResponseStatus.GONE,
    Code.OUT_OF_RANGE.value()        -> HttpResponseStatus.BAD_REQUEST,
    Code.UNIMPLEMENTED.value()       -> HttpResponseStatus.NOT_IMPLEMENTED,
    Code.INTERNAL.value()            -> HttpResponseStatus.INTERNAL_SERVER_ERROR,
    Code.UNAVAILABLE.value()         -> HttpResponseStatus.NOT_ACCEPTABLE,
    Code.DATA_LOSS.value()           -> HttpResponseStatus.PARTIAL_CONTENT,
    Code.UNAUTHENTICATED.value()     -> HttpResponseStatus.UNAUTHORIZED
  )

  def buildFullHttpResponse(
   requestMsg: HttpMessage,
   responseBody: String,
   responseStatus: HttpResponseStatus,
   responseContentType: String
  ): FullHttpResponse = {

    val buf = Unpooled.copiedBuffer(responseBody, StandardCharsets.UTF_8)

    val res = new DefaultFullHttpResponse(
      requestMsg.protocolVersion(),
      responseStatus,
      buf
    )

    res.headers().set(HttpHeaderNames.CONTENT_TYPE, responseContentType)

    HttpUtil.setContentLength(res, buf.readableBytes)
    HttpUtil.setKeepAlive(res, HttpUtil.isKeepAlive(requestMsg))

    res

  }

  def jsonException2GatewayExceptionPF[U]: PartialFunction[Throwable, Try[U]] = {
    case _: NoSuchElementException => Failure(InvalidArgument("Wrong json input. Check proto file"))
    case err: JsonFormatException => Failure(InvalidArgument("Wrong json syntax: " + err.msg))
    case err => Failure(InvalidArgument("Wrong json input. Check proto file. Details: " + err.getMessage))
  }

} 
Example 13
Source File: RiakMessageEncoder.scala    From spark-riak-connector   with Apache License 2.0 5 votes vote down vote up
package com.basho.riak.stub

import java.nio.ByteBuffer
import java.util

import com.basho.riak.client.core.RiakMessage
import com.basho.riak.client.core.netty.RiakMessageCodec
import io.netty.buffer.Unpooled

import scala.collection.JavaConversions._

object RiakMessageEncoder extends RiakMessageCodec {

  def encode(messages: RiakMessage*): ByteBuffer = {
    val buffer = Unpooled.buffer(messages.head.getData.length)
    messages.foreach(encode(null, _, buffer)) // scalastyle:ignore
    buffer.nioBuffer()
  }

  def decode(in: ByteBuffer): Option[RiakMessage] = {
    val out = new util.ArrayList[AnyRef]()
    val buffer = Unpooled.wrappedBuffer(in)
    decode(null, buffer, out) // scalastyle:ignore
    List(out: _*) match {
      case msg :: _ =>
        in.position(buffer.readerIndex())
        Some(msg.asInstanceOf[RiakMessage])
      case Nil => None
    }
  }
} 
Example 14
Source File: EchoClientHandler.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter2.echoclient

import io.netty.buffer.{ ByteBuf, Unpooled }
import io.netty.channel.ChannelHandler.Sharable
import io.netty.channel.{ ChannelHandlerContext, SimpleChannelInboundHandler }
import io.netty.util.CharsetUtil

@Sharable //标记该类的实例可以被多个 Channel 共享
class EchoClientHandler extends SimpleChannelInboundHandler[ByteBuf] {
  override def channelActive(ctx: ChannelHandlerContext): Unit = {
    //当被通知 Channel是活跃的时候,发送一条消息
    ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8))
  }

  override def channelRead0(ctx: ChannelHandlerContext, in: ByteBuf): Unit = {
    //记录已接收消息的转储
    System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8))
  }

  override def exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable): Unit = {
    //在发生异常时,记录错误并关闭Channel
    cause.printStackTrace()
    ctx.close()
  }
} 
Example 15
Source File: NettyNioServer.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter4

import io.netty.bootstrap.ServerBootstrap
import io.netty.buffer.Unpooled
import io.netty.channel._
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import java.net.InetSocketAddress
import java.nio.charset.Charset


class NettyNioServer {
  @throws[Exception]
  def server(port: Int): Unit = {
    val buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")))
    //为非阻塞模式使用NioEventLoopGroup
    val group: EventLoopGroup = new NioEventLoopGroup
    try { //创建ServerBootstrap
      val b = new ServerBootstrap
      b.group(group)
        .channel(classOf[NioServerSocketChannel])
        .localAddress(new InetSocketAddress(port))
        //指定 ChannelInitializer,对于每个已接受的连接都调用它
        .childHandler {
          new ChannelInitializer[SocketChannel]() {
            @throws[Exception]
            override def initChannel(ch: SocketChannel): Unit = {
              ch.pipeline.addLast(new ChannelInboundHandlerAdapter() {
                @throws[Exception]
                override def channelActive(ctx: ChannelHandlerContext): Unit = {
                  //将消息写到客户端,并添加ChannelFutureListener,
                  //以便消息一被写完就关闭连接
                  ctx.writeAndFlush(buf.duplicate)
                    .addListener(ChannelFutureListener.CLOSE)
                }
              })
            }
          }
        }
      //绑定服务器以接受连接
      val f = b.bind.sync()
      f.channel.closeFuture.sync()
    } finally {
      //释放所有的资源
      group.shutdownGracefully.sync()
    }
  }
} 
Example 16
Source File: NettyOioServer.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter4

import io.netty.bootstrap.ServerBootstrap
import io.netty.buffer.Unpooled
import io.netty.channel._
import io.netty.channel.oio.OioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.oio.OioServerSocketChannel
import java.net.InetSocketAddress
import java.nio.charset.Charset


class NettyOioServer {
  @throws[Exception]
  def server(port: Int): Unit = {
    val buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")))
    val group: EventLoopGroup = new OioEventLoopGroup
    try {
      //创建 ServerBootstrap
      val b = new ServerBootstrap
      b.group(group)
        //使用 OioEventLoopGroup以允许阻塞模式(旧的I/O)
        .channel(classOf[OioServerSocketChannel])
        .localAddress(new InetSocketAddress(port))
        //指定 ChannelInitializer,对于每个已接受的连接都调用它
        .childHandler {
          new ChannelInitializer[SocketChannel]() {
            @throws[Exception]
            override def initChannel(ch: SocketChannel): Unit = {
              ch.pipeline.addLast(new ChannelInboundHandlerAdapter() {
                @throws[Exception]
                override def channelActive(ctx: ChannelHandlerContext): Unit = {
                  ctx.writeAndFlush(buf.duplicate).addListener( //将消息写到客户端,并添加 ChannelFutureListener,
                    //以便消息一被写完就关闭连接
                    ChannelFutureListener.CLOSE)
                }
              })
            }
          }
        }
      //绑定服务器以接受连接
      val f = b.bind.sync()
      f.channel.closeFuture.sync()
    } finally {
      //释放所有的资源
      group.shutdownGracefully.sync()
    }
  }
} 
Example 17
Source File: ChannelOperationExamples.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter4

import io.netty.buffer.Unpooled
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
import io.netty.channel.socket.nio.NioSocketChannel
import io.netty.util.CharsetUtil
import java.util.concurrent.Executors


  def writingToChannelFromManyThreads(): Unit = {
    val channel = CHANNEL_FROM_SOMEWHERE
    //创建持有要写数据的ByteBuf
    val buf = Unpooled.copiedBuffer("your data", CharsetUtil.UTF_8)
    //创建将数据写到Channel 的 Runnable
    val writer: Runnable = () ⇒ channel.write(buf.duplicate())
    //获取到线程池Executor 的引用
    val executor = Executors.newCachedThreadPool
    //递交写任务给线程池以便在某个线程中执行
    // write in one thread
    executor.execute(writer)
    //递交另一个写任务以便在另一个线程中执行
    // write in another thread
    executor.execute(writer)
    //...
  }
} 
Example 18
Source File: ChannelFutures.scala    From netty-in-action-scala   with Apache License 2.0 5 votes vote down vote up
package nia.chapter6

import io.netty.buffer.Unpooled
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
import io.netty.channel.socket.nio.NioSocketChannel


  def addingChannelFutureListener(): Unit = {
    val channel = CHANNEL_FROM_SOMEWHERE
    // get reference to pipeline;
    val someMessage = SOME_MSG_FROM_SOMEWHERE
    //...
    val future = channel.write(someMessage)
    future.addListener(new ChannelFutureListener() {
      override def operationComplete(f: ChannelFuture): Unit = {
        if (!f.isSuccess) {
          f.cause.printStackTrace()
          f.channel.close
        }
      }
    })
  }
} 
Example 19
Source File: ConnectionQuerySpec.scala    From finagle-postgres   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.postgres.connection

import com.twitter.concurrent.AsyncStream
import com.twitter.finagle.postgres.{Row, Spec}
import com.twitter.finagle.postgres.messages._
import com.twitter.finagle.postgres.values.Charsets
import com.twitter.util.Await
import io.netty.buffer.Unpooled

class ConnectionQuerySpec extends Spec {
  "A postgres connection" should {
    def toList[T](rows: AsyncStream[T]): List[T] = Await.result(rows.toSeq).toList
    "handle an empty query response" in {
      val connection = new Connection(Connected)

      connection.send(Query(""))
      connection.receive(EmptyQueryResponse)
      val r@SelectResult(fields, rows) = connection.receive(ReadyForQuery('I')).get

      fields.length mustEqual 0
      r.complete.isDone mustBe true
      toList(rows) mustEqual List()
    }

    "handle a create table query" in {
      val connection = new Connection(Connected)

      connection.send(Query("create table ids"))
      connection.receive(CommandComplete(CreateTable))
      val response = connection.receive(ReadyForQuery('I'))

      response must equal(Some(CommandCompleteResponse(1)))
    }

    "handle a delete query" in {
      val connection = new Connection(Connected)

      connection.send(Query("delete from ids"))
      connection.receive(CommandComplete(Delete(2)))
      val response = connection.receive(ReadyForQuery('I'))

      response must equal(Some(CommandCompleteResponse(2)))

    }

    "handle an insert query" in {
      val connection = new Connection(Connected)

      connection.send(Query("insert into ids values (1)"))
      connection.receive(CommandComplete(Insert(1)))
      val response = connection.receive(ReadyForQuery('I'))

      response must equal(Some(CommandCompleteResponse(1)))

    }

    "handle an update query" in {
      val connection = new Connection(Connected)

      connection.send(Query("update ids set id = 2 where id = 1"))
      connection.receive(CommandComplete(Update(1)))
      val response = connection.receive(ReadyForQuery('I'))

      response must equal(Some(CommandCompleteResponse(1)))
    }

    "handle an empty select query" in {
      val connection = new Connection(Connected)

      connection.send(Query("select * from emails"))
      val r@SelectResult(fields, rows) = connection.receive(RowDescription(Array(FieldDescription("email",16728,2,1043,-1,-1,0)))).get
      connection.receive(CommandComplete(Select(0)))
      connection.receive(ReadyForQuery('I'))

      assert(fields sameElements Array(Field("email", 0, 1043)))
      r.complete.isDone mustBe true
      toList(rows) must equal (List())
    }

    "handle a select query" in {
      val connection = new Connection(Connected)

      val row1 = DataRow(Array(Some(Unpooled.copiedBuffer("[email protected]".getBytes(Charsets.Utf8)))))
      val row2 = DataRow(Array(Some(Unpooled.copiedBuffer("[email protected]".getBytes(Charsets.Utf8)))))

      connection.send(Query("select * from emails"))
      val r@SelectResult(fields, rows) = connection.receive(RowDescription(Array(FieldDescription("email",16728,2,1043,-1,-1,0)))).get

      connection.receive(row1)
      connection.receive(row2)
      connection.receive(CommandComplete(Select(2)))
      connection.receive(ReadyForQuery('I'))

      fields must contain theSameElementsAs Array(Field("email", 0, 1043))
      r.complete.isDone mustBe true
      toList(rows) must equal (List(row1, row2))
    }
  }
} 
Example 20
Source File: Numerics.scala    From finagle-postgres   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.postgres.values

import java.math.BigInteger

import io.netty.buffer.{ByteBuf, Unpooled}

private object Numerics {
  private val NUMERIC_POS = 0x0000
  private val NUMERIC_NEG = 0x4000
  private val NUMERIC_NAN = 0xC000
  private val NUMERIC_NULL = 0xF000
  private val NumericDigitBaseExponent = 4
  val biBase = BigInteger.valueOf(10000)

  private def getUnsignedShort(buf: ByteBuf) = {
    val high = buf.readByte().toInt
    val low = buf.readByte()
    (high << 8) | low
  }

  private def base10exponent(in: java.math.BigDecimal) = {
     in.round(new java.math.MathContext(1)).scale() * -1
  }

  def readNumeric(buf: ByteBuf) = {
    val len = getUnsignedShort(buf)
    val weight = buf.readShort()
    val sign = getUnsignedShort(buf)
    val displayScale = getUnsignedShort(buf)

    //digits are actually unsigned base-10000 numbers (not straight up bytes)
    val digits = Array.fill(len)(buf.readShort())
    val bdDigits = digits.map(BigDecimal(_))

    if(bdDigits.length > 0) {
      val unscaled = bdDigits.foldLeft(BigDecimal(0)) {
        case (acc, n) => acc * 10000 + n
      }

      val scaleFactor = (weight  + 1 - len) * NumericDigitBaseExponent
      val unsigned = unscaled.bigDecimal.movePointRight(scaleFactor).setScale(displayScale)

      sign match {
        case NUMERIC_POS => BigDecimal(unsigned)
        case NUMERIC_NEG => BigDecimal(unsigned.negate())
        case NUMERIC_NAN => throw new NumberFormatException("Decimal is NaN")
        case NUMERIC_NULL => throw new NumberFormatException("Decimal is NUMERIC_NULL")
      }
    } else {
      BigDecimal(0)
    }
  }

  def writeNumeric(in: BigDecimal) = {
    val minimized = BigDecimal(in.bigDecimal.stripTrailingZeros())
    val unscaled = minimized.bigDecimal.unscaledValue().abs()
    val sign = minimized.signum

    def findDigits(i: BigInteger, current: List[Short] = Nil): List[Short] = if(i.signum() != 0) {
      val Array(q, r) = i.divideAndRemainder(biBase)
      findDigits(q, r.shortValue() :: current)
    } else current

    //the decimal point must align on a base-10000 digit
    val padZeroes = 4 - (minimized.scale % 4)
    val paddedUnscaled = Option(padZeroes)
      .filterNot(_ == 0)
      .map(a => BigInteger.valueOf(10).pow(a))
      .map(unscaled.multiply)
      .getOrElse(unscaled)

    val digits = findDigits(paddedUnscaled, Nil)

    val weight = {
      val powers10 = base10exponent(in.bigDecimal) - base10exponent(new java.math.BigDecimal(paddedUnscaled))
      val mod4 = if (powers10 % 4 >= 0) powers10 % 4 else 4 + powers10 % 4

      digits.length + (powers10 - mod4) / 4 - 1
    }
    val bufSize =
      2 + //digit length
      2 + //weight
      2 + //sign
      2 + //scale
      digits.length * 2 //a short for each digit

    val buf = Unpooled.wrappedBuffer(new Array[Byte](bufSize))
    val scale = if(in.scale < 0) 0 else in.scale
    buf.resetWriterIndex()
    buf.writeShort(digits.length)
    buf.writeShort(weight)
    buf.writeShort(if(sign < 0) NUMERIC_NEG else NUMERIC_POS)
    buf.writeShort(scale)
    digits foreach (d => buf.writeShort(d))
    buf
  }
} 
Example 21
Source File: HStores.scala    From finagle-postgres   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.postgres.values

import java.nio.charset.Charset

import scala.util.parsing.combinator.RegexParsers

import io.netty.buffer.{ByteBuf, Unpooled}

object HStores {
  object HStoreStringParser extends RegexParsers {
    def key:Parser[String] = "\"" ~ """([^"\\]*(\\.[^"\\]*)*)""".r ~ "\"" ^^ {
      case o~value~c => value.replace("\\\"", "\"").replace("\\\\", "\\")
    }

    def value = key | "NULL"

    def item:Parser[(String, Option[String])] = key ~ "=>" ~ value ^^ {
      case key~arrow~"NULL" => (key, None)
      case key~arrow~value => (key, Some(value))
    }

    def items:Parser[Map[String, Option[String]]] = repsep(item, ", ") ^^ { l => l.toMap }

    def apply(input:String):Option[Map[String, Option[String]]] = parseAll(items, input) match {
      case Success(result, _) => Some(result)
      case failure:NoSuccess => None
    }
  }

  def parseHStoreString(str: String) = HStoreStringParser(str)

  def formatHStoreString(hstore: Map[String, Option[String]]) = hstore.map {
    case (k, v) =>
      val key = s""""${k.replace("\"", "\\\"")}""""
      val value = v.map(str => s""""${str.replace("\"", "\\\"")}"""").getOrElse("NULL")
      s"""$key => $value"""
  }.mkString(",")

  def decodeHStoreBinary(buf: ByteBuf, charset: Charset) = {
    val count = buf.readInt()
    val pairs = Array.fill(count) {
      val keyLength = buf.readInt()
      val key = Array.fill(keyLength)(buf.readByte())
      val valueLength = buf.readInt()
      val value = valueLength match {
        case -1 => None
        case l =>
          val valueBytes = Array.fill(l)(buf.readByte())
          Some(valueBytes)
      }
      new String(key, charset) -> value.map(new String(_, charset))
    }
    pairs.toMap
  }

  def encodeHStoreBinary(hstore: Map[String, Option[String]], charset: Charset) = {
    val buf = Unpooled.buffer()
    buf.writeInt(hstore.size)
    hstore foreach {
      case (key, value) =>
        val keyBytes = key.getBytes(charset)
        buf.writeInt(keyBytes.length)
        buf.writeBytes(keyBytes)
        value match {
          case None => buf.writeInt(-1)
          case Some(v) =>
            val valueBytes = v.getBytes(charset)
            buf.writeInt(valueBytes.length)
            buf.writeBytes(valueBytes)
        }
    }
    buf
  }

} 
Example 22
Source File: EnumSpec.scala    From finagle-postgres   with Apache License 2.0 5 votes vote down vote up
package com.twitter.finagle.postgres.generic

import java.nio.charset.StandardCharsets

import com.twitter.finagle.postgres.generic.enumeration.InvalidValue
import com.twitter.finagle.postgres.values.{ValueDecoder, ValueEncoder}
import com.twitter.util.{Return, Throw}
import io.netty.buffer.Unpooled
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class EnumSpec extends AnyFlatSpec with Matchers {

  sealed trait TestEnum
  case object CaseOne extends TestEnum
  case object CaseTwo extends TestEnum

  sealed trait AnotherBranch extends TestEnum
  case object CaseThree extends AnotherBranch

  val UTF8 = StandardCharsets.UTF_8


  "Enum decoding" should "decode enumeration ADTs from strings" in  {

    val decoder = ValueDecoder[TestEnum]

    decoder.decodeText("enum_recv", "CaseOne") shouldEqual Return(CaseOne)
    decoder.decodeText("enum_recv", "CaseTwo") shouldEqual Return(CaseTwo)
    decoder.decodeText("enum_recv", "CaseThree") shouldEqual Return(CaseThree)

    decoder.decodeBinary(
      "enum_recv",
      Unpooled.copiedBuffer("CaseOne", UTF8),
      UTF8
    ) shouldEqual Return(CaseOne)

    decoder.decodeBinary(
      "enum_recv",
      Unpooled.copiedBuffer("CaseTwo", UTF8),
      UTF8
    ) shouldEqual Return(CaseTwo)

    decoder.decodeBinary(
      "enum_recv",
      Unpooled.copiedBuffer("CaseThree", UTF8),
      UTF8
    ) shouldEqual Return(CaseThree)

  }

  it should "fail for an invalid value" in {
    val decoder = ValueDecoder[TestEnum]

    decoder.decodeText("enum_recv", "CasePurple") shouldEqual Throw(InvalidValue("CasePurple"))
    decoder.decodeBinary(
      "enum_recv",
      Unpooled.copiedBuffer("CasePurple", UTF8),
      UTF8
    ) shouldEqual Throw(InvalidValue("CasePurple"))

  }

  "Enum encoding" should "encode enumeration ADTs to Strings" in {
    val encoder = ValueEncoder[TestEnum]
    encoder.encodeText(CaseOne) shouldEqual Some("CaseOne")
    encoder.encodeText(CaseTwo) shouldEqual Some("CaseTwo")
    encoder.encodeText(CaseThree) shouldEqual Some("CaseThree")
    encoder.encodeBinary(CaseOne, UTF8).get.toString(UTF8) shouldEqual "CaseOne"
    encoder.encodeBinary(CaseTwo, UTF8).get.toString(UTF8) shouldEqual "CaseTwo"
    encoder.encodeBinary(CaseThree, UTF8).get.toString(UTF8) shouldEqual "CaseThree"
  }

}