<commit_before>/* 
* Copyright 2004-2005 OpenSymphony 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License. You may obtain a copy 
* of the License at 
* 
*   http://www.apache.org/licenses/LICENSE-2.0 
*   
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
* License for the specific language governing permissions and limitations 
* under the License.
* 
*/

/*
* Previously Copyright (c) 2001-2004 <NAME>
*/

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;

using Common.Logging;

namespace Quartz.Job
{
	/// <summary>
	/// Built in job for executing native executables in a separate process.
	/// </summary>
	/// <author><NAME></author>
	/// <author><NAME></author>
	/// <author><NAME></author>
	public class NativeJob : IJob
	{
	    private readonly ILog log;

		/// <summary> 
		/// Required parameter that specifies the name of the command (executable) 
		/// to be ran.
		/// </summary>
		public const string PropertyCommand = "command";

		/// <summary> 
		/// Optional parameter that specifies the parameters to be passed to the
		/// executed command.
		/// </summary>
		public const string PropertyParameters = "parameters";


		/// <summary> 
		/// Optional parameter (value should be 'true' or 'false') that specifies 
		/// whether the job should wait for the execution of the native process to 
		/// complete before it completes.
		/// 
		/// <p>Defaults to <see langword="true" />.</p>  
		/// </summary>
		public const string PropertyWaitForProcess = "waitForProcess";

		/// <summary> 
		/// Optional parameter (value should be 'true' or 'false') that specifies 
		/// whether the spawned process's stdout and stderr streams should be 
		/// consumed.  If the process creates output, it is possible that it might
		/// 'hang' if the streams are not consumed.
		/// 
		/// <p>Defaults to <see langword="false" />.</p>  
		/// </summary>
		public const string PropertyConsumeStreams = "consumeStreams";


        /// <summary>
        /// Gets the log.
        /// </summary>
        /// <value>The log.</value>
	    protected ILog Log
	    {
	        get { return log; }
	    }

        /// <summary>
        /// Initializes a new instance of the <see cref="NativeJob"/> class.
        /// </summary>
	    public NativeJob()
	    {
            log = LogManager.GetLogger(typeof(NativeJob));
	    }

	    /*
		* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		* 
		* Interface.
		* 
		* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		*/

		/// <summary>
		/// Called by the <see cref="IScheduler" /> when a <see cref="Trigger" />
		/// fires that is associated with the <see cref="IJob" />.
		/// <p>
		/// The implementation may wish to set a  result object on the
		/// JobExecutionContext before this method exits.  The result itself
		/// is meaningless to Quartz, but may be informative to
		/// <see cref="IJobListener" />s or
		/// <see cref="ITriggerListener" />s that are watching the job's
		/// execution.
		/// </p>
		/// </summary>
		/// <param name="context"></param>
		public virtual void Execute(JobExecutionContext context)
		{
			JobDataMap data = context.MergedJobDataMap;

			String command = data.GetString(PropertyCommand);

			String parameters = data.GetString(PropertyParameters) ?? "";

		    bool wait = true;
			if (data.ContainsKey(PropertyWaitForProcess))
			{
				wait = data.GetBooleanValue(PropertyWaitForProcess);
			}
			bool consumeStreams = false;
			if (data.ContainsKey(PropertyConsumeStreams))
			{
				consumeStreams = data.GetBooleanValue(PropertyConsumeStreams);
			}

			int exitCode = RunNativeCommand(command, parameters, wait, consumeStreams);
		    context.Result = exitCode;
		}

