Beispiel #1
0
        /// <summary>
        /// Uses reflection to loop through the BatchDescription and JobDescriptions and update
        /// any property with a RelativePath attribute so that they start with the path from
        /// the current execution directory to the configuration directory.
        /// </summary>
        private static void SetPathsRelativeToConfigFile(string configFile, BatchDescription <J> batch)
        {
            var configPath = Path.GetDirectoryName(configFile);

            var batchType    = batch.GetType();
            var batchMembers = batchType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);

            foreach (var member in batchMembers)
            {
                var attributes = member.GetCustomAttributes(typeof(RelativePathAttribute), false);
                if (attributes.Length > 0)
                {
                    var prop = batchType.GetProperty(member.Name, BindingFlags.Public | BindingFlags.Instance);
                    if (prop != null && prop.CanWrite)
                    {
                        var value = (string)prop.GetValue(batch);
                        if (!string.IsNullOrEmpty(value))
                        {
                            prop.SetValue(batch, Path.Combine(configPath, value), null);
                        }
                    }
                }
            }

            foreach (var job in batch.Jobs)
            {
                var jobType    = job.GetType();
                var jobMembers = jobType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
                foreach (var member in jobMembers)
                {
                    var attributes = member.GetCustomAttributes(typeof(RelativePathAttribute), false);
                    if (attributes.Length > 0)
                    {
                        var prop = jobType.GetProperty(member.Name, BindingFlags.Public | BindingFlags.Instance);
                        if (prop != null && prop.CanWrite)
                        {
                            var value = prop.GetValue(job);
                            if (value is string)
                            {
                                prop.SetValue(job, Path.Combine(configPath, (string)value), null);
                            }
                            else if (value is string[])
                            {
                                var paths = (string[])value;
                                for (int i = 0; i < paths.Length; i++)
                                {
                                    paths[i] = Path.Combine(configPath, paths[i]);
                                }

                                prop.SetValue(job, paths, null);
                            }
                        }
                    }
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Process command line arguments, deserialize job configuration data, instantiate the
        /// PowerTool, and process each job.
        /// </summary>
        public override ExitCode Run(string[] args)
        {
            var toolDescription = (PowerToolAttribute)Attribute.GetCustomAttribute(typeof(T), typeof(PowerToolAttribute));
            var result          = ExitCode.Success;

            string configFile = null;
            bool   showHelp   = false;
            bool   isVerbose  = false;

            var options = new OptionSet()
                          .Add("v|verbose", "All logging will be written to the console.", v => isVerbose = v != null)
                          .Add("h|?|help", "Prints this help message.", v => showHelp           = v != null)
                          .Add("config=", "{PATH} to JSON configuration file.", v => configFile = v);

            try
            {
                var extra = options.Parse(args);
            }
            catch
            {
                Console.WriteLine("Error parsing options.");
                result = ExitCode.UnexpectedOptions;
            }

            if (result != ExitCode.Success)
            {
                // No-op
            }
            else if (showHelp || string.IsNullOrEmpty(configFile))
            {
                // Print help
                Console.WriteLine("{0}: {1}", toolDescription.Name, toolDescription.Description);
                Console.WriteLine("How to operate:");
                options.WriteOptionDescriptions(Console.Out);
            }
            else if (!File.Exists(configFile))
            {
                // No configuration file
                this.Error("Configuration file not found.");
                result = ExitCode.ConfigurationFileNotFound;
            }
            else
            {
                PowerToolConsoleProgram <T, J> .ConfigureVerbosity(isVerbose);

                // A batch contains common high level information for a PowerTool as well as a list of jobs.
                BatchDescription <J> batch = null;
                try
                {
                    batch = JsonConvert.DeserializeObject <BatchDescription <J> >(File.ReadAllText(configFile));
                }
                catch (Exception e) when(e is JsonSerializationException || e is JsonReaderException)
                {
                    this.Info("Failed to parse JSON: {0}", e.Message);
                    this.Error("Configuration file could not be parsed.");
                    result = ExitCode.BadConfiguration;
                }

                if (result == ExitCode.Success)
                {
                    PowerToolConsoleProgram <T, J> .SetPathsRelativeToConfigFile(configFile, batch);

                    PowerToolConsoleProgram <T, J> .ConfigureLoggingToFile(batch.LogFilePath);

                    var logger = new NLogAdapter(PowerToolConsoleProgram <T, J> .logger);
                    if (string.IsNullOrEmpty(batch.OutputFolderPath))
                    {
                        this.Error("No output directory specified.");
                        result = ExitCode.BadConfiguration;
                    }
                    else
                    {
                        if (!Directory.Exists(batch.OutputFolderPath))
                        {
                            this.Info("Creating output directory: {0}", batch.OutputFolderPath);
                            Directory.CreateDirectory(batch.OutputFolderPath);
                        }

                        if (batch.Jobs == null)
                        {
                            this.Warn("No jobs defined.");
                        }
                        else
                        {
                            var worker = new T();
                            worker.Setup(batch, logger);

                            this.Info("Starting {0} jobs", batch.Jobs.Length);

                            var processedJobs = new HashSet <string>();
                            int i             = 0;

                            foreach (var job in batch.Jobs)
                            {
                                if (processedJobs.Contains(job.Name))
                                {
                                    this.Warn("Duplicate job name: {0}. Skipping job.", job.Name);
                                    continue;
                                }

                                if (result != ExitCode.Success)
                                {
                                    break;
                                }

                                result = worker.Process(job);
                                processedJobs.Add(job.Name);

                                i++;
                                this.Info("Finished job {0} of {1}", i, batch.Jobs.Length);
                            }
                        }
                    }
                }
            }

            Console.WriteLine(
                "Finished running tool: {0}. Exited with code: {1:N0} {2}",
                toolDescription.Name,
                (int)result,
                PowerToolConsoleProgram <T, J> .GetExitCodeDescription(result));
            return(result);
        }
 internal void Setup(BatchDescription <T> batch, ILogAdapter logger)
 {
     this.batch  = batch;
     this.logger = logger;
 }