Exemplo n.º 1
0
  bool UNICOREClient::submit(const JobDescription& jobdesc, XMLNode& id,
                             bool delegate) {

    std::string faultstring;

    logger.msg(INFO, "Creating and sending request");

    // Create job request
    /*
       bes-factory:CreateActivity
         bes-factory:ActivityDocument
           jsdl:JobDefinition
     */
    PayloadSOAP req(unicore_ns);
    XMLNode op = req.NewChild("bes-factory:CreateActivity");
    XMLNode act_doc = op.NewChild("bes-factory:ActivityDocument");
    set_bes_factory_action(req, "CreateActivity");
    WSAHeader(req).To(rurl.str());
    //XMLNode proxyHeader = req.Header().NewChild("u6:Proxy");
    if (true) {
      std::string pem_str;
      std::ifstream proxy_file(proxyPath.c_str()/*, ifstream::in*/);
      std::getline<char>(proxy_file, pem_str, 0);
      req.Header().NewChild("u6:Proxy") = pem_str;
      //std::cout << "\n----\n" << "pem_str = " << pem_str << "\n----\n"; //debug code, remove!
    }
    //std::string jsdl_str;
    //std::getline<char>(jsdl_file, jsdl_str, 0);
    std::string jsdl_str;
    if (!jobdesc.UnParse(jsdl_str, "nordugrid:jsdl")) {
      logger.msg(INFO, "Unable to submit job. Job description is not valid in the %s format", "nordugrid:jsdl");
      return false;
    }
    XMLNode jsdl_doc = act_doc.NewChild(XMLNode(jsdl_str));
    //std::cout << "\n----\n" << jsdl_str << "\n----\n"; //Debug line to verify the activity document
    jsdl_doc.Namespaces(unicore_ns); // Unify namespaces
    PayloadSOAP *resp = NULL;

    XMLNode ds =
      act_doc["jsdl:JobDefinition"]["jsdl:JobDescription"]["jsdl:DataStaging"];
    for (; (bool)ds; ds = ds[1]) {
      // FilesystemName - ignore
      // CreationFlag - ignore
      // DeleteOnTermination - ignore
      XMLNode source = ds["jsdl:Source"];
      XMLNode target = ds["jsdl:Target"];
      if ((bool)source) {
        std::string s_name = ds["jsdl:FileName"];
        if (!s_name.empty()) {
          XMLNode x_url = source["jsdl:URI"];
          std::string s_url = x_url;
          if (s_url.empty())
            s_url = "./" + s_name;
          else {
            URL u_url(s_url);
            if (!u_url) {
              if (s_url[0] != '/')
                s_url = "./" + s_url;
            }
            else {
              if (u_url.Protocol() == "file") {
                s_url = u_url.Path();
                if (s_url[0] != '/')
                  s_url = "./" + s_url;
              }
              else
                s_url.resize(0);
            }
          }
          if (!s_url.empty())
            x_url.Destroy();
        }
      }
    }
    act_doc.GetXML(jsdl_str);
    logger.msg(DEBUG, "Job description to be sent: %s", jsdl_str);

    // Try to figure out which credentials are used
    // TODO: Method used is unstable beacuse it assumes some predefined
    // structure of configuration file. Maybe there should be some
    // special methods of ClientTCP class introduced.
    std::string deleg_cert;
    std::string deleg_key;
    if (delegate) {
      client->Load(); // Make sure chain is ready
      XMLNode tls_cfg = find_xml_node((client->GetConfig())["Chain"],
                                      "Component", "name", "tls.client");
      if (tls_cfg) {
        deleg_cert = (std::string)(tls_cfg["ProxyPath"]);
        if (deleg_cert.empty()) {
          deleg_cert = (std::string)(tls_cfg["CertificatePath"]);
          deleg_key = (std::string)(tls_cfg["KeyPath"]);
        }
        else
          deleg_key = deleg_cert;
      }
      if (deleg_cert.empty() || deleg_key.empty()) {
        logger.msg(ERROR, "Failed to find delegation credentials in "
                   "client configuration");
        return false;
      }
    }
    // Send job request + delegation
    if (client) {
      if (delegate) {
        DelegationProviderSOAP deleg(deleg_cert, deleg_key);
        logger.msg(INFO, "Initiating delegation procedure");
        if (!deleg.DelegateCredentialsInit(*(client->GetEntry()),
                                           &(client->GetContext()))) {
          logger.msg(ERROR, "Failed to initiate delegation");
          return false;
        }
        deleg.DelegatedToken(op);
      }
      MCC_Status status =
        client->process("http://schemas.ggf.org/bes/2006/08/bes-factory/"
                        "BESFactoryPortType/CreateActivity", &req, &resp);
      if (!status) {
        logger.msg(ERROR, "Submission request failed");
        return false;
      }
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      attributes_req.set("SOAP:ACTION", "http://schemas.ggf.org/bes/2006/08/"
                         "bes-factory/BESFactoryPortType/CreateActivity");
      MessageAttributes attributes_rep;
      MessageContext context;

      if (delegate) {
        DelegationProviderSOAP deleg(deleg_cert, deleg_key);
        logger.msg(INFO, "Initiating delegation procedure");
        if (!deleg.DelegateCredentialsInit(*client_entry, &context)) {
          logger.msg(ERROR, "Failed to initiate delegation");
          return false;
        }
        deleg.DelegatedToken(op);
      }
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "Submission request failed");
        return false;
      }
      logger.msg(INFO, "Submission request succeed");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a submission request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR, "A response to a submission request was not "
                   "a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }
    //XMLNode id;
    SOAPFault fs(*resp);
    if (!fs) {
      (*resp)["CreateActivityResponse"]["ActivityIdentifier"].New(id);
      //id.GetDoc(jobid);
      //std::cout << "\n---\nActivityIdentifier:\n" << (std::string)((*resp)["CreateActivityResponse"]["ActivityIdentifier"]) << "\n---\n";//debug code
      delete resp;

      UNICOREClient luc((std::string)id["Address"], client_config); //local unicore client
      //std::cout << "\n---\nid element containing (?) Job Address:\n" << (std::string)id << "\n---\n";//debug code
      return luc.uasStartJob();
      //return true;
    }
    else {
      faultstring = fs.Reason();
      std::string s;
      resp->GetXML(s);
      delete resp;
      logger.msg(DEBUG, "Submission returned failure: %s", s);
      logger.msg(ERROR, "Submission failed, service returned: %s", faultstring);
      return false;
    }
  }