		private int RunNativeCommand(String command, string parameters, bool wait, bool consumeStreams)
		{
			string[] cmd;
			string[] args = new string[2];
			args[0] = command;
			args[1] = parameters;
		    int result = -1;

			try
			{
				//with this variable will be done the swithcing
				string osName = Environment.GetEnvironmentVariable("OS");
                if (osName == null)
                {
                    throw new JobExecutionException("Could not read environment variable for OS");
                }

				if (osName.ToLower().IndexOf("windows") > -1)
				{
    				cmd = new string[args.Length + 2];
					cmd[0] = "cmd.exe";
					cmd[1] = "/C";
					for (int i = 0; i < args.Length; i++)
					{
						cmd[i + 2] = args[i];
					}
				}
                else if (osName.ToLower().IndexOf("linux") > -1) 
                {
                    cmd = new String[3];
                    cmd[0] = "/bin/sh";
                    cmd[1] = "-c";
                    cmd[2] = args[0] + " " + args[1];
                } 
                else 
                { 
                    // try this... 
                    cmd = args;
                }

				// Executes the command
				string temp = "";
				for (int i = 1; i < cmd.Length; i++)
				{
					temp += cmd[i] + " ";
				}

                temp = temp.Trim();

                Log.Info(string.Format(CultureInfo.InvariantCulture, "About to run {0} {1}...", cmd[0], temp));

				Process proc = new Process();
			    
                proc.StartInfo.FileName = cmd[0];
                proc.StartInfo.Arguments = temp;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
			    proc.StartInfo.CreateNoWindow = true;
			    proc.StartInfo.UseShellExecute = false;
			    proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.RedirectStandardOutput = true;
			    proc.Start();

				// Consumes the stdout from the process
				StreamConsumer stdoutConsumer = new StreamConsumer(this, proc.StandardOutput.BaseStream, "stdout");

				// Consumes the stderr from the process
				if (consumeStreams)
				{
					StreamConsumer stderrConsumer = new StreamConsumer(this, proc.StandardError.BaseStream, "stderr");
					stdoutConsumer.Start();
					stderrConsumer.Start();
				}

				if (wait)
				{
					proc.WaitForExit();
                    result = proc.ExitCode;
				}
				// any error message?
			    
			}
			catch (Exception x)
			{
				throw new JobExecutionException("Error launching native command: " + x.Message, x, false);
			}
            return result;
		}

		/// <summary> 
		/// Consumes data from the given input stream until EOF and prints the data to stdout
		/// </summary>
		/// <author>cooste</author>
		/// <author><NAME></author>
		internal class StreamConsumer : QuartzThread
		{
			internal NativeJob outer;
			internal Stream inputStream;
			internal string type;

            /// <summary>
            /// Initializes a new instance of the <see cref="StreamConsumer"/> class.
            /// </summary>
            /// <param name="enclosingInstance">The enclosing instance.</param>
            /// <param name="inputStream">The input stream.</param>
            /// <param name="type">The type.</param>
			public StreamConsumer(NativeJob enclosingInstance, Stream inputStream, string type)
			{
				outer = enclosingInstance;
				this.inputStream = inputStream;
				this.type = type;
			}

			/// <summary> 
			/// Runs this object as a separate thread, printing the contents of the input stream
			/// supplied during instantiation, to either Console. or stderr
			/// </summary>
			public override void Run()
			{
			    try
			    {
                    using (StreamReader br = new StreamReader(inputStream))
                    {
                        string line;

                        while ((line = br.ReadLine()) != null)
                        {
                            if (type == "stderr")
                            {
                                outer.Log.Warn(string.Format(CultureInfo.InvariantCulture, "{0}>{1}", type, line));
                            }
                            else
                            {
                                outer.Log.Info(string.Format(CultureInfo.InvariantCulture, "{0}>{1}", type, line));
                            }
                        }
                    }

			    }
				catch (IOException ioe)
				{
					outer.Log.Error(string.Format(CultureInfo.InvariantCulture, "Error consuming {0} stream of spawned process.", type), ioe);
				}
			}
		}
	}
}
<commit_msg>QRQRTZNET-154: Support for setting the working directory in NativeJob<commit_after>/* 
* Copyright 2004-2005 OpenSymphony 
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License. You may obtain a copy 
* of the License at 
* 
*   http://www.apache.org/licenses/LICENSE-2.0 
*   
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
* License for the specific language governing permissions and limitations 
* under the License.
* 
*/

/*
* Previously Copyright (c) 2001-2004 <NAME>
*/

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;

using Common.Logging;

