00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <stdexcept>
00027 #include <string>
00028 #include <vector>
00029
00030
00031 #include <vos/corelibs/vos/vos.hh>
00032 #include "property.hh"
00033 #include <typechain/typechain.hh>
00034
00035 #include <assert.h>
00036
00037
00038 using namespace std;
00039
00040 NoPropertyAccessControl NoPropertyAccessControl::static_;
00041 ReadOnlyPropertyAccessControl ReadOnlyPropertyAccessControl::static_;
00042 DoNothingPropertyListener DoNothingPropertyListener::static_;
00043 DoNothingPropertySecurityInitializer DoNothingPropertySecurityInitializer::static_;
00044 PropertySecurityInitializer* LocalProperty::securitycallback =
00045 &DoNothingPropertySecurityInitializer::static_;
00046
00047 map<string, PropertyAccessControl::AssignAC> PropertyAccessControl::policies;
00048
00049 void PropertyAccessControl::addPolicy(PropertyAccessControl* ac)
00050 {
00051 policies[ac->getPolicyName()].ac = ac;
00052 policies[ac->getPolicyName()].fac = 0;
00053 }
00054
00055 void PropertyAccessControl::addPolicyFactory(const string& name, PropertyAccessControlFactory ac)
00056 {
00057 policies[name].ac = 0;
00058 policies[name].fac = ac;
00059 }
00060
00061 PropertyAccessControl* PropertyAccessControl::getPolicy(const string& name, LocalProperty* lv)
00062 {
00063 if(policies.count(name)) {
00064 if(policies[name].ac) return policies[name].ac;
00065 else {
00066 return (*policies[name].fac)(name, lv);
00067 }
00068 } else return 0;
00069 }
00070
00071 void PropertyAccessControl::removePolicy(const string& name)
00072 {
00073 policies.erase(name);
00074 }
00075
00076
00077
00078
00079
00080
00081 Property::Property(MetaObject* superobject)
00082 : MetaObject(superobject), raw_data(""), raw_datatype("?"), raw_length(-1), data(""), datatype("?"), data_length(0), decoded(false)
00083 {
00084 }
00085
00086
00087
00088
00089
00090 const string Property::getType()
00091 {
00092 return string("property:property");
00093 }
00094
00095 void Property::checkDecoded() {
00096 if(!decoded) {
00097 LOG("Property", 4, "Property::checkDecoded: Decoding data of type " << raw_datatype << "." );
00098 readRaw(data);
00099 datatype = TypeChain::decode(data, raw_datatype);
00100 data_length = data.size();
00101 decoded = true;
00102 }
00103 }
00104
00105
00106 int Property::getLength() {
00107 checkDecoded();
00108 return data_length;
00109 }
00110
00111 void Property::read(string& target) {
00112 read(target, 0, -1);
00113 }
00114
00115 void Property::read(string& target, int start, int length) {
00116 checkDecoded();
00117 if(length == -1)
00118 target = data.substr(start);
00119 else
00120 target = data.substr(start, length);
00121 }
00122
00123 string Property::read() {
00124 string s;
00125 read(s);
00126 return s;
00127 }
00128
00129 string Property::read(int start, int length) {
00130 string s;
00131 read(s, start, length);
00132 return s;
00133 }
00134
00135 int Property::getRawLength() {
00136 return raw_length;
00137 }
00138
00139 void Property::readRaw(string& target) {
00140 readRaw(target, 0, getRawLength());
00141 }
00142
00143 void Property::readRaw(string& target, int start, int length) {
00144 if(length == -1)
00145 target = raw_data.substr(start);
00146 else
00147 target = raw_data.substr(start, length);
00148 }
00149
00150 string Property::readRaw() {
00151 string s;
00152 readRaw(s);
00153 return s;
00154 }
00155
00156 string Property::readRaw(int start, int length) {
00157 string s;
00158 readRaw(s, start, length);
00159 return s;
00160 }
00161
00162 void Property::asyncRead()
00163 {
00164 string dcp;
00165 read(dcp);
00166 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyReplace,
00167 *this, *this,
00168 dcp, getDataType(),
00169 false);
00170 for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00171 (*i).second->notifyPropertyChange(*event);
00172 }
00173 }
00174
00175 void Property::asyncRead(int start, int length)
00176 {
00177 string dcp;
00178 read(dcp, start, length);
00179 vRef<PropertyEvent> event = new PropertyEvent(PropertyEvent::PropertyWrite,
00180 *this, *this,
00181 start, length,
00182 dcp, getDataType(),
00183 false);
00184 for(PropertyListenerMap::iterator i = propertyListeners.begin(); i != propertyListeners.end(); i++) {
00185 (*i).second->notifyPropertyChange(*event);
00186 }
00187 }
00188
00189
00190 void Property::write(int start, const string& newdata) {
00191 if(start < 0)
00192 start = raw_data.size() + start;
00193 raw_data.replace(start, newdata.size(), newdata);
00194 raw_length = raw_data.size();
00195 decoded = false;
00196 }
00197
00198
00199 void Property::replace(const string& newdata, const string& newtype) {
00200 raw_data = newdata;
00201
00202 if(newtype != "?")
00203 raw_datatype = newtype;
00204 raw_length = raw_data.size();
00205 decoded = false;
00206 }
00207
00208 const string Property::getDataType() {
00209 checkDecoded();
00210 return datatype;
00211 }
00212
00213
00214 const string Property::getRawDataType() {
00215 return raw_datatype;
00216 }
00217
00218 void Property::registerExtenders()
00219 {
00220 static bool done = false;
00221 if(! done) {
00222 LocalSite::addLocalObjectExtension(typeid(LocalProperty).name(),
00223 &LocalProperty::new_LocalProperty);
00224 LocalSite::addLocalObjectExtension(typeid(Property).name(),
00225 &LocalProperty::new_LocalProperty);
00226 LocalSite::addLocalObjectExtension("property:property",
00227 &LocalProperty::new_LocalProperty);
00228
00229 RemoteSite::addRemoteObjectExtension(typeid(RemoteProperty).name(),
00230 &RemoteProperty::new_RemoteProperty);
00231 RemoteSite::addRemoteObjectExtension(typeid(Property).name(),
00232 &RemoteProperty::new_RemoteProperty);
00233 RemoteSite::addRemoteObjectExtension("property:property",
00234 &RemoteProperty::new_RemoteProperty);
00235 done = true;
00236 }
00237 }
00238
00239 void Property::setProperty(Vobject& on,
00240 const string& propname,
00241 const string& propval,
00242 const string& valtype,
00243 PropertyAccessControl* pac)
00244 throw (AccessControlError, TypeChain::DecodeError, RemoteError)
00245 {
00246 rREF(Vobject::ParentChildRelation&, r, setPropertyWithReturn(on, propname, propval, valtype, pac), );
00247 }
00248
00249 Vobject::ParentChildRelation& Property::setPropertyWithReturn(Vobject& on,
00250 const string& propname,
00251 const string& propval,
00252 const string& valtype,
00253 PropertyAccessControl* pac,
00254 bool letErrorThrough)
00255 throw (AccessControlError, TypeChain::DecodeError, RemoteError)
00256 {
00257 int i;
00258 for(i = propname.size()-1; i >= 0 && propname[i] != '/'; i--);
00259 string path = (i > 0 ? propname.substr(0, i) : "");
00260 string name = propname.substr(i+1);
00261 try {
00262 vRef<Vobject> parent = on.findObject(path);
00263 vRef<ParentChildRelation> c = parent->findChild(name);
00264 if(Property* p = meta_cast<Property*>(c->child)) {
00265 p->replace(propval, valtype);
00266 }
00267 c->acquire();
00268 return *c;
00269 } catch(Vobject::NoSuchObjectError x) {
00270 if(letErrorThrough) throw x;
00271 vRef<Vobject> parent = on.findObject(path);
00272
00273 vRef<LocalSite> ls = Site::getDefaultPeer();
00274 vRef<MetaObject> m = ls->createMetaObject(propname.c_str(),
00275 "property:property", 0);
00276 LocalProperty* lp = MetaObject::meta_cast<LocalProperty*>(&m);
00277 if(pac)
00278 lp->insertPropertyAccessControl(-1, pac);
00279 lp->addParentListener(&DoNothingListener::static_);
00280 parent->insertChild(-1, name, lp);
00281 return setPropertyWithReturn(on, propname, propval, valtype, pac, true);
00282 }
00283 }
00284
00285 void Property::setProperty(Vobject& on,
00286 const string& propname,
00287 double propval,
00288 PropertyAccessControl* pac)
00289 throw (AccessControlError, TypeChain::DecodeError, RemoteError)
00290 {
00291 rREF(Vobject::ParentChildRelation&, r, setPropertyWithReturn(on, propname, propval, pac), );
00292 }
00293
00294 Vobject::ParentChildRelation& Property::setPropertyWithReturn(Vobject& on,
00295 const string& propname,
00296 double propval,
00297 PropertyAccessControl* pac)
00298 throw (AccessControlError, TypeChain::DecodeError, RemoteError)
00299 {
00300
00301
00302 try {
00303 Vobject::ParentChildRelation& c = on.findChild(propname);
00304 if(Property* p = meta_cast<Property*>(c.child)) {
00305 char num[32];
00306 snprintf(num, sizeof(num), "%f", propval);
00307 p->replace(num, "text/x-float");
00308 }
00309 return c;
00310 } catch(Vobject::NoSuchObjectError) {
00311 vRef<MetaObject> m = Site::getDefaultPeer()->createMetaObject( propname.c_str(), typeid(Property).name(), 0);
00312 LocalProperty* lp = MetaObject::meta_cast<LocalProperty*>(&m);
00313 if(pac)
00314 lp->insertPropertyAccessControl(-1, pac);
00315 lp->addParentListener(&DoNothingListener::static_);
00316 on.insertChild(-1, propname, lp);
00317 return setPropertyWithReturn(on, propname, propval, pac);
00318 }
00319 }
00320
00321 string Property::getProperty(Vobject& on, const string& name) {
00322 vRef<Vobject> v = on.findObject(name);
00323 Property* p = meta_cast<Property*>(&v);
00324 if(!p) throw bad_cast();
00325 return p->read();
00326 }
00327
00328 string Property::getProperty(Vobject& on, const string& name, const string& defVal) {
00329 try {
00330 return Property::getProperty(on, name);
00331 } catch(Vobject::NoSuchObjectError) {
00332 return defVal;
00333 } catch(bad_cast) {
00334 return defVal;
00335 }
00336 }
00337
00338
00339 int Property::getIntProperty(Vobject& on, const string& name) {
00340 int v;
00341 string s;
00342 vRef<Property> p = meta_cast<Property*>(&(on.findObject(name)));
00343 if(!&p)
00344 throw bad_cast();
00345 p->read(s);
00346 sscanf(s.c_str(), "%d", &v);
00347 return v;
00348 }
00349
00350 int Property::getIntProperty(Vobject& on, const string& name, int defaultVal) {
00351 try {
00352 return Property::getIntProperty(on, name);
00353 } catch(NoSuchObjectError) {
00354 return defaultVal;
00355 } catch(bad_cast) {
00356 return defaultVal;
00357 }
00358 }
00359
00360 int Property::getIntProperty(Vobject& on, const string& name, int lowerLimit,
00361 int upperLimit)
00362 {
00363 int v;
00364 v = Property::getIntProperty(on, name);
00365 if(v < lowerLimit) return lowerLimit;
00366 if(v > upperLimit) return upperLimit;
00367 return v;
00368 }
00369
00370 int Property::getIntProperty(Vobject& on, const string& name, int defaultVal,
00371 int lowerLimit, int upperLimit)
00372 {
00373 int v;
00374 v = Property::getIntProperty(on, name, defaultVal);
00375 if(v < lowerLimit) return lowerLimit;
00376 if(v > upperLimit) return upperLimit;
00377 return v;
00378 }
00379
00380
00381 void Property::setIntProperty(Vobject& on, const string& name, int val,
00382 PropertyAccessControl* ac)
00383 {
00384 char num[64];
00385 snprintf(num, sizeof(num), "%d", val);
00386 Property::setProperty(on, name, num, "text/x-int", ac);
00387 }
00388
00389 void Property::setIntProperty(Vobject& on, const string& name, int val,
00390 int lowerLimit, int upperLimit, PropertyAccessControl* ac)
00391 {
00392 if(val < lowerLimit) val = lowerLimit;
00393 if(val > upperLimit) val = upperLimit;
00394 Property::setIntProperty(on, name, val, ac);
00395 }
00396
00397
00398
00399 double Property::getFloatProperty(Vobject& on, const string& name) {
00400 double v;
00401 string s;
00402 vRef<Property> p = meta_cast<Property*>(&(on.findObject(name)));
00403 if(!&p) throw bad_cast();
00404 p->read(s);
00405 sscanf(s.c_str(), "%lg", &v);
00406 return v;
00407 }
00408
00409 bool Property::getBoolProperty(Vobject& on, const string& name) {
00410 string s;
00411 vRef<Property> p = meta_cast<Property*>(&(on.findObject(name)));
00412 if(!&p) throw bad_cast();
00413 p->read(s);
00414 if(s == "yes")
00415 return true;
00416 else
00417 return false;
00418 }
00419
00420
00421 double Property::getFloatProperty(Vobject& on, const string& name, double defaultVal) {
00422 double v = defaultVal;
00423 try {
00424 v = getFloatProperty(on, name);
00425 } catch(Vobject::NoSuchObjectError) {
00426 v = defaultVal;
00427 } catch(bad_cast) {
00428 v = defaultVal;
00429 }
00430 return v;
00431 }
00432
00433 bool Property::getBoolProperty(Vobject& on, const string& name, bool defaultVal)
00434 {
00435 try {
00436 return getBoolProperty(on, name);
00437 } catch(NoSuchObjectError) {
00438 return defaultVal;
00439 } catch(bad_cast) {
00440 return defaultVal;
00441 }
00442 return defaultVal;
00443 }
00444
00445
00446 double Property::getFloatProperty(Vobject& on, const string& name, double defaultVal, double lowerLimit, double upperLimit) {
00447 double v = getFloatProperty(on, name, defaultVal);
00448 if(v < lowerLimit) return lowerLimit;
00449 if(v > upperLimit) return upperLimit;
00450 return v;
00451 }
00452
00453 double Property::getFloatProperty(Vobject& on, const string& name, double lowLim, double upLim) {
00454 double v = getFloatProperty(on, name);
00455 if(v < lowLim) return lowLim;
00456 if(v > upLim) return upLim;
00457 return v;
00458 }
00459
00460
00461
00462 void Property::setFloatProperty(Vobject& on, const string& name, double val,
00463 double lowerLimit, double upperLimit, PropertyAccessControl* ac) {
00464 if(val < lowerLimit) val = lowerLimit;
00465 if(val > upperLimit) val = upperLimit;
00466 setProperty(on, name, val, ac);
00467 }
00468
00469 void Property::setFloatProperty(Vobject& on, const string& name, double val,
00470 PropertyAccessControl* ac) {
00471 setProperty(on, name, val, ac);
00472 }
00473
00474
00475 void Property::setBoolProperty(Vobject& on, const string& name, bool val,
00476 PropertyAccessControl* ac) {
00477 string s;
00478 if(val)
00479 s = "yes";
00480 else
00481 s = "no";
00482 setProperty(on, name, s, "text/x-yes-no", ac);
00483 }
00484
00485 void Property::setFloatVectorProperty(Vobject& on, const string& name, vector<double> v, PropertyAccessControl* ac) {
00486 string s = "";
00487 char c[256];
00488 for(vector<double>::const_iterator i = v.begin(); i != v.end(); i++) {
00489 snprintf(c, sizeof(c), "%.15g", *i);
00490 s += c;
00491 if(i != v.end())
00492 s += " ";
00493 }
00494 setProperty(on, name, s, "text/x-vector/float", ac);
00495 }
00496
00497
00498 vector<double> Property::getFloatVectorProperty(Vobject& on, const string& name) {
00499 string::size_type start, end;
00500 start = end = 0;
00501 string s = getProperty(on, name);
00502 vector<double> v;
00503 const char* SEP = " \t,";
00504 while( ( start = s.find_first_not_of(SEP, start) ) != s.npos) {
00505 end = s.find_first_of(SEP, start);
00506 v.push_back( strtod( s.substr(start, end - start).c_str(), NULL ) );
00507 start = end + 1;
00508 }
00509 return v;
00510 }
00511
00512 void Property::readFromFile(const string& filename, const string& type) {
00513 ifstream f(filename.c_str(), ios::in|ios::binary);
00514 if(!f.is_open() || f.bad())
00515 throw runtime_error(string("Error opening file \"") + filename + "\" for reading.");
00516 f.seekg(0, ios::end);
00517 unsigned long size = f.tellg();
00518 f.seekg(0, ios::beg);
00519 char* buffer = new char[size+1];
00520 f.read(buffer, size);
00521 f.close();
00522 string val(buffer, size);
00523 if(type == "")
00524 replace(val, getDataType());
00525 else
00526 replace(val, type);
00527 free(buffer);
00528 }
00529
00530 void Property::writeStringToFile(const string& s, const string& filename) {
00531 ofstream f(filename.c_str(), ios::out|ios::binary);
00532 if(!f.is_open() || f.bad())
00533 throw runtime_error(string("Error opening file \"") + filename + "\" for writing.");
00534 f.write(s.c_str(), s.length());
00535 if(f.bad())
00536 throw runtime_error(string("Error writing to file \"")+filename+"\"");
00537 }
00538
00539
00540 void Property::writeToFile(const string& filename, int offset, int length)
00541 {
00542 string s;
00543 read(s, offset, length);
00544 writeStringToFile(s, filename);
00545 }
00546
00547 void Property::writeRawToFile(const string& filename, int offset, int length)
00548 {
00549 string s;
00550 readRaw(s, offset, length);
00551 writeStringToFile(s, filename);
00552 }
00553
00554
00555 void DoNothingPropertySecurityInitializer::initializePropertyAccessControl(LocalProperty* p, Vobject& requester)
00556 {
00557 p->insertPropertyAccessControl(-1, &NoPropertyAccessControl::static_);
00558 }
00559
00560 void Property::addPropertyListener(PropertyListener* pl, bool refresh)
00561 {
00562 propertyListeners[pl] = pl;
00563 if(RefCounted* rc = dynamic_cast<RefCounted*>(pl)) {
00564 rc->acquire();
00565 rc->addExciseListener(this);
00566 }
00567 }
00568
00569 void Property::removePropertyListener(PropertyListener* pl)
00570 {
00571 if(propertyListeners.count(pl)) {
00572 propertyListeners.erase(pl);
00573 if(RefCounted* rc = dynamic_cast<RefCounted*>(pl)) {
00574 rc->removeExciseListener(this);
00575 rc->release();
00576 }
00577 }
00578 }
00579
00580 void Property::notifyObjectExcise(RefCounted* object)
00581 {
00582 if(Site* st = dynamic_cast<Site*>(object)) {
00583 PropertyListenerSiteWrapper plsw(st);
00584 PropertyListenerMap::iterator i = propertyListeners.find(&plsw);
00585 if(i != propertyListeners.end()) {
00586 removePropertyListener((*i).second);
00587
00588 LOG("Property", 5, "going to delete plsw at " << (*i).second);
00589 PropertyListener* pl = (*i).second;
00590 delete pl;
00591 }
00592 }
00593 if(PropertyListener* pl = dynamic_cast<PropertyListener*>(object)) {
00594 removePropertyListener(pl);
00595 }
00596 }
00597
00598 void Property::doExcise()
00599 {
00600 LOG("refcount", 3, "Begun excising property for " << getURL().getString() << " count is " << getCount());
00601 MetaObject::doExcise();
00602
00603 for(PropertyListenerMap::iterator i = propertyListeners.begin();
00604 i != propertyListeners.end(); i++)
00605 {
00606 if(RefCounted* rc = dynamic_cast<RefCounted*>((*i).second)) {
00607 rc->removeExciseListener(this);
00608 rc->release();
00609 }
00610 if(PropertyListenerSiteWrapper* plsw = dynamic_cast<PropertyListenerSiteWrapper*>((*i).second)) {
00611 delete plsw;
00612 }
00613 }
00614 propertyListeners.clear();
00615 LOG("refcount", 3, "Done excising property for " << getURL().getString());
00616 LOG("refcount", 3, "Count on this is " << getCount());
00617 }
00618
00619 void Property::doSaveState(MessageBlock& output, set<string>& types, bool portable)
00620 {
00621 vRef<Message> m = new Message();
00622 m->setMethod("property:replace");
00623 m->insertField(-1, "data", readRaw(), true);
00624 m->insertField(-1, "datatype", getDataType(), true);
00625 output.insertMessage(-1, &m);
00626 }
00627
00628 PropertyListener::~PropertyListener()
00629 {
00630 }
00631
00632 PropertyListenerSiteWrapper::PropertyListenerSiteWrapper(Site* s)
00633 : site(s)
00634 {
00635 site->acquire();
00636 }
00637
00638 PropertyListenerSiteWrapper::PropertyListenerSiteWrapper(Site* s, const string& fn)
00639 : firstnonce(fn), site(s)
00640 {
00641 site->acquire();
00642 }
00643
00644 PropertyListenerSiteWrapper::~PropertyListenerSiteWrapper()
00645 {
00646 LOG("plsw", 5, "deleting plsw " << site << " which wraps " << site->getURL().getString());
00647 site->release();
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 void PropertyListenerSiteWrapper::notifyPropertyChange(const PropertyEvent& event)
00668 {
00669 vRef<Message> m = new Message();
00670 m->setType("update");
00671 m->setFrom(event.getProperty()->getURL().getString());
00672 m->setTo(site->getURL().getString());
00673 m->setMethod("property:replace-update");
00674 if(firstnonce.size() > 0) {
00675 m->setNonce(firstnonce);
00676 firstnonce="";
00677 }
00678 m->insertField(-1, "data", event.getNewValue());
00679 m->insertField(-1, "datatype", event.getNewDataType());
00680 site->sendMessage(&m);
00681 }
00682
00683
00684