NCBI C++ ToolKit
soap_message.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: soap_message.cpp 84832 2018-12-17 14:45:09Z gouriano $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Andrei Gourianov
27 *
28 * File Description:
29 * Hold the content of, send and receive SOAP messages
30 */
31 
32 #include <ncbi_pch.hpp>
33 #include <serial/serial.hpp>
34 #include <serial/objostr.hpp>
35 #include <serial/objistr.hpp>
36 #include <serial/objostrxml.hpp>
38 #include <serial/serialimpl.hpp>
39 #include "soap_writehook.hpp"
40 #include "soap_readhook.hpp"
41 #include <algorithm>
42 
44 
46 // "http://www.w3.org/2003/05/soap-envelope";
47  "http://schemas.xmlsoap.org/soap/envelope/"; // v1.1
48 
50  : m_Fault(CSoapFault::e_not_set), m_Prefix("env")
51 {
52  RegisterObjectType(CSoapFault::GetTypeInfo);
53 }
54 
55 CSoapMessage::CSoapMessage(const string& namespace_name)
56  : m_Fault(CSoapFault::e_not_set), m_Prefix("env"),
57  m_DefNamespaceName(namespace_name)
58 {
59  RegisterObjectType(CSoapFault::GetTypeInfo);
60 }
61 
63 {
64 }
65 
67 {
68  return ms_SoapNamespace;
69 }
70 
72 {
73  m_Prefix = prefix;
74 }
75 
76 const string& CSoapMessage::GetSoapNamespacePrefix(void) const
77 {
78  return m_Prefix;
79 }
80 
82 {
83  m_DefNamespaceName = ns_name;
84 }
86 {
87  return m_DefNamespaceName;
88 }
89 
90 
92  EMessagePart destination)
93 {
94 // verify namespace
95  if (!m_DefNamespaceName.empty()) {
96  CSerialObject* ser = const_cast<CSerialObject*>(&obj);
97  CAnyContentObject* any = dynamic_cast<CAnyContentObject*>(ser);
98  if (any) {
99  if ((any->GetNamespaceName()).empty()) {
101  }
102  } else {
103  if (!ser->HasNamespaceName()) {
106  }
107  }
108  }
109 
110  if (destination == eMsgHeader) {
111  m_Header.push_back( CConstRef<CSerialObject>(&obj));
112  } else if (destination == eMsgBody) {
113  m_Body.push_back( CConstRef<CSerialObject>(&obj));
114  } else {
115  m_FaultDetail.push_back( CConstRef<CSerialObject>(&obj));
116  }
117 }
118 
119 
121 {
122  CObjectOStreamXml* os = 0;
123  bool schema = false, loc = false;
124  string ns_default;
125  ESerialDataFormat fmt = out.GetDataFormat();
126  if (fmt == eSerial_Xml) {
127  os = dynamic_cast<CObjectOStreamXml*>(&out);
128  if (os) {
129  schema = os->GetReferenceSchema();
130  os->SetReferenceSchema();
131  loc = os->GetUseSchemaLocation();
132  os->SetUseSchemaLocation(false);
133  ns_default = os->GetDefaultSchemaNamespace();
135  }
136  }
137 
139 
140  if (!m_Header.empty()) {
141 // This is to make the stream think the Header was not empty.
142 // Since Header is optional, we do not have to make it *always*
144  env.SetHeader().SetAnyContent().push_back(h);
145  }
146 
147 // This is to make the stream think the Body was not empty.
148 // Body is mandatory
150  env.SetBody().SetAnyContent().push_back(h);
151 
152  CSoapFault* flt = 0;
153  if (!m_FaultDetail.empty()) {
154 // This is to make the stream think the Detail was not empty.
155 // Since Detail is optional, we do not have to make it *always*
156  flt = dynamic_cast<CSoapFault*>(const_cast<CSerialObject*>(
157  GetSerialObject("Fault", eMsgBody).GetPointer()));
158  if (!flt) {
159 // throw exception here (?)
160  } else {
162  flt->SetDetail().SetAnyContent().push_back(h2);
163  }
164  }
165 
168 
171 
174 
175  x_VerifyFaultObj(true);
176  out << env;
177  x_VerifyFaultObj(false);
178 
179  if (flt) {
180  flt->SetDetail().SetAnyContent().clear();
181  }
182  if (os) {
184  os->SetUseSchemaLocation(loc);
185  os->SetDefaultSchemaNamespace(ns_default);
186  }
187 }
188 
189 
191 {
192  Reset();
194 
197 
200 
203 
204  in >> env;
205  x_Check(env);
206  x_VerifyFaultObj(false);
207 }
208 
209 
211 {
212  RegisterObjectType(*type_getter());
213 }
214 
216 {
217  if (find(m_Types.begin(), m_Types.end(), &type) == m_Types.end()) {
218  m_Types.push_back(&type);
219  }
220 }
221 
223 {
225 }
226 
227 
229 {
231  m_Header.clear();
232  m_Body.clear();
233  m_FaultDetail.clear();
234 }
235 
238 {
239  if (source == eMsgHeader) {
240  return m_Header;
241  } else if (source == eMsgBody) {
242  return m_Body;
243  } else {
244  return m_FaultDetail;
245  }
246 }
247 
250  EMessagePart source) const
251 {
252  const TSoapContent& src = GetContent(source);
253  TSoapContent::const_iterator it;
254  for (it= src.begin(); it != src.end(); ++it) {
255  if ((*it)->GetThisTypeInfo()->GetName() == type_name) {
256  return (*it);
257  }
258  }
259  return CConstRef<CSerialObject>(0);
260 }
261 
264  EMessagePart source) const
265 {
266  const TSoapContent& src = GetContent(source);
267  TSoapContent::const_iterator it;
268  for (it= src.begin(); it != src.end(); ++it) {
269  const CAnyContentObject* obj =
270  dynamic_cast<const CAnyContentObject*>(it->GetPointer());
271  if (obj && obj->GetName() == name) {
272  return CConstRef<CAnyContentObject>(obj);
273  }
274  }
276 }
277 
279 {
280 
281  if (env.GetNamespaceName() != GetSoapNamespace()) {
283  return;
284  }
285 
286 // http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383510
287 // An immediate child element of the SOAP Header not understood
288  const TSoapContent& src = GetContent(eMsgHeader);
289  if (!src.empty()) {
290  TSoapContent::const_iterator it= src.begin();
291  const CAnyContentObject* obj =
292  dynamic_cast<const CAnyContentObject*>(it->GetPointer());
293  if (obj) {
294  const vector<CSerialAttribInfoItem>& att = obj->GetAttributes();
295  vector<CSerialAttribInfoItem>::const_iterator a;
296  for (a= att.begin(); a != att.end(); ++a) {
297  if (a->GetName() == "mustUnderstand" &&
298  (a->GetValue() == "1" || a->GetValue() == "true")) {
300  }
301  }
302  }
303  }
304 }
305 
306 // serial lib does not support QName, so...
307 void CSoapMessage::x_VerifyFaultObj(bool add_prefix) const
308 {
309  CConstRef<CSoapFault> fault_ref = SOAP_GetKnownObject<CSoapFault>(*this);
310  if (fault_ref) {
311  CSoapFault* fault = const_cast<CSoapFault*>(fault_ref.GetPointer());
312  string code = fault->GetFaultcode();
313  const string& prefix = GetSoapNamespacePrefix();
314  string str1, str2, newcode;
315  if (NStr::SplitInTwo(code, ":", str1, str2)) {
316  code = str2;
317  }
318  if (add_prefix) {
319  code = prefix + ':' + code;
320  }
321  fault->SetFaultcode(code);
322  }
323 }
324 
325 
Serializable object that stores any combination of parsable data.
Definition: serialbase.hpp:264
CObjectIStream –.
Definition: objistr.hpp:93
CObjectOStreamXml –.
Definition: objostrxml.hpp:54
CObjectOStream –.
Definition: objostr.hpp:83
CObjectTypeInfo –.
Definition: objectinfo.hpp:94
CRef –.
Definition: ncbiobj.hpp:618
Base class for all serializable objects.
Definition: serialbase.hpp:150
void SetFaultcode(const TFaultcode &value)
const TFaultcode & GetFaultcode(void) const
void SetDetail(TDetail &value)
@ eVersionMismatch
Definition: soap_fault.hpp:61
~CSoapMessage(void)
static const char * ms_SoapNamespace
CConstRef< CSerialObject > GetSerialObject(const string &type_name, EMessagePart source) const
void x_Check(const CSoapEnvelope &env)
vector< const CTypeInfo * > m_Types
static const string GetSoapNamespace(void)
string m_DefNamespaceName
CSoapFault::ESoap_FaultcodeEnum m_Fault
const string & GetSoapNamespacePrefix(void) const
const TSoapContent & GetContent(EMessagePart source) const
TSoapContent m_FaultDetail
void x_VerifyFaultObj(bool add_prefix) const
void Write(CObjectOStream &out) const
void SetSoapNamespacePrefix(const string &prefix)
void Read(CObjectIStream &in)
CSoapMessage(void)
void AddObject(const CSerialObject &obj, EMessagePart destination)
void SetDefaultObjectNamespaceName(const string &ns_name)
TSoapContent m_Header
const string & GetDefaultObjectNamespaceName(void) const
CConstRef< CAnyContentObject > GetAnyContentObject(const string &name, EMessagePart source) const
TSoapContent m_Body
void RegisterObjectType(TTypeInfoGetter type_getter)
vector< CConstRef< CSerialObject > > TSoapContent
void Reset(void)
CTypeInfo class contains all information about C++ types (both basic and classes): members and layout...
Definition: typeinfo.hpp:76
std::ofstream out("events_result.xml")
main entry point for tests
static const char * schema
Definition: stats.c:20
static HENV env
Definition: transaction2.c:38
const string & GetNamespaceName(void) const
Get namespace name.
TTypeInfo(* TTypeInfoGetter)(void)
Definition: serialdef.hpp:63
bool HasNamespaceName(void) const
Check if object data type has namespace name.
void SetNamespaceName(const string &ns_name)
Set namespace name.
virtual const CTypeInfo * GetThisTypeInfo(void) const =0
#define XSERIAL_TYPEINFO_WRITELOCK
Definition: serialimpl.hpp:277
const string & GetName(void) const
Get local name.
ESerialDataFormat
Data file format.
Definition: serialdef.hpp:71
const vector< CSerialAttribInfoItem > & GetAttributes(void) const
Get object attributes.
@ eSerial_Xml
XML.
Definition: serialdef.hpp:75
void SetLocalReadHook(CObjectIStream &stream, CReadObjectHook *hook) const
Set local (for the specified stream) read hook.
Definition: objectinfo.cpp:366
void SetUseSchemaLocation(bool use_loc=true)
Put Schema location information into generated XML document.
Definition: objostrxml.cpp:145
void SetReferenceSchema(bool use_schema=true)
Make generated XML document reference XML schema.
Definition: objostrxml.cpp:128
bool GetUseSchemaLocation(void) const
Get Schema location output parameter.
Definition: objostrxml.cpp:149
string GetDefaultSchemaNamespace(void)
Get default value of namespace name of generated DTD documents.
bool GetReferenceSchema(void) const
Get Schema referencing parameter.
Definition: objostrxml.cpp:132
void SetLocalWriteHook(CObjectOStream &stream, CWriteObjectHook *hook) const
Set local (for the specified stream) write hook.
Definition: objectinfo.cpp:393
void SetDefaultSchemaNamespace(const string &schema_ns)
Set default value of namespace name of generated DTD documents.
TObjectType * GetPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1684
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static bool SplitInTwo(const CTempString str, const CTempString delim, string &str1, string &str2, TSplitFlags flags=0)
Split a string into two pieces using the specified delimiters.
Definition: ncbistr.cpp:3554
const CTypeInfo * SetNamespaceName(const string &ns_name) const
Set namespace name.
Definition: typeinfo.cpp:197
@ e_not_set
constexpr bool empty(list< Ts... >) noexcept
const CharType(& source)[N]
Definition: pointer.h:1149
unsigned int a
Definition: ncbi_localip.c:102
std::istream & in(std::istream &in_, double &x_)
static const char * prefix[]
Definition: pcregrep.c:405
Definition: inftrees.h:24
Definition: type.c:6
static const char * type_name(CS_INT value)
Definition: will_convert.c:122
Modified on Fri Apr 12 17:19:16 2024 by modify_doxy.py rev. 669887