namespace Quartz.Job
{
	/// <summary>
	/// Built in job for executing native executables in a separate process.
	/// </summary>
	/// <author><NAME></author>
	/// <author>James House</author>
	/// <author><NAME></author>
	public class NativeJob : IJob
	{
	    private readonly ILog log;

		/// <summary> 
		/// Required parameter that specifies the name of the command (executable) 
		/// to be ran.
		/// </summary>
		public const string PropertyCommand = "command";

		/// <summary> 
		/// Optional parameter that specifies the parameters to be passed to the
		/// executed command.
		/// </summary>
		public const string PropertyParameters = "parameters";

		/// <summary> 
		/// Optional parameter (value should be 'true' or 'false') that specifies 
		/// whether the job should wait for the execution of the native process to 
		/// complete before it completes.
		/// 
		/// <p>Defaults to <see langword="true" />.</p>  
		/// </summary>
		public const string PropertyWaitForProcess = "waitForProcess";

		/// <summary> 
		/// Optional parameter (value should be 'true' or 'false') that specifies 
		/// whether the spawned process's stdout and stderr streams should be 
		/// consumed.  If the process creates output, it is possible that it might
		/// 'hang' if the streams are not consumed.
		/// 
		/// <p>Defaults to <see langword="false" />.</p>  
		/// </summary>
		public const string PropertyConsumeStreams = "consumeStreams";

        /// <summary> 
        /// Optional parameter that specifies the workling directory to be used by 
        /// the executed command.
        /// </summary>
        public const string PropertyWorkingDirectory = "workingDirectory";


        /// <summary>
        /// Gets the log.
        /// </summary>
        /// <value>The log.</value>
	    protected ILog Log
	    {
	        get { return log; }
	    }

        /// <summary>
        /// Initializes a new instance of the <see cref="NativeJob"/> class.
        /// </summary>
	    public NativeJob()
	    {
            log = LogManager.GetLogger(typeof(NativeJob));
	    }

	    /*
		* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		* 
		* Interface.
		* 
		* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		*/

		/// <summary>
		/// Called by the <see cref="IScheduler" /> when a <see cref="Trigger" />
		/// fires that is associated with the <see cref="IJob" />.
		/// <p>
		/// The implementation may wish to set a  result object on the
		/// JobExecutionContext before this method exits.  The result itself
		/// is meaningless to Quartz, but may be informative to
		/// <see cref="IJobListener" />s or
		/// <see cref="ITriggerListener" />s that are watching the job's
		/// execution.
		/// </p>
		/// </summary>
		/// <param name="context"></param>
		public virtual void Execute(JobExecutionContext context)
		{
			JobDataMap data = context.MergedJobDataMap;

			String command = data.GetString(PropertyCommand);

			String parameters = data.GetString(PropertyParameters) ?? "";

		    bool wait = true;
			if (data.ContainsKey(PropertyWaitForProcess))
			{
				wait = data.GetBooleanValue(PropertyWaitForProcess);
			}
			bool consumeStreams = false;
			if (data.ContainsKey(PropertyConsumeStreams))
			{
				consumeStreams = data.GetBooleanValue(PropertyConsumeStreams);
			}

            string workingDirectory = data.GetString(PropertyWorkingDirectory);

			int exitCode = RunNativeCommand(command, parameters, workingDirectory, wait, consumeStreams);
		    context.Result = exitCode;
		}

