@Override
  public HandleStatus handle(final MessageReference ref) throws Exception {
    if (filter != null && !filter.match(ref.getMessage())) {
      return HandleStatus.NO_MATCH;
    }

    synchronized (this) {
      if (!active || !session.isWritable(this)) {
        if (logger.isDebugEnabled()) {
          logger.debug(this + "::Ignoring reference on bridge as it is set to inactive ref=" + ref);
        }
        return HandleStatus.BUSY;
      }

      if (deliveringLargeMessage) {
        return HandleStatus.BUSY;
      }

      if (logger.isTraceEnabled()) {
        logger.trace("Bridge " + this + " is handling reference=" + ref);
      }

      ref.handled();

      synchronized (refs) {
        refs.put(ref.getMessage().getMessageID(), ref);
      }

      final ServerMessage message = beforeForward(ref.getMessage());

      final SimpleString dest;

      if (forwardingAddress != null) {
        dest = forwardingAddress;
      } else {
        // Preserve the original address
        dest = message.getAddress();
      }

      pendingAcks.countUp();

      try {
        if (message.isLargeMessage()) {
          deliveringLargeMessage = true;
          deliverLargeMessage(dest, ref, (LargeServerMessage) message);
          return HandleStatus.HANDLED;
        } else {
          return deliverStandardMessage(dest, ref, message);
        }
      } catch (Exception e) {
        // If an exception happened, we must count down immediately
        pendingAcks.countDown();
        throw e;
      }
    }
  }
 /** @param credits */
 private void sendCredits(final int credits) {
   pendingFlowControl.countUp();
   flowControlExecutor.execute(
       new Runnable() {
         public void run() {
           try {
             sessionContext.sendConsumerCredits(ClientConsumerImpl.this, credits);
           } finally {
             pendingFlowControl.countDown();
           }
         }
       });
 }
 /** Sending an initial credit for slow consumers */
 private void startSlowConsumer() {
   if (isTrace) {
     ActiveMQClientLogger.LOGGER.trace(
         "Sending 1 credit to start delivering of one message to slow consumer");
   }
   sendCredits(1);
   try {
     // We use an executor here to guarantee the messages will arrive in order.
     // However when starting a slow consumer, we have to guarantee the credit was sent before we
     // can perform any
     // operations like forceDelivery
     pendingFlowControl.await(10, TimeUnit.SECONDS);
   } catch (InterruptedException e) {
     // will just ignore and forward the ignored
     Thread.currentThread().interrupt();
   }
 }
  @Override
  public void sendAcknowledged(final Message message) {
    if (logger.isTraceEnabled()) {
      logger.trace("BridgeImpl::sendAcknowledged received confirmation for message " + message);
    }
    if (active) {
      try {

        final MessageReference ref;

        synchronized (refs) {
          ref = refs.remove(message.getMessageID());
        }

        if (ref != null) {
          if (logger.isTraceEnabled()) {
            logger.trace(
                "BridgeImpl::sendAcknowledged bridge "
                    + this
                    + " Acking "
                    + ref
                    + " on queue "
                    + ref.getQueue());
          }
          ref.getQueue().acknowledge(ref);
          pendingAcks.countDown();
        } else {
          if (logger.isTraceEnabled()) {
            logger.trace(
                "BridgeImpl::sendAcknowledged bridge "
                    + this
                    + " could not find reference for message "
                    + message);
          }
        }
      } catch (Exception e) {
        ActiveMQServerLogger.LOGGER.bridgeFailedToAck(e);
      }
    }
  }