/**
   * Replaces the payload format with property values from messageContext.
   *
   * @param format
   * @param resultCTX
   * @param synCtx
   */
  private void replaceCTX(String format, StringBuffer resultCTX, MessageContext synCtx) {
    Matcher ctxMatcher;

    if (mediaType != null && (mediaType.equals(JSON_TYPE) || mediaType.equals(TEXT_TYPE))) {
      ctxMatcher = ctxPattern.matcher(format);
    } else {
      ctxMatcher = ctxPattern.matcher("<pfPadding>" + format + "</pfPadding>");
    }
    while (ctxMatcher.find()) {
      String ctxMatchSeq = ctxMatcher.group();
      String expressionTxt = ctxMatchSeq.substring(5, ctxMatchSeq.length());

      String replaceValue = synCtx.getProperty(expressionTxt).toString();

      if (mediaType.equals(JSON_TYPE) && inferReplacementType(replaceValue).equals(XML_TYPE)) {
        // XML to JSON conversion here
        try {
          replaceValue = "<jsonObject>" + replaceValue + "</jsonObject>";
          OMElement omXML = AXIOMUtil.stringToOM(replaceValue);
          replaceValue = JsonUtil.toJsonString(omXML).toString();
        } catch (XMLStreamException e) {
          handleException(
              "Error parsing XML for JSON conversion, please check your property values return valid XML: ",
              synCtx);
        } catch (AxisFault e) {
          handleException("Error converting XML to JSON", synCtx);
        }
      } else if (mediaType.equals(XML_TYPE)
          && inferReplacementType(replaceValue).equals(JSON_TYPE)) {
        // JSON to XML conversion here
        try {
          OMElement omXML = JsonUtil.toXml(IOUtils.toInputStream(replaceValue), false);
          if (JsonUtil.isAJsonPayloadElement(omXML)) { // remove <jsonObject/> from result.
            Iterator children = omXML.getChildElements();
            String childrenStr = "";
            while (children.hasNext()) {
              childrenStr += (children.next()).toString().trim();
            }
            replaceValue = childrenStr;
          } else {
            replaceValue = omXML.toString();
          }
        } catch (AxisFault e) {
          handleException(
              "Error converting JSON to XML, please check your property values return valid JSON: ",
              synCtx);
        }
      }
      ctxMatcher.appendReplacement(resultCTX, replaceValue);
    }
    ctxMatcher.appendTail(resultCTX);
  }
 /**
  * Extract payload from the synapse message context.
  *
  * @param messageContext synapse message context
  * @return payload
  */
 public static String collectPayload(MessageContext messageContext) {
   String payload = null;
   try {
     org.apache.axis2.context.MessageContext a2mc =
         ((Axis2MessageContext) messageContext).getAxis2MessageContext();
     if (JsonUtil.hasAJsonPayload(a2mc)) {
       payload = JsonUtil.jsonPayloadToString(a2mc);
     } else {
       payload = messageContext.getEnvelope().toString();
     }
   } catch (Exception e) {
     // SOAP envelop is not created yet
     payload = "NONE";
   }
   return payload;
 }
 private boolean mediate(MessageContext synCtx, String format) {
   if (!isDoingXml(synCtx) && !isDoingJson(synCtx)) {
     log.error(
         "#mediate. Could not identify the payload format of the existing payload prior to mediate.");
     return false;
   }
   org.apache.axis2.context.MessageContext axis2MessageContext =
       ((Axis2MessageContext) synCtx).getAxis2MessageContext();
   StringBuffer result = new StringBuffer();
   StringBuffer resultCTX = new StringBuffer();
   regexTransformCTX(resultCTX, synCtx, format);
   replace(resultCTX.toString(), result, synCtx);
   String out = result.toString().trim();
   if (log.isDebugEnabled()) {
     log.debug("#mediate. Transformed payload format>>> " + out);
   }
   if (mediaType.equals(XML_TYPE)) {
     try {
       JsonUtil.removeJsonPayload(axis2MessageContext);
       OMElement omXML = AXIOMUtil.stringToOM(out);
       if (!checkAndReplaceEnvelope(
           omXML,
           synCtx)) { // check if the target of the PF 'format' is the entire SOAP envelop, not
                      // just the body.
         axis2MessageContext.getEnvelope().getBody().addChild(omXML.getFirstElement());
       }
     } catch (XMLStreamException e) {
       handleException("Error creating SOAP Envelope from source " + out, synCtx);
     }
   } else if (mediaType.equals(JSON_TYPE)) {
     JsonUtil.newJsonPayload(axis2MessageContext, out, true, true);
   } else if (mediaType.equals(TEXT_TYPE)) {
     JsonUtil.removeJsonPayload(axis2MessageContext);
     axis2MessageContext.getEnvelope().getBody().addChild(getTextElement(out));
   }
   // need to honour a content-type of the payload media-type as output from the payload
   // {re-merging patch https://wso2.org/jira/browse/ESBJAVA-3014}
   setContentType(synCtx);
   return true;
 }
  public static org.apache.axis2.context.MessageContext attachMessage(
      String jsonMessage, org.apache.axis2.context.MessageContext axis2Ctx) {
    if (jsonMessage == null) {
      log.error("Cannot attach null JSON string.");
      return null;
    }

    AxisConfiguration axisConfig = axis2Ctx.getConfigurationContext().getAxisConfiguration();
    if (axisConfig == null) {
      log.warn("Cannot create AxisConfiguration. AxisConfiguration is null.");
      return null;
    }

    try {
      SOAPFactory soapFactory = new SOAP12Factory();
      SOAPEnvelope envelope = soapFactory.createSOAPEnvelope();
      envelope.addChild(JsonUtil.newJsonPayload(axis2Ctx, jsonMessage, true, true));
      axis2Ctx.setEnvelope(envelope);
      return axis2Ctx;
    } catch (Exception e) {
      log.error("Cannot attach message to Message Context. Error: " + e.getMessage(), e);
      return null;
    }
  }
  public boolean dispatch(MessageContext messageContext) {

    if (log.isDebugEnabled()) {
      log.debug(
          "Sending the message to client with message processor ["
              + messageProcessor.getName()
              + "]");
    }

    // The below code is just for keeping the backward compatibility with the old code.
    if (targetEndpoint == null) {
      targetEndpoint =
          (String) messageContext.getProperty(ForwardingProcessorConstants.TARGET_ENDPOINT);
    }

    MessageContext outCtx = null;
    SOAPEnvelope originalEnvelop = messageContext.getEnvelope();

    if (targetEndpoint != null) {
      Endpoint ep = messageContext.getEndpoint(targetEndpoint);

      try {

        // Send message to the client
        while (!isSuccessful && !isTerminated) {
          try {
            // For each retry we need to have a fresh copy of the actual message. otherwise retry
            // may not
            // work as expected.
            messageContext.setEnvelope(MessageHelper.cloneSOAPEnvelope(originalEnvelop));
            OMElement firstChild = null; //
            org.apache.axis2.context.MessageContext origAxis2Ctx =
                ((Axis2MessageContext) messageContext).getAxis2MessageContext();
            if (JsonUtil.hasAJsonPayload(origAxis2Ctx)) {
              firstChild = origAxis2Ctx.getEnvelope().getBody().getFirstElement();
            } // Had to do this because MessageHelper#cloneSOAPEnvelope does not clone
            // OMSourcedElemImpl correctly.
            if (JsonUtil.hasAJsonPayload(firstChild)) { //
              OMElement clonedFirstElement =
                  messageContext.getEnvelope().getBody().getFirstElement();
              if (clonedFirstElement != null) {
                clonedFirstElement.detach();
                messageContext.getEnvelope().getBody().addChild(firstChild);
              }
            } // Had to do this because MessageHelper#cloneSOAPEnvelope does not clone
            // OMSourcedElemImpl correctly.
            origAxis2Ctx.setProperty(
                HTTPConstants.NON_ERROR_HTTP_STATUS_CODES, getNonRetryStatusCodes());
            outCtx = sender.send(ep, messageContext);
            isSuccessful = true;

          } catch (Exception e) {

            // this means send has failed due to some reason so we have to retry it
            if (e instanceof SynapseException) {
              isSuccessful = isNonRetryErrorCode(e.getCause().getMessage());
            }
            if (!isSuccessful) {
              log.error(
                  "BlockingMessageSender of message processor ["
                      + this.messageProcessor.getName()
                      + "] failed to send message to the endpoint");
            }
          }

          if (isSuccessful) {
            if (outCtx != null) {
              if ("true"
                  .equals(outCtx.getProperty(ForwardingProcessorConstants.BLOCKING_SENDER_ERROR))) {

                // this means send has failed due to some reason so we have to retry it
                isSuccessful =
                    isNonRetryErrorCode(
                        (String) outCtx.getProperty(SynapseConstants.ERROR_MESSAGE));

                if (isSuccessful) {
                  sendThroughReplySeq(outCtx);
                } else {
                  // This means some error has occurred so must try to send down the fault sequence.
                  log.error(
                      "BlockingMessageSender of message processor ["
                          + this.messageProcessor.getName()
                          + "] failed to send message to the endpoint");
                  sendThroughFaultSeq(outCtx);
                }
              } else {
                // Send the message down the reply sequence if there is one
                sendThroughReplySeq(outCtx);
                messageConsumer.ack();
                attemptCount = 0;
                isSuccessful = true;

                if (log.isDebugEnabled()) {
                  log.debug(
                      "Successfully sent the message to endpoint ["
                          + ep.getName()
                          + "]"
                          + " with message processor ["
                          + messageProcessor.getName()
                          + "]");
                }
              }
            } else {
              // This Means we have invoked an out only operation
              // remove the message and reset the count
              messageConsumer.ack();
              attemptCount = 0;
              isSuccessful = true;

              if (log.isDebugEnabled()) {
                log.debug(
                    "Successfully sent the message to endpoint ["
                        + ep.getName()
                        + "]"
                        + " with message processor ["
                        + messageProcessor.getName()
                        + "]");
              }
            }
          }

          if (!isSuccessful) {
            // Then we have to retry sending the message to the client.
            prepareToRetry();
          } else {
            if (messageProcessor.isPaused()) {
              this.messageProcessor.resumeService();
              log.info(
                  "Resuming the service of message processor [" + messageProcessor.getName() + "]");
            }
          }
        }
      } catch (Exception e) {
        log.error(
            "Message processor ["
                + messageProcessor.getName()
                + "] failed to send the message to"
                + " client",
            e);
      }
    } else {
      // No Target Endpoint defined for the Message
      // So we do not have a place to deliver.
      // Here we log a warning and remove the message
      // todo: we can improve this by implementing a target inferring mechanism

      log.warn(
          "Property "
              + ForwardingProcessorConstants.TARGET_ENDPOINT
              + " not found in the message context , Hence removing the message ");

      messageConsumer.ack();
    }

    return true;
  }
 private boolean isDoingJson(MessageContext messageContext) {
   return JsonUtil.hasAJsonPayload(
       ((Axis2MessageContext) messageContext).getAxis2MessageContext());
 }
  /**
   * Replaces the payload format with SynapsePath arguments which are evaluated using
   * getArgValues().
   *
   * @param format
   * @param result
   * @param synCtx
   */
  private void replace(String format, StringBuffer result, MessageContext synCtx) {
    HashMap<String, String>[] argValues = getArgValues(synCtx);
    HashMap<String, String> replacement;
    Map.Entry<String, String> replacementEntry;
    String replacementValue = null;
    Matcher matcher;

    matcher = pattern.matcher(format);
    try {
      while (matcher.find()) {
        String matchSeq = matcher.group();
        int argIndex;
        try {
          argIndex = Integer.parseInt(matchSeq.substring(1, matchSeq.length()));
        } catch (NumberFormatException e) {
          argIndex = Integer.parseInt(matchSeq.substring(2, matchSeq.length() - 1));
        }
        replacement = argValues[argIndex - 1];
        replacementEntry = replacement.entrySet().iterator().next();
        if (mediaType.equals(JSON_TYPE)
            && inferReplacementType(replacementEntry).equals(XML_TYPE)) {
          // XML to JSON conversion here
          try {
            replacementValue = "<jsonObject>" + replacementEntry.getKey() + "</jsonObject>";
            OMElement omXML = AXIOMUtil.stringToOM(replacementValue);
            replacementValue =
                JsonUtil.toJsonString(omXML)
                    .toString()
                    .replaceAll(
                        ESCAPE_DOUBLE_QUOTE_WITH_FIVE_BACK_SLASHES,
                        ESCAPE_DOUBLE_QUOTE_WITH_NINE_BACK_SLASHES)
                    .replaceAll(
                        ESCAPE_DOLLAR_WITH_TEN_BACK_SLASHES, ESCAPE_DOLLAR_WITH_SIX_BACK_SLASHES);
            replacementValue = JsonUtil.toJsonString(omXML).toString();
          } catch (XMLStreamException e) {
            handleException(
                "Error parsing XML for JSON conversion, please check your xPath expressions return valid XML: ",
                synCtx);
          } catch (AxisFault e) {
            handleException("Error converting XML to JSON", synCtx);
          }
        } else if (mediaType.equals(XML_TYPE)
            && inferReplacementType(replacementEntry).equals(JSON_TYPE)) {
          // JSON to XML conversion here
          try {
            OMElement omXML =
                JsonUtil.toXml(IOUtils.toInputStream(replacementEntry.getKey()), false);
            if (JsonUtil.isAJsonPayloadElement(omXML)) { // remove <jsonObject/> from result.
              Iterator children = omXML.getChildElements();
              String childrenStr = "";
              while (children.hasNext()) {
                childrenStr += (children.next()).toString().trim();
              }
              replacementValue = childrenStr;
            } else { /// ~
              replacementValue = omXML.toString();
            }
            // replacementValue = omXML.toString();
          } catch (AxisFault e) {
            handleException(
                "Error converting JSON to XML, please check your JSON Path expressions return valid JSON: ",
                synCtx);
          }
        } else {
          // No conversion required, as path evaluates to regular String.
          replacementValue = replacementEntry.getKey();
          // This is to replace " with \" and \\ with \\\\
          if (mediaType.equals(JSON_TYPE)
              && inferReplacementType(replacementEntry).equals(STRING_TYPE)
              && (!replacementValue.startsWith("{") && !replacementValue.startsWith("["))) {
            replacementValue =
                replacementValue
                    .replaceAll(
                        Matcher.quoteReplacement("\\\\"),
                        ESCAPE_BACK_SLASH_WITH_SIXTEEN_BACK_SLASHES)
                    .replaceAll("\"", ESCAPE_DOUBLE_QUOTE_WITH_TEN_BACK_SLASHES);
          } else if ((mediaType.equals(JSON_TYPE)
                  && inferReplacementType(replacementEntry).equals(JSON_TYPE))
              && (!replacementValue.startsWith("{") && !replacementValue.startsWith("["))) {
            // This is to handle only the string value
            replacementValue =
                replacementValue.replaceAll("\"", ESCAPE_DOUBLE_QUOTE_WITH_TEN_BACK_SLASHES);
          }
        }
        matcher.appendReplacement(result, replacementValue);
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      log.error("#replace. Mis-match detected between number of formatters and arguments", e);
    }
    matcher.appendTail(result);
  }