00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <spl/configuration/ConfigurationSettings.h>
00018 #include <spl/Environment.h>
00019 #include <spl/Exception.h>
00020 #include <spl/text/StringBuffer.h>
00021 #include <spl/xml/XmlElement.h>
00022
00023 #ifdef _WINDOWS
00024 #include <spl/configuration/windows/WinRegKey.h>
00025 #endif
00026
00027 ConfigurationSettings::ConfigurationSettings()
00028 : m_sections(), m_filename()
00029 {
00030 }
00031
00032 ConfigurationSettings::ConfigurationSettings(const String& filename)
00033 : m_sections(), m_filename()
00034 {
00035 Load(filename);
00036 }
00037
00038 ConfigurationSettings::ConfigurationSettings(const ConfigurationSettings& config)
00039 : m_filename(config.m_filename), m_sections(config.m_sections)
00040 {
00041 }
00042
00043 ConfigurationSettings::~ConfigurationSettings()
00044 {
00045 }
00046
00047 ConfigurationSettings& ConfigurationSettings::operator =(const ConfigurationSettings& config)
00048 {
00049 m_filename = config.m_filename;
00050 m_sections = config.m_sections;
00051
00052 return *this;
00053 }
00054
00055 ConfigurationSection& ConfigurationSettings::Section(const String& name)
00056 {
00057 if (! m_sections.ContainsKey(name))
00058 {
00059 m_sections.Set(name, ConfigurationSection(name));
00060 }
00061 return m_sections.GetRef(name);
00062 }
00063
00064 void ConfigurationSettings::Load(const String& filename)
00065 {
00066 m_filename = filename;
00067 if ( m_filename.EndsWith(".ini") )
00068 {
00069 TextReader reader(File::OpenText(filename));
00070 DelimitedFilePtr ini = DelimitedFile::Parse(reader, '=');
00071 Load(ini);
00072 return;
00073 }
00074 else if ( m_filename.EndsWith( ".config" ) || m_filename.EndsWith( ".xml" ) )
00075 {
00076 XmlDocumentPtr doc = XmlDocument::Parse(filename);
00077 Load(doc);
00078 return;
00079 }
00080 else
00081 {
00082 throw new ConfigurationException("Unknown file type.");
00083 }
00084 }
00085
00086 void ConfigurationSettings::Load(XmlDocument& appconfig)
00087 {
00088 m_sections.Clear();
00089
00090 XmlElementPtr config = appconfig.RootElement();
00091 if ( config.IsNull() || ! config->Name().Equals("configuration") )
00092 {
00093 throw new InvalidArgumentException("Invalid file format, expected <configuration>");
00094 }
00095
00096 XmlNodePtr section = config->FirstChildElement();
00097 while(section.IsNotNull())
00098 {
00099 XmlElementPtr node = section->FirstChildElement();
00100 while ( node.IsNotNull() )
00101 {
00102 if (! node->Name().Equals("add"))
00103 {
00104 throw new InvalidArgumentException("Expected <add> tag.");
00105 }
00106
00107 XmlAttributePtr keynode = node->Attribute("key");
00108 XmlAttributePtr valnode = node->Attribute("value");
00109
00110 if ( keynode.IsNull() || valnode.IsNull() )
00111 {
00112 throw new InvalidArgumentException("Malformed <add> tag.");
00113 }
00114
00115 StringPtr key = keynode->Value();
00116 StringPtr val = valnode->Value();
00117
00118 Section(section->Name()).Set(*key, *val);
00119
00120 node = node->NextSiblingElement();
00121 }
00122
00123 section = section->NextSibling();
00124 }
00125 }
00126
00127 void ConfigurationSettings::Load(const DelimitedFile& inifile)
00128 {
00129 m_sections.Clear();
00130
00131 String section;
00132
00133 for ( int r = 0; r < inifile.RowCount(); r++ )
00134 {
00135 DataRowPtr row = inifile.RowAt(r);
00136 if ( row->Count() == 0 )
00137 {
00138 continue;
00139 }
00140 StringPtr key = row->Cell(0)->ToString();
00141 if (key->StartsWith('['))
00142 {
00143
00144 section = *key->Mid(1, key->Length() - 1);
00145 ASSERT(! section.EndsWith(']'));
00146 Section(section);
00147 continue;
00148 }
00149 if ( row->Count() == 1 )
00150 {
00151 Section(section).Set(*key, String(""));
00152 }
00153 else if ( row->Count() == 2 )
00154 {
00155 Section(section).Set(*key, row->Cell(1)->ToString());
00156 }
00157 else
00158 {
00159 throw new InvalidArgumentException("Invalid file format, too many columns.");
00160 }
00161 }
00162 }
00163
00164 bool ConfigurationSettings::ContainsKey(const String& section, const String& key)
00165 {
00166 return Section(section).ContainsKey(key);
00167 }
00168
00169 void ConfigurationSettings::Add(const String& section, const String& key, const String& value)
00170 {
00171 Section(section).Set(key, value);
00172 }
00173
00174 StringPtr ConfigurationSettings::Value(const String& section, const String& key)
00175 {
00176 if ( ! m_sections.ContainsKey(section) )
00177 {
00178 m_sections.Set(section, ConfigurationSection(section));
00179 }
00180 return m_sections.Get(section).Value(key);
00181 }
00182
00183 List<StringPtr>& ConfigurationSettings::Values(const String& section, const String& key)
00184 {
00185 if ( ! m_sections.ContainsKey(section) )
00186 {
00187 m_sections.Set(section, ConfigurationSection(section));
00188 }
00189 return m_sections.Get(section).Values(key);
00190 }
00191
00192 StringPtr ConfigurationSettings::ToXmlString()
00193 {
00194 StringBuffer xml("<?xml version=\"1.0\"?>\n<configuration>\n");
00195
00196 for (Hashtable<String, ConfigurationSection>::Iterator iter(m_sections.Begin()); iter.Next(); )
00197 {
00198 xml.Append(iter.CurrentRef().ToXmlString());
00199 }
00200
00201 xml.Append("</configuration>\n");
00202 return xml.ToString();
00203 }
00204
00205 StringPtr ConfigurationSettings::ToIniString()
00206 {
00207 StringBuffer ini;
00208 for (Hashtable<String, ConfigurationSection>::Iterator iter(m_sections.Begin()); iter.Next(); )
00209 {
00210 ini.Append(iter.CurrentRef().ToIniString());
00211 }
00212 return ini.ToString();
00213 }
00214
00215 ConfigurationSettingsPtr ConfigurationSettings::LoadAppConfig()
00216 {
00217 ConfigurationSettingsPtr cfgp;
00218 String processName = Environment::ProcessName();
00219
00220 #ifdef _WINDOWS
00221
00222
00223 String path("Software\\SPL\\" + Environment::ProcessName());
00224
00225 if (WinRegKey::KeyExists(WinRegKey::HiveLocalMachine, path))
00226 {
00227 WinRegKey key(path, WinRegKey::HiveLocalMachine);
00228 List<WinRegKey> sections(key.ListSubKeys());
00229
00230 for(List<WinRegKey>::Iterator iter(sections.Begin()); iter.Next(); )
00231 {
00232 String sectionName(iter.CurrentRef().KeyName());
00233 List<WinRegKey> subKeys(iter.CurrentRef().ListSubKeys());
00234
00235 for(List<WinRegKey>::Iterator iterSub(subKeys.Begin()); iterSub.Next(); )
00236 {
00237 cfgp->Add(sectionName, iterSub.CurrentRef().KeyName(), iterSub.CurrentRef().Value());
00238 }
00239 }
00240 return cfgp;
00241 }
00242
00243 #endif
00244
00245 if (File::Exists(processName + ".ini"))
00246 {
00247 cfgp = new ConfigurationSettings();
00248 cfgp->Load(processName + ".ini");
00249 }
00250 else if (File::Exists(processName + ".xml"))
00251 {
00252 cfgp = new ConfigurationSettings();
00253 cfgp->Load(processName + ".xml");
00254 }
00255
00256 return cfgp;
00257 }
00258
00259 void ConfigurationSettings::SaveToIniFile(const String& filename)
00260 {
00261 ASSERT(filename.EndsWith(".ini"));
00262
00263 if (File::Exists(filename))
00264 {
00265 File::Delete(filename);
00266 }
00267
00268 TextWriterPtr writer(File::CreateText(filename));
00269
00270 for(Hashtable<String, ConfigurationSection>::Iterator iter(m_sections.Begin()); iter.Next(); )
00271 {
00272 writer->Write(iter.CurrentRef().ToIniString());
00273 }
00274
00275 writer->Close();
00276 }
00277
00278 void ConfigurationSettings::SaveToXmlFile(const String& filename)
00279 {
00280 ASSERT(filename.EndsWith(".xml"));
00281
00282 if (File::Exists(filename))
00283 {
00284 File::Delete(filename);
00285 }
00286
00287 TextWriterPtr writer(File::CreateText(filename));
00288
00289 for(Hashtable<String, ConfigurationSection>::Iterator iter(m_sections.Begin()); iter.Next(); )
00290 {
00291 writer->Write(iter.CurrentRef().ToXmlString());
00292 }
00293
00294 writer->Close();
00295 }
00296
00297 void ConfigurationSettings::SaveToRegistry()
00298 {
00299 #ifndef _WINDOWS
00300 throw new Exception("Not supported");
00301 #else
00302 String path("Software\\SPL\\" + Environment::ProcessName());
00303 if (!WinRegKey::KeyExists(WinRegKey::HiveLocalMachine, path))
00304 {
00305 WinRegKey::Create(WinRegKey::HiveLocalMachine, path);
00306 }
00307
00308 WinRegKey rootKey(path, WinRegKey::HiveLocalMachine);
00309 rootKey.OpenForReadWrite();
00310
00311 for(Hashtable<String, ConfigurationSection>::Iterator iter(m_sections.Begin()); iter.Next(); )
00312 {
00313
00314 String sectionPath = path + "\\" + iter.CurrentKeyRef();
00315 WinRegKey sectionKey(WinRegKey::Create(WinRegKey::HiveLocalMachine, sectionPath));
00316 sectionKey.OpenForReadWrite();
00317
00318 for (Hashtable<String, List<StringPtr> >::Iterator viter(iter.CurrentRef().Begin()); viter.Next(); )
00319 {
00320 for (List<StringPtr>::Iterator liter(viter.CurrentRef().Begin()); liter.Next(); )
00321 {
00322 sectionKey.SetSubKey(viter.CurrentKeyRef(), liter.CurrentRef());
00323 }
00324 }
00325 sectionKey.Close();
00326 }
00327
00328 rootKey.Close();
00329 #endif
00330 }
00331
00332 #ifdef DEBUG
00333 void ConfigurationSettings::ValidateMem() const
00334 {
00335 m_sections.ValidateMem();
00336 m_filename.ValidateMem();
00337 }
00338
00339 void ConfigurationSettings::CheckMem() const
00340 {
00341 m_sections.CheckMem();
00342 m_filename.CheckMem();
00343 }
00344 #endif