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

vos/metaobjects/property/property.hh

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001, 2002 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <tetron@interreality.org>
00022     Additions by Reed Hedges <reed@zerohour.net> marked with initials "rh" and date.
00023 */
00024 #ifndef _PROPERTY_HH_
00025 #define _PROPERTY_HH_
00026 
00027 #include <typeinfo>
00028 #include <set>
00029 #include <assert.h>
00030 
00031 #include <vos/corelibs/vos/vos.hh>
00032 #include <typechain/typechain.hh>
00033 
00034 
00035 #if defined(_WIN32) && defined(_MSC_VER)
00036 # ifdef PROPERTY_EXPORTS
00037 #  define PROPERTY_API __declspec(dllexport)
00038 # else
00039 #  define PROPERTY_API __declspec(dllimport)
00040 # endif
00041 #else
00042 # define PROPERTY_API
00043 #endif
00044 
00045 #include "propertylistener.hh"
00046 
00047 class PropertyAccessControl;
00048 
00049 /** @class Property property.hh vos/metaobjects/property/property.hh
00050  *
00051  *  Property stores data of any type and size.  The Property classes
00052  *  store this data in two forms: decoded and raw. The raw data is the
00053  *  data as it exists within the %VOS system. This data may be decoded
00054  *  according to its datatype before being read out of this class
00055  *  (then cached). The read(), getLength(), and getDataType() methods
00056  *  are for the decoded data and final (usually, MIME) type. The
00057  *  readRaw(), getRawLength() and getRawDataType() methods are for the
00058  *  raw data. Data is decoded using the TypeChain class. 
00059  */
00060 class PROPERTY_API Property : public virtual MetaObject, public ObjectExciseListener
00061 {
00062 protected:
00063 // these ought to be private... but converting the
00064 // code would be kinda annoying at this point
00065     string raw_data;
00066     string raw_datatype;
00067     int raw_length;
00068     string data;
00069     string datatype;
00070     int data_length;
00071     bool decoded;
00072 
00073     Property(MetaObject* superobject);
00074 
00075     Property(MetaObject* superobject, const string& d, const string& dt);
00076 
00077     typedef map<PropertyListener*, PropertyListener*, PropertyListenerSiteWrapper::Cmp> PropertyListenerMap;
00078 
00079     PropertyListenerMap propertyListeners;
00080 
00081     /** write contents of s to a file named filename. */
00082     static void writeStringToFile(const string& s, const string& filename);
00083 
00084     /** Decodes data if need be */
00085     virtual void checkDecoded() ;
00086 
00087 public:
00088 
00089     /** @name Read and write property data */
00090     // @{
00091 
00092     /** Get length (bytes) of decoded data. */
00093     virtual int getLength() ;
00094 
00095     /** Read decoded data into target, possibly performing decode if necesary
00096      * @see read(string, int, int)
00097      */
00098     virtual void read(string& target) ;
00099 
00100     /** Read a substring of decoded data into target, possibly performing decode if necesary
00101      * @param target    Place data in this string
00102      * @param start     Byte offset to start reading
00103      * @param length    Number of bytes to read. If this parameter is -1, read
00104      *                  until the end of the data.
00105      */
00106     virtual void read(string& target, int start, int length) ;
00107 
00108     /** Return decoded data, possibly performing decode if necesary
00109      * @see read(string, int int)
00110      */
00111     virtual string read();
00112 
00113     /** Return substring of decoded data, possibly performing decode if necesary        @see read(string, int int)
00114      */
00115     virtual string read(int start, int length) ;
00116 
00117     /** Get length (bytes) of undecoded, raw data. */
00118     virtual int getRawLength();
00119 
00120     /** Read raw, undecoded data into target. */
00121     virtual void readRaw(string& target);
00122 
00123     /** Read substring of raw data into target.
00124         This is the fundamental method which the other
00125         read() methods are based on, so you only have to override this.
00126         @param target   The data is copied into this string.
00127         @param start    Offset (bytes) from which to start reading.
00128         @param length   Number of bytes to read. If this is -1, read until the end of the data.
00129      */
00130     virtual void readRaw(string& target, int start, int length);
00131 
00132     /** Return raw, undecoded data */
00133     virtual string readRaw();
00134 
00135     /** Return substring of raw, undecoded data */
00136     virtual string readRaw(int start, int length);
00137 
00138     /** Download property and call notifyPropertyReplaced when done. */
00139     virtual void asyncRead();
00140 
00141     /** Download property and call notifyPropertyWrite when done. */
00142     virtual void asyncRead(int start, int length);
00143 
00144     /** Write newdata into property value, starting at byte position start */
00145     virtual void write(int start, const string& newdata);
00146 
00147     /** Completely change the value and type of data stored in this property.
00148         @param newdata New data.
00149         @param newtype The type of the new datatype. If no type identifier was supplied, the previous one is kept.  NOTE: the initial datatype (set by the constructor) is "?" which is (or should be) an invalid value for any application.
00150     */
00151     virtual void replace(const string& newdata, const string& newtype = "?");
00152 
00153     /** Return type of decoded data (usually a MIME type) */
00154     virtual const string getDataType() ;
00155 
00156     /** Return type of raw, undeocded data (a typechain string) */
00157     virtual const string getRawDataType();
00158 
00159     //@}
00160 
00161 
00162 
00163     /** @name Utility functions. Use these static methods to help get and
00164         set subproperties of objects. */
00165     // @{
00166 
00167     /** Set a subproperty, creating it if necesary named 'propname' of 'on', to 'propval'
00168      *  @param on   Object to set a subproperty on
00169      *  @param propname Name of the property to set
00170      *  @param propval  New value of the property
00171      *  @param proptype New type for property
00172      *  @param pac  Property access control to add to the object it it had to be created (If property exists, this argument is ignored)
00173      */
00174     static void Property::setProperty(Vobject& on,
00175                                       const string& propname,
00176                                       const string& propval,
00177                                       const string& valtype,
00178                                       PropertyAccessControl* pac)
00179         throw (AccessControlError, TypeChain::DecodeError, RemoteError);
00180 
00181     /** Set a subproperty on an object, returning relation between object and property.
00182      *  @param on   Object to set a subproperty on
00183      *  @param propname Name of the property to set
00184      *  @param propval  New value of the property
00185      *  @param proptype New type for property
00186      *  @param pac  Property access control to add to the object it it had to be created (If property exists, this argument is ignored)
00187      *  @return object expressing relation between the object and the property
00188      */
00189     static Vobject::ParentChildRelation& Property::setPropertyWithReturn(Vobject& on,
00190                                                                          const string& propname,
00191                                                                          const string& propval,
00192                                                                          const string& valtype,
00193                                                                          PropertyAccessControl* pac,
00194                                                                          bool letErrorThrough = false)
00195         throw (AccessControlError, TypeChain::DecodeError, RemoteError);
00196 
00197     /** Set a subproperty, creating it if necesary named 'propname' of 'on', to 'propval'
00198      *  @param on   Object to set a subproperty on
00199      *  @param propname Name of the property to set
00200      *  @param propval  New value of the property
00201      *  @param pac  Property access control to add to the object it it had to be created (If property exists, this argument is ignored)
00202      */
00203     static void Property::setProperty(Vobject& on,
00204                                       const string& propname,
00205                                       double propval,
00206                                       PropertyAccessControl* pac)
00207         throw (AccessControlError, TypeChain::DecodeError, RemoteError);
00208 
00209     /** Set a subproperty on an object, returning relation between object and property.
00210      *  @param on   Object to set a subproperty on
00211      *  @param propname Name of the property to set
00212      *  @param propval  New value of the property
00213      *  @param pac  Property access control to add to the object it it had to be created (If property exists, this argument is ignored)
00214      *  @return object expressing relation between the object and the property
00215      *
00216      *  @todo move these into a specialized class from which MetaObjecs 
00217      *  using properties can inherit.
00218      */
00219     static Vobject::ParentChildRelation& Property::setPropertyWithReturn(
00220         Vobject& on, const string& propname, double propval,
00221         PropertyAccessControl* pac)
00222             throw (AccessControlError, TypeChain::DecodeError, RemoteError);
00223 
00224     static string getProperty(Vobject& on, const string& name);
00225 
00226     static string getProperty(Vobject& on, const string& name, const string& defaultVal);
00227 
00228 
00229     static int getIntProperty(Vobject& on, const string& name);
00230 
00231     static int getIntProperty(Vobject& on, const string& name, int defaultVal);
00232 
00233     static int getIntProperty(Vobject& on, const string& name, int lowerLimit,
00234         int upperLimit);
00235 
00236     static int getIntProperty(Vobject& on, const string& name, int defaultVal,
00237         int lowerLimit, int upperLimit);
00238 
00239     static void setIntProperty(Vobject& on, const string& name, int val,
00240         PropertyAccessControl* ac);
00241 
00242     static void setIntProperty(Vobject& on, const string& name, int val,
00243         int lowerLimit, int upperLimit, PropertyAccessControl* ac);
00244 
00245 
00246 
00247     static double Property::getFloatProperty(Vobject& on, const string& name,
00248         double lowLim, double upLim) ;
00249 
00250     static double Property::getFloatProperty(Vobject& on, const string& name,
00251         double defaultVal, double lowerLimit, double upperLimit) ;
00252 
00253     static double Property::getFloatProperty(Vobject& on, const string& name,
00254         double defaultVal) ;
00255 
00256     static double Property::getFloatProperty(Vobject& on, const string& name) ;
00257 
00258     static void setFloatProperty(Vobject& on, const string& name, double val,
00259         double lowerLimit, double upperLimit, PropertyAccessControl* ac);
00260 
00261     static void setFloatProperty(Vobject& on, const string& name, double val,
00262         PropertyAccessControl* ac);
00263 
00264 
00265 
00266     static void setBoolProperty(Vobject& on, const string& name, bool val,
00267         PropertyAccessControl* ac);
00268 
00269     static bool Property::getBoolProperty(Vobject& on, const string& name);
00270 
00271     static bool Property::getBoolProperty(Vobject& on, const string& name,
00272         bool defaultVal);
00273 
00274 
00275 
00276     static void setFloatVectorProperty(Vobject& on, const string& name, vector<double> v, PropertyAccessControl* ac);
00277 
00278     /** Parse contents of property named 'name' into a vector of doubles */
00279     static vector<double> getFloatVectorProperty(Vobject& on, const string& name);
00280 
00281     //@}
00282 
00283     /** Add a new property listener to this property. This listener's methods
00284      * will be called when the property is modified.
00285      * @see PropertyListener
00286      * @param pl    The new property listener. If it is also a RefCounted
00287      * object, references will be acquired correctly.
00288      */
00289     virtual void addPropertyListener(PropertyListener* pl, bool refresh = true);
00290 
00291     /** Remove the property listener 'pl' from this property.
00292      * @param pl    Listener to remove. If it is also a RefCounted object,
00293      * references will be released correctly.
00294      */
00295     virtual void removePropertyListener(PropertyListener* pl);
00296 
00297      /**
00298      * @deprecated use writeToFile
00299      */
00300     static void Property::writeToFile(Property* p, const string& filename, int offset=0, int length=-1) {
00301         p->writeToFile(filename, offset, length);
00302     }
00303 
00304     /** Write decoded property value of p to a file named filename. if offset and length are supplied, write substring.
00305      * @throw runtime_error if there is an error opening or writing to the file.
00306      */
00307     void Property::writeToFile(const string& filename, int offset = 0, int length = -1);
00308 
00309     /**
00310      *  @deprecated use writeRawToFile.
00311      */
00312     static void Property::writeRawToFile(Property* p, const string& filename, int offset=0, int length=-1) {
00313         p->writeRawToFile(filename, offset, length);
00314     }
00315 
00316     /** Write raw, undecoded property data to file
00317      * @throw runtime_error on error opening or writing to file
00318      * @return return code from fwrite(). */
00319     void Property::writeRawToFile(const string& filename, int offset = 0, int length = 1);
00320 
00321     /** Read data from file into this property.
00322      * @param filename  Name of file to read from.
00323      * @param type      New datatype for this property. If empty ("") or
00324      *                  omitted, then the existing datatype will be used.
00325      * @throw runtime_error On error opening or reading from file.
00326      */
00327     void Property::readFromFile(const string& filename, const string& type = "");
00328 
00329     /** Register property type with factory */
00330     static void registerExtenders();
00331 
00332     /** Return MetaObject type, "property" */
00333     virtual const string getType();
00334 
00335     virtual void notifyObjectExcise(RefCounted* object);
00336     virtual void doExcise();
00337     virtual void doSaveState(MessageBlock& output, set<string>& types, bool portable);
00338 };
00339 
00340 class LocalProperty;
00341 
00342 typedef PropertyAccessControl* (*PropertyAccessControlFactory)(const string& type, LocalProperty* lv);
00343 
00344 /** @class PropertyAccessControl property.hh vos/metaobjects/property/property.hh
00345  *  Use subclasses of PropertyAccessControl to implement various access control
00346  *  policies on property reads and writes.
00347  */
00348 class PROPERTY_API PropertyAccessControl
00349 {
00350 private:
00351     struct AssignAC
00352     {
00353         PropertyAccessControl* ac;
00354         PropertyAccessControlFactory fac;
00355     };
00356     static map<string, AssignAC> policies;
00357 
00358 public:
00359     /** AccessControl callback to check if a given Vobject is
00360         permitted to read a section of this property.
00361         @param event the requested read
00362     */
00363     virtual bool checkReadPermission(PropertyEvent& event, string& message) = 0;
00364 
00365     /** AccessControl callback to check if a given Vobject is
00366         permitted to change this property.
00367         @param event the requested change
00368     */
00369     virtual bool checkChangePermission(PropertyEvent& event, string& message) = 0;
00370 
00371     /** Get a short string describing this policy. */
00372     virtual const string getPolicyName() = 0;
00373 
00374     /** Add a new access control policy.  This policy will be
00375         available as whatever name is returned by ac->getPolicyName().
00376         @param ac The policy object.
00377     */
00378     static void addPolicy(PropertyAccessControl* ac);
00379 
00380     /** Add a new access control policy.  The difference between this
00381         and the other addPolicy method is that a policy factory
00382         creates a new policy object each time getPolicy() is called,
00383         whereas otherwise the same policy object will be returned each
00384         time.  This is useful if you want to write an access control
00385         policy bound to a specific object that keeps some state about that
00386         object.
00387         @param name The policy name.  This should be the same as the name
00388         returned by getPolicyName() for the factory-created objects.
00389         @param ac The policy factory.
00390     */
00391     static void addPolicyFactory(const string& name, PropertyAccessControlFactory ac);
00392 
00393     /** Get the requested policy given the name and LocalVobject.
00394         @param name The policy name, registered at some point using addPolicy()
00395         @param lv The LocalProperty this policy will be added to
00396         (doesn't actually add it, but a policy factory may want to
00397         know what object it is being added to)
00398         @return the policy object, or NULL if there is no registered policy with that name
00399     */
00400     static PropertyAccessControl* getPolicy(const string& name, LocalProperty* lv);
00401 
00402     /** Remove policy with the given name.
00403         @param name policy name
00404     */
00405     static void removePolicy(const string& name);
00406 };
00407 
00408 /** @class NoPropertyAccessControl property.hh vos/metaobjects/property/property.hh
00409  * Access control policy for properties that always says yes. */
00410 class PROPERTY_API NoPropertyAccessControl : public PropertyAccessControl
00411 {
00412 public:
00413     static NoPropertyAccessControl static_;
00414 
00415     virtual const string getPolicyName()
00416         { return "insecure"; }
00417 
00418     virtual bool checkReadPermission(PropertyEvent& event, string& message)
00419         { return true; };
00420     virtual bool checkChangePermission(PropertyEvent& event, string& message)
00421         { return true; };
00422 };
00423 
00424 /** @class ReadOnlyPropertyAccessControl property.hh vos/metaobjects/property/property.hh
00425  * Access control policy for properties permits unlimited reads but denies 
00426  * allwrites and replaces. */
00427 class PROPERTY_API ReadOnlyPropertyAccessControl : public PropertyAccessControl
00428 {
00429 public:
00430     static ReadOnlyPropertyAccessControl static_;
00431 
00432     virtual const string getPolicyName()
00433         { return "readonly"; }
00434 
00435     virtual bool checkReadPermission(PropertyEvent& event, string& message)
00436         { return true; };
00437     virtual bool checkChangePermission(PropertyEvent& event, string& message)
00438         { message = "This property is read-only."; return false; };
00439 };
00440 
00441 class LocalProperty;
00442 
00443 class PROPERTY_API PropertySecurityInitializer
00444 {
00445 public:
00446     virtual void initializePropertyAccessControl(LocalProperty* p, Vobject& requester) = 0;
00447 };
00448 
00449 class PROPERTY_API DoNothingPropertySecurityInitializer : public PropertySecurityInitializer
00450 {
00451 public:
00452     static DoNothingPropertySecurityInitializer static_;
00453     virtual void initializePropertyAccessControl(LocalProperty* p, Vobject& requester);
00454 };
00455 
00456 
00457 /** @class LocalProperty property.hh vos/metaobjects/property/property.hh
00458  * Local version of property */
00459 class PROPERTY_API LocalProperty : public virtual Property
00460 {
00461 protected:
00462     deque<PropertyAccessControl*> accesscontrols;
00463     static PropertySecurityInitializer* securitycallback;
00464 
00465     void getLengthHandler(Message* m);
00466     void readHandler(Message* m);
00467     void writeHandler(Message* m);
00468     void replaceHandler(Message* m);
00469     void startListeningHandler(Message* m);
00470     void stopListeningHandler(Message* m);
00471 public:
00472     LocalProperty(MetaObject* superobject);
00473     LocalProperty(MetaObject* superobject, const string& d, const string& dt = "?");
00474     virtual ~LocalProperty();
00475     static MetaObject* new_LocalProperty(MetaObject* superobject, const string& type);
00476     static void setSecurityCallback(PropertySecurityInitializer*);
00477     virtual void write(Vobject& initiator, int start, const string& newdata);
00478     virtual void write(int start, const string& newdata);
00479     virtual void replace(Vobject& initiator, const string& newdata,
00480                          const string& newtype = "?");
00481     virtual void replace(const string& newdata, const string& newtype = "?");
00482     virtual void addPropertyListener(PropertyListener* pl, bool refresh = true);
00483     /** Insert a new policy into the access policy list.  The access
00484         policy list is traversed from beginning to end, calling each
00485         access control policy in order until either a policy returns
00486         false (deny) or the end of the list is reached.  If access is
00487         denied, list traversal immediately stops and the requested
00488         action is denied.  If the end of the list is reached without a
00489         denial, the requested action is permitted.
00490 
00491         @param pos The position to be inserted into.  As with most
00492         other parts of %VOS, a positive value counts from the beginning
00493         and a negative value counts from the end.  In particular, a
00494         position of 0 will insert at the head of the list, making it
00495         the the first policy to be consulted.  A position of -1 will
00496         insert at the end of the list, making it the last policy to be
00497         consulted.
00498 
00499         @param ac the access control policy
00500     */
00501     virtual void insertPropertyAccessControl(int pos, PropertyAccessControl* ac);
00502 
00503     /** Add a named policy.
00504         @see VobjectAccessControl::getPolicy
00505         @see VobjectAccessControl::addPolicy
00506     */
00507     virtual void insertPropertyAccessControl(int pos, const string& policyname);
00508 
00509     /** Remove the access policy at the specified position.
00510         @param pos the position of the policy in the policy list
00511         @see insertAccessControl */
00512     virtual void removePropertyAccessControl(int pos);
00513 
00514     /** Remove all instances of the specified access policy from the
00515         policy list.
00516         @param m the access control policy to remove
00517         @see insertAccessControl */
00518     virtual void removePropertyAccessControl(PropertyAccessControl* m);
00519 
00520     /** Remove all policies matching this name.
00521         @see VobjectAccessControl::addPolicy
00522         @see VobjectAccessControl::getPolicy
00523     */
00524     virtual void removePropertyAccessControl(const string& policyname);
00525 
00526     /** @return the current access control policy list.
00527         @see insertAccessControl */
00528     virtual const deque<PropertyAccessControl*>& getPropertyAccessControls();
00529 
00530     /** Traverse the access policy list and determine whether to allow
00531         this event
00532         @param e the event to permit
00533         @return true if the event is permitted, false to deny this event
00534      */
00535     virtual bool validatePropertyAccess(PropertyEvent& e, string& message);
00536 
00537     virtual void initializeSecurity(Vobject& requester);
00538     virtual const string getSource() { return data; }
00539 
00540     /** Set a default access control policy. */
00541     virtual void initialize() {
00542         insertPropertyAccessControl(-1, &NoPropertyAccessControl::static_);
00543     }
00544 };
00545 
00546 
00547 /** @class RemoteProperty property.hh vos/metaobjects/property/property.hh
00548 * Remote version of property; sends messages over network to Local object. */
00549 class PROPERTY_API RemoteProperty : public virtual Property
00550 {
00551 private:
00552     void lengthUpdateHandler(Message* m);
00553     void writeUpdateHandler(Message* m);
00554     void replaceUpdateHandler(Message* m);
00555     void startListeningReplyHandler(Message* m);
00556 
00557 protected:
00558     int offset;
00559     virtual void checkDecoded() ;
00560     bool first_read;                // indicates that no read message has been sent yet
00561 
00562 public:
00563     RemoteProperty(MetaObject* superobject);
00564     static MetaObject* new_RemoteProperty(MetaObject* superobject, const string& type);
00565     virtual void read(string& target, int start, int length) ;
00566     virtual void readRaw(string& target, int start, int length);
00567     virtual void asyncRead();
00568     virtual void asyncRead(int start, int length);
00569     virtual int getLength() ;
00570     virtual int getRawLength();
00571     virtual const string getRawDataType();
00572     virtual void write(int start, const string& newdata);
00573     virtual void clearCache();
00574     virtual void replace(const string& newdata, const string& newtype = "?");
00575     virtual void addPropertyListener(PropertyListener* pl, bool refresh = true);
00576     virtual void removePropertyListener(PropertyListener* pl);
00577 };
00578 
00579 
00580 
00581 
00582 
00583 #endif

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