Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/hello/hello.cc

Go to the documentation of this file.
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 ]]>

Generated on Tue Aug 12 03:55:43 2003 for Interreality Project - VOS by doxygen 1.3.2