00001 // <![CDATA[ 00002 // Bring in all the various class definitions 00003 #include "hello.hh" 00004 00005 /* Hello constructor, does nothing except passing the argument up. 00006 Without getting too deep into metaobject's implementation, the 00007 "superobject" is the _actual_ Vobject which this MetaObject is 00008 attached to. 00009 */ 00010 Hello::Hello(MetaObject* superobject) : MetaObject(superobject) 00011 { } 00012 00013 /* Return the VOS type, as explained in hello.hh */ 00014 const string Hello::getType() { 00015 return "example:hello"; 00016 } 00017 00018 void Hello::registerExtenders() 00019 { 00020 /* Registering an extension consists of supplying a type string and a 00021 function to call to construct a new metaobject for that type. Here we 00022 register functions for the abstract class, the local class, and the VOS 00023 type name, meaning the user can call LocalSite::createMetaObject() with 00024 any of these three strings and get an object with the Hello 00025 extension. 00026 */ 00027 LocalSite::addLocalObjectExtension(typeid(Hello).name(), &LocalHello::new_LocalHello); 00028 LocalSite::addLocalObjectExtension(typeid(LocalHello).name(), &LocalHello::new_LocalHello); 00029 LocalSite::addLocalObjectExtension("example:hello", &LocalHello::new_LocalHello); 00030 00031 /* Note that for remote objects the VOS type name is extremely 00032 important: it is the VOS type name we get from the network, and 00033 we use it to automatically instantiate the correct extensions 00034 for the newly discovered object. 00035 */ 00036 RemoteSite::addRemoteObjectExtension(typeid(Hello).name(), &RemoteHello::new_RemoteHello); 00037 RemoteSite::addRemoteObjectExtension(typeid(RemoteHello).name(), &RemoteHello::new_RemoteHello); 00038 RemoteSite::addRemoteObjectExtension("example:hello", &RemoteHello::new_RemoteHello); 00039 } 00040 00041 /* Constructor. Note that because we have to 00042 inherit using virtual base classes -- 00043 class LocalHello : public virtual Hello { ... }; 00044 -- we must explicitly specify which constructors get called. 00045 */ 00046 LocalHello::LocalHello(MetaObject* superobject) 00047 : Hello(superobject), MetaObject(superobject) 00048 { 00049 /* This might look like a scary function call, but it's actually 00050 very simple. What we are doing here is telling the system that 00051 when this object receives a message with the method 00052 "example:hello", it should call the method LocalHello::handleHello 00053 on this object. The template is merely necessary to keep C++'s 00054 static type checking happy. 00055 */ 00056 addMessageHandler<LocalHello>("example:hello", this, &LocalHello::handleHello); 00057 } 00058 00059 /* The ACTUAL hello method! All this extra stuff exists solely to 00060 enable us to be able to call this incredibly amazing function over 00061 a network. 00062 */ 00063 string LocalHello::hello(const string& s) 00064 { 00065 return ("Hello there! You said \"" + s + "\""); 00066 } 00067 00068 /* This method is called by VOS when a message bearing the method 00069 "example:hello" is received by this object. 00070 */ 00071 void LocalHello::handleHello(Message* m) 00072 { 00073 /* Construct a new message. (See an explanation of the 00074 meaning of vRef<> in the online API documentation, 00075 or the comments of helloclient.cc). 00076 */ 00077 vRef<Message> reply = new Message(); 00078 00079 /* LocalVobject has a convenience method which will set 00080 up the reply for us, such as initializing with the 00081 correct nonce. See API documentation for details. */ 00082 LocalVobject::initReply(this, &reply, m, "example:hello-reply"); 00083 try { 00084 // Now call hello() with the field called "text". 00085 string s = hello(m->getField("text").value); 00086 // The result goes into a field called "text" in the reply. 00087 reply->insertField(-1, "text", s); 00088 } catch(Message::NoSuchFieldError) { 00089 // oops! The message we got didn't have the field we were looking for. 00090 reply->insertField(-1, "error", "need a field \"text\""); 00091 } 00092 try { 00093 /* Get a handle on the object that sent this message to us 00094 and send it the reply. */ 00095 vRef<Vobject> v = findObject(m->getFrom()); 00096 v->sendMessage(&reply); 00097 } catch(NoSuchSiteError) { 00098 } catch(NoSuchObjectError) { 00099 } catch(AccessControlError) { 00100 } catch(RemoteError) { 00101 } catch(URL::BadURLError) { 00102 } 00103 } 00104 00105 // Return a new hello object . See hello.hh for more details. 00106 MetaObject* LocalHello::new_LocalHello(MetaObject* superobject, const string& type) 00107 { 00108 return new LocalHello(superobject); 00109 } 00110 00111 00112 /* Constructor. Same note about virtual base classes in LocalHello 00113 goes for this as well. 00114 */ 00115 RemoteHello::RemoteHello(MetaObject* superobject) 00116 : Hello(superobject), MetaObject(superobject) 00117 { } 00118 00119 /* The client stub implementation of hello. */ 00120 string RemoteHello::hello(const string& s) 00121 { 00122 string ret; // will hold return value 00123 00124 // Create a new message. Hopefully you know about vRef by now. 00125 vRef<Message> m = new Message(); 00126 00127 /* RemoteVobject::initFields is a convenience funtion to 00128 initialize some of the fields on the message, including 00129 generating a nonce.. It also returns the local site which 00130 is peered to this remote site, which we need if we want to 00131 wait for a reply. 00132 */ 00133 vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "example:hello", true); 00134 00135 // Now add a field, tagged "text" 00136 m->insertField(-1, "text", s); 00137 00138 /* Send it off. Note that what we are actually doing 00139 here is calling sendMessage on the superobject, which 00140 will do the actual sending to the remote site (via 00141 some underlying transport) for us. 00142 */ 00143 sendMessage(&m); 00144 00145 // get our (remote) site 00146 vRef<RemoteSite> site = dynamic_cast<RemoteSite&>(getSite()); 00147 00148 /* Wait until either a message is received on our 00149 local site from the supplied remote site bearing 00150 the given nonce, or time runs out. Returns the 00151 message that matches the nonce, or throws a 00152 TimeoutError if we ran out of time. 00153 */ 00154 vRef<Message> n = ls->waitFor(m->getNonce(), &site); 00155 try { 00156 // We got a reply back. Extract the answer from the "text" field. 00157 ret = n->getField("text").value; 00158 } catch(Message::NoSuchFieldError) { 00159 // Whoops. There wasn't a "text" field. 00160 // We could perhaps throw an exception here. 00161 ret = "***site did not return a text field***"; 00162 } 00163 00164 // return our results. 00165 return ret; 00166 } 00167 00168 // Return a new hello object . See hello.hh for more details. 00169 MetaObject* RemoteHello::new_RemoteHello(MetaObject* superobject, const string& type) 00170 { 00171 return new RemoteHello(superobject); 00172 } 00173 00174 // end of hello.cc ]]>