		private int RunNativeCommand(String command, string parameters, string workingDirectory, bool wait, bool consumeStreams)
		{
			string[] cmd;
			string[] args = new string[2];
			args[0] = command;
			args[1] = parameters;
		    int result = -1;

			try
			{
				//with this variable will be done the swithcing
				string osName = Environment.GetEnvironmentVariable("OS");
                if (osName == null)
                {
                    throw new JobExecutionException("Could not read environment variable for OS");
                }

				if (osName.ToLower().IndexOf("windows") > -1)
				{
    				cmd = new string[args.Length + 2];
					cmd[0] = "cmd.exe";
					cmd[1] = "/C";
					for (int i = 0; i < args.Length; i++)
					{
						cmd[i + 2] = args[i];
					}
				}
                else if (osName.ToLower().IndexOf("linux") > -1) 
                {
                    cmd = new String[3];
                    cmd[0] = "/bin/sh";
                    cmd[1] = "-c";
                    cmd[2] = args[0] + " " + args[1];
                } 
                else 
                { 
                    // try this... 
                    cmd = args;
                }

				// Executes the command
				string temp = "";
				for (int i = 1; i < cmd.Length; i++)
				{
					temp += cmd[i] + " ";
				}

                temp = temp.Trim();

                Log.Info(string.Format(CultureInfo.InvariantCulture, "About to run {0} {1}...", cmd[0], temp));

				Process proc = new Process();
			    
                proc.StartInfo.FileName = cmd[0];
                proc.StartInfo.Arguments = temp;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
			    proc.StartInfo.CreateNoWindow = true;
			    proc.StartInfo.UseShellExecute = false;
			    proc.StartInfo.RedirectStandardError = true;
                proc.StartInfo.RedirectStandardOutput = true;

                if (!String.IsNullOrEmpty(workingDirectory))
                {
                    proc.StartInfo.WorkingDirectory = workingDirectory;
                }

			    proc.Start();

				// Consumes the stdout from the process
				StreamConsumer stdoutConsumer = new StreamConsumer(this, proc.StandardOutput.BaseStream, "stdout");

				// Consumes the stderr from the process
				if (consumeStreams)
				{
					StreamConsumer stderrConsumer = new StreamConsumer(this, proc.StandardError.BaseStream, "stderr");
					stdoutConsumer.Start();
					stderrConsumer.Start();
				}

				if (wait)
				{
					proc.WaitForExit();
                    result = proc.ExitCode;
				}
				// any error message?
			    
			}
			catch (Exception x)
			{
				throw new JobExecutionException("Error launching native command: " + x.Message, x, false);
			}
            return result;
		}

		/// <summary> 
		/// Consumes data from the given input stream until EOF and prints the data to stdout
		/// </summary>
		/// <author>cooste</author>
		/// <author><NAME></author>
		internal class StreamConsumer : QuartzThread
		{
			internal NativeJob outer;
			internal Stream inputStream;
			internal string type;

            /// <summary>
            /// Initializes a new instance of the <see cref="StreamConsumer"/> class.
            /// </summary>
            /// <param name="enclosingInstance">The enclosing instance.</param>
            /// <param name="inputStream">The input stream.</param>
            /// <param name="type">The type.</param>
			public StreamConsumer(NativeJob enclosingInstance, Stream inputStream, string type)
			{
				outer = enclosingInstance;
				this.inputStream = inputStream;
				this.type = type;
			}

			/// <summary> 
			/// Runs this object as a separate thread, printing the contents of the input stream
			/// supplied during instantiation, to either Console. or stderr
			/// </summary>
			public override void Run()
			{
			    try
			    {
                    using (StreamReader br = new StreamReader(inputStream))
                    {
                        string line;

                        while ((line = br.ReadLine()) != null)
                        {
                            if (type == "stderr")
                            {
                                outer.Log.Warn(string.Format(CultureInfo.InvariantCulture, "{0}>{1}", type, line));
                            }
                            else
                            {
                                outer.Log.Info(string.Format(CultureInfo.InvariantCulture, "{0}>{1}", type, line));
                            }
                        }
                    }

			    }
				catch (IOException ioe)
				{
					outer.Log.Error(string.Format(CultureInfo.InvariantCulture, "Error consuming {0} stream of spawned process.", type), ioe);
				}
			}
		}
	}
}

{'fraction_non_alphanumeric': 0.1304608999563128, 'fraction_numerical': 0.005297072957623416, 'mean_word_length': 1.8326372776488786, 'pattern_counts': {'":': 0, '<': 132, '<?xml version=': 0, '>': 136, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5420532', 'n_tokens_mistral': 5724, 'n_tokens_neox': 4778, 'n_words': 1428}