00001 // TestSOAP.cpp: implementation of the TestSOAP class. 00002 // 00003 // this is a simple server that allows testing of Simple SOAP 00004 // 00005 // $Id: TestSOAP.cpp,v 1.1 2005/03/22 22:30:30 gjpc Exp $ 00006 // 00007 // $Log: TestSOAP.cpp,v $ 00008 // Revision 1.1 2005/03/22 22:30:30 gjpc 00009 // This is the intial check in of the Simple SOAP library. 00010 // 00011 // The code compiles and executes under MSVC .NET and GNU 3.3 00012 // 00013 // It has been run under Debian, SUSE, CYGWIN and WinXP 00014 // 00015 00016 #include <string.h> 00017 #include <iostream> 00018 00019 #include "SOAPDispatcher.h" 00020 #include "SOAPMethod.h" 00021 #include "Base64Encoder.h" 00022 00023 #if !defined(SOAPENCODER_H) 00024 #include "SOAPEncoder.h" 00025 #endif // SOAPENCODER_H 00026 #if !defined(SOAPELEMENT_H) 00027 #include "SOAPElement.h" 00028 #endif // !defined(SOAPELEMENT_H) 00029 #ifndef _SSTREAM_ 00030 #include <sstream> 00031 #endif // _SSTREAM_ 00032 #ifndef __TestSOAP__ 00033 #include "TestSOAP.h" 00034 #endif // __TestSOAP__ 00035 00036 // TestSOAP::MyData 00037 // here we declare the structures for the RPC's 00038 // Each RPC has an entry describing it the MyData structure 00039 // We must declare the structures before the TestSOAP ctor to 00040 // avoid any forward referecning problems when building the tables 00041 struct TestSOAP::MyData 00042 { 00044 class Addition : public SOAPMethod 00045 { 00046 public: 00047 Addition() : returnValue( 0 ) {} 00048 virtual std::string methodName() { return "Addition"; } 00049 virtual bool encode( SOAPEncoder& soapEncoder ); 00050 virtual bool execute( SOAPElement& theCall ); 00051 00052 private: 00053 double returnValue; 00054 00055 } m_Addition; 00056 00058 class Subtraction : public SOAPMethod 00059 { 00060 public: 00061 Subtraction() : returnValue( 0 ) {} 00062 virtual std::string methodName() { return "Subtraction"; } 00063 virtual bool encode( SOAPEncoder& soapEncoder ); 00064 virtual bool execute( SOAPElement& theCall ); 00065 00066 private: 00067 double returnValue; 00068 00069 } m_Subtraction; 00070 00072 class Base64Test : public SOAPMethod 00073 { 00074 public: 00075 Base64Test() : returnValue( 0 ) { myMethod = NULL; } 00076 virtual std::string methodName() { return "Base64Test"; } 00077 virtual bool encode( SOAPEncoder& soapEncoder ); 00078 virtual bool execute( SOAPElement& theCall ); 00079 00080 private: 00081 unsigned char *returnValue; 00082 unsigned long returnLength; 00083 SOAPElement *myMethod; 00084 00085 } m_Base64Test; 00086 00087 00088 }; 00089 00090 00092 // TestSOAP 00093 // This single object is used by both clients and servers to perform SOAP RPc's 00094 // Add any Method above to this table so that the Dispatcher can find it 00095 TestSOAP::TestSOAP() : 00096 m_pData( new MyData ) 00097 { 00098 insertMethod( &(m_pData->m_Addition ) ); 00099 insertMethod( &(m_pData->m_Subtraction ) ); 00100 insertMethod( &(m_pData->m_Base64Test ) ); 00101 } 00102 00103 TestSOAP::~TestSOAP() 00104 { 00105 // nothing to do 00106 } 00107 00109 // now we implement the encoders and executioners this differs from the book 00110 // because some helper functions were added to SoapMethod to hadle common faults 00111 00113 // the Dispatcher calls this method if the execute succeeds 00114 bool TestSOAP::MyData::Addition::encode( SOAPEncoder& soapEncoder ) 00115 { 00116 soapEncoder.encodeArg( returnValue ); 00117 return true; 00118 } 00119 00120 // When an Addition RPC arrives the method is fed into this executioner 00121 bool TestSOAP::MyData::Addition::execute( SOAPElement& theMethod ) 00122 { 00123 if ( ImustUnderstand( theMethod ) ) 00124 return false; 00125 00126 if ( theMethod.accessorName() == methodName() ) 00127 { 00128 if ( theMethod.numElements() == 2 ) 00129 { 00130 // ok we have a leagal call get the args and perform the addition 00131 double a = atof( theMethod.elementAt( 0 ).value().c_str() ); 00132 double b = atof( theMethod.elementAt( 1 ).value().c_str() ); 00133 returnValue = a + b; 00134 return true; 00135 } 00136 else 00137 wrongNumberArgumentsFault( theMethod, "2" ); 00138 } 00139 else 00140 unkownMethodFault( theMethod ); 00141 00142 return false; 00143 } 00144 00146 // the Dispatcher calls this method if the execute succeeds 00147 bool TestSOAP::MyData::Subtraction::encode( SOAPEncoder& soapEncoder ) 00148 { 00149 soapEncoder.encodeArg( returnValue ); 00150 return true; 00151 } 00152 00153 // When a Subtraction RPC arrives the method is fed into this executioner 00154 bool TestSOAP::MyData::Subtraction::execute( SOAPElement& theMethod ) 00155 { 00156 if ( ImustUnderstand( theMethod ) ) 00157 return false; 00158 00159 if ( theMethod.accessorName() == methodName() ) 00160 { 00161 if ( theMethod.numElements() == 2 ) 00162 { 00163 double a = atof( theMethod.elementAt( 0 ).value().c_str() ); 00164 double b = atof( theMethod.elementAt( 1 ).value().c_str() ); 00165 returnValue = a - b; 00166 return true; 00167 } 00168 else 00169 wrongNumberArgumentsFault( theMethod, "2" ); 00170 } 00171 else 00172 unkownMethodFault( theMethod ); 00173 00174 return false; 00175 } 00176 00177 00179 // the Dispatcher calls this method if the execute succeeds 00180 bool TestSOAP::MyData::Base64Test::encode( SOAPEncoder& soapEncoder ) 00181 { 00182 soapEncoder.encodeBase64( myMethod->elementAt( 0 ).accessorName().c_str(), returnValue, returnLength ); 00183 return true; 00184 } 00185 00186 // When a Subtraction RPC arrives the method is fed into this executioner 00187 bool TestSOAP::MyData::Base64Test::execute( SOAPElement& theMethod ) 00188 { 00189 if ( ImustUnderstand( theMethod ) ) 00190 return false; 00191 00192 if ( theMethod.accessorName() == methodName() ) 00193 { 00194 if ( theMethod.numElements() == 1 ) 00195 { 00196 myMethod = &theMethod; 00197 returnValue = Base64Encoder().decodeValue( theMethod.elementAt( 0 ).value().c_str(), returnLength ); 00198 return true; 00199 } 00200 else 00201 wrongNumberArgumentsFault( theMethod, "2" ); 00202 } 00203 else 00204 unkownMethodFault( theMethod ); 00205 00206 return false; 00207 } 00208 00209