Exemplo n.º 2
0
  bool UNICOREClient::kill(const std::string& jobid) {

    std::string result, faultstring;
    logger.msg(INFO, "Creating and sending request to terminate a job");

    PayloadSOAP req(unicore_ns);
    XMLNode jobref =
      req.NewChild("bes-factory:TerminateActivities").
      NewChild(XMLNode(jobid));
    set_bes_factory_action(req, "TerminateActivities");
    WSAHeader(req).To(rurl.str());

    // Send kill request
    PayloadSOAP *resp = NULL;
    if (client) {
      MCC_Status status =
        client->process("http://schemas.ggf.org/bes/2006/08/bes-factory/"
                        "BESFactoryPortType/TerminateActivities", &req, &resp);
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      attributes_req.set("SOAP:ACTION", "http://schemas.ggf.org/bes/2006/08/"
                         "bes-factory/BESFactoryPortType/TerminateActivities");
      MessageAttributes attributes_rep;
      MessageContext context;
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "A job termination request failed");
        return false;
      }
      logger.msg(INFO, "A job termination request succeed");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a job termination request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR, "The response of a job termination request was "
                   "not a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }

    XMLNode cancelled, fs;
    (*resp)["TerminateActivitiesResponse"]
    ["Response"]["Cancelled"].New(cancelled);
    result = (std::string)cancelled;
    (*resp)["Fault"]["faultstring"].New(fs);
    faultstring = (std::string)fs;
    delete resp;
    if (faultstring != "") {
      logger.msg(ERROR, faultstring);
      return false;
    }
    if (result != "true") {
      logger.msg(ERROR, "Job termination failed");
      return false;
    }
    return true;
  }
