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

vos/metaobjects/misc/services.cc

Go to the documentation of this file.
00001 /* $Id: services.cc,v 1.15 2003/07/23 00:17:27 reed Exp $ */
00002 
00003 
00004 /* This file was generated by otd2cpp.pl.
00005 
00006     Copyright (C) 2002 Peter Amstutz <tetron@interreality.org>
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Lesser General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Lesser General Public License for more details.
00017 
00018     You should have received a copy of the GNU Lesser General Public
00019     License along with this library; if not, write to the Free Software
00020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00021 
00022 */
00023 
00024 /** @file services.cc Code: a MetaObject for Services object types. */
00025 
00026 #include <vos/corelibs/vos/vos.hh>
00027 #include <vos/metaobjects/property/property.hh>
00028 #include "services.hh"
00029 #include "hypercard.hh"
00030 
00031 using namespace LSD;
00032 using namespace std;
00033 
00034 Services* Services::defaultServiceDir = 0;
00035 string Services::serviceDirURL("vop://localhost:4231/services");
00036 
00037 
00038 /* Constructor */
00039 Services::Services(MetaObject* s)
00040     : MetaObject(s)
00041 {
00042     accessControl = &NoPropertyAccessControl::static_;
00043 }
00044 
00045 /* Destructor */
00046 Services::~Services() {
00047 }
00048 
00049 /* Get/Set default AC */
00050 void Services::setPropertyAccessControl(PropertyAccessControl* ac) {
00051     accessControl = ac;
00052 }
00053 PropertyAccessControl* Services::getPropertyAccessControl() {
00054     return accessControl;
00055 }
00056 
00057 Services* Services::getDefaultServicesDir()
00058 {
00059     if(! defaultServiceDir) {
00060         // following acquire released by: destructor or notifyObjectExcise()
00061         defaultServiceDir = meta_cast<Services*>(&(Vobject::findObjectFromRoot(serviceDirURL)));
00062     }
00063     if(defaultServiceDir) {
00064         defaultServiceDir->acquire(); // released by: caller
00065         return defaultServiceDir;
00066     } else {
00067         LOG("services", 2, "Could not contact default service list daemon");
00068         throw bad_cast();
00069     }
00070 }
00071 
00072 void Services::setDefaultServiceDir(const string& url)
00073 {
00074     serviceDirURL = url;
00075 }
00076 
00077 void Services::registerServiceWithDefault(Vobject* service, const string& title, const string& desc)
00078 {
00079     vRef<Services> dir = getDefaultServicesDir();
00080     dir->registerService(service, title, desc);
00081 }
00082 
00083 void Services::registerService(Vobject* service, const string& title, const string& desc)
00084 {
00085     vRef<Site> site = getSite();
00086 
00087     vRef<Hypercard> h = meta_cast<Hypercard*>(site->createMetaObject("", "misc:hypercard", 0));
00088     h->set_link(service);
00089 
00090     vRef<Property> t = meta_cast<Property*>(site->createMetaObject("", "property:property", 0));
00091     t->replace(title);
00092     h->insertChild(-1, "misc:title", &t);
00093 
00094     vRef<Property> d = meta_cast<Property*>(site->createMetaObject("", "property:property", 0));
00095     d->replace(desc);
00096     h->insertChild(-1, "misc:description", &d);
00097 
00098     const TypeSet& ts = service->getTypes();
00099     for(TypeSet::const_iterator i = ts.begin(); i != ts.end(); i++) {
00100         h->addType(string("linktype=") + *i);
00101     }
00102 
00103     insertChild(-1, title, &h);
00104 }
00105 
00106 LocalServices::LocalServices(MetaObject* s) : Services(s), MetaObject(s)
00107 {
00108     accessControl = &NoPropertyAccessControl::static_;
00109 
00110     addMessageHandler<LocalServices>("misc:service-query", this, &LocalServices::handleQuery);
00111     addMessageHandler<LocalServices>("misc:end-service-query", this, &LocalServices::handleEndQuery);
00112 }
00113 
00114 LocalServices::~LocalServices() {
00115 }
00116 
00117 /* Initialize required subobjects: */
00118 
00119 void LocalServices::initialize(PropertyAccessControl* ac) {
00120     accessControl = ac;
00121     initialize();
00122 }
00123 
00124 void LocalServices::initialize() {
00125 
00126     vRef<LocalSite> localsite = Site::getDefaultPeer();
00127 }
00128 
00129 
00130 RemoteServices::RemoteServices(MetaObject* s) : Services(s), MetaObject(s)
00131 {
00132     addUpdateHandler<RemoteServices>("misc:service-advertisement", this, &RemoteServices::handleAdvertisement);
00133 }
00134 
00135 RemoteServices::~RemoteServices() {
00136 }
00137 
00138 int RemoteServices::query(const string& typepattern,
00139                           const string& titlepattern,
00140                           const string& descpattern,
00141                           const string& urlpattern,
00142                           LSD::ServiceAdvertismentListener* cb)
00143 {
00144     LOG("RemoteServices", 3, "sending service-query message...");
00145     vRef<Message> m = new Message();
00146     vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "misc:service-query", false);
00147     m->insertField(-1, "type", typepattern);
00148     m->insertField(-1, "title", titlepattern);
00149     m->insertField(-1, "desc", descpattern);
00150     m->insertField(-1, "url", urlpattern);
00151     char n[32];
00152     snprintf(n, sizeof(n), "%i", rand());
00153     m->setNonce(n);
00154     sendMessage(&m);
00155 
00156     queries[atoi(m->getNonce().c_str())] = cb;
00157 
00158     //vRef<RemoteSite> rs = dynamic_cast<RemoteSite&>(getSite());
00159     //vRef<Message> reply = ls->waitFor(m->getNonce(), &rs);
00160 
00161     return atoi(m->getNonce().c_str());
00162 }
00163 
00164 void RemoteServices::endQuery(int r)
00165 {
00166     vRef<Message> m = new Message();
00167     vRef<LocalSite> ls = RemoteVobject::initFields(this, &m, "misc:end-service-query", false);
00168     char n[32];
00169     snprintf(n, sizeof(n), "%i", r);
00170     m->setNonce(n);
00171 
00172     sendMessage(&m);
00173 
00174     queries.erase(r);
00175 }
00176 
00177 void RemoteServices::handleAdvertisement(Message* m)
00178 {
00179     LOG("RemoteServices", 3, "handleAdvertisement");
00180     int r = atoi(m->getNonce().c_str());
00181     if(queries.count(r)) {
00182         LSD::Service s;
00183         for(int i = 0; i < m->getNumFields(); i++) {
00184             const Message::Field& f = m->getField(i);
00185             if(f.key == "title") s.title = f.value;
00186             else if(f.key == "desc") s.description = f.value;
00187             else if(f.key == "url") s.url = f.value;
00188             else if(f.key == "type") s.types.insert(f.value);
00189         }
00190         queries[r]->notifyNewService(r, s);
00191     }
00192 }
00193 
00194 /* Return type string ("misc:services") */
00195 
00196 const string Services::getType() {
00197     return string("misc:services");
00198 }
00199 
00200 /* Register extenders with libvos MetaFactory */
00201 void Services::registerExtenders() {
00202     static bool done = false;
00203 
00204     Hypercard::registerExtenders();
00205 
00206     if(! done) {
00207     LocalSite::addLocalObjectExtension(typeid(LocalServices).name(), &LocalServices::new_LocalServices);
00208     LocalSite::addLocalObjectExtension(typeid(Services).name(), &LocalServices::new_LocalServices);
00209     LocalSite::addLocalObjectExtension("misc:services", &LocalServices::new_LocalServices);
00210     RemoteSite::addRemoteObjectExtension(typeid(RemoteServices).name(), &RemoteServices::new_RemoteServices);
00211     RemoteSite::addRemoteObjectExtension(typeid(Services).name(), &RemoteServices::new_RemoteServices);
00212     RemoteSite::addRemoteObjectExtension("misc:services", &RemoteServices::new_RemoteServices);
00213     done = true;
00214     }
00215 }
00216 
00217 /* Generators for factory */
00218 
00219 
00220 MetaObject* LocalServices::new_LocalServices(MetaObject *s, const string& type) {
00221     LocalServices* o = new LocalServices(s);
00222     o->addChildListener(o);
00223     return o;
00224 }
00225 
00226 MetaObject* RemoteServices::new_RemoteServices(MetaObject *s, const string& type) {
00227     return new RemoteServices(s);
00228 }
00229 
00230 
00231 void LocalServices::notifyChildInserted(VobjectEvent& event)
00232 {
00233     try {
00234         if(event.getParent() == this) {
00235             Hypercard* hc = meta_cast<Hypercard*>(event.getChild());
00236             if(hc)
00237                 hc->addChildListener(this);
00238         }
00239     } catch(bad_cast) {
00240     } catch(NoSuchObjectError) {
00241     }
00242 }
00243 
00244 void LocalServices::notifyChildReplaced(VobjectEvent& event)
00245 {
00246     try {
00247         if(event.getParent() == this) {
00248             Hypercard* oldhc = meta_cast<Hypercard*>(event.getOldChild());
00249             if(oldhc)
00250                 oldhc->removeChildListener(this);
00251 
00252             Hypercard* newhc = meta_cast<Hypercard*>(event.getNewChild());
00253             if(newhc)
00254                 newhc->addChildListener(this);
00255         }
00256     } catch(bad_cast) {
00257     } catch(NoSuchObjectError) {
00258     }
00259 }
00260 
00261 void LocalServices::notifyChildRemoved(VobjectEvent& event)
00262 {
00263     try {
00264         if(event.getParent() == this) {
00265             Hypercard* oldhc = meta_cast<Hypercard*>(event.getOldChild());
00266             if(oldhc)
00267                 oldhc->removeChildListener(this);
00268         } else {
00269             vRef<ParentChildRelation> pcr = event.getParent()->findParent(*this);
00270             if(event.getContextualName() == "misc:link") {
00271                 // destroy the hypercard as well
00272                 Hypercard* oldhc = meta_cast<Hypercard*>(event.getParent());
00273                 if(!oldhc) throw bad_cast();
00274                 try {
00275                     vRef<Vobject> t = oldhc->findObject("misc:title");
00276                     t->excise();
00277                 } catch(NoSuchObjectError) { }
00278                 try {
00279                     vRef<Vobject> d = oldhc->findObject("misc:description");
00280                     d->excise();
00281                 } catch(NoSuchObjectError) { }
00282                 oldhc->excise();
00283             }
00284         }
00285     } catch(bad_cast) {
00286     } catch(NoSuchObjectError) {
00287     }
00288 }
00289 
00290 void LocalServices::handleQuery(Message* m)
00291 {
00292     try {
00293         LOG("LocalServices", 3, "Recieved query.");
00294         vRef<Site> site = m->getSourceSite();
00295         ServiceListenerSiteWrapper* note = new ServiceListenerSiteWrapper(this, &site, m->getNonce().c_str());
00296         int r = query(m->getField("type").value,
00297                       m->getField("title").value,
00298                       m->getField("desc").value,
00299                       m->getField("url").value,
00300                       note);
00301         assert(r != -1);
00302         note->setQueryID(r);
00303         queries[r] = note;
00304     } catch(Message::NoSuchFieldError) {
00305     }
00306 }
00307 
00308 int LocalServices::query(const string& typepattern,
00309                          const string& titlepattern,
00310                          const string& descpattern,
00311                          const string& urlpattern,
00312                          LSD::ServiceAdvertismentListener* cb)
00313 {
00314     cerr << "Internal Error! (You must override LocalServices::query)\n";
00315     return -1;
00316 
00317 }
00318 
00319 void LocalServices::endQuery(int q)
00320 {
00321 }
00322 
00323 void LocalServices::handleEndQuery(Message* m)
00324 {
00325     int r = atoi(m->getNonce().c_str());
00326     endQuery(r);
00327     LSD::ServiceAdvertismentListener* sal = queries[r];
00328     queries.erase(r);
00329     if(dynamic_cast<ServiceListenerSiteWrapper*>(sal)) delete sal;
00330 }
00331 
00332 ServiceListenerSiteWrapper::ServiceListenerSiteWrapper(LocalServices* s, Site* r, const string& n)
00333     : services(s), site(r), nonce(n)
00334 {
00335     site->acquire(); // released by: destructor
00336     site->addExciseListener(this);
00337     services->acquire(); // released by: destructor
00338 }
00339 
00340 ServiceListenerSiteWrapper::~ServiceListenerSiteWrapper()
00341 {
00342     site->release(); // acquired by: constructor
00343     services->release(); // acquired by: constructor
00344 }
00345 
00346 void ServiceListenerSiteWrapper::notifyNewService(int id, const LSD::Service& s)
00347 {
00348     LOG("ServiceListenerSiteWrapper", 3, "notifyNewService");
00349     vRef<Message> m = new Message();
00350     m->setType("update");
00351     m->setFrom(services->getURL().getString());
00352     assert(&site);
00353     m->setTo(site->getURL().getString());
00354     m->setMethod("misc:service-advertisement");
00355     m->setNonce(nonce);
00356 
00357     for(set<string>::const_iterator i = s.types.begin(); i != s.types.end(); i++) {
00358         m->insertField(-1, "type", *i);
00359     }
00360     m->insertField(-1, "title", s.title);
00361     m->insertField(-1, "desc", s.description);
00362     m->insertField(-1, "url", s.url);
00363 
00364     site->sendMessage(&m);
00365 }
00366 
00367 void ServiceListenerSiteWrapper::notifyObjectExcise(RefCounted* rc)
00368 {
00369     services->endQuery(queryID);
00370     services->queries.erase(queryID);
00371     delete this;
00372 }

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