# # File:: config.rb # Description:: AssetBuild Configuration Classes, XML file parser. # # Author:: David Muir # Date:: 28 June 2008 # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'pipeline/os/path' require 'pipeline/util/environment' include Pipeline require 'rexml/document' include REXML module AssetBuild # # == Description # Command queue options class. This currently only stores a port integer # for the distributed command queue. It is required to be configurable # so we can run multiple builders on the same machine. # class CommandQueueOptions attr_accessor :port def initialize( port ) throw ArgumentError.new( "Invalid port integer (#{port.class})." ) \ unless ( port.is_a?( Integer ) ) @port = port end def pretty_print( indent = 0, indent_char = "\t" ) puts ( pretty_string( indent, indent_char ) ) end def pretty_string( indent = 0, indent_char = "\t" ) message = '' indent.times do message << indent_char; end message << "CommandQueue\n" (indent+1).times do message << indent_char; end message << "Port: #{@port}\n" message end def fill_env( env ) env.add( 'port', @port.to_s ) end #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- def CommandQueueOptions::from_xml( xml_node ) throw ArgumentError.new( 'Invalid command_queue node, name mismatch.' ) \ unless ( 'command_queue' == xml_node.name ) port = xml_node.attributes['port'].to_i CommandQueueOptions.new( port ) end end # # == Description # class Report attr_reader :path attr_reader :webserver attr_reader :xslt_html attr_reader :xslt_text attr_reader :db attr_reader :email def initialize( path, webserver, xslt_html, xslt_text, email, db ) @path = path @webserver = webserver @xslt_html = xslt_html @xslt_text = xslt_text @email = email @db = db end def pretty_print( indent = 0, indent_char = "\t" ) puts ( pretty_string( indent, indent_char ) ) end def pretty_string( indent = 0, indent_char = "\t" ) message = '' indent.times do message << indent_char; end message << "Report\n" (indent+1).times do message << indent_char; end message << "Path: #{@path}\n" (indent+1).times do message << indent_char; end message << "Webserver: #{@webserver}\n" (indent+1).times do message << indent_char; end message << "XSLT HTML: #{@xslt_html}\n" (indent+1).times do message << indent_char; end message << "XSLT Text: #{@xslt_text}\n" message << @email.pretty_string( indent+1, indent_char ) unless ( nil == @email ) message << @db.pretty_string( indent+1, indent_char ) unless ( nil == @db ) message end def fill_env( env ) env.add( 'path', @path ) env.add( 'webserver', @webserver ) env.add( 'xslt_html', @xslt_html ) env.add( 'xslt_text', @xslt_text ) end #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- def Report::from_xml( project, branch, xml_node ) throw ArgumentError.new( 'Invalid report node, name mismatch.' ) \ unless ( 'report' == xml_node.name ) throw ArgumentError::new( "Invalid project object (#{project.class})." ) \ unless ( project.is_a?( Project ) ) throw ArgumentError::new( "Invalid branch object (#{branch.class})." ) \ unless ( branch.is_a?( Branch ) ) env = Environment.new() branch.fill_env( env ) path = env.subst( xml_node.attributes['path'] ) webserver = env.subst( xml_node.attributes['webserver'] ) xslt_html = env.subst( xml_node.attributes['xslt_html'] ) xslt_text = env.subst( xml_node.attributes['xslt_text'] ) email = nil xml_node.elements.each( 'email' ) do |node| email = Email.from_xml( project, node ) end db = nil Report.new( path, webserver, xslt_html, xslt_text, email, db ) end end # # == Description # Project email configuration. # class Email # Known keys: :maintainer, :list, :from attr_reader :addresses attr_reader :aliases attr_reader :xslt def initialize( xslt, addresses, aliases = {} ) @xslt = xslt @addresses = addresses @aliases = aliases end def pretty_print( indent = 0, indent_char = "\t" ) puts ( pretty_string( indent, indent_char ) ) end def pretty_string( indent = 0, indent_char = "\t" ) message = '' indent.times do message << indent_char; end message << "Email\n" (indent+1).times do message << indent_char; end message << "XSLT: #{@xslt}\n" @addresses.each_pair do |k,v| (indent+1).times do message << indent_char; end message << "#{k} [#{@aliases[k]}]:\n" v.each do |addr| (indent+2).times do message << indent_char; end message << "#{addr}\n" end end message end #--------------------------------------------------------------------- # Class Methods #--------------------------------------------------------------------- def Email.from_xml( project, xml_node ) throw ArgumentError.new( 'Invalid email config node, name mismatch.' ) \ unless ( 'email' == xml_node.name ) env = Environment.new() project.fill_env( env ) xslt = env.subst( xml_node.attributes['xslt'] ) addresses = { :maintainer => xml_node.attributes['maintainer'], :from => xml_node.attributes['from'], :list => xml_node.attributes['list'].split( ',' ) } aliases = { :maintainer => xml_node.attributes['maintainer_friendly'], :from => xml_node.attributes['from_friendly'], :list => xml_node.attributes['list_friendly'].split( ',' ) } Email.new( xslt, addresses, aliases ) end end # # == Description # XML Configuration file parser. # class Configuration attr_reader :project attr_reader :branch_name attr_reader :config_filename # Config XML filename attr_reader :command_queue # Command queue options attr_reader :report # Report options def initialize( project, branch_name ) c = Pipeline::Config::instance() @project = project @branch_name = branch_name @targets = {} @config_filename = OS::Path.combine( c.toolsconfig, 'assetbuild.xml' ) reload( ) end def reload( ) @project.load_config() parse_xml( ) end def pretty_print( indent = 0, indent_char = "\t" ) puts ( pretty_string( indent, indent_char ) ) end def pretty_string( indent = 0, indent_char = "\t" ) message = "AssetBuild Configuration\n" (indent+1).times do message << indent_char; end message << "Config filename: #{@config_filename}\n" @targets.each_pair do |name, target| message << pretty_string( indent+1, indent_char ); end unless ( @targets.nil? ) message << @command_queue.pretty_string( indent+1, indent_char ) unless ( @command_queue.nil? ) message << @report.pretty_string( indent+1, indent_char ) unless ( @report.nil? ) message end #-------------------------------------------------------------------- # Private #-------------------------------------------------------------------- private def parse_xml( ) # Parse config XML file = File.new( @config_filename ) doc = REXML::Document.new( file ) @command_queue = CommandQueueOptions::from_xml( doc.root.elements['command_queue'] ) @report = Report::from_xml( @project, @branch_name, doc.root.elements['report'] ) end end end # AssetBuild module # End of config.rb