Exemplo n.º 3
0
  bool UNICOREClient::clean(const std::string& jobid) {

    std::string result, faultstring;
    logger.msg(INFO, "Creating and sending request to terminate a job");

    PayloadSOAP req(unicore_ns);
    XMLNode op = req.NewChild("a-rex:ChangeActivityStatus");
    XMLNode jobref = op.NewChild(XMLNode(jobid));
    XMLNode jobstate = op.NewChild("a-rex:NewStatus");
    jobstate.NewAttribute("bes-factory:state") = "Finished";
    jobstate.NewChild("a-rex:state") = "Deleted";
    // Send clean request
    PayloadSOAP *resp = NULL;
    if (client) {
      MCC_Status status = client->process("", &req, &resp);
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      MessageAttributes attributes_rep;
      MessageContext context;
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "A job cleaning request failed");
        return false;
      }
      logger.msg(INFO, "A job cleaning request succeed");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a job cleaning request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR, "The response of a job cleaning request was not "
                   "a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }

    if (!((*resp)["ChangeActivityStatusResponse"])) {
      delete resp;
      XMLNode fs;
      (*resp)["Fault"]["faultstring"].New(fs);
      faultstring = (std::string)fs;
      if (faultstring != "") {
        logger.msg(ERROR, faultstring);
        return false;
      }
      if (result != "true") {
        logger.msg(ERROR, "Job termination failed");
        return false;
      }
    }
    delete resp;
    return true;
  }
Exemplo n.º 4
0
  bool UNICOREClient::sstat(std::string& status) {

    std::string state, faultstring;
    logger.msg(INFO, "Creating and sending a service status request");

    PayloadSOAP req(unicore_ns);
    XMLNode jobref =
      req.NewChild("bes-factory:GetFactoryAttributesDocument");
    set_bes_factory_action(req, "GetFactoryAttributesDocument");
    WSAHeader(req).To(rurl.str());

    // Send status request
    PayloadSOAP *resp = NULL;
    if (client) {
      MCC_Status status =
        client->process("http://schemas.ggf.org/bes/2006/08/bes-factory/"
                        "BESFactoryPortType/GetFactoryAttributesDocument",
                        &req, &resp);
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      attributes_req.set("SOAP:ACTION", "http://schemas.ggf.org/bes/2006/08/"
                         "bes-factory/BESFactoryPortType/"
                         "GetFactoryAttributesDocument");
      MessageAttributes attributes_rep;
      MessageContext context;
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "A service status request failed");
        return false;
      }
      logger.msg(INFO, "A service status request succeeded");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a service status request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR, "The response of a service status request was "
                   "not a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }
    XMLNode st;
    logger.msg(DEBUG, "Response:\n%s", (std::string)(*resp));
    (*resp)["GetFactoryAttributesDocumentResponse"]
    ["FactoryResourceAttributesDocument"].New(st);
    st.GetDoc(state, true);
    delete resp;
    if (state == "") {
      logger.msg(ERROR, "The service status could not be retrieved");
      return false;
    }
    else {
      status = state;
      return true;
    }
  }
Exemplo n.º 5
0
  bool UNICOREClient::stat(const std::string& jobid, std::string& status) {

    std::string state, substate, faultstring;
    logger.msg(INFO, "Creating and sending a status request");

    PayloadSOAP req(unicore_ns);
    XMLNode jobref =
      req.NewChild("bes-factory:GetActivityStatuses").
      NewChild(XMLNode(jobid));
    set_bes_factory_action(req, "GetActivityStatuses");
    WSAHeader(req).To(rurl.str());

    // Send status request
    PayloadSOAP *resp = NULL;

    if (client) {
      MCC_Status status =
        client->process("http://schemas.ggf.org/bes/2006/08/bes-factory/"
                        "BESFactoryPortType/GetActivityStatuses", &req, &resp);
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      attributes_req.set("SOAP:ACTION", "http://schemas.ggf.org/bes/2006/08/"
                         "bes-factory/BESFactoryPortType/GetActivityStatuses");
      MessageAttributes attributes_rep;
      MessageContext context;
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "A status request failed");
        return false;
      }
      logger.msg(INFO, "A status request succeed");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a status request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR,
                   "The response of a status request was not a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }
    XMLNode st, fs;
    (*resp)["GetActivityStatusesResponse"]["Response"]
    ["ActivityStatus"].New(st);
    state = (std::string)st.Attribute("state");
    XMLNode sst;
    (*resp)["GetActivityStatusesResponse"]["Response"]
    ["ActivityStatus"]["state"].New(sst);
    substate = (std::string)sst;
    (*resp)["Fault"]["faultstring"].New(fs);
    faultstring = (std::string)fs;
    delete resp;
    if (faultstring != "") {
      logger.msg(ERROR, faultstring);
      return false;
    }
    else if (state == "") {
      logger.msg(ERROR, "The job status could not be retrieved");
      return false;
    }
    else {
      status = state + "/" + substate;
      return true;
    }
  }
