Back to index

nordugrid-arc-nox  1.1.0~rc6
WSA.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <cstring>
00006 
00007 #include "WSA.h"
00008 
00009 namespace Arc {
00010 
00011 static std::string strip_spaces(const std::string& s) {
00012   std::string::size_type start = 0;
00013   for(;start<s.length();++start) if(!isspace(s[start])) break;
00014   std::string::size_type end = s.length()-1;
00015   for(;end>=start;--end) if(!isspace(s[end])) break;
00016   return s.substr(start,end-start+1);
00017 }
00018 
00019 static void remove_empty_nodes(XMLNode& parent,const char* name) {
00020   while(true) {
00021     XMLNode to = parent[name];
00022     if(!to) break;
00023     if(to.Size() > 0) break;
00024     if(!(((std::string)to).empty())) break;
00025     to.Destroy();
00026   };
00027   return;
00028 }
00029 
00030 
00031 static XMLNode get_node(XMLNode& parent,const char* name) {
00032   XMLNode n = parent[name];
00033   if(!n) n=parent.NewChild(name);
00034   return n;
00035 }
00036 
00037 
00038 WSAEndpointReference::WSAEndpointReference(XMLNode epr) : epr_(epr) {}
00039 
00040 WSAEndpointReference::WSAEndpointReference(const WSAEndpointReference& wsa) : epr_(wsa.epr_) {}
00041 
00042 
00043 WSAEndpointReference::WSAEndpointReference(const std::string&) {
00044 }
00045 
00046 
00047 WSAEndpointReference::WSAEndpointReference(void) {
00048 }
00049 
00050 
00051 WSAEndpointReference::~WSAEndpointReference(void) {
00052   remove_empty_nodes(epr_,"wsa:Address");
00053   remove_empty_nodes(epr_,"wsa:ReferenceParameters");
00054   remove_empty_nodes(epr_,"wsa:MetaData");
00055 }
00056 
00057 
00058 std::string WSAEndpointReference::Address(void) const {
00059   return strip_spaces(const_cast<XMLNode&>(epr_)["wsa:Address"]);
00060 }
00061 
00062 WSAEndpointReference& WSAEndpointReference::operator=(const std::string& address) {
00063   Address(address);
00064   return *this;
00065 }
00066 
00067 void WSAEndpointReference::Address(const std::string& uri) {
00068   get_node(epr_,"wsa:Address")=uri; 
00069 }
00070 
00071 
00072 XMLNode WSAEndpointReference::ReferenceParameters(void) {
00073   return get_node(epr_,"wsa:ReferenceParameters");
00074 }
00075 
00076 
00077 XMLNode WSAEndpointReference::MetaData(void) {
00078   return get_node(epr_,"wsa:MetaData");
00079 }
00080 
00081 
00082 WSAEndpointReference::operator XMLNode(void) {
00083   return epr_;
00084 }
00085 
00086 
00087 WSAHeader::WSAHeader(SOAPEnvelope& soap) {
00088   header_=soap.Header();
00089   header_allocated_=false;
00090   // apply predefined namespace prefix
00091   NS ns;
00092   ns["wsa"]=WSA_NAMESPACE;
00093   header_.Namespaces(ns);
00094 } 
00095 
00096 WSAHeader::WSAHeader(const std::string&) {
00097 }
00098 
00099 
00100 WSAHeader::~WSAHeader(void) {
00101   if(!header_) return;
00102   // Scan for empty WSA element and remove them from tree
00103   remove_empty_nodes(header_,"wsa:To");
00104   remove_empty_nodes(header_,"wsa:From");
00105   remove_empty_nodes(header_,"wsa:ReplyTo");
00106   remove_empty_nodes(header_,"wsa:FaultTo");
00107   remove_empty_nodes(header_,"wsa:MessageID");
00108   remove_empty_nodes(header_,"wsa:RelatesTo");
00109   remove_empty_nodes(header_,"wsa:ReferenceParameters");
00110   remove_empty_nodes(header_,"wsa:Action");
00111 }
00112 
00113 
00114 std::string WSAHeader::To(void) const {
00115   return strip_spaces(const_cast<XMLNode&>(header_)["wsa:To"]);
00116 }
00117 
00118 
00119 void WSAHeader::To(const std::string& uri) {
00120   get_node(header_,"wsa:To")=uri; 
00121 }
00122 
00123 
00124 std::string WSAHeader::Action(void) const {
00125   return strip_spaces(const_cast<XMLNode&>(header_)["wsa:Action"]);
00126 }
00127 
00128 
00129 void WSAHeader::Action(const std::string& uri) {
00130   get_node(header_,"wsa:Action")=uri; 
00131 }
00132 
00133 
00134 std::string WSAHeader::MessageID(void) const {
00135   return strip_spaces(const_cast<XMLNode&>(header_)["wsa:MessageID"]);
00136 }
00137 
00138 
00139 void WSAHeader::MessageID(const std::string& uri) {
00140   get_node(header_,"wsa:MessageID")=uri; 
00141 }
00142 
00143 
00144 std::string WSAHeader::RelatesTo(void) const {
00145   return strip_spaces(const_cast<XMLNode&>(header_)["wsa:RelatesTo"]);
00146 }
00147 
00148 
00149 void WSAHeader::RelatesTo(const std::string& uri) {
00150   get_node(header_,"wsa:RelatesTo")=uri; 
00151 }
00152 
00153 
00154 WSAEndpointReference WSAHeader::From(void) {
00155   return WSAEndpointReference(get_node(header_,"wsa:From"));
00156 }
00157 
00158 
00159 WSAEndpointReference WSAHeader::ReplyTo(void) {
00160   return WSAEndpointReference(get_node(header_,"wsa:ReplyTo"));
00161 }
00162 
00163 
00164 WSAEndpointReference WSAHeader::FaultTo(void) {
00165   return WSAEndpointReference(get_node(header_,"wsa:FaultTo"));
00166 }
00167 
00168 std::string WSAHeader::RelationshipType(void) const {
00169   return strip_spaces(const_cast<XMLNode&>(header_)["wsa:ReplyTo"].Attribute("wsa:RelationshipType"));
00170 }
00171 
00172 
00173 void WSAHeader::RelationshipType(const std::string& uri) {
00174   XMLNode n = get_node(header_,"wsa:ReplyTo");
00175   XMLNode a = n.Attribute("wsa:RelationshipType");
00176   if(!a) a=n.NewAttribute("wsa:RelationshipType");
00177   a=uri;
00178 }
00179 
00180 
00181 //XMLNode WSAHeader::ReferenceParameters(void) {
00182 //  return get_node(header_,"wsa:ReferenceParameters");
00183 //}
00184 
00185 XMLNode WSAHeader::ReferenceParameter(int num) {
00186   for(int i=0;;++i) {
00187     XMLNode n = header_.Child(i);
00188     if(!n) return n;
00189     XMLNode a = n.Attribute("wsa:IsReferenceParameter");
00190     if(!a) continue;
00191     if(strcasecmp("true",((std::string)a).c_str()) != 0) continue;
00192     if((num--) <= 0) return n;
00193   };
00194 }
00195 
00196 XMLNode WSAHeader::ReferenceParameter(const std::string& name) {
00197   XMLNode n_ = header_[name];
00198   for(int i=0;;++i) {
00199     XMLNode n = n_[i];
00200     if(!n) return n;
00201     XMLNode a = n.Attribute("wsa:IsReferenceParameter");
00202     if(!a) continue;
00203     if(strcasecmp("true",((std::string)a).c_str()) != 0) continue;
00204     return n;
00205   };
00206 }
00207 
00208 XMLNode WSAHeader::NewReferenceParameter(const std::string& name) {
00209   XMLNode n = header_.NewChild(name);
00210   XMLNode a = n.NewAttribute("wsa:IsReferenceParameter");
00211   a="true";
00212   return n;
00213 }
00214 
00215 bool WSAHeader::Check(SOAPEnvelope& soap) {
00216   if(soap.NamespacePrefix(WSA_NAMESPACE).empty()) return false;
00217   WSAHeader wsa(soap);
00218   if(!wsa.header_["wsa:Action"]) return false;
00219   if(!wsa.header_["wsa:To"]) return false;
00220   return true;
00221 }
00222 
00223 void WSAFaultAssign(SOAPEnvelope& message,WSAFault fid) {
00224   // TODO: Detail
00225   SOAPFault& fault = *(message.Fault());
00226   if(&fault == NULL) return;
00227   NS ns;
00228   ns["wsa"]="http://www.w3.org/2005/08/addressing";
00229   message.Namespaces(ns);
00230   switch(fid) {
00231     case WSAFaultInvalidAddressingHeader:
00232     case WSAFaultInvalidAddress: 
00233     case WSAFaultInvalidEPR:
00234     case WSAFaultInvalidCardinality:
00235     case WSAFaultMissingAddressInEPR:
00236     case WSAFaultDuplicateMessageID:
00237     case WSAFaultActionMismatch:
00238     case WSAFaultOnlyAnonymousAddressSupported:
00239     case WSAFaultOnlyNonAnonymousAddressSupported:
00240       fault.Code(SOAPFault::Sender);
00241       fault.Subcode(1,"wsa:InvalidAddressingHeader"); 
00242       fault.Reason(0,"A header representing a Message Addressing Property is not valid and the message cannot be processed");
00243       switch(fid) {
00244         case WSAFaultInvalidAddress:      fault.Subcode(2,"wsa:InvalidAddress"); break;
00245         case WSAFaultInvalidEPR:          fault.Subcode(2,"wsa:InvalidEPR"); break;
00246         case WSAFaultInvalidCardinality:  fault.Subcode(2,"wsa:InvalidCardinality"); break;
00247         case WSAFaultMissingAddressInEPR: fault.Subcode(2,"wsa:MissingAddressInEPR"); break;
00248         case WSAFaultDuplicateMessageID:  fault.Subcode(2,"wsa:DuplicateMessageID"); break;
00249         case WSAFaultActionMismatch:      fault.Subcode(2,"wsa:ActionMismatch"); break;
00250         case WSAFaultOnlyAnonymousAddressSupported: fault.Subcode(2,"wsa:OnlyAnonymousAddressSupported"); break;
00251         case WSAFaultOnlyNonAnonymousAddressSupported: fault.Subcode(2,"wsa:OnlyNonAnonymousAddressSupported"); break;
00252         default: break;
00253       };
00254     break;
00255     case WSAFaultMessageAddressingHeaderRequired:
00256       fault.Code(SOAPFault::Sender);
00257       fault.Subcode(1,"wsa:MessageAddressingHeaderRequired"); 
00258       fault.Reason(0,"A required header representing a Message Addressing Property is not present");
00259     break;
00260     case WSAFaultDestinationUnreachable:
00261       fault.Code(SOAPFault::Sender);
00262       fault.Subcode(1,"wsa:DestinationUnreachable"); 
00263       fault.Reason(0,"No route can be determined to reach [destination]");
00264     break;
00265     case WSAFaultActionNotSupported:
00266       fault.Code(SOAPFault::Sender);
00267       fault.Subcode(1,"wsa:ActionNotSupported"); 
00268       fault.Reason(0,"The [action] cannot be processed at the receiver");
00269     break;
00270     case WSAFaultEndpointUnavailable:
00271       fault.Code(SOAPFault::Receiver);
00272       fault.Subcode(1,"wsa:EndpointUnavailable"); 
00273       fault.Reason(0,"The endpoint is unable to process the message at this time");
00274     break;
00275     default: break;
00276   };
00277 }
00278 
00279 WSAFault WSAFaultExtract(SOAPEnvelope& message) {
00280   // TODO: extend XML interface to compare QNames
00281   WSAFault fid = WSAFaultNone;
00282   SOAPFault& fault = *(message.Fault());
00283   if(&fault == NULL) return fid;
00284   //XMLNode::NS ns;
00285   //ns["wsa"]="http://www.w3.org/2005/08/addressing";
00286   //message.Namespaces(ns);
00287   std::string prefix = message.NamespacePrefix("http://www.w3.org/2005/08/addressing");
00288   std::string code = fault.Subcode(1);
00289   if(code.empty()) return fid;
00290   if(!prefix.empty()) {
00291     prefix=":"+prefix;
00292     if(strncasecmp(prefix.c_str(),code.c_str(),prefix.length()) != 0) return fid;
00293     code=code.substr(prefix.length());
00294   };
00295   fid=WSAFaultUnknown;
00296   if(strcasecmp(code.c_str(),"InvalidAddressingHeader") == 0) {
00297     fid=WSAFaultInvalidAddressingHeader;
00298     std::string subcode = fault.Subcode(2);
00299     if(!subcode.empty()) {
00300       if(!prefix.empty()) {
00301         prefix=":"+prefix;
00302         if(strncasecmp(prefix.c_str(),subcode.c_str(),prefix.length()) != 0) return fid;
00303         subcode=subcode.substr(prefix.length());
00304       };
00305       if(strcasecmp(subcode.c_str(),"InvalidAddress") == 0) {
00306         fid=WSAFaultInvalidAddress;
00307       } else if(strcasecmp(subcode.c_str(),"InvalidEPR") == 0) {
00308         fid=WSAFaultInvalidEPR;
00309       } else if(strcasecmp(subcode.c_str(),"InvalidCardinality") == 0) {
00310         fid=WSAFaultInvalidCardinality;
00311       } else if(strcasecmp(subcode.c_str(),"MissingAddressInEPR") == 0) {
00312         fid=WSAFaultMissingAddressInEPR;
00313       } else if(strcasecmp(subcode.c_str(),"DuplicateMessageID") == 0) {
00314         fid=WSAFaultDuplicateMessageID;
00315       } else if(strcasecmp(subcode.c_str(),"ActionMismatch") == 0) {
00316         fid=WSAFaultActionMismatch;
00317       } else if(strcasecmp(subcode.c_str(),"OnlyAnonymousAddressSupported") == 0) {
00318         fid=WSAFaultOnlyAnonymousAddressSupported;
00319       } else if(strcasecmp(subcode.c_str(),"OnlyNonAnonymousAddressSupported") == 0) {
00320         fid=WSAFaultOnlyNonAnonymousAddressSupported;
00321       };
00322     };
00323   } else if(strcasecmp(code.c_str(),"MessageAddressingHeaderRequired") == 0) {
00324     fid=WSAFaultMessageAddressingHeaderRequired;
00325   } else if(strcasecmp(code.c_str(),"DestinationUnreachable") == 0) {
00326     fid=WSAFaultDestinationUnreachable;
00327   } else if(strcasecmp(code.c_str(),"ActionNotSupported") == 0) {
00328     fid=WSAFaultActionNotSupported;
00329   } else if(strcasecmp(code.c_str(),"EndpointUnavailable") == 0) {
00330     fid=WSAFaultEndpointUnavailable;
00331   };
00332   return fid;
00333 }
00334 
00335 } // namespace Arc
00336