@Test
  public void testWrite() throws Exception {
    ActiveMQBuffer buff = ActiveMQBuffers.wrappedBuffer(ByteBuffer.allocate(128));
    EmbeddedChannel channel = createChannel();

    Assert.assertEquals(0, channel.outboundMessages().size());

    NettyConnection conn = new NettyConnection(emptyMap, channel, new MyListener(), false, false);
    conn.write(buff);
    channel.runPendingTasks();
    Assert.assertEquals(1, channel.outboundMessages().size());
  }
  @Override
  public void load() throws Exception {
    mapFactories.clear();

    List<RecordInfo> data = new ArrayList<>();

    ArrayList<PreparedTransactionInfo> list = new ArrayList<>();

    jmsJournal.load(data, list, null);

    for (RecordInfo record : data) {
      long id = record.id;

      ActiveMQBuffer buffer = ActiveMQBuffers.wrappedBuffer(record.data);

      byte rec = record.getUserRecordType();

      if (rec == CF_RECORD) {
        PersistedConnectionFactory cf = new PersistedConnectionFactory();
        cf.decode(buffer);
        cf.setId(id);
        mapFactories.put(cf.getName(), cf);
      } else if (rec == DESTINATION_RECORD) {
        PersistedDestination destination = new PersistedDestination();
        destination.decode(buffer);
        destination.setId(id);
        destinations.put(new Pair<>(destination.getType(), destination.getName()), destination);
      } else if (rec == BINDING_RECORD) {
        PersistedBindings bindings = new PersistedBindings();
        bindings.decode(buffer);
        bindings.setId(id);
        Pair<PersistedType, String> key = new Pair<>(bindings.getType(), bindings.getName());
        mapBindings.put(key, bindings);
      } else {
        throw new IllegalStateException("Invalid record type " + rec);
      }
    }
  }
 @Override
 public ActiveMQBuffer createTransportBuffer(int size) {
   return ActiveMQBuffers.dynamicBuffer(size);
 }
 public ActiveMQBuffer createTransportBuffer(final int size) {
   return ActiveMQBuffers.dynamicBuffer(size);
 }
  public void write(
      ActiveMQBuffer buffer,
      final boolean flush,
      final boolean batched,
      final ChannelFutureListener futureListener) {

    try {
      writeLock.acquire();

      try {
        if (batchBuffer == null && batchingEnabled && batched && !flush) {
          // Lazily create batch buffer

          batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE);
        }

        if (batchBuffer != null) {
          batchBuffer.writeBytes(buffer, 0, buffer.writerIndex());

          if (batchBuffer.writerIndex() >= BATCHING_BUFFER_SIZE || !batched || flush) {
            // If the batch buffer is full or it's flush param or not batched then flush the buffer

            buffer = batchBuffer;
          } else {
            return;
          }

          if (!batched || flush) {
            batchBuffer = null;
          } else {
            // Create a new buffer

            batchBuffer = ActiveMQBuffers.dynamicBuffer(BATCHING_BUFFER_SIZE);
          }
        }

        // depending on if we need to flush or not we can use a voidPromise or
        // use a normal promise
        final ByteBuf buf = buffer.byteBuf();
        final ChannelPromise promise;
        if (flush || futureListener != null) {
          promise = channel.newPromise();
        } else {
          promise = channel.voidPromise();
        }

        EventLoop eventLoop = channel.eventLoop();
        boolean inEventLoop = eventLoop.inEventLoop();
        if (!inEventLoop) {
          if (futureListener != null) {
            channel.writeAndFlush(buf, promise).addListener(futureListener);
          } else {
            channel.writeAndFlush(buf, promise);
          }
        } else {
          // create a task which will be picked up by the eventloop and trigger the write.
          // This is mainly needed as this method is triggered by different threads for the same
          // channel.
          // if we not do this we may produce out of order writes.
          final Runnable task =
              new Runnable() {
                @Override
                public void run() {
                  if (futureListener != null) {
                    channel.writeAndFlush(buf, promise).addListener(futureListener);
                  } else {
                    channel.writeAndFlush(buf, promise);
                  }
                }
              };
          // execute the task on the eventloop
          eventLoop.execute(task);
        }

        // only try to wait if not in the eventloop otherwise we will produce a deadlock
        if (flush && !inEventLoop) {
          while (true) {
            try {
              boolean ok = promise.await(10000);

              if (!ok) {
                ActiveMQClientLogger.LOGGER.timeoutFlushingPacket();
              }

              break;
            } catch (InterruptedException e) {
              throw new ActiveMQInterruptedException(e);
            }
          }
        }
      } finally {
        writeLock.release();
      }
    } catch (InterruptedException e) {
      throw new ActiveMQInterruptedException(e);
    }
  }
  public static ActiveMQBuffer toActiveMQBuffer(ByteSequence bytes) {
    ActiveMQBuffer buffer = ActiveMQBuffers.fixedBuffer(bytes.length);

    buffer.writeBytes(bytes.data, bytes.offset, bytes.length);
    return buffer;
  }