Menu

#9 Bootstrap Configuration File

Next release
open
5
2005-03-17
2005-03-15
Anonymous
No

First off, this library looks very cool. I plan to try it out on my next
project.

Second, how about adding support for a "bootstrap" configuration
file? That is, a configuration file that defines where configuration
data can be found (possibly from a multitude of different sources
and/or source types). The application could then call a single static
method, say Nini.Config.Bootstrap.LoadConfigs(), that would
instantiate, load, and merge all of the configuration sources defined
within the bootstrap configuration file. Thus, we remove the
requirement that the application know exactly where its configuration
data is located and how it is distributed across the set of possible
sources.

An obvious first choice would be the .config file for the application,
with something like the following:

<configuration>
<configSections>
<section name="Nini"
type="Nini.Config.BootstrapSectionHandler" />
</configSections>
<Nini>
<Xml path="FactoryWide.xml" />
<Xml path="AreaWide.xml" />
<Xml path="ToolSpecific.xml" />
<Argv />
</Nini>
</configuration>

The example would load and merge the configuration data from the
three XML sources, in order, and then allow any setting to be
overridden by the command line. Configuration sources could be
added, source types could be swapped, all without any extra code
on the part of the application.

Anyway, just a thought I had.

Thanks,

Phillip M. Hoff
phillip.m.hoff@intel.com
phillip@orst.edu

Discussion

  • Brent R. Matzelle

    Logged In: YES
    user_id=163900

    That is an excellent idea. I've been playing around with an
    idea like that for some time now. Let me think about how
    that might work. If you have any more suggestions for
    implementing this feature then please add them here. Thanks!

     
  • Brent R. Matzelle

    • milestone: 403999 --> Next release
    • assigned_to: nobody --> bmatzelle
     
  • Phillip M. Hoff

    Phillip M. Hoff - 2005-03-18

    Logged In: YES
    user_id=1240125

    Sorry for posting this inline, but I don't see an attach file option for
    followups.

    Below is a proof-of-concept of the idea (with the added ability for Nini
    clients to create their own custom configuration sources and still have the
    bootstrapper load them automatically or to override how the bootstrapper
    loads the provided configuration sources). I only added support for Ini,
    Xml, and Argv configuration sources; too tired to add others.

    Files were compiled and executed with Mono 1.1.4.

    Thanks,

    Phillip M. Hoff
    phillip.m.hoff@intel.com
    phillip@orst.edu

    NiniBootstrap.cs:

    using System;
    using System.Collections;
    using System.Configuration;
    using System.Xml;
    using Nini.Config;

    namespace Nini.Config.Bootstrap
    {
    public class BootstrapConfigurationSectionHandler :
    IConfigurationSectionHandler
    {
    public BootstrapConfigurationSectionHandler()
    {
    }

    public object Create(object parent, object configContext,
    XmlNode section)
    {
    return section;
    }
    }

    public delegate IConfigSource
    BootstrapConfigSourceGenerator(XmlNode section);

    public class BootstrapConfiguration
    {
    private static IConfigSource _source;
    private static Hashtable _generators;

    public static IConfigSource Source
    {
    get
    {
    if (_source == null)
    {
    XmlNode section = (XmlNode)
    ConfigurationSettings.GetConfig("Nini");

    foreach (XmlNode childNode in
    section.ChildNodes)
    {
    if
    (BootstrapConfiguration.SourceGenerators.Contains(childNode.LocalName)
    )
    {
    IConfigSource childSource =
    ((BootstrapConfigSourceGenerator)
    BootstrapConfiguration.SourceGenerators[childNode.LocalName])(childNod
    e);

    if (_source == null)
    {
    _source = childSource;
    }
    else
    {
    _source.Merge(childSource);
    }
    }
    }
    }

    return _source;
    }
    }

    public static Hashtable SourceGenerators
    {
    get
    {
    if (_generators == null)
    {
    _generators = new Hashtable();

    _generators["Ini"] = new
    BootstrapConfigSourceGenerator(OnGenerateIniConfigSource);
    _generators["Xml"] = new
    BootstrapConfigSourceGenerator(OnGenerateXmlConfigSource);
    _generators["Argv"] = new
    BootstrapConfigSourceGenerator(OnGenerateArgvConfigSource);
    }

    return _generators;
    }
    }

    private static IConfigSource
    OnGenerateIniConfigSource(XmlNode node)
    {
    return new
    IniConfigSource(node.Attributes["path"].InnerText);
    }

    private static IConfigSource
    OnGenerateXmlConfigSource(XmlNode node)
    {
    return new
    XmlConfigSource(node.Attributes["path"].InnerText);
    }

    private static IConfigSource
    OnGenerateArgvConfigSource(XmlNode node)
    {
    ArgvConfigSource source = new
    ArgvConfigSource(Environment.GetCommandLineArgs());

    foreach (XmlNode switchNode in
    node.SelectNodes("Switch"))
    {

    source.AddSwitch(switchNode.Attributes["config"].InnerText,
    switchNode.Attributes["longName"].InnerText);
    }

    return source;
    }
    }

    public class NiniBootstrap
    {
    public static void Main()
    {
    BootstrapConfiguration.SourceGenerators["Custom"] = new
    BootstrapConfigSourceGenerator(OnGenerateCustomConfigSource);

    IConfigSource source = BootstrapConfiguration.Source;

    Console.WriteLine("NiniBootstrap1.ini: Test1: Key: {0}",
    source.Configs["Test1"].GetString("Key"));
    Console.WriteLine("NiniBootstrap2.ini: Test2: Key: {0}",
    source.Configs["Test2"].GetString("Key"));
    Console.WriteLine("Custom: Test3: Key: {0}",
    source.Configs["Test3"].GetString("Key"));
    Console.WriteLine("Overridden: TestOverride: Key: {0}",
    source.Configs["TestOverride"].GetString("Key"));
    }

    private static IConfigSource
    OnGenerateCustomConfigSource(XmlNode node)
    {
    return new
    IniConfigSource(node.Attributes["path"].InnerText);
    }
    }
    }

    NiniBootstrap.exe.config:

    <configuration>
    <configSections>
    <section name="Nini"
    type="Nini.Config.Bootstrap.BootstrapConfigurationSectionHandler,NiniBoo
    tstrap" />
    </configSections>
    <Nini>
    <Ini path="NiniBootstrap1.ini" />
    <Ini path="NiniBootstrap2.ini" />
    <Custom path="NiniBootstrap3.ini" />
    <Argv>
    <Switch config="TestOverride" longName="Key" />
    </Argv>
    </Nini>
    </configuration>

    NiniBootstrap1.ini:

    [Test1]
    Key=Value1

    [TestOverride]
    Key=Value1

    NiniBootstrap2.ini:

    [Test2]
    Key=Value2

    [TestOverride]
    Key=Value2

    NiniBootstrap3.ini:

    [Test3]
    Key=Value3

    [TestOverride]
    Key=Value3

    Output:

    $ mcs NiniBootstrap.cs -r:Nini.dll
    $ mono NiniBootstrap.exe
    NiniBootstrap1.ini: Test1: Key: Value1
    NiniBootstrap2.ini: Test2: Key: Value2
    Custom: Test3: Key: Value3
    Overridden: TestOverride: Key: Value3
    $ mono NiniBootstrap.exe -Key:Foo
    NiniBootstrap1.ini: Test1: Key: Value1
    NiniBootstrap2.ini: Test2: Key: Value2
    Custom: Test3: Key: Value3
    Overridden: TestOverride: Key: Foo

     

Log in to post a comment.

MongoDB Logo MongoDB