OW_provinstOpenWBEM_ConfigSettingData.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Novell, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Novell, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 ****************************************************************************/
00030 
00035 #include "OW_config.h"
00036 #include "OW_CppInstanceProviderIFC.hpp"
00037 #include "OW_CppSimpleAssociatorProviderIFC.hpp"
00038 #include "OW_CIMClass.hpp"
00039 #include "OW_CIMInstance.hpp"
00040 #include "OW_CIMException.hpp"
00041 #include "OW_CIMValue.hpp"
00042 #include "OW_CIMProperty.hpp"
00043 #include "OW_CIMObjectPath.hpp"
00044 #include "OW_ConfigOpts.hpp"
00045 #include "OW_ConfigFile.hpp"
00046 #include "OW_ConfigException.hpp"
00047 #include "OW_Format.hpp"
00048 #include "OW_TempFileStream.hpp"
00049 #include "OW_FileSystem.hpp"
00050 #include <fstream>
00051 #include <sys/types.h>
00052 #include <sys/stat.h>
00053 #include <unistd.h>
00054 
00055 
00056 namespace OW_NAMESPACE
00057 {
00058 
00059 class OpenWBEM_ConfigSettingDataInstProv : public virtual CppInstanceProviderIFC
00060 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00061    , public virtual CppSimpleAssociatorProviderIFC
00062 #endif // #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00063 {
00064 public:
00065 
00066    void initialize(const ProviderEnvironmentIFCRef& env)
00067    {
00068       loadConfigMap(env); 
00069    }
00070 
00072    virtual ~OpenWBEM_ConfigSettingDataInstProv()
00073    {
00074    }
00075 
00077    virtual void enumInstanceNames(
00078       const ProviderEnvironmentIFCRef& env,
00079       const String& ns,
00080       const String& className,
00081       CIMObjectPathResultHandlerIFC& result,
00082       const CIMClass& cimClass )
00083    {
00084       (void)cimClass;
00085       env->getLogger()->logDebug("In OpenWBEM_ConfigSettingDataInstProv::enumInstanceNames");
00086 
00087       if (mapNeedsLoad(getConfigFile(env)))
00088       {
00089          loadConfigMap(env); 
00090       }
00091 
00092       CIMObjectPath newCop(className, ns);
00093 
00094 
00095       for (ConfigItemsMap::const_iterator iter = m_configItems.begin(); 
00096            iter != m_configItems.end(); ++iter)
00097       {
00098          String id = makeID(iter->first); 
00099          newCop.setKeyValue("InstanceID", CIMValue(id)); 
00100          result.handle(newCop);
00101       }
00102 
00103    }
00104 
00105 
00107    virtual CIMInstance getInstance(
00108       const ProviderEnvironmentIFCRef& env,
00109       const String& ns,
00110       const CIMObjectPath& instanceName,
00111       WBEMFlags::ELocalOnlyFlag localOnly,
00112       WBEMFlags::EIncludeQualifiersFlag includeQualifiers,
00113       WBEMFlags::EIncludeClassOriginFlag includeClassOrigin,
00114       const StringArray* propertyList,
00115       const CIMClass& cimClass )
00116    {
00117       (void)ns;
00118       env->getLogger()->logDebug("In OpenWBEM_ConfigSettingDataInstProv::getInstance");
00119 
00120       if (mapNeedsLoad(getConfigFile(env)))
00121       {
00122          loadConfigMap(env); 
00123       }
00124 
00125       CIMInstance newInst = cimClass.newInstance();
00126       newInst.updatePropertyValues(instanceName.getKeys());
00127 
00128       String id; 
00129       CIMValue cv = instanceName.getKeyValue("InstanceID"); 
00130       if (!cv || cv.getType() != CIMDataType::STRING || cv.isArray())
00131       {
00132          OW_THROWCIM(CIMException::INVALID_PARAMETER); 
00133       }
00134       cv.get(id); 
00135 
00136       StringArray sa = id.tokenize(":"); 
00137       if (sa.size() != 3)
00138       {
00139          OW_THROWCIM(CIMException::INVALID_PARAMETER); 
00140       }
00141 
00142       String& configName = sa[2]; 
00143 
00144       ConfigItemsMap::const_iterator iter = m_configItems.find(configName); 
00145       if (iter == m_configItems.end())
00146       {
00147          OW_THROWCIM(CIMException::NOT_FOUND); 
00148       }
00149 
00150       const ConfigData& cd = iter->second; 
00151 
00152       newInst.setProperty("Value", CIMValue(cd.Value)); 
00153       newInst.setProperty("CurrentEffectiveValue", CIMValue(cd.CurrentEffectiveValue));
00154       // This property is Required
00155       newInst.setProperty("ElementName", CIMValue(configName)); 
00156       newInst.setProperty("Caption", CIMValue(cd.Caption)); 
00157       newInst.setProperty("Description", CIMValue(cd.Description)); 
00158 
00159       return newInst.clone(localOnly,includeQualifiers,includeClassOrigin,propertyList);
00160    }
00161 
00163    virtual CIMObjectPath createInstance(
00164       const ProviderEnvironmentIFCRef& env,
00165       const String& ns,
00166       const CIMInstance& cimInstance )
00167    {
00168       (void)env;
00169       (void)ns;
00170       (void)cimInstance;
00171         OW_THROWCIMMSG(CIMException::FAILED, "Provider does not support createInstance");
00172    }
00173 
00175    virtual void modifyInstance(
00176       const ProviderEnvironmentIFCRef& env,
00177       const String& ns,
00178       const CIMInstance& modifiedInstance,
00179       const CIMInstance& previousInstance,
00180       WBEMFlags::EIncludeQualifiersFlag includeQualifiers,
00181       const StringArray* propertyList,
00182       const CIMClass& theClass)
00183    {
00184       (void)ns;
00185       (void)includeQualifiers;
00186       (void)theClass;
00187       env->getLogger()->logDebug("In OpenWBEM_ConfigSettingDataInstProv::modifyInstance");
00188 
00189       if (propertyList)
00190       {
00191          if (propertyList->size() == 0)
00192          {
00193             return; 
00194          }
00195          if (propertyList->size() > 1 
00196             || !(*propertyList)[0].equalsIgnoreCase("value"))
00197          {
00198             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00199                         "Only the \"Value\" parameter can be modified"); 
00200          }
00201       }
00202 
00203       String oldvalue; 
00204       CIMValue cv = previousInstance.getPropertyValue("Value"); 
00205       if (!cv || cv.getType() != CIMDataType::STRING || cv.isArray())
00206       {
00207          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00208                      "Bad or Missing \"Value\" property"); 
00209       }
00210       cv.get(oldvalue); 
00211 
00212       String newvalue; 
00213 
00214       cv = modifiedInstance.getPropertyValue("Value"); 
00215       if (!cv || cv.getType() != CIMDataType::STRING || cv.isArray())
00216       {
00217          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00218                      "Bad or Missing \"Value\" property"); 
00219       }
00220       cv.get(newvalue); 
00221 
00222       if (oldvalue == newvalue)
00223       {
00224          // nothing to do 
00225          return; 
00226       }
00227 
00228       String configfile = getConfigFile(env); 
00229 
00230       std::ifstream file(configfile.c_str());
00231       if (!file)
00232       {
00233          OW_THROWCIMMSG(CIMException::FAILED, Format("Unable to read config"
00234                   " file: %1", configfile).c_str());
00235       }
00236 
00237       cv = modifiedInstance.getPropertyValue("InstanceID"); 
00238       if (!cv || cv.getType() != CIMDataType::STRING || cv.isArray())
00239       {
00240          OW_THROWCIM(CIMException::INVALID_PARAMETER); 
00241       }
00242       String id; 
00243       cv.get(id); 
00244 
00245       StringArray sa = id.tokenize(":"); 
00246       if (sa.size() != 3)
00247       {
00248          OW_THROWCIM(CIMException::INVALID_PARAMETER); 
00249       }
00250 
00251       String configName = sa[2]; 
00252 
00253 
00254       TempFileStream tfs; 
00255 
00256       String line;
00257       bool foundItem = false; 
00258       while (file)
00259       {
00260          line = String::getLine(file);
00261          String tline = line; 
00262          if (!tline.empty() && tline[0] == ';')
00263          {
00264             do
00265             {
00266                tline = tline.substring(1); 
00267             } while (!tline.empty() && tline[0] == ';');
00268          }
00269          size_t idx = tline.indexOf('=');
00270          if (idx != String::npos)
00271          {
00272             String item = tline.substring(0, idx).trim();
00273             if (item == configName)
00274             {
00275                if (foundItem)
00276                {
00277                   // We've already written this config item.  
00278                   // omit remaining lines that resemble it. 
00279                   continue; 
00280                }
00281                line = configName + " = " + newvalue; 
00282                foundItem = true; 
00283             }
00284          }
00285          tfs << line << "\n"; 
00286       }
00287       if (!foundItem)
00288       {
00289          tfs << "\n" << configName << " = " << newvalue << "\n"; 
00290       }
00291       file.close(); 
00292       tfs.rewind(); 
00293 
00294       // we can't use FileSystem::rename() because it only works if 
00295       // src and dest are on the same device. 
00296       String bkpfilename = configfile + ".bkp"; 
00297       std::ofstream bkpfile(bkpfilename.c_str()); 
00298       if (!bkpfile)
00299       {
00300          OW_THROWCIMMSG(CIMException::FAILED, Format("Error opening %1 for writing", 
00301                                           bkpfilename).c_str()); 
00302       }
00303       std::ifstream ifile(configfile.c_str()); 
00304       if (!ifile)
00305       {
00306          OW_THROWCIMMSG(CIMException::FAILED, Format("Error opening %1 for reading", 
00307                                           ifile).c_str()); 
00308       }
00309       bkpfile << ifile.rdbuf(); 
00310       bkpfile.close(); 
00311       ifile.close(); 
00312 
00313       std::ofstream ofile(configfile.c_str()); 
00314       if (!ofile)
00315       {
00316          OW_THROWCIMMSG(CIMException::FAILED, Format("Error opening %1 for writing", 
00317                                           ofile).c_str()); 
00318       }
00319       ofile << tfs.rdbuf(); 
00320       ofile.close(); 
00321       // no need to reload configMap here.  It will automatically be done 
00322       // on the next read operation (if there is one). 
00323    }
00324 
00326    virtual void deleteInstance(
00327       const ProviderEnvironmentIFCRef& env,
00328       const String& ns,
00329       const CIMObjectPath& cop)
00330    {
00331       (void)env;
00332       (void)ns;
00333       (void)cop;
00334         OW_THROWCIMMSG(CIMException::FAILED, "Provider does not support deleteInstance");
00335    }
00336 
00338    virtual void getInstanceProviderInfo(InstanceProviderInfo &info)
00339    {
00340       info.addInstrumentedClass("OpenWBEM_ConfigSettingData");
00341    }
00342 
00343 #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00344 
00345     virtual void doReferences(const ProviderEnvironmentIFCRef &env, 
00346                                   CIMInstanceResultHandlerIFC &result, 
00347                                   const String &ns, 
00348                                   const CIMObjectPath &objectName, 
00349                                   const CIMClass &assocClass, 
00350                                   const String &resultClass, 
00351                                   const String &role, 
00352                                   const String &resultRole) 
00353       {
00354          CIMInstance newInst = assocClass.newInstance(); 
00355          String lcname = objectName.getClassName(); 
00356          lcname.toLowerCase(); 
00357          String lrole = role; 
00358          lrole.toLowerCase(); 
00359          String lresultRole = resultRole; 
00360          lresultRole.toLowerCase(); 
00361          if (lcname == "openwbem_objectmanager")
00362          {
00363             if ((!lrole.empty() && lrole != "managedelement")
00364                || (!lresultRole.empty() && lresultRole != "settingdata"))
00365             {
00366                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, 
00367                            "Bad Role or ResultRole"); 
00368             }
00369             lrole = "ManagedElement"; 
00370             lresultRole = "SettingData"; 
00371 
00372             newInst.setProperty(lrole, CIMValue(objectName)); 
00373             CIMObjectPath settingCOP("OpenWBEM_ConfigSettingData", ns); 
00374 
00375             for (ConfigItemsMap::const_iterator iter = m_configItems.begin(); 
00376                  iter != m_configItems.end(); ++iter)
00377             {
00378                settingCOP.setKeyValue("InstanceID", 
00379                                  CIMValue(makeID(iter->first))); 
00380                newInst.setProperty(lresultRole, CIMValue(settingCOP)); 
00381                result.handle(newInst); 
00382             }
00383          }
00384          else if (lcname == "openwbem_configsettingdata")
00385          {
00386             if ((!lrole.empty() && lrole != "settingdata")
00387                || (!lresultRole.empty() && lresultRole != "managedelement"))
00388             {
00389                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, 
00390                            "Bad Role or ResultRole"); 
00391             }
00392             lrole = "SettingData"; 
00393             lresultRole = "ManagedElement"; 
00394 
00395             CIMObjectPathArray cpa = env->getCIMOMHandle()->enumInstanceNamesA(ns, "OpenWBEM_ObjectManager"); 
00396             if (cpa.size() != 1)
00397             {
00398                OW_THROWCIMMSG(CIMException::FAILED, 
00399                            "Unable to retrieve a single instance of OpenWBEM_ObjectManager"); 
00400             }
00401             newInst.setProperty(lrole, CIMValue(objectName)); 
00402             newInst.setProperty(lresultRole, CIMValue(cpa[0])); 
00403             result.handle(newInst); 
00404          }
00405       }
00406 
00408       virtual void getAssociatorProviderInfo(AssociatorProviderInfo &info)
00409       {
00410          info.addInstrumentedClass("OpenWBEM_ObjectManagerConfigSettingData");
00411       }
00412 #endif // #ifndef OW_DISABLE_ASSOCIATION_TRAVERSAL
00413 
00414 private: 
00415    struct ConfigData
00416    {
00417       String Value; 
00418       String CurrentEffectiveValue; 
00419       String Caption; 
00420       String Description; 
00421       //String InstanceID; 
00422       //String ElementName; 
00423    };
00424 
00425    typedef SortedVectorMap<String, ConfigData> ConfigItemsMap; 
00426 
00427    SortedVectorMap<String, ConfigData> m_configItems; 
00429 
00430    time_t m_fileMTime; 
00432    String makeID(const String& confName)
00433    {
00434       String rval = "OpenWBEM:ConfigItem:"; 
00435       rval += confName; 
00436       return rval; 
00437    }
00439    bool mapNeedsLoad(const String& filename)
00440    {
00441       struct stat st; 
00442 
00443         if (stat(filename.c_str(), &st) != 0)
00444         {
00445          OW_THROWCIMMSG(CIMException::FAILED, Format("Cannot stat %1: %2",
00446                      filename, strerror(errno)).c_str()); 
00447         }
00448       
00449       if (st.st_mtime != m_fileMTime)
00450       {
00451          return true;
00452       }
00453       return false; 
00454    }
00455 
00457    String getConfigFile(const ProviderEnvironmentIFCRef& env)
00458    {
00459       String filename = env->getConfigItem("owcimomd.config_file"); 
00460 
00461       if (filename.empty())
00462       {
00463          OW_THROWCIMMSG(CIMException::FAILED, "Cannot determine config file"); 
00464       }
00465 
00466       return filename; 
00467    }
00468 
00470    void loadConfigMap(const ProviderEnvironmentIFCRef& env)
00471    {
00472       String filename = getConfigFile(env); 
00473       m_configItems.clear(); 
00474 
00475       struct stat st; 
00476         if (stat(filename.c_str(), &st) != 0)
00477         {
00478          OW_THROWCIMMSG(CIMException::FAILED, Format("Cannot stat %1: %2",
00479                      filename, strerror(errno)).c_str()); 
00480         }
00481       
00482       m_fileMTime = st.st_mtime; 
00483 
00484       std::ifstream file(filename.c_str());
00485       if (!file)
00486       {
00487          OW_THROWCIMMSG(CIMException::FAILED, Format("Unable to read config"
00488                   " file: %1", filename).c_str());
00489       }
00490 
00491       String line;
00492       int lineNum = 0;
00493       while (file)
00494       {
00495          lineNum++;
00496          line = String::getLine(file);
00497          if (!line.empty())
00498          {
00499             // If comment line, ignore
00500             if (line[0] == '#' || line[0] == ';')
00501             {
00502                continue;
00503             }
00504             size_t idx = line.indexOf('=');
00505             if (idx != String::npos)
00506             {
00507                if (idx + 1 < line.length())
00508                {
00509                   String itemValue = line.substring(idx + 1).trim();
00510                   if (!itemValue.empty())
00511                   {
00512                      String item = line.substring(0, idx).trim();
00513                      ConfigItemsMap::iterator it = m_configItems.find(item);
00514                      if (it == m_configItems.end())
00515                      {
00516                         ConfigData cd; 
00517                         cd.Value = itemValue; 
00518                         cd.CurrentEffectiveValue = env->getConfigItem(item); 
00519                         m_configItems.insert(std::make_pair(item, cd));
00520                      }
00521                   }
00522                }
00523             }
00524             else
00525             {
00526                OW_THROWCIMMSG(CIMException::FAILED, Format("Error in config file:"
00527                   " %1 at line %2.\n  Line is %3", filename, lineNum,
00528                   line).c_str());
00529             }
00530          }
00531       }
00532       file.close(); 
00533 
00534       for(const ConfigOpts::NameAndDefault* niter = &ConfigOpts::g_defaults[0]; 
00535           niter != ConfigOpts::g_defaultsEnd; ++niter)
00536       {
00537          String curValue = env->getConfigItem(niter->name, String(niter->defaultValue));
00538          ConfigItemsMap::iterator it = m_configItems.find(niter->name); 
00539          if (it == m_configItems.end())
00540          {
00541             ConfigData cd; 
00542             cd.CurrentEffectiveValue = curValue; 
00543             m_configItems.insert(std::make_pair(niter->name, cd));
00544          }
00545          else
00546          {
00547             it->second.CurrentEffectiveValue = curValue; 
00548          }
00549       }
00550 
00551    }
00552 
00553 
00554 };
00555 
00556 
00557 }
00558 
00559 
00560 
00561 
00562 OW_PROVIDERFACTORY(OpenWBEM::OpenWBEM_ConfigSettingDataInstProv, owprovinstOpenWBEM_ConfigSettingData)
00563 
00564 
00565 
00566    
00567 

Generated on Thu Feb 9 08:48:10 2006 for openwbem by  doxygen 1.4.6