Exemplo n.º 6
0
  bool UNICOREClient::uasStartJob(){
        std::string state, faultstring;
    logger.msg(INFO, "Creating and sending a start job request");

    PayloadSOAP req(unicore_ns);
    XMLNode SOAPMethod =
      req.NewChild("jms:Start");
    WSAHeader(req).To(rurl.str());
    WSAHeader(req).Action("http://schemas.ggf.org/bes/2006/08/bes-activity/BESActivityPortType/StartRequest");

    // Send status request
    PayloadSOAP *resp = NULL;
    if (client) {
      MCC_Status status =
        client->process("http://schemas.ggf.org/bes/2006/08/bes-activity/BESActivityPortType/StartRequest",
                        &req, &resp);
      if (resp == NULL) {
        logger.msg(VERBOSE, "There was no SOAP response");
        return false;
      }
    }
    else if (client_entry) {
      Message reqmsg;
      Message repmsg;
      MessageAttributes attributes_req;
      attributes_req.set("SOAP:ACTION", "http://schemas.ggf.org/bes/2006/08/bes-activity/BESActivityPortType/StartRequest");
      MessageAttributes attributes_rep;
      MessageContext context;
      reqmsg.Payload(&req);
      reqmsg.Attributes(&attributes_req);
      reqmsg.Context(&context);
      repmsg.Attributes(&attributes_rep);
      repmsg.Context(&context);
      MCC_Status status = client_entry->process(reqmsg, repmsg);
      if (!status) {
        logger.msg(ERROR, "A start job request failed");
        return false;
      }
      logger.msg(INFO, "A start job request succeeded");
      if (repmsg.Payload() == NULL) {
        logger.msg(VERBOSE, "There was no response to a start job request");
        return false;
      }
      try {
        resp = dynamic_cast<PayloadSOAP*>(repmsg.Payload());
      } catch (std::exception&) {}
      if (resp == NULL) {
        logger.msg(ERROR, "The response of a start job request was "
                   "not a SOAP message");
        delete repmsg.Payload();
        return false;
      }
    }
    else {
      logger.msg(ERROR, "There is no connection chain configured");
      return false;
    }
    SOAPFault fs(*resp);
    if (!fs) {
      return true;
    }
    else {
      faultstring = fs.Reason();
      std::string s;
      resp->GetXML(s);
      delete resp;
      logger.msg(DEBUG, "Submission returned failure: %s", s);
      logger.msg(ERROR, "Submission failed, service returned: %s", faultstring);
      return false;
    }


  }
