Orocos Real-Time Toolkit  2.5.0
PropertyLoader.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Sat May 7 12:56:52 CEST 2005  PropertyLoader.cxx
00003 
00004                         PropertyLoader.cxx -  description
00005                            -------------------
00006     begin                : Sat May 07 2005
00007     copyright            : (C) 2005 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 
00040 #include "PropertyLoader.hpp"
00041 #include "rtt-config.h"
00042 #ifdef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00043 #include ORODAT_CORELIB_PROPERTIES_MARSHALLING_INCLUDE
00044 #include ORODAT_CORELIB_PROPERTIES_DEMARSHALLING_INCLUDE
00045 #endif
00046 #include "../Logger.hpp"
00047 #include "../TaskContext.hpp"
00048 #include "PropertyBagIntrospector.hpp"
00049 #include "../types/PropertyComposition.hpp"
00050 #include <fstream>
00051 
00052 using namespace std;
00053 using namespace RTT;
00054 using namespace RTT::detail;
00055 
00056 bool PropertyLoader::load(const std::string& filename, TaskContext* target) const
00057 {
00058     Logger::In in("PropertyLoader:load");
00059 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00060         log(Error) << "No Property DemarshallInterface configured !" << endlog();
00061         return false;
00062 
00063 #else
00064     if ( target->provides()->properties() == 0) {
00065         log(Error) << "TaskContext " <<target->getName()<<" has no Properties to configure." << endlog();
00066         return false;
00067     }
00068 
00069     log(Info) << "Loading properties into TaskContext '" <<target->getName()
00070                   <<"' with '"<<filename<<"'."<< endlog();
00071     bool failure = false;
00072     OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER* demarshaller = 0;
00073     try
00074     {
00075         demarshaller = new OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER (filename);
00076     } catch (...) {
00077         log(Error) << "Could not open file "<< filename << endlog();
00078         return false;
00079     }
00080     try {
00081         PropertyBag propbag;
00082         vector<ActionInterface*> assignComs;
00083 
00084         if ( demarshaller->deserialize( propbag ) )
00085         {
00086             // compose propbag:
00087             PropertyBag composed_props;
00088             if ( composePropertyBag(propbag, composed_props) == false) {
00089                 delete demarshaller;
00090                 return false;
00091             }
00092             // take restore-copy;
00093             PropertyBag backup;
00094             copyProperties( backup, *target->provides()->properties() );
00095             // First test if the updateProperties will succeed:
00096             if ( refreshProperties(  *target->provides()->properties(), composed_props, false) ) { // not strict
00097                 // this just adds the new properties, *should* never fail, but
00098                 // let's record failure to be sure.
00099                 failure = !updateProperties( *target->provides()->properties(), composed_props );
00100             } else {
00101                 // restore backup in case of failure:
00102                 refreshProperties( *target->provides()->properties(), backup, false ); // not strict
00103                 failure = true;
00104             }
00105             // cleanup
00106             deletePropertyBag( backup );
00107         }
00108         else
00109             {
00110                 log(Error) << "Some error occured while parsing "<< filename.c_str() <<endlog();
00111                 failure = true;
00112             }
00113     } catch (...)
00114     {
00115         log(Error)
00116                       << "Uncaught exception in deserialise !"<< endlog();
00117         failure = true;
00118     }
00119     delete demarshaller;
00120     return !failure;
00121 #endif // OROPKG_CORELIB_PROPERTIES_MARSHALLING
00122 
00123 }
00124 
00125 bool PropertyLoader::configure(const std::string& filename, TaskContext* target, bool all ) const
00126 {
00127     Logger::In in("PropertyLoader:configure");
00128 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00129         log(Error) << "No Property DemarshallInterface configured !" << endlog();
00130         return false;
00131 
00132 #else
00133     if ( target->provides()->properties() == 0) {
00134         log(Error) << "TaskContext " <<target->getName()<<" has no Properties to configure." << endlog();
00135         return false;
00136     }
00137 
00138     log(Info) << "Configuring TaskContext '" <<target->getName()
00139                   <<"' with '"<<filename<<"'."<< endlog();
00140     bool failure = false;
00141     OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER* demarshaller = 0;
00142     try
00143     {
00144         demarshaller = new OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER (filename);
00145     } catch (...) {
00146         log(Error) << "Could not open file "<< filename << endlog();
00147         return false;
00148     }
00149     try {
00150         PropertyBag propbag;
00151 
00152         if ( demarshaller->deserialize( propbag ) )
00153         {
00154             // compose propbag:
00155             PropertyBag composed_props;
00156             if ( composePropertyBag(propbag, composed_props) == false) {
00157                 delete demarshaller;
00158                 return false;
00159             }
00160             // take restore-copy;
00161             PropertyBag backup;
00162             copyProperties( backup, *target->provides()->properties() );
00163             if ( refreshProperties( *target->provides()->properties(), composed_props, all ) == false ) {
00164                 // restore backup:
00165                 refreshProperties( *target->provides()->properties(), backup );
00166                 failure = true;
00167                 }
00168             // cleanup
00169             deletePropertyBag( backup );
00170         }
00171         else
00172             {
00173                 log(Error) << "Some error occured while parsing "<< filename.c_str() <<endlog();
00174                 failure = true;
00175             }
00176         deletePropertyBag( propbag );
00177     } catch (...)
00178     {
00179         log(Error)
00180                       << "Uncaught exception in deserialise !"<< endlog();
00181         failure = true;
00182     }
00183     delete demarshaller;
00184     return !failure;
00185 #endif // OROPKG_CORELIB_PROPERTIES_MARSHALLING
00186 
00187 }
00188 
00189 bool PropertyLoader::store(const std::string& filename, TaskContext* target) const
00190 {
00191     Logger::In in("PropertyLoader::store");
00192 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00193     log(Error) << "No Property Marshaller configured !" << endlog();
00194     return false;
00195 #else
00196     std::ofstream file( filename.c_str() );
00197     if ( file )
00198     {
00199         // Write results
00200         PropertyBag* compProps = target->properties();
00201         PropertyBag allProps;
00202 
00203         // decompose repos into primitive property types.
00204         PropertyBagIntrospector pbi( allProps );
00205         pbi.introspect( *compProps );
00206 
00207         OROCLS_CORELIB_PROPERTIES_MARSHALLING_DRIVER<std::ostream> marshaller( file );
00208         marshaller.serialize( allProps );
00209         deletePropertyBag( allProps );
00210         log(Info) << "Wrote "<< filename <<endlog();
00211     }
00212     else {
00213         log(Error) << "Could not open file "<< filename <<" for writing."<<endlog();
00214         return false;
00215     }
00216     return true;
00217 #endif
00218 }
00219 
00220 bool PropertyLoader::save(const std::string& filename, TaskContext* target, bool all) const
00221 {
00222     Logger::In in("PropertyLoader::save");
00223 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00224         log(Error) << "No Property MarshallInterface configured !" << endlog();
00225         return false;
00226 
00227 #else
00228     if ( target->provides()->properties() == 0 ) {
00229         log(Error) << "TaskContext "<< target->getName()
00230                       << " does not have Properties to save." << endlog();
00231         return false;
00232     }
00233     PropertyBag allProps;
00234     PropertyBag  decompProps;
00235 
00236     // first check if the target file exists.
00237     std::ifstream ifile( filename.c_str() );
00238     // if target file does not exist, skip this step.
00239     if ( ifile ) {
00240         ifile.close();
00241         log(Info) << target->getName()<<" updating of file "<< filename << endlog();
00242         // The demarshaller itself will open the file.
00243         OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER demarshaller( filename );
00244         if ( demarshaller.deserialize( allProps ) == false ) {
00245             // Parse error, abort writing of this file.
00246             log(Error) << "While updating "<< target->getName() <<" : Failed to read "<< filename << endlog();
00247             return false;
00248         }
00249     }
00250     else {
00251         log(Info) << "Creating "<< filename << endlog();
00252         return store(filename, target);
00253     }
00254 
00255     // Write results
00256     PropertyBag* compProps = target->properties();
00257 
00258     // decompose repos into primitive property types.
00259     PropertyBagIntrospector pbi( decompProps );
00260     pbi.introspect( *compProps );
00261 
00262     //Add target properties to existing properties
00263     bool updater = false;
00264     if (all) {
00265         log(Info) << "Writing all properties of "<<target->getName()<<" to file "<< filename << endlog();
00266         updater = updateProperties( allProps, decompProps ); // add new.
00267     }
00268     else {
00269         log(Info) << "Refreshing properties in file "<< filename << " with values of properties of "<<target->getName() << endlog();
00270         updater = refreshProperties( allProps, decompProps ); // only refresh existing.
00271     }
00272     if (updater == false) {
00273         log(Error) << "Could not update properties of file "<< filename <<"."<<endlog();
00274         deletePropertyBag( allProps );
00275         deletePropertyBag( decompProps );
00276         return false;
00277     }
00278     // ok, finish.
00279     // serialize and cleanup
00280     std::ofstream file( filename.c_str() );
00281     if ( file )
00282         {
00283             OROCLS_CORELIB_PROPERTIES_MARSHALLING_DRIVER<std::ostream> marshaller( file );
00284             marshaller.serialize( allProps );
00285             log(Info) << "Wrote "<< filename <<endlog();
00286         }
00287     else {
00288         log(Error) << "Could not open file "<< filename <<" for writing."<<endlog();
00289         deletePropertyBag( allProps );
00290         return false;
00291     }
00292     // allProps contains copies (clone()), thus may be safely deleted :
00293     deletePropertyBag( allProps );
00294     deletePropertyBag( decompProps );
00295     return true;
00296 #endif
00297 }
00298 
00299 bool PropertyLoader::configure(const std::string& filename, TaskContext* task, const std::string& name ) const
00300 {
00301     Logger::In in("PropertyLoader:configure");
00302 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00303     log(Error) << "No Property DemarshallInterface configured !" << endlog();
00304     return false;
00305 
00306 #else
00307     log(Info) << "Reading Property '" <<name
00308               <<"' from file '"<<filename<<"'."<< endlog();
00309     bool failure = false;
00310     OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER* demarshaller = 0;
00311     try
00312     {
00313         demarshaller = new OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER (filename);
00314     } catch (...) {
00315         log(Error) << "Could not open file "<< filename << endlog();
00316         return false;
00317     }
00318     try {
00319         PropertyBag propbag;
00320         if ( demarshaller->deserialize( propbag ) )
00321         {
00322             // compose propbag:
00323             PropertyBag composed_props;
00324             if ( composePropertyBag(propbag, composed_props) == false) {
00325                 deletePropertyBag( propbag );
00326                 delete demarshaller;
00327                 return false;
00328             }
00329             failure = !refreshProperty( *(task->provides()->properties()), composed_props, name );
00330         }
00331         else
00332             {
00333                 log(Error) << "Some error occured while parsing "<< filename.c_str() <<endlog();
00334                 failure = true;
00335             }
00336         deletePropertyBag( propbag );
00337     } catch (...)
00338     {
00339         log(Error) << "Uncaught exception in deserialise !"<< endlog();
00340         failure = true;
00341     }
00342     delete demarshaller;
00343     return !failure;
00344 #endif // OROPKG_CORELIB_PROPERTIES_MARSHALLING
00345 }
00346 
00347 bool PropertyLoader::save(const std::string& filename, TaskContext* task, const std::string& name) const
00348 {
00349     Logger::In in("PropertyLoader::save");
00350 #ifndef OROPKG_CORELIB_PROPERTIES_MARSHALLING
00351         log(Error) << "No Property MarshallInterface configured !" << endlog();
00352         return false;
00353 
00354 #else
00355     PropertyBag fileProps;
00356     // Update exising file ?
00357     {
00358         // first check if the target file exists.
00359         std::ifstream ifile( filename.c_str() );
00360         // if target file does not exist, skip this step.
00361         if ( ifile ) {
00362             ifile.close();
00363             log(Info) << "Updating file "<< filename << " with properties of "<<task->getName()<<endlog();
00364             // The demarshaller itself will open the file.
00365             OROCLS_CORELIB_PROPERTIES_DEMARSHALLING_DRIVER demarshaller( filename );
00366             if ( demarshaller.deserialize( fileProps ) == false ) {
00367                 // Parse error, abort writing of this file.
00368                 log(Error) << "Failed to read "<< filename << endlog();
00369                 return false;
00370             }
00371         }
00372         else
00373             log(Info) << "Creating "<< filename << endlog();
00374     }
00375 
00376     // decompose task properties into primitive property types.
00377     PropertyBag  taskProps;
00378     PropertyBagIntrospector pbi( taskProps );
00379     pbi.introspect( *(task->provides()->properties()) );
00380 
00381     bool failure;
00382     failure = ! updateProperty( fileProps, taskProps, name );
00383 
00384     deletePropertyBag( taskProps );
00385 
00386     if ( failure ) {
00387         log(Error) << "Could not update properties of file "<< filename <<"."<<endlog();
00388         deletePropertyBag( fileProps );
00389         return false;
00390     }
00391     // serialize and cleanup
00392     std::ofstream file( filename.c_str() );
00393     if ( file )
00394         {
00395             OROCLS_CORELIB_PROPERTIES_MARSHALLING_DRIVER<std::ostream> marshaller( file );
00396             marshaller.serialize( fileProps );
00397             log(Info) << "Wrote Property "<<name <<" to "<< filename <<endlog();
00398         }
00399     else {
00400         log(Error) << "Could not open file "<< filename <<" for writing."<<endlog();
00401         deletePropertyBag( fileProps );
00402         return false;
00403     }
00404     // fileProps contains copies (clone()), thus may be safely deleted :
00405     deletePropertyBag( fileProps );
00406     return true;
00407 #endif
00408 }
00409