00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00039 Services::Services(MetaObject* s)
00040 : MetaObject(s)
00041 {
00042 accessControl = &NoPropertyAccessControl::static_;
00043 }
00044
00045
00046 Services::~Services() {
00047 }
00048
00049
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
00061 defaultServiceDir = meta_cast<Services*>(&(Vobject::findObjectFromRoot(serviceDirURL)));
00062 }
00063 if(defaultServiceDir) {
00064 defaultServiceDir->acquire();
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
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
00159
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
00195
00196 const string Services::getType() {
00197 return string("misc:services");
00198 }
00199
00200
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
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
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();
00336 site->addExciseListener(this);
00337 services->acquire();
00338 }
00339
00340 ServiceListenerSiteWrapper::~ServiceListenerSiteWrapper()
00341 {
00342 site->release();
00343 services->release();
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 }