public void process(String[] arg) {
    if (arg.length != 13 && arg.length != 14) {
      System.out.println("Invalid number of arguments! " + arg.length);
      printUsage();
      System.exit(-1);
    }

    String sourceHost;
    String sourceUser;
    String sourcePass;
    int sourcePort;
    String queue;

    String targetHost;
    int targetPort;
    String targetUser;
    String targetPassword;
    String producingAddress;

    int commit;

    int waitTimeout;

    String filter = null;

    try {
      sourceHost = arg[1];
      sourcePort = Integer.parseInt(arg[2]);
      sourceUser = arg[3];
      sourcePass = arg[4];
      queue = arg[5];

      targetHost = arg[6];
      targetPort = Integer.parseInt(arg[7]);
      targetUser = arg[8];
      targetPassword = arg[9];
      producingAddress = arg[10];

      waitTimeout = Integer.parseInt(arg[11]);
      commit = Integer.parseInt(arg[12]);

      if (arg.length == 14) {
        filter = arg[13];
      }
    } catch (Exception e) {
      e.printStackTrace();
      printUsage();
      System.exit(-1);
      return; // the compiler doesn't understand exit as leaving the VM
    }

    Map<String, Object> sourceParameters = new HashMap<String, Object>();
    sourceParameters.put(TransportConstants.HOST_PROP_NAME, sourceHost);
    sourceParameters.put(TransportConstants.PORT_PROP_NAME, sourcePort);

    Map<String, Object> targetParameters = new HashMap<String, Object>();
    sourceParameters.put(TransportConstants.HOST_PROP_NAME, targetHost);
    sourceParameters.put(TransportConstants.PORT_PROP_NAME, targetPort);

    try {
      TransportConfiguration configurationSource =
          new TransportConfiguration(NettyConnectorFactory.class.getName(), sourceParameters);

      ServerLocator locatorSource = ActiveMQClient.createServerLocator(false, configurationSource);

      ClientSessionFactory factorySource = locatorSource.createSessionFactory();

      ClientSession sessionSource =
          factorySource.createSession(sourceUser, sourcePass, false, false, false, false, 0);

      ClientConsumer consumer;

      if (filter == null) {
        consumer = sessionSource.createConsumer(queue);
      } else {
        consumer = sessionSource.createConsumer(queue, filter);
      }

      TransportConfiguration configurationTarget =
          new TransportConfiguration(NettyConnectorFactory.class.getName(), targetParameters);

      ServerLocator locatorTarget =
          ActiveMQClient.createServerLocatorWithoutHA(configurationTarget);

      ClientSessionFactory factoryTarget = locatorTarget.createSessionFactory();

      ClientSession sessionTarget =
          factoryTarget.createSession(targetUser, targetPassword, false, false, false, false, 0);

      ClientProducer producer = sessionTarget.createProducer(producingAddress);

      sessionSource.start();

      int countMessage = 0;

      while (true) {
        ClientMessage message = consumer.receive(waitTimeout);
        if (message == null) {
          break;
        }

        message.acknowledge();

        if (!message.containsProperty("_HQ_TOOL_original_address")) {
          message.putStringProperty("_HQ_TOOL_original_address", message.getAddress().toString());
        }

        LinkedList<String> listToRemove = new LinkedList<String>();

        for (SimpleString name : message.getPropertyNames()) {
          if (name.toString().startsWith("_HQ_ROUTE_TO")) {
            listToRemove.add(name.toString());
          }
        }

        for (String str : listToRemove) {
          message.removeProperty(str);
        }

        producer.send(message);

        if (countMessage++ % commit == 0) {
          System.out.println("Sent " + countMessage + " messages");
          sessionTarget.commit();
          sessionSource.commit();
        }
      }

      sessionTarget.commit();
      sessionSource.commit();
      consumer.close();
      producer.close();

      sessionSource.close();
      sessionTarget.close();

      locatorSource.close();
      locatorTarget.close();

    } catch (Exception e) {
      e.printStackTrace();
      printUsage();
      System.exit(-1);
    }
  }
  /**
   * @param numberOfMessages
   * @param session
   * @throws Exception
   */
  private void sendMessages(int numberOfMessages, ClientSession session) throws Exception {
    ClientProducer producer = session.createProducer(inQueue);

    for (int i = 0; i < numberOfMessages; i++) {
      ActiveMQTextMessage txt = new ActiveMQTextMessage(session);
      txt.setIntProperty("msg", i);
      txt.setText("Message Number (" + i + ")");
      txt.doBeforeSend();
      producer.send(txt.getCoreMessage());
    }

    session.commit();
  }
    public void onMessage(ClientMessage message) {

      try {

        message.acknowledge();
        ClientMessage outmsg = session.createMessage(true);

        outmsg.putIntProperty("out_msg", message.getIntProperty("msg"));

        producer.send(outmsg);

        if (rollbackFirstMessage) {
          session.rollback();
          rollbackFirstMessage = false;
          return;
        }

        if (counter.incrementAndGet() % 200 == 0) {
          System.out.println("rollback " + message);
          session.rollback();
        } else {
          commitLatch.countDown();
          session.commit();
        }
      } catch (Exception e) {
        e.printStackTrace();
        try {
          session.rollback();
        } catch (Exception ignored) {
          ignored.printStackTrace();
        }
      }
    }
  /**
   * @param numberOfMessages
   * @param numberOfBytes
   * @param delayDelivery
   * @param session
   * @param producer
   * @throws FileNotFoundException
   * @throws IOException
   * @throws org.apache.activemq.api.core.ActiveMQException
   */
  private void sendMessages(
      final int numberOfMessages,
      final long numberOfBytes,
      final long delayDelivery,
      final ClientSession session,
      final ClientProducer producer)
      throws Exception {
    LargeMessageTestBase.log.debug("NumberOfBytes = " + numberOfBytes);
    for (int i = 0; i < numberOfMessages; i++) {
      ClientMessage message = session.createMessage(true);

      // If the test is using more than 1M, we will only use the Streaming, as it require too much
      // memory from the
      // test
      if (numberOfBytes > 1024 * 1024 || i % 2 == 0) {
        LargeMessageTestBase.log.debug("Sending message (stream)" + i);
        message.setBodyInputStream(UnitTestCase.createFakeLargeStream(numberOfBytes));
      } else {
        LargeMessageTestBase.log.debug("Sending message (array)" + i);
        byte[] bytes = new byte[(int) numberOfBytes];
        for (int j = 0; j < bytes.length; j++) {
          bytes[j] = UnitTestCase.getSamplebyte(j);
        }
        message.getBodyBuffer().writeBytes(bytes);
      }
      message.putIntProperty(new SimpleString("counter-message"), i);
      if (delayDelivery > 0) {
        long time = System.currentTimeMillis();
        message.putLongProperty(new SimpleString("original-time"), time);
        message.putLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME, time + delayDelivery);

        producer.send(message);
      } else {
        producer.send(message);
      }
    }
  }