private AMQProducerBrokerExchange getProducerBrokerExchange(ProducerId id) throws IOException {
   AMQProducerBrokerExchange result = producerExchanges.get(id);
   if (result == null) {
     synchronized (producerExchanges) {
       result = new AMQProducerBrokerExchange();
       result.setConnectionContext(context);
       // todo implement reconnect https://issues.apache.org/jira/browse/ARTEMIS-194
       if (context.isReconnect()
           || (context.isNetworkConnection() && this.acceptorUsed.isAuditNetworkProducers())) {
         if (protocolManager.getPersistenceAdapter() != null) {
           result.setLastStoredSequenceId(
               protocolManager.getPersistenceAdapter().getLastProducerSequenceId(id));
         }
       }
       SessionState ss = state.getSessionState(id.getParentId());
       if (ss != null) {
         result.setProducerState(ss.getProducerState(id));
         ProducerState producerState = ss.getProducerState(id);
         if (producerState != null && producerState.getInfo() != null) {
           ProducerInfo info = producerState.getInfo();
           result.setMutable(info.getDestination() == null || info.getDestination().isComposite());
         }
       }
       producerExchanges.put(id, result);
     }
   }
   return result;
 }
  @Override
  public Response processMessage(Message messageSend) {
    Response resp = null;
    try {
      ProducerId producerId = messageSend.getProducerId();
      AMQProducerBrokerExchange producerExchange = getProducerBrokerExchange(producerId);
      final AMQConnectionContext pcontext = producerExchange.getConnectionContext();
      final ProducerInfo producerInfo = producerExchange.getProducerState().getInfo();
      boolean sendProducerAck =
          !messageSend.isResponseRequired()
              && producerInfo.getWindowSize() > 0
              && !pcontext.isInRecoveryMode();

      AMQSession session = protocolManager.getSession(producerId.getParentId());

      if (producerExchange.canDispatch(messageSend)) {
        SendingResult result = session.send(producerExchange, messageSend, sendProducerAck);
        if (result.isBlockNextSend()) {
          if (!context.isNetworkConnection() && result.isSendFailIfNoSpace()) {
            throw new ResourceAllocationException(
                "Usage Manager Memory Limit reached. Stopping producer ("
                    + producerId
                    + ") to prevent flooding "
                    + result.getBlockingAddress()
                    + "."
                    + " See http://activemq.apache.org/producer-flow-control.html for more info");
          }

          if (producerInfo.getWindowSize() > 0 || messageSend.isResponseRequired()) {
            // in that case don't send the response
            // this will force the client to wait until
            // the response is got.
            context.setDontSendReponse(true);
          } else {
            // hang the connection until the space is available
            session.blockingWaitForSpace(producerExchange, result);
          }
        } else if (sendProducerAck) {
          ProducerAck ack = new ProducerAck(producerInfo.getProducerId(), messageSend.getSize());
          this.dispatchAsync(ack);
        }
      }
    } catch (Throwable e) {
      if (e instanceof ActiveMQSecurityException) {
        resp = new ExceptionResponse(new JMSSecurityException(e.getMessage()));
      } else {
        resp = new ExceptionResponse(e);
      }
    }
    return resp;
  }