OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ConfigurationMember.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Globalization;
31 using System.Net;
32 using System.Reflection;
33 using System.Xml;
34 using log4net;
35 using OpenMetaverse;
36 //using OpenSim.Framework.Console;
37 
38 namespace OpenSim.Framework
39 {
40  public class ConfigurationMember
41  {
42  #region Delegates
43 
44  public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result);
45 
46  public delegate void ConfigurationOptionsLoad();
47 
48  #endregion
49 
50  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51  private int cE = 0;
52 
53  private string configurationDescription = String.Empty;
54  private string configurationFilename = String.Empty;
55  private XmlNode configurationFromXMLNode = null;
56  private List<ConfigurationOption> configurationOptions = new List<ConfigurationOption>();
57  private IGenericConfig configurationPlugin = null;
58 
62  private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll";
63 
64  private ConfigurationOptionsLoad loadFunction;
65  private ConfigurationOptionResult resultFunction;
66 
67  private bool useConsoleToPromptOnError = true;
68 
69  public ConfigurationMember(string configuration_filename, string configuration_description,
70  ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
71  {
72  configurationFilename = configuration_filename;
73  configurationDescription = configuration_description;
74  loadFunction = load_function;
75  resultFunction = result_function;
76  useConsoleToPromptOnError = use_console_to_prompt_on_error;
77  }
78 
79  public ConfigurationMember(XmlNode configuration_xml, string configuration_description,
80  ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
81  {
82  configurationFilename = String.Empty;
83  configurationFromXMLNode = configuration_xml;
84  configurationDescription = configuration_description;
85  loadFunction = load_function;
86  resultFunction = result_function;
87  useConsoleToPromptOnError = use_console_to_prompt_on_error;
88  }
89 
90  public void setConfigurationFilename(string filename)
91  {
92  configurationFilename = filename;
93  }
94 
95  public void setConfigurationDescription(string desc)
96  {
97  configurationDescription = desc;
98  }
99 
100  public void setConfigurationResultFunction(ConfigurationOptionResult result)
101  {
102  resultFunction = result;
103  }
104 
105  public void forceConfigurationPluginLibrary(string dll_filename)
106  {
107  configurationPluginFilename = dll_filename;
108  }
109 
110  private void checkAndAddConfigOption(ConfigurationOption option)
111  {
112  if ((option.configurationKey != String.Empty && option.configurationQuestion != String.Empty) ||
113  (option.configurationKey != String.Empty && option.configurationUseDefaultNoPrompt))
114  {
115  if (!configurationOptions.Contains(option))
116  {
117  configurationOptions.Add(option);
118  }
119  }
120  else
121  {
122  m_log.Info(
123  "Required fields for adding a configuration option is invalid. Will not add this option (" +
124  option.configurationKey + ")");
125  }
126  }
127 
128  public void addConfigurationOption(string configuration_key,
129  ConfigurationOption.ConfigurationTypes configuration_type,
130  string configuration_question, string configuration_default,
131  bool use_default_no_prompt)
132  {
133  ConfigurationOption configOption = new ConfigurationOption();
134  configOption.configurationKey = configuration_key;
135  configOption.configurationQuestion = configuration_question;
136  configOption.configurationDefault = configuration_default;
137  configOption.configurationType = configuration_type;
138  configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
139  configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever
140  checkAndAddConfigOption(configOption);
141  }
142 
143  public void addConfigurationOption(string configuration_key,
144  ConfigurationOption.ConfigurationTypes configuration_type,
145  string configuration_question, string configuration_default,
146  bool use_default_no_prompt,
148  {
149  ConfigurationOption configOption = new ConfigurationOption();
150  configOption.configurationKey = configuration_key;
151  configOption.configurationQuestion = configuration_question;
152  configOption.configurationDefault = configuration_default;
153  configOption.configurationType = configuration_type;
154  configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
155  configOption.shouldIBeAsked = shouldIBeAskedDelegate;
156  checkAndAddConfigOption(configOption);
157  }
158 
159  // TEMP - REMOVE
161  {
162  if (cE > 1)
163  m_log.Error("READING CONFIGURATION COUT: " + cE.ToString());
164 
165 
166  configurationPlugin = LoadConfigDll(configurationPluginFilename);
167  configurationOptions.Clear();
168  if (loadFunction == null)
169  {
170  m_log.Error("Load Function for '" + configurationDescription +
171  "' is null. Refusing to run configuration.");
172  return;
173  }
174 
175  if (resultFunction == null)
176  {
177  m_log.Error("Result Function for '" + configurationDescription +
178  "' is null. Refusing to run configuration.");
179  return;
180  }
181 
182  //m_log.Debug("[CONFIG]: Calling Configuration Load Function...");
183  loadFunction();
184 
185  if (configurationOptions.Count <= 0)
186  {
187  m_log.Error("[CONFIG]: No configuration options were specified for '" + configurationOptions +
188  "'. Refusing to continue configuration.");
189  return;
190  }
191 
192  bool useFile = true;
193  if (configurationPlugin == null)
194  {
195  m_log.Error("[CONFIG]: Configuration Plugin NOT LOADED!");
196  return;
197  }
198 
199  if (configurationFilename.Trim() != String.Empty)
200  {
201  configurationPlugin.SetFileName(configurationFilename);
202  try
203  {
204  configurationPlugin.LoadData();
205  useFile = true;
206  }
207  catch (XmlException e)
208  {
209  m_log.WarnFormat("[CONFIG] Not using {0}: {1}",
210  configurationFilename,
211  e.Message.ToString());
212  //m_log.Error("Error loading " + configurationFilename + ": " + e.ToString());
213  useFile = false;
214  }
215  }
216  else
217  {
218  if (configurationFromXMLNode != null)
219  {
220  m_log.Info("Loading from XML Node, will not save to the file");
221  configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml);
222  }
223 
224  m_log.Info("XML Configuration Filename is not valid; will not save to the file.");
225  useFile = false;
226  }
227 
228  foreach (ConfigurationOption configOption in configurationOptions)
229  {
230  bool convertSuccess = false;
231  object return_result = null;
232  string errorMessage = String.Empty;
233  bool ignoreNextFromConfig = false;
234  while (convertSuccess == false)
235  {
236  string console_result = String.Empty;
237  string attribute = null;
238  if (useFile || configurationFromXMLNode != null)
239  {
240  if (!ignoreNextFromConfig)
241  {
242  attribute = configurationPlugin.GetAttribute(configOption.configurationKey);
243  }
244  else
245  {
246  ignoreNextFromConfig = false;
247  }
248  }
249 
250  if (attribute == null)
251  {
252  if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false)
253  {
254  console_result = configOption.configurationDefault;
255  }
256  else
257  {
258  if ((configOption.shouldIBeAsked != null &&
259  configOption.shouldIBeAsked(configOption.configurationKey)) ||
260  configOption.shouldIBeAsked == null)
261  {
262  if (configurationDescription.Trim() != String.Empty)
263  {
264  console_result =
265  MainConsole.Instance.CmdPrompt(
266  configurationDescription + ": " + configOption.configurationQuestion,
267  configOption.configurationDefault);
268  }
269  else
270  {
271  console_result =
272  MainConsole.Instance.CmdPrompt(configOption.configurationQuestion,
273  configOption.configurationDefault);
274  }
275  }
276  else
277  {
278  //Dont Ask! Just use default
279  console_result = configOption.configurationDefault;
280  }
281  }
282  }
283  else
284  {
285  console_result = attribute;
286  }
287 
288  // if the first character is a "$", assume it's the name
289  // of an environment variable and substitute with the value of that variable
290  if (console_result.StartsWith("$"))
291  console_result = Environment.GetEnvironmentVariable(console_result.Substring(1));
292 
293  switch (configOption.configurationType)
294  {
295  case ConfigurationOption.ConfigurationTypes.TYPE_STRING:
296  return_result = console_result;
297  convertSuccess = true;
298  break;
299  case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY:
300  if (console_result.Length > 0)
301  {
302  return_result = console_result;
303  convertSuccess = true;
304  }
305  errorMessage = "a string that is not empty";
306  break;
307  case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN:
308  bool boolResult;
309  if (Boolean.TryParse(console_result, out boolResult))
310  {
311  convertSuccess = true;
312  return_result = boolResult;
313  }
314  errorMessage = "'true' or 'false' (Boolean)";
315  break;
316  case ConfigurationOption.ConfigurationTypes.TYPE_BYTE:
317  byte byteResult;
318  if (Byte.TryParse(console_result, out byteResult))
319  {
320  convertSuccess = true;
321  return_result = byteResult;
322  }
323  errorMessage = "a byte (Byte)";
324  break;
325  case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER:
326  char charResult;
327  if (Char.TryParse(console_result, out charResult))
328  {
329  convertSuccess = true;
330  return_result = charResult;
331  }
332  errorMessage = "a character (Char)";
333  break;
334  case ConfigurationOption.ConfigurationTypes.TYPE_INT16:
335  short shortResult;
336  if (Int16.TryParse(console_result, out shortResult))
337  {
338  convertSuccess = true;
339  return_result = shortResult;
340  }
341  errorMessage = "a signed 32 bit integer (short)";
342  break;
343  case ConfigurationOption.ConfigurationTypes.TYPE_INT32:
344  int intResult;
345  if (Int32.TryParse(console_result, out intResult))
346  {
347  convertSuccess = true;
348  return_result = intResult;
349  }
350  errorMessage = "a signed 32 bit integer (int)";
351  break;
352  case ConfigurationOption.ConfigurationTypes.TYPE_INT64:
353  long longResult;
354  if (Int64.TryParse(console_result, out longResult))
355  {
356  convertSuccess = true;
357  return_result = longResult;
358  }
359  errorMessage = "a signed 32 bit integer (long)";
360  break;
361  case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS:
362  IPAddress ipAddressResult;
363  if (IPAddress.TryParse(console_result, out ipAddressResult))
364  {
365  convertSuccess = true;
366  return_result = ipAddressResult;
367  }
368  errorMessage = "an IP Address (IPAddress)";
369  break;
370  case ConfigurationOption.ConfigurationTypes.TYPE_UUID:
371  UUID uuidResult;
372  if (UUID.TryParse(console_result, out uuidResult))
373  {
374  convertSuccess = true;
375  return_result = uuidResult;
376  }
377  errorMessage = "a UUID (UUID)";
378  break;
379  case ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE:
380  UUID uuidResult2;
381  if (UUID.TryParse(console_result, out uuidResult2))
382  {
383  convertSuccess = true;
384 
385  if (uuidResult2 == UUID.Zero)
386  uuidResult2 = UUID.Random();
387 
388  return_result = uuidResult2;
389  }
390  errorMessage = "a non-null UUID (UUID)";
391  break;
392  case ConfigurationOption.ConfigurationTypes.TYPE_Vector3:
393  Vector3 vectorResult;
394  if (Vector3.TryParse(console_result, out vectorResult))
395  {
396  convertSuccess = true;
397  return_result = vectorResult;
398  }
399  errorMessage = "a vector (Vector3)";
400  break;
401  case ConfigurationOption.ConfigurationTypes.TYPE_UINT16:
402  ushort ushortResult;
403  if (UInt16.TryParse(console_result, out ushortResult))
404  {
405  convertSuccess = true;
406  return_result = ushortResult;
407  }
408  errorMessage = "an unsigned 16 bit integer (ushort)";
409  break;
410  case ConfigurationOption.ConfigurationTypes.TYPE_UINT32:
411  uint uintResult;
412  if (UInt32.TryParse(console_result, out uintResult))
413  {
414  convertSuccess = true;
415  return_result = uintResult;
416  }
417  errorMessage = "an unsigned 32 bit integer (uint)";
418  break;
419  case ConfigurationOption.ConfigurationTypes.TYPE_UINT64:
420  ulong ulongResult;
421  if (UInt64.TryParse(console_result, out ulongResult))
422  {
423  convertSuccess = true;
424  return_result = ulongResult;
425  }
426  errorMessage = "an unsigned 64 bit integer (ulong)";
427  break;
428  case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT:
429  float floatResult;
430  if (
431  float.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
432  out floatResult))
433  {
434  convertSuccess = true;
435  return_result = floatResult;
436  }
437  errorMessage = "a single-precision floating point number (float)";
438  break;
439  case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE:
440  double doubleResult;
441  if (
442  Double.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
443  out doubleResult))
444  {
445  convertSuccess = true;
446  return_result = doubleResult;
447  }
448  errorMessage = "an double-precision floating point number (double)";
449  break;
450  }
451 
452  if (convertSuccess)
453  {
454  if (useFile)
455  {
456  configurationPlugin.SetAttribute(configOption.configurationKey, console_result);
457  }
458 
459  if (!resultFunction(configOption.configurationKey, return_result))
460  {
461  m_log.Info(
462  "The handler for the last configuration option denied that input, please try again.");
463  convertSuccess = false;
464  ignoreNextFromConfig = true;
465  }
466  }
467  else
468  {
469  if (configOption.configurationUseDefaultNoPrompt)
470  {
471  m_log.Error(string.Format(
472  "[CONFIG]: [{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n",
473  configOption.configurationKey, console_result, errorMessage,
474  configurationFilename));
475  convertSuccess = true;
476  }
477  else
478  {
479  m_log.Warn(string.Format(
480  "[CONFIG]: [{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n",
481  configOption.configurationKey, console_result, errorMessage,
482  configurationFilename));
483  ignoreNextFromConfig = true;
484  }
485  }
486  }
487  }
488 
489  if (useFile)
490  {
491  configurationPlugin.Commit();
492  configurationPlugin.Close();
493  }
494  }
495 
496  private static IGenericConfig LoadConfigDll(string dllName)
497  {
498  Assembly pluginAssembly = Assembly.LoadFrom(dllName);
499  IGenericConfig plug = null;
500 
501  foreach (Type pluginType in pluginAssembly.GetTypes())
502  {
503  if (pluginType.IsPublic)
504  {
505  if (!pluginType.IsAbstract)
506  {
507  Type typeInterface = pluginType.GetInterface("IGenericConfig", true);
508 
509  if (typeInterface != null)
510  {
511  plug =
512  (IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
513  }
514  }
515  }
516  }
517 
518  pluginAssembly = null;
519  return plug;
520  }
521 
522  public void forceSetConfigurationOption(string configuration_key, string configuration_value)
523  {
524  configurationPlugin.LoadData();
525  configurationPlugin.SetAttribute(configuration_key, configuration_value);
526  configurationPlugin.Commit();
527  configurationPlugin.Close();
528  }
529  }
530 }
static NumberFormatInfo NumberFormatInfo
Definition: Culture.cs:39
delegate bool ConfigurationOptionShouldBeAsked(string configuration_key)
ConfigurationMember(XmlNode configuration_xml, string configuration_description, ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
ConfigurationMember(string configuration_filename, string configuration_description, ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
void forceSetConfigurationOption(string configuration_key, string configuration_value)
void addConfigurationOption(string configuration_key, ConfigurationOption.ConfigurationTypes configuration_type, string configuration_question, string configuration_default, bool use_default_no_prompt)
void setConfigurationResultFunction(ConfigurationOptionResult result)
ConfigurationOptionShouldBeAsked shouldIBeAsked
void setConfigurationFilename(string filename)
void forceConfigurationPluginLibrary(string dll_filename)
void addConfigurationOption(string configuration_key, ConfigurationOption.ConfigurationTypes configuration_type, string configuration_question, string configuration_default, bool use_default_no_prompt, ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate)