Automated Coder

Exploring the Code of CruiseControl.Net

Starting the Monitor

Posted by Craig Sutherland on 12 November, 2008

Introduction

This is the first in a series of posts of building a prototype replacement for CCTray (my basic design is here). This series will mainly be about what I have done and why. At the end of the series I’ll have a working prototype replacement for CCTray.

A Beginning Point

Every application needs a start point. This will have at least a Main routine, perhaps with input arguments and it will do something (at least for a working application).

My prototype is no different, but I do have one twist. The same application will be used both for starting the main UI interface and any worker processes. As such it needs a way to distinguish between the various calls. To do this the application will check the input parameters against the configuration. The basic process will be:

  1. Load the application configuration
  2. Check the args for a command name, otherwise use the default from the configuration
  3. Instantiate an instance of the command
  4. Load the user configuration
  5. Run the command

This sounds like a pretty simple process and in reality, it is!

However to make the application more testable, I moved most of this functionality into the Core project and exposed it via interfaces. The BootStrap project just goes through the above sequence, plus adds some logging information.

The Application Configuration

The configuration for the application comes from two locations. The first is the configuration stored in the app.config file, the second comes from an XML config file stored in the user settings (more on this later).

The app.config configuration stores settings on the commands to run, the default settings and the location of the XML configuration. This information is accessed via the IApplicationConfigurationReader interface:

IApplicationConfigurationReader
IApplicationConfigurationReader

To load the configuration there is a class (ConfigurationHandler) in the bootstrap project which implements IConfigurationSectionHandler. This is to allow the configuration to use the configuration framework within .Net. This creates an instance of the class that implements IApplicationConfiguratioReader (XmlApplicationConfigurationReader) and calls ReadConfiguration(). This method then loads all the configuration settings. If the settings are missing then the default settings are initialised instead.

The four properties are straight-forward, they merely expose different settings that can be used. ConfigurationLocation is where the user configuration is located – by default this is in the ApplicationData folder. DefaultCommand is the command that will be used if no command was passed in on the command-line. This is a required property and must be set in the configuration. Finally InterProcessType and InterProcessUri are used for configuring the communications channel – I will talk more about these when I get to the communications in a future post.

The final part of this interface is RetrieveCommand(). This attempts to match the requested command with a command that is stored in the list. If the command cannot be found, it returns null, otherwise it will return the type to use for the command.

Parsing the Args

To handle the parsing of the command-line I have added an interface called IArgsParser:

IArgsParser
IArgsParser

The property is to allow the application to set the command-line args – this could have been a method, but it was just as easy to use a property.

FindCommand() will then search the args for a command to run. This will be the first arg that is not prefixed with a dash or slash. It will then use an instance of IApplicationConfigurationReader to find the type of command to run and return this. If either step fails it will return null (and cause the application to crash!)

CheckForArgument() and RetrieveArgument() are helper functions for finding a specific argument. CheckForArgument() merely returns whether the argument exists or not, while RetrieveArgument() returns the actual value. These are used in various places within the application.

Instantiating the Command

The actual commands, or logic to be run, must implement IApplicationCommand:

IApplicationCommand
IApplicationCommand

This has one method – Run(). This takes in the args, application configuration and user configuration.

To instantiate this instance I have a helper class called ObjectHelper. The Create<TObject>() method takes in a string containing the type name and returns a typed instance (hence the generic parameter). At the moment it mainly performs validation, but in future I will extend it to also handle searching in an extensions folder.

I’ll be posting a lot more about this interface and some implementations in the future.

Loading the Monitor Configuration

The final interface used by the bootstrap is IConfigurationServer:

IConfigurationService
IConfigurationService

This interfaces merely saves or loads the user configuration to disk (or potentially another location). When I talk about the configuration in a future post I’ll talk about how this interface works. For now, just know that the bootstrap instantiates an instance of this interface from the configuration and passes it onto the command.

That’s It!

The final step is just to call the Run() method on the application command, which the bootstrap does. From here on it is up to the application command to do all the work.

In my next post I’ll start looking at some of the commands and how they tie into the configuration.

One Response to “Starting the Monitor”

  1. [...] my last post (here) I started work on a replacement for CCTray. My initial work involved building a bootstrap [...]

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>