public ExtensibilityElement unmarshall(
      Class parentType, QName elementType, Element el, Definition def, ExtensionRegistry extReg)
      throws WSDLException {
    SOAPBody soapBody = (SOAPBody) extReg.createExtension(parentType, elementType);
    String partsStr = DOMUtils.getAttribute(el, SOAPConstants.ATTR_PARTS);
    String use = DOMUtils.getAttribute(el, SOAPConstants.ATTR_USE);
    String encStyleStr = DOMUtils.getAttribute(el, SOAPConstants.ATTR_ENCODING_STYLE);
    String namespaceURI = DOMUtils.getAttribute(el, Constants.ATTR_NAMESPACE);
    String requiredStr =
        DOMUtils.getAttributeNS(el, Constants.NS_URI_WSDL, Constants.ATTR_REQUIRED);

    if (partsStr != null) {
      soapBody.setParts(StringUtils.parseNMTokens(partsStr));
    }

    if (use != null) {
      soapBody.setUse(use);
    }

    if (encStyleStr != null) {
      soapBody.setEncodingStyles(StringUtils.parseNMTokens(encStyleStr));
    }

    if (namespaceURI != null) {
      soapBody.setNamespaceURI(namespaceURI);
    }

    if (requiredStr != null) {
      soapBody.setRequired(new Boolean(requiredStr));
    }

    return soapBody;
  }
  /**
   * Initializes this object.
   *
   * @param key Property-key to use for locating initialization properties.
   * @param type Property-type to use for locating initialization properties.
   * @exception ProcessingException when initialization fails
   */
  public void initialize(String key, String type) throws ProcessingException {
    super.initialize(key, type);

    StringBuffer errorBuf = new StringBuffer();

    // serverName = getRequiredProperty(SERVER_NAME_PROP, errorBuf);

    headerLocation = getPropertyValue(NF_HEADER_LOCATION_PROP);

    isAsyncLocation = getPropertyValue(IS_ASYNCHRONOUS_LOCATION_PROP);

    orbAgentAddr = getPropertyValue(ORB_AGENT_ADDR_PROP);

    orbAgentPort = getPropertyValue(ORB_AGENT_PORT_PROP);

    orbAgentAddrLocation = getPropertyValue(ORB_AGENT_ADDR_PROP_LOCATION);

    orbAgentPortLocation = getPropertyValue(ORB_AGENT_PORT_PROP_LOCATION);

    if (!StringUtils.hasValue(isAsyncLocation)) {
      try {
        isAsync =
            StringUtils.getBoolean(
                (String) getRequiredPropertyValue(DEFAULT_IS_ASYNCHRONOUS_PROP, errorBuf));
      } catch (FrameworkException fe) {
        errorBuf.append(
            "No value is specified for either "
                + IS_ASYNCHRONOUS_LOCATION_PROP
                + "or"
                + DEFAULT_IS_ASYNCHRONOUS_PROP
                + ". One of the values should be present"
                + fe.getMessage());
      }
    }

    if (!StringUtils.hasValue(headerLocation)) {
      try {
        header = getRequiredPropertyValue(DEFAULT_HEADER_PROP, errorBuf);
      } catch (Exception e) {
        errorBuf.append(
            "No value is specified for "
                + NF_HEADER_LOCATION_PROP
                + "or"
                + DEFAULT_HEADER_PROP
                + ". One of the values should be present"
                + e.getMessage());
      }
    }

    if (errorBuf.length() > 0) throw new ProcessingException(errorBuf.toString());
  }
  /**
   * Validate message payloads by comparing to a control message.
   *
   * @param receivedMessage
   * @param validationContext
   * @param context
   */
  protected void validateMessageContent(
      Message receivedMessage,
      Message controlMessage,
      XmlMessageValidationContext validationContext,
      TestContext context) {
    if (controlMessage == null || controlMessage.getPayload() == null) {
      log.info("Skip message payload validation as no control message was defined");
      return;
    }

    if (!(controlMessage.getPayload() instanceof String)) {
      throw new IllegalArgumentException(
          "DomXmlMessageValidator does only support message payload of type String, "
              + "but was "
              + controlMessage.getPayload().getClass());
    }

    String controlMessagePayload = controlMessage.getPayload(String.class);

    if (receivedMessage.getPayload() == null
        || !StringUtils.hasText(receivedMessage.getPayload(String.class))) {
      Assert.isTrue(
          !StringUtils.hasText(controlMessagePayload),
          "Unable to validate message payload - received message payload was empty, control message payload is not");
      return;
    } else if (!StringUtils.hasText(controlMessagePayload)) {
      return;
    }

    log.info("Start XML tree validation ...");

    Document received = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class));
    Document source = XMLUtils.parseMessagePayload(controlMessagePayload);

    XMLUtils.stripWhitespaceNodes(received);
    XMLUtils.stripWhitespaceNodes(source);

    if (log.isDebugEnabled()) {
      log.debug("Received message:\n" + XMLUtils.serialize(received));
      log.debug("Control message:\n" + XMLUtils.serialize(source));
    }

    validateXmlTree(
        received,
        source,
        validationContext,
        namespaceContextBuilder.buildContext(receivedMessage, validationContext.getNamespaces()),
        context);
  }
  /**
   * Checks whether the given node contains a validation matcher
   *
   * @param node
   * @return true if node value contains validation matcher, false if not
   */
  private boolean isValidationMatcherExpression(Node node) {
    switch (node.getNodeType()) {
      case Node.ELEMENT_NODE:
        return node.getFirstChild() != null
            && StringUtils.hasText(node.getFirstChild().getNodeValue())
            && ValidationMatcherUtils.isValidationMatcherExpression(
                node.getFirstChild().getNodeValue().trim());

      case Node.ATTRIBUTE_NODE:
        return StringUtils.hasText(node.getNodeValue())
            && ValidationMatcherUtils.isValidationMatcherExpression(node.getNodeValue().trim());

      default:
        return false; // validation matchers makes no sense
    }
  }
  @Override
  protected void fillVoiceXmlDocument(
      Document document, Element formElement, VoiceXmlDialogueContext dialogueContext)
      throws VoiceXmlDocumentRenderingException {

    List<String> submitNameList = new ArrayList<String>();
    VariableList submitVariableList = mSubmitParameters;
    if (submitVariableList != null) {
      addVariables(formElement, submitVariableList);

      for (Entry<String, String> entry : mSubmitParameters) {
        submitNameList.add(entry.getKey());
      }
    }

    Element subdialogueElement = DomUtils.appendNewElement(formElement, SUBDIALOG_ELEMENT);
    subdialogueElement.setAttribute(NAME_ATTRIBUTE, SUBDIALOGUE_FORM_ITEM_NAME);
    subdialogueElement.setAttribute(SRC_ATTRIBUTE, mUri);

    if (!submitNameList.isEmpty()) {
      subdialogueElement.setAttribute(NAME_LIST_ATTRIBUTE, StringUtils.join(submitNameList, " "));
    }

    for (Parameter parameter : mParameters) {
      Element paramElement = DomUtils.appendNewElement(subdialogueElement, PARAM_ELEMENT);
      paramElement.setAttribute(NAME_ATTRIBUTE, parameter.getName());
      setAttribute(paramElement, VALUE_ATTRIBUTE, parameter.getValue());
      setAttribute(paramElement, EXPR_ATTRIBUTE, parameter.getExpression());
    }

    SubmitMethod submitMethod = mMethod;
    if (submitMethod != null) {
      subdialogueElement.setAttribute(METHOD_ATTRIBUTE, submitMethod.name());
    }

    DocumentFetchConfiguration fetchConfiguration = mFetchConfiguration;
    if (fetchConfiguration != null) {
      applyFetchAudio(subdialogueElement, fetchConfiguration.getFetchAudio());
      applyRessourceFetchConfiguration(subdialogueElement, fetchConfiguration);
    }

    Element filledElement = DomUtils.appendNewElement(subdialogueElement, FILLED_ELEMENT);

    createVarElement(
        filledElement, SUBDIALOGUE_RESULT_VARIABLE_NAME, "dialog." + SUBDIALOGUE_FORM_ITEM_NAME);

    if (mPostDialogueScript != null) {
      createScript(filledElement, mPostDialogueScript);
    }

    createScript(
        filledElement,
        RIVR_SCOPE_OBJECT + ".addValueResult(" + SUBDIALOGUE_RESULT_VARIABLE_NAME + ");");
    createGotoSubmit(filledElement);
  }
  public void marshall(
      Class parentType,
      QName elementType,
      ExtensibilityElement extension,
      PrintWriter pw,
      Definition def,
      ExtensionRegistry extReg)
      throws WSDLException {
    SOAPBody soapBody = (SOAPBody) extension;

    if (soapBody != null) {
      String tagName = DOMUtils.getQualifiedValue(SOAPConstants.NS_URI_SOAP, "body", def);

      if (parentType != null && MIMEPart.class.isAssignableFrom(parentType)) {
        pw.print("    ");
      }

      pw.print("        <" + tagName);

      DOMUtils.printAttribute(
          SOAPConstants.ATTR_PARTS, StringUtils.getNMTokens(soapBody.getParts()), pw);
      DOMUtils.printAttribute(SOAPConstants.ATTR_USE, soapBody.getUse(), pw);
      DOMUtils.printAttribute(
          SOAPConstants.ATTR_ENCODING_STYLE,
          StringUtils.getNMTokens(soapBody.getEncodingStyles()),
          pw);
      DOMUtils.printAttribute(Constants.ATTR_NAMESPACE, soapBody.getNamespaceURI(), pw);

      Boolean required = soapBody.getRequired();

      if (required != null) {
        DOMUtils.printQualifiedAttribute(Constants.Q_ATTR_REQUIRED, required.toString(), def, pw);
      }

      pw.println("/>");
    }
  }
  /**
   * Handle document type definition with validation of publicId and systemId.
   *
   * @param received
   * @param source
   * @param validationContext
   * @param namespaceContext
   */
  private void doDocumentTypeDefinition(
      Node received,
      Node source,
      XmlMessageValidationContext validationContext,
      NamespaceContext namespaceContext,
      TestContext context) {

    Assert.isTrue(
        source instanceof DocumentType,
        "Missing document type definition in expected xml fragment");

    DocumentType receivedDTD = (DocumentType) received;
    DocumentType sourceDTD = (DocumentType) source;

    if (log.isDebugEnabled()) {
      log.debug(
          "Validating document type definition: "
              + receivedDTD.getPublicId()
              + " ("
              + receivedDTD.getSystemId()
              + ")");
    }

    if (!StringUtils.hasText(sourceDTD.getPublicId())) {
      Assert.isNull(
          receivedDTD.getPublicId(),
          ValidationUtils.buildValueMismatchErrorMessage(
              "Document type public id not equal",
              sourceDTD.getPublicId(),
              receivedDTD.getPublicId()));
    } else if (sourceDTD.getPublicId().trim().equals(CitrusConstants.IGNORE_PLACEHOLDER)) {
      if (log.isDebugEnabled()) {
        log.debug(
            "Document type public id: '"
                + receivedDTD.getPublicId()
                + "' is ignored by placeholder '"
                + CitrusConstants.IGNORE_PLACEHOLDER
                + "'");
      }
    } else {
      Assert.isTrue(
          StringUtils.hasText(receivedDTD.getPublicId())
              && receivedDTD.getPublicId().equals(sourceDTD.getPublicId()),
          ValidationUtils.buildValueMismatchErrorMessage(
              "Document type public id not equal",
              sourceDTD.getPublicId(),
              receivedDTD.getPublicId()));
    }

    if (!StringUtils.hasText(sourceDTD.getSystemId())) {
      Assert.isNull(
          receivedDTD.getSystemId(),
          ValidationUtils.buildValueMismatchErrorMessage(
              "Document type system id not equal",
              sourceDTD.getSystemId(),
              receivedDTD.getSystemId()));
    } else if (sourceDTD.getSystemId().trim().equals(CitrusConstants.IGNORE_PLACEHOLDER)) {
      if (log.isDebugEnabled()) {
        log.debug(
            "Document type system id: '"
                + receivedDTD.getSystemId()
                + "' is ignored by placeholder '"
                + CitrusConstants.IGNORE_PLACEHOLDER
                + "'");
      }
    } else {
      Assert.isTrue(
          StringUtils.hasText(receivedDTD.getSystemId())
              && receivedDTD.getSystemId().equals(sourceDTD.getSystemId()),
          ValidationUtils.buildValueMismatchErrorMessage(
              "Document type system id not equal",
              sourceDTD.getSystemId(),
              receivedDTD.getSystemId()));
    }

    validateXmlTree(
        received.getNextSibling(),
        source.getNextSibling(),
        validationContext,
        namespaceContext,
        context);
  }
  /**
   * Validate namespaces in message. The method compares namespace declarations in the root element
   * of the received message to expected namespaces. Prefixes are important too, so differing
   * namespace prefixes will fail the validation.
   *
   * @param expectedNamespaces
   * @param receivedMessage
   */
  protected void validateNamespaces(
      Map<String, String> expectedNamespaces, Message receivedMessage) {
    if (CollectionUtils.isEmpty(expectedNamespaces)) {
      return;
    }

    if (receivedMessage.getPayload() == null
        || !StringUtils.hasText(receivedMessage.getPayload(String.class))) {
      throw new ValidationException(
          "Unable to validate message namespaces - receive message payload was empty");
    }

    log.info("Start XML namespace validation");

    Document received = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class));

    Map<String, String> foundNamespaces =
        XMLUtils.lookupNamespaces(receivedMessage.getPayload(String.class));

    if (foundNamespaces.size() != expectedNamespaces.size()) {
      throw new ValidationException(
          "Number of namespace declarations not equal for node "
              + XMLUtils.getNodesPathName(received.getFirstChild())
              + " found "
              + foundNamespaces.size()
              + " expected "
              + expectedNamespaces.size());
    }

    for (Entry<String, String> entry : expectedNamespaces.entrySet()) {
      String namespace = entry.getKey();
      String url = entry.getValue();

      if (foundNamespaces.containsKey(namespace)) {
        if (!foundNamespaces.get(namespace).equals(url)) {
          throw new ValidationException(
              "Namespace '"
                  + namespace
                  + "' values not equal: found '"
                  + foundNamespaces.get(namespace)
                  + "' expected '"
                  + url
                  + "' in reference node "
                  + XMLUtils.getNodesPathName(received.getFirstChild()));
        } else {
          log.info(
              "Validating namespace " + namespace + " value as expected " + url + " - value OK");
        }
      } else {
        throw new ValidationException(
            "Missing namespace "
                + namespace
                + "("
                + url
                + ") in node "
                + XMLUtils.getNodesPathName(received.getFirstChild()));
      }
    }

    log.info("XML namespace validation finished successfully: All values OK");
  }
  /**
   * Validate message with a XML schema.
   *
   * @param receivedMessage
   * @param validationContext
   */
  protected void validateXMLSchema(
      Message receivedMessage, XmlMessageValidationContext validationContext) {
    if (receivedMessage.getPayload() == null
        || !StringUtils.hasText(receivedMessage.getPayload(String.class))) {
      return;
    }

    try {
      Document doc = XMLUtils.parseMessagePayload(receivedMessage.getPayload(String.class));

      if (!StringUtils.hasText(doc.getFirstChild().getNamespaceURI())) {
        return;
      }

      log.info("Starting XML schema validation ...");

      XmlValidator validator = null;
      XsdSchemaRepository schemaRepository = null;
      if (validationContext.getSchema() != null) {
        validator =
            applicationContext
                .getBean(validationContext.getSchema(), XsdSchema.class)
                .createValidator();
      } else if (validationContext.getSchemaRepository() != null) {
        schemaRepository =
            applicationContext.getBean(
                validationContext.getSchemaRepository(), XsdSchemaRepository.class);
      } else if (schemaRepositories.size() == 1) {
        schemaRepository = schemaRepositories.get(0);
      } else if (schemaRepositories.size() > 0) {
        for (XsdSchemaRepository repository : schemaRepositories) {
          if (repository.canValidate(doc)) {
            schemaRepository = repository;
          }
        }

        if (schemaRepository == null) {
          throw new CitrusRuntimeException(
              String.format(
                  "Failed to find proper schema repository in Spring bean context for validating element '%s(%s)'",
                  doc.getFirstChild().getLocalName(), doc.getFirstChild().getNamespaceURI()));
        }
      } else {
        log.warn(
            "Neither schema instance nor schema repository defined - skipping XML schema validation");
        return;
      }

      if (schemaRepository != null) {
        if (!schemaRepository.canValidate(doc)) {
          throw new CitrusRuntimeException(
              String.format(
                  "Unable to find proper XML schema definition for element '%s(%s)' in schema repository '%s'",
                  doc.getFirstChild().getLocalName(),
                  doc.getFirstChild().getNamespaceURI(),
                  schemaRepository.getName()));
        }

        List<Resource> schemas = new ArrayList<>();
        for (XsdSchema xsdSchema : schemaRepository.getSchemas()) {
          if (xsdSchema instanceof XsdSchemaCollection) {
            for (Resource resource : ((XsdSchemaCollection) xsdSchema).getSchemaResources()) {
              schemas.add(resource);
            }
          } else if (xsdSchema instanceof WsdlXsdSchema) {
            for (Resource resource : ((WsdlXsdSchema) xsdSchema).getSchemaResources()) {
              schemas.add(resource);
            }
          } else {
            synchronized (transformerFactory) {
              ByteArrayOutputStream bos = new ByteArrayOutputStream();
              try {
                transformerFactory
                    .newTransformer()
                    .transform(xsdSchema.getSource(), new StreamResult(bos));
              } catch (TransformerException e) {
                throw new CitrusRuntimeException(
                    "Failed to read schema " + xsdSchema.getTargetNamespace(), e);
              }
              schemas.add(new ByteArrayResource(bos.toByteArray()));
            }
          }
        }

        validator =
            XmlValidatorFactory.createValidator(
                schemas.toArray(new Resource[schemas.size()]), WsdlXsdSchema.W3C_XML_SCHEMA_NS_URI);
      }

      SAXParseException[] results = validator.validate(new DOMSource(doc));
      if (results.length == 0) {
        log.info("Schema of received XML validated OK");
      } else {
        log.error(
            "Schema validation failed for message:\n"
                + XMLUtils.prettyPrint(receivedMessage.getPayload(String.class)));

        // Report all parsing errors
        log.debug("Found " + results.length + " schema validation errors");
        StringBuilder errors = new StringBuilder();
        for (SAXParseException e : results) {
          errors.append(e.toString());
          errors.append("\n");
        }
        log.debug(errors.toString());

        throw new ValidationException("Schema validation failed:", results[0]);
      }
    } catch (IOException e) {
      throw new CitrusRuntimeException(e);
    } catch (SAXException e) {
      throw new CitrusRuntimeException(e);
    }
  }
  /**
   * Make the actual CORBA call.
   *
   * @param serverName Name of the server as known in the COS Naming Service.
   * @param reload Flag indicating whether object reference should be refreshed (true) or any
   *     previously-cached version should be used (false).
   * @param header Header message to send.
   * @param message Body message to send.
   * @return Response that caller should return.
   * @exception Exception Thrown on any errors.
   */
  private String makeClientCall(String serverName, boolean reload, String header, String message)
      throws Exception {
    ORB orb = null;

    // If the alternate ip and port are provided
    if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort)) {
      // Key to store the orb in a static map for access the next time around
      String key = orbAgentAddr + ":" + orbAgentPort;

      synchronized (orbStore) {
        orb = (ORB) orbStore.get(key);

        if (orb == null) {
          Properties props = new Properties();
          props.put(ORB_AGENT_ADDR_PROP, orbAgentAddr);
          props.put(ORB_AGENT_PORT_PROP, orbAgentPort);
          orb = new CorbaPortabilityLayer(new String[0], props, null, serverName).getORB();

          orbStore.put(key, orb);
        } else {
          if (Debug.isLevelEnabled(Debug.IO_STATUS))
            Debug.log(
                Debug.IO_STATUS,
                "Using cached orb with properties "
                    + "ORBagentAddr = ["
                    + orbAgentAddr
                    + "] ORBagentPort = ["
                    + orbAgentPort
                    + "]");
        }
      }
    } else {
      if (Debug.isLevelEnabled(Debug.IO_STATUS))
        Debug.log(Debug.IO_STATUS, "Using the default orb ..");

      orb = Supervisor.getSupervisor().getCPL().getORB();
    }

    ObjectLocator ob_loc = new ObjectLocator(orb);

    if (reload) {
      ob_loc.removeFromCache(serverName);
      if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort))
        ob_loc.removeFromCache(serverName, orbAgentAddr, orbAgentPort);
    }

    RequestHandler rh = null;
    // The key corresponding to secondary install object references depends on host address and port
    // too.
    if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort))
      rh = RequestHandlerHelper.narrow(ob_loc.find(serverName, orbAgentAddr, orbAgentPort));
    else rh = RequestHandlerHelper.narrow(ob_loc.find(serverName));

    if (rh == null) {
      throw new Exception("Object named [" + serverName + "] is not of IDL type RequestHandler.");
    }

    // Make sure that the header contains any available customer context information.
    header = CustomerContext.getInstance().propagate(header);

    if (Debug.isLevelEnabled(Debug.IO_STATUS))
      Debug.log(Debug.IO_STATUS, "Header value:\n" + header);

    ThreadMonitor.ThreadInfo tmti =
        ThreadMonitor.start(
            "Message-processor ["
                + getName()
                + "] making CORBA client call with header:\n"
                + header);

    try {
      if (isAsync) {
        rh.processAsync(header, message);

        return (message);
      } else {
        org.omg.CORBA.StringHolder response = new org.omg.CORBA.StringHolder("");

        rh.processSync(header, message, response);

        return (response.value);
      }
    } finally {
      ThreadMonitor.stop(tmti);
    }
  }
  /**
   * If NF_HEADER_LOCATION_PROP exists in context use as the header to forward to Gateway. If
   * IS_ASYNCHRONOUS_PROP exists in context then use that value to call either processAsync or
   * processSync
   *
   * @param input MessageObject containing the value to be processed *
   * @param mpcontext The context
   * @return Optional NVPair containing a Destination name and a MessageObject, or null if none.
   * @exception ProcessingException Thrown if processing fails.
   * @exception MessageException Thrown if bad message.
   */
  public NVPair[] process(MessageProcessorContext ctx, MessageObject input)
      throws MessageException, ProcessingException {
    if (input == null) return null;

    try {
      serverName = getRequiredProperty(ctx, input, SERVER_NAME_PROP);
    } catch (MessageException me) {
      throw new ProcessingException(me.getMessage());
    }

    if (StringUtils.hasValue(headerLocation)) {
      try {
        header = getString(headerLocation, ctx, input);
      } catch (MessageException me) {
        throw new ProcessingException(me.getMessage());
      }
    }

    if (StringUtils.hasValue(isAsyncLocation)) {
      try {
        isAsync = StringUtils.getBoolean(getString(isAsyncLocation, ctx, input));
      } catch (FrameworkException fe) {
        throw new ProcessingException(
            "Value of " + IS_ASYNCHRONOUS_LOCATION_PROP + " is not TRUE/FALSE. " + fe.getMessage());
      }
    }

    // Fetch the alternate Orb Address, if one exists at the specified context location
    if (StringUtils.hasValue(orbAgentAddrLocation)) {
      try {
        if (exists(orbAgentAddrLocation, ctx, input, true)) {
          orbAgentAddr = getString(orbAgentAddrLocation, ctx, input);
          if (Debug.isLevelEnabled(Debug.MSG_STATUS))
            Debug.log(
                Debug.MSG_STATUS,
                "RequestHandlerClient:: alternate orb exists with orb agent address ["
                    + orbAgentAddr
                    + "]");
        }
      } catch (MessageException me) {
        throw new ProcessingException(me.getMessage());
      }
    }

    // Fetch the alternate Orb Port, if one exists at the specified context location
    if (StringUtils.hasValue(orbAgentPortLocation)) {
      try {
        if (exists(orbAgentPortLocation, ctx, input, true)) {
          orbAgentPort = getString(orbAgentPortLocation, ctx, input);
          if (Debug.isLevelEnabled(Debug.MSG_STATUS))
            Debug.log(
                Debug.MSG_STATUS,
                "RequestHandlerClient:: alternate orb exists with orb agent port ["
                    + orbAgentPort
                    + "]");
        }
      } catch (MessageException me) {
        throw new ProcessingException(me.getMessage());
      }
    }

    String msg = input.getString();

    try {
      try {
        return (formatNVPair(makeClientCall(serverName, false, header, msg)));
      } catch (Exception e) {
        // Any of the following exceptions indicate that the failure might be due to
        // a CORBA communications issue (stale object reference) that should be retried.
        if ((e instanceof org.omg.CORBA.OBJECT_NOT_EXIST)
            || (e instanceof org.omg.CORBA.TRANSIENT)
            || (e instanceof org.omg.CORBA.COMM_FAILURE)
            || (e instanceof org.omg.CORBA.INV_OBJREF)
            || (e instanceof org.omg.CORBA.UNKNOWN)) {
          Debug.warning(
              "Caught the following CORBA communication error, so retrying:\n"
                  + e.toString()
                  + "\n"
                  + Debug.getStackTrace(e));

          return (formatNVPair(makeClientCall(serverName, true, header, msg)));
        } else {
          // It's not a communication exception indicating that retry is recommended,
          // so just re-throw it.
          throw e;
        }
      }
    } catch (Exception e) {
      if (e instanceof InvalidDataException) {
        Debug.error(e.toString() + "\n" + Debug.getStackTrace(e));

        throw new MessageException(((InvalidDataException) e).errorMessage);
      } else {
        Debug.error(e.toString() + "\n" + Debug.getStackTrace(e));

        throw new ProcessingException(e.toString());
      }
    }
  }