This is post 4 in a series devoted to extending CruiseControl.NET to support multiple build configurations for a single project. In this post, I will cover the use of the Velocity engine and outputting responses from the plugin.
ICruiseAction.Execute method
The second post in this series addressed the interfaces that your plugin is required to implement. The main method to implement is the ICruiseAction.Execute method, which accepts an ICruiseRequest object and returns an IResponse object. What exactly is an IResponse, and how can your plugin create it?
As mentioned in other posts, if you ever have questions about how something works, I suggest that you consult the ccnet source code. The main reference that I’ve been using is the ProjectReportProjectPlugin class. Examination of this class shows that it uses an object called IVelocityViewGenerator to generate responses. It acquires the IVelocityViewGenerator reference from its constructor(injected by the runtime).
IVelocityViewGenerator - How is it used?
The following code has been borrowed from the ProjectReportProjectPlugin’s Execute method implementation:
Hashtable velocityContext = new Hashtable(); velocityContext["projectName"] = projectSpecifier.ProjectName; velocityContext["externalLinks"] = farmService.GetExternalLinks(projectSpecifier); velocityContext["noLogsAvailable"] = (buildSpecifiers.Length == 0); return viewGenerator.GenerateView(@"ProjectReport.vm", velocityContext);
Take a moment and let the code sync in. The object is only used once, in the method’s return statement. The interface is rather simple, and has but a single method. The interface follows:
public interface IVelocityViewGenerator
{
HtmlFragmentResponse GenerateView(string templateName, Hashtable velocityContext);
}
If you examine the HtmlFragmentResponse object, it implements the IResponse interface, which is the return type for the ICruiseAction.Execute method.
The GenerateView method accepts a template name, and a velocityContext; a basic hashtable. The return statement from the code listing shows a string literal, “ProjectReport.vm”, and a hashtable.
The hashtable that is passed to the GenerateView method has been populated with a number of items, such as the project name. The hash table is keyed on string values, and the values are objects.
Now that you know what the GenerateView method accepts, what do you think the arguments actually are? What is “ProjectReport.vm”, and what is that hashtable?
Velocity & Templates
The literal “ProjectReport.vm” is obviously a filename, so I looked through the ccnet distro for the file. The file is located in the dashboard’s templates directory, along with a bunch of other .vm files. It’s a simple text file, that appears to be some sort of html template. The full source for the file follows:
<h2>Project Report for $projectName</h2> #if ($externalLinks.Length > 0) <table class="ExternalLinks"> <tr> <th>External Links</th> </tr> #foreach ($externalLink in $externalLinks) <tr bgcolor="Ivory"> <td align="Left"> <a href="$externalLink.Url">$externalLink.Name</a> </td> </tr> #end </table> #end <p> #if ($noLogsAvailable) There are currently no build logs available for this project - make sure your Build Server configuration is correct and that this Project's build is not throwing any exceptions #else #if ($pluginInfo) <h3>Most Recent Build Results</h3> $pluginInfo Click <a href="$mostRecentBuildUrl">here</a> for the full build report. #else Click <a href="$mostRecentBuildUrl">here</a> for the most recent build report. #end #end </p>
Like I said, it appears to be html. However, scattered throughout the source are various directives. Statements or commands appear to begin with the pound sign, while property/variable references appear to begin with a dollar sign. In fact, the very first line of the template refers to a property/variable named $projectName. Does that ring a bell? If you refer to the first code listing, the velocityContext hashmap has a key named “projectName”.
Putting two and two together, its apparent that the IVelocityViewGenerator.GenerateView method takes the name of a template, and the second argument, the velocityContext hashmap, contains references that can be expanded when the template is processed.
This templating system piqued my interest, and I discovered that Velocity is the name of a templating project hosted by Apache. The official home page is available here. The reference is here, and the user’s guide is here. These resources will prove to be very valuable as you develop your own velocity templates.
And one more thing. This is a dotnet project, so the original java version of Velocity isn’t being used. One of the project references for the dashboard is an assembly named NVelocity. A quick google search of that term yield the home page for the project, which is a dotnet port of Velocity. I haven’t fully researched the project, so I don’t know how complete it is, nor do I know the differences. This definitely deserves further investigation.
Conclusion
You should now know how the ICruiseAction.Execute method behaves, and how to generate responses via the velocity runtime. I’ve also provided the docs and reference for Velocity, which will aid you in composing your own custom templates.
The next post will cover the template that I have developed for my build configuration plugin.