Exemplo n.º 7
0
MCC_Status MCC_SOAP_Client::process(Message& inmsg,Message& outmsg) {
  // Extracting payload
  if(!inmsg.Payload()) return make_soap_fault(outmsg,true,"No message to send");
  PayloadSOAP* inpayload = NULL;
  try {
    inpayload = dynamic_cast<PayloadSOAP*>(inmsg.Payload());
  } catch(std::exception& e) { };
  if(!inpayload) return make_soap_fault(outmsg,true,"No SOAP message to send");
  //Checking authentication and authorization;
  if(!ProcessSecHandlers(inmsg,"outgoing")) {
    logger.msg(ERROR, "Security check failed in SOAP MCC for outgoing message");
    return make_soap_fault(outmsg,true,"Security check failed for outgoing SOAP message");
  };
  // Converting payload to Raw
  PayloadRaw nextpayload;
  std::string xml; inpayload->GetXML(xml);
  nextpayload.Insert(xml.c_str());
  // Creating message to pass to next MCC and setting new payload.. 
  Message nextinmsg = inmsg;
  nextinmsg.Payload(&nextpayload);
  // Specifying attributes for binding to underlying protocols - HTTP so far
  std::string soap_action;
  bool soap_action_defined = inmsg.Attributes()->count("SOAP:ACTION") > 0;
  if(soap_action_defined) {
    soap_action=inmsg.Attributes()->get("SOAP:ACTION");
  } else {
    soap_action_defined=true; //WSAHeader(*inpayload).hasAction(); - SOAPAction must be always present
    soap_action=WSAHeader(*inpayload).Action();
  };
  if(inpayload->Version() == SOAPEnvelope::Version_1_2) {
    std::string mime_type("application/soap+xml");
    if(soap_action_defined) mime_type+=" ;action=\""+soap_action+"\"";
    nextinmsg.Attributes()->set("HTTP:Content-Type",mime_type);
  } else {
    nextinmsg.Attributes()->set("HTTP:Content-Type","text/xml");
    if(soap_action_defined) nextinmsg.Attributes()->set("HTTP:SOAPAction","\""+soap_action+"\"");
  };
  // Call next MCC 
  MCCInterface* next = Next();
  if(!next) return make_soap_fault(outmsg,true,"Internal chain failure: no next component");
  Message nextoutmsg = outmsg; nextoutmsg.Payload(NULL);
  MCC_Status ret = next->process(nextinmsg,nextoutmsg); 
  // Do checks and create SOAP response
  // TODO: pass SOAP action from HTTP header to SOAP:ACTION attribute
  if(!ret) {
    std::string errstr = "Failed to send SOAP message: "+(std::string)ret;
    return make_soap_fault(outmsg,nextoutmsg,false,errstr.c_str());
  };
  if(!nextoutmsg.Payload()) {
    return make_soap_fault(outmsg,nextoutmsg,false,"No response for SOAP message recieved");
  };
  MessagePayload* retpayload = nextoutmsg.Payload();
  if(!retpayload) return make_soap_fault(outmsg,nextoutmsg,false,"No valid response for SOAP message recieved");
  PayloadSOAP* outpayload  = new PayloadSOAP(*retpayload);
  if(!outpayload) {
    return make_soap_fault(outmsg,nextoutmsg,false,"Response is not SOAP");
  };
  if(!(*outpayload)) {
    delete outpayload; return make_soap_fault(outmsg,nextoutmsg,false,"Response is not valid SOAP");
  };
  outmsg = nextoutmsg;
  outmsg.Payload(outpayload);
  delete nextoutmsg.Payload(); nextoutmsg.Payload(NULL);
  //Checking authentication and authorization; 
  if(!ProcessSecHandlers(outmsg,"incoming")) {
    logger.msg(ERROR, "Security check failed in SOAP MCC for incoming message");
    delete outpayload; return make_soap_fault(outmsg,false,"Security check failed for incoming SOAP message");
  };
  return MCC_Status(STATUS_OK);
}
Exemplo n.º 8
0
MCC_Status MCC_SOAP_Service::process(Message& inmsg,Message& outmsg) {
  // Extracting payload
  MessagePayload* inpayload = inmsg.Payload();
  if(!inpayload) {
    logger.msg(WARNING, "empty input payload");
    return make_raw_fault(outmsg,"Missing incoming request");
  }
  // Converting payload to SOAP
  PayloadSOAP nextpayload(*inpayload);
  if(!nextpayload) {
    logger.msg(WARNING, "incoming message is not SOAP");
    return make_raw_fault(outmsg,"Incoming request is not SOAP");
  }
  // Creating message to pass to next MCC and setting new payload.. 
  // Using separate message. But could also use same inmsg.
  // Just trying to keep it intact as much as possible.
  Message nextinmsg = inmsg;
  nextinmsg.Payload(&nextpayload);
  if(WSAHeader::Check(nextpayload)) {
    std::string endpoint_attr = WSAHeader(nextpayload).To();
    nextinmsg.Attributes()->set("SOAP:ENDPOINT",endpoint_attr);
    nextinmsg.Attributes()->set("ENDPOINT",endpoint_attr);
  };
  SOAPSecAttr* sattr = new SOAPSecAttr(nextpayload);
  nextinmsg.Auth()->set("SOAP",sattr);
  // Checking authentication and authorization; 
  if(!ProcessSecHandlers(nextinmsg,"incoming")) {
    logger.msg(ERROR, "Security check failed in SOAP MCC for incoming message");
    return make_raw_fault(outmsg, "Security check failed for SOAP request");
  };
  // TODO: pass SOAP action from HTTP header to SOAP:ACTION attribute
  // Call next MCC 
  MCCInterface* next = Next();
  if(!next) {
    logger.msg(WARNING, "empty next chain element");
    return make_raw_fault(outmsg,"Internal error");
  }
  Message nextoutmsg = outmsg; nextoutmsg.Payload(NULL);
  MCC_Status ret = next->process(nextinmsg,nextoutmsg); 
  // Do checks and extract SOAP response
  if(!ret) {
    if(nextoutmsg.Payload()) delete nextoutmsg.Payload();
    logger.msg(WARNING, "next element of the chain returned error status: %s",(std::string)ret);
    if(ret.getKind() == UNKNOWN_SERVICE_ERROR) {
      return make_raw_fault(outmsg,"No requested service found");
    } else {
      return make_raw_fault(outmsg,"Internal error");
    }
  }
  if(!nextoutmsg.Payload()) {
    logger.msg(WARNING, "next element of the chain returned empty payload");
    return make_raw_fault(outmsg,"There is no response");
  }
  PayloadSOAP* retpayload = NULL;
  try {
    retpayload = dynamic_cast<PayloadSOAP*>(nextoutmsg.Payload());
  } catch(std::exception& e) { };
  if(!retpayload) {
    // There is a chance that next MCC decided to return pre-rendered SOAP
    // or otherwise valid non-SOAP response. For that case we simply pass 
    // it back to previous MCC and let it decide.
    logger.msg(INFO, "next element of the chain returned unknown payload - passing through");
    //Checking authentication and authorization; 
    if(!ProcessSecHandlers(nextoutmsg,"outgoing")) {
      logger.msg(ERROR, "Security check failed in SOAP MCC for outgoing message");
      delete nextoutmsg.Payload();
      return make_raw_fault(outmsg,"Security check failed for SOAP response");
    };
    outmsg = nextoutmsg;
    return MCC_Status(STATUS_OK);
  };
  if(!(*retpayload)) {
    delete retpayload;
    return make_raw_fault(outmsg,"There is no valid SOAP response");
  };
  //Checking authentication and authorization; 
  if(!ProcessSecHandlers(nextoutmsg,"outgoing")) {
    logger.msg(ERROR, "Security check failed in SOAP MCC for outgoing message");
    delete retpayload; return make_raw_fault(outmsg,"Security check failed for SOAP response");
  };
  // Convert to Raw - TODO: more efficient conversion
  PayloadRaw* outpayload = new PayloadRaw;
  std::string xml; retpayload->GetXML(xml);
  outpayload->Insert(xml.c_str());
  outmsg = nextoutmsg; outmsg.Payload(NULL);
  // Specifying attributes for binding to underlying protocols - HTTP so far
  std::string soap_action;
  bool soap_action_defined = nextoutmsg.Attributes()->count("SOAP:ACTION") > 0;
  if(soap_action_defined) {
    soap_action=nextoutmsg.Attributes()->get("SOAP:ACTION");
  } else {
    soap_action_defined=WSAHeader(*retpayload).hasAction();
    soap_action=WSAHeader(*retpayload).Action();
  };
  if(retpayload->Version() == SOAPEnvelope::Version_1_2) {
    // TODO: For SOAP 1.2 Content-Type is not sent in case of error - probably harmless
    std::string mime_type("application/soap+xml");
    if(soap_action_defined) mime_type+=" ;action=\""+soap_action+"\"";
    outmsg.Attributes()->set("HTTP:Content-Type",mime_type);
  } else {
    outmsg.Attributes()->set("HTTP:Content-Type","text/xml");
    if(soap_action_defined) outmsg.Attributes()->set("HTTP:SOAPAction",soap_action);
  };
  if(retpayload->Fault() != NULL) {
    // Maybe MCC_Status should be used instead ?
    outmsg.Attributes()->set("HTTP:CODE","500"); // TODO: For SOAP 1.2 :Sender fault must generate 400
    outmsg.Attributes()->set("HTTP:REASON","SOAP FAULT");
    // CONFUSED: SOAP 1.2 says that SOAP message is sent in response only if
    // HTTP code is 200 "Only if status line is 200, the SOAP message serialized according 
    // to the rules for carrying SOAP messages in the media type given by the Content-Type 
    // header field ...". But it also associates SOAP faults with HTTP error codes. So it 
    // looks like in case of SOAP fault SOAP fault messages is not sent. That sounds 
    // stupid - not implementing.
  };
  delete retpayload;
  outmsg.Payload(outpayload);
  return MCC_Status(STATUS_OK);
}