MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Diagnostics.CodeAnalysis;7using System.IO;8using System.Linq;9using System.Management.Automation.Runspaces;10using System.Runtime.Serialization;11 12// Stops compiler from warning about unknown warnings13#pragma warning disable 1634, 169114 15namespace System.Management.Automation16{17 /// <summary>18 /// Contains the definition of a job which is defined in a19 /// job store.20 /// </summary>21 /// <remarks>The actual implementation of this class will22 /// happen in M2</remarks>23 public class JobDefinition : ISerializable24 {25 private string _name;26 27 /// <summary>28 /// A friendly Name for this definition.29 /// </summary>30 public string Name31 {32 get { return _name; }33 34 set { _name = value; }35 }36 37 /// <summary>38 /// The type that derives from JobSourceAdapter39 /// that contains the logic for invocation and40 /// management of this type of job.41 /// </summary>42 public Type JobSourceAdapterType { get; }43 44 private string _moduleName;45 46 /// <summary>47 /// Module name for the module containing48 /// the source adapter implementation.49 /// </summary>50 public string ModuleName51 {52 get { return _moduleName; }53 54 set { _moduleName = value; }55 }56 57 private string _jobSourceAdapterTypeName;58 59 /// <summary>60 /// Job source adapter type name.61 /// </summary>62 public string JobSourceAdapterTypeName63 {64 get { return _jobSourceAdapterTypeName; }65 66 set { _jobSourceAdapterTypeName = value; }67 }68 69 /// <summary>70 /// Name of the job that needs to be loaded71 /// from the specified module.72 /// </summary>73 public string Command { get; }74 75 private Guid _instanceId;76 77 /// <summary>78 /// Unique Guid for this job definition.79 /// </summary>80 public Guid InstanceId81 {82 get83 {84 return _instanceId;85 }86 87 set88 {89 _instanceId = value;90 }91 }92 93 /// <summary>94 /// Save this definition to the specified95 /// file on disk.96 /// </summary>97 /// <param name="stream">Stream to save to.</param>98 public virtual void Save(Stream stream)99 {100 throw new NotImplementedException();101 }102 103 /// <summary>104 /// Load this definition from the specified105 /// file on disk.106 /// </summary>107 /// <param name="stream"></param>108 public virtual void Load(Stream stream)109 {110 throw new NotImplementedException();111 }112 113 /// <summary>114 /// Returns information about this job like115 /// name, definition, parameters etc.116 /// </summary>117 public CommandInfo CommandInfo118 {119 get120 {121 return null;122 }123 }124 125 /// <summary>126 /// Public constructor for testing.127 /// </summary>128 /// <param name="jobSourceAdapterType">Type of adapter to use to create a job.</param>129 /// <param name="command">The command string.</param>130 /// <param name="name">The job name.</param>131 public JobDefinition(Type jobSourceAdapterType, string command, string name)132 {133 JobSourceAdapterType = jobSourceAdapterType;134 if (jobSourceAdapterType != null)135 {136 _jobSourceAdapterTypeName = jobSourceAdapterType.Name;137 }138 139 Command = command;140 _name = name;141 _instanceId = Guid.NewGuid();142 }143 144 /// <summary>145 /// </summary>146 /// <param name="info"></param>147 /// <param name="context"></param>148 protected JobDefinition(SerializationInfo info, StreamingContext context)149 {150 throw new NotImplementedException();151 }152 153 /// <summary>154 /// </summary>155 /// <param name="info"></param>156 /// <param name="context"></param>157 public virtual void GetObjectData(SerializationInfo info, StreamingContext context)158 {159 throw new NotImplementedException();160 }161 }162 163 /// <summary>164 /// Class that helps define the parameters to165 /// be passed to a job so that the job can be166 /// instantiated without having to specify167 /// the parameters explicitly. Helps in168 /// passing job parameters to disk.169 /// </summary>170 /// <remarks>This class is not required if171 /// CommandParameterCollection adds a public172 /// constructor.The actual implementation of173 /// this class will happen in M2</remarks>174 public class JobInvocationInfo : ISerializable175 {176 /// <summary>177 /// Friendly name associated with this specification.178 /// </summary>179 public string Name180 {181 get182 {183 return _name;184 }185 186 set187 {188 if (value == null)189 throw new PSArgumentNullException("value");190 _name = value;191 }192 }193 194 private string _name = string.Empty;195 196 private string _command;197 198 /// <summary>199 /// Command string to execute.200 /// </summary>201 public string Command202 {203 get204 {205 return _command ?? _definition.Command;206 }207 208 set209 {210 _command = value;211 }212 }213 214 private JobDefinition _definition;215 216 /// <summary>217 /// Definition associated with the job.218 /// </summary>219 public JobDefinition Definition220 {221 get222 {223 return _definition;224 }225 226 set227 {228 _definition = value;229 }230 }231 232 private List<CommandParameterCollection> _parameters;233 234 /// <summary>235 /// Parameters associated with this specification.236 /// </summary>237 public List<CommandParameterCollection> Parameters238 {239 get { return _parameters ??= new List<CommandParameterCollection>(); }240 }241 242 /// <summary>243 /// Unique identifies for this specification.244 /// </summary>245 public Guid InstanceId { get; } = Guid.NewGuid();246 247 /// <summary>248 /// Save this specification to a file.249 /// </summary>250 /// <param name="stream">Stream to save to.</param>251 public virtual void Save(Stream stream)252 {253 throw new NotImplementedException();254 }255 256 /// <summary>257 /// Load this specification from a file.258 /// </summary>259 /// <param name="stream">Stream to load from.</param>260 public virtual void Load(Stream stream)261 {262 throw new NotImplementedException();263 }264 265 /// <summary>266 /// Constructor.267 /// </summary>268 protected JobInvocationInfo()269 { }270 271 /// <summary>272 /// Create a new job definition with a single set of parameters.273 /// </summary>274 /// <param name="definition">The job definition.</param>275 /// <param name="parameters">The parameter collection to use.</param>276 public JobInvocationInfo(JobDefinition definition, Dictionary<string, object> parameters)277 {278 _definition = definition;279 var convertedCollection = ConvertDictionaryToParameterCollection(parameters);280 if (convertedCollection != null)281 {282 Parameters.Add(convertedCollection);283 }284 }285 286 /// <summary>287 /// Create a new job definition with a multiple sets of parameters. This allows288 /// different parameters for different machines.289 /// </summary>290 /// <param name="definition">The job definition.</param>291 /// <param name="parameterCollectionList">Collection of sets of parameters to use for the child jobs.</param>292 [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",293 Justification = "This is forced by the interaction of PowerShell and Workflow.")]294 public JobInvocationInfo(JobDefinition definition, IEnumerable<Dictionary<string, object>> parameterCollectionList)295 {296 _definition = definition;297 if (parameterCollectionList == null) return;298 foreach (var parameterCollection in parameterCollectionList)299 {300 if (parameterCollection == null) continue;301 CommandParameterCollection convertedCollection = ConvertDictionaryToParameterCollection(parameterCollection);302 if (convertedCollection != null)303 {304 Parameters.Add(convertedCollection);305 }306 }307 }308 309 /// <summary>310 /// </summary>311 /// <param name="definition"></param>312 /// <param name="parameters"></param>313 public JobInvocationInfo(JobDefinition definition, CommandParameterCollection parameters)314 {315 _definition = definition;316 Parameters.Add(parameters ?? new CommandParameterCollection());317 }318 319 /// <summary>320 /// </summary>321 /// <param name="definition"></param>322 /// <param name="parameters"></param>323 public JobInvocationInfo(JobDefinition definition, IEnumerable<CommandParameterCollection> parameters)324 {325 _definition = definition;326 if (parameters == null) return;327 foreach (var parameter in parameters)328 {329 Parameters.Add(parameter);330 }331 }332 333 /// <summary>334 /// </summary>335 /// <param name="info"></param>336 /// <param name="context"></param>337 protected JobInvocationInfo(SerializationInfo info, StreamingContext context)338 {339 throw new NotImplementedException();340 }341 342 /// <summary>343 /// </summary>344 /// <param name="info"></param>345 /// <param name="context"></param>346 public virtual void GetObjectData(SerializationInfo info, StreamingContext context)347 {348 throw new NotImplementedException();349 }350 351 /// <summary>352 /// Utility function to turn a dictionary of name/value pairs into a parameter collection.353 /// </summary>354 /// <param name="parameters">The dictionary to convert.</param>355 /// <returns>The converted collection.</returns>356 private static CommandParameterCollection ConvertDictionaryToParameterCollection(IEnumerable<KeyValuePair<string, object>> parameters)357 {358 if (parameters == null)359 return null;360 CommandParameterCollection paramCollection = new CommandParameterCollection();361 foreach (CommandParameter paramItem in362 parameters.Select(static param => new CommandParameter(param.Key, param.Value)))363 {364 paramCollection.Add(paramItem);365 }366 367 return paramCollection;368 }369 }370 371 /// <summary>372 /// Abstract class for a job store which will373 /// contain the jobs of a specific type.374 /// </summary>375 public abstract class JobSourceAdapter376 {377 /// <summary>378 /// Name for this store.379 /// </summary>380 public string Name { get; set; } = string.Empty;381 382 /// <summary>383 /// Get a token that allows for construction of a job with a previously assigned384 /// Id and InstanceId. This is only possible if this JobSourceAdapter is the385 /// creator of the original job.386 /// The original job must have been saved using "SaveJobIdForReconstruction"387 /// </summary>388 /// <param name="instanceId">Instance Id of the job to recreate.</param>389 /// <returns>JobIdentifier to be used in job construction.</returns>390 protected JobIdentifier RetrieveJobIdForReuse(Guid instanceId)391 {392 return JobManager.GetJobIdentifier(instanceId, this.GetType().Name);393 }394 395 /// <summary>396 /// Saves the Id information for a job so that it can be constructed at a later time.397 /// This will only allow this job source adapter type to recreate the job.398 /// </summary>399 /// <param name="job">The job whose id information to store.</param>400 /// <param name="recurse">Recurse to save child job Ids.</param>401 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Only jobs that derive from Job2 should have reusable IDs.")]402 public void StoreJobIdForReuse(Job2 job, bool recurse)403 {404 if (job == null)405 {406 PSTraceSource.NewArgumentNullException(nameof(job), RemotingErrorIdStrings.JobSourceAdapterCannotSaveNullJob);407 }408 409 JobManager.SaveJobId(job.InstanceId, job.Id, this.GetType().Name);410 if (recurse && job.ChildJobs != null && job.ChildJobs.Count > 0)411 {412 Hashtable duplicateDetector = new Hashtable();413 duplicateDetector.Add(job.InstanceId, job.InstanceId);414 foreach (Job child in job.ChildJobs)415 {416 if (child is not Job2 childJob) continue;417 StoreJobIdForReuseHelper(duplicateDetector, childJob, true);418 }419 }420 }421 422 private void StoreJobIdForReuseHelper(Hashtable duplicateDetector, Job2 job, bool recurse)423 {424 if (duplicateDetector.ContainsKey(job.InstanceId)) return;425 duplicateDetector.Add(job.InstanceId, job.InstanceId);426 427 JobManager.SaveJobId(job.InstanceId, job.Id, this.GetType().Name);428 429 if (!recurse || job.ChildJobs == null) return;430 foreach (Job child in job.ChildJobs)431 {432 if (child is not Job2 childJob) continue;433 StoreJobIdForReuseHelper(duplicateDetector, childJob, recurse);434 }435 }436 437 /// <summary>438 /// Create a new job with the specified definition.439 /// </summary>440 /// <param name="definition">Job definition to use.</param>441 /// <returns>Job object.</returns>442 public Job2 NewJob(JobDefinition definition)443 {444 return NewJob(new JobInvocationInfo(definition, new Dictionary<string, object>()));445 }446 447 /// <summary>448 /// Creates a new job with the definition as specified by449 /// the provided definition name and path. If path is null450 /// then a default location will be used to find the job451 /// definition by name.452 /// </summary>453 /// <param name="definitionName">Job definition name.</param>454 /// <param name="definitionPath">Job definition file path.</param>455 /// <returns>Job2 object.</returns>456 public virtual Job2 NewJob(string definitionName, string definitionPath)457 {458 return null;459 }460 461 /// <summary>462 /// Create a new job with the specified JobSpecification.463 /// </summary>464 /// <param name="specification">Specification.</param>465 /// <returns>Job object.</returns>466 public abstract Job2 NewJob(JobInvocationInfo specification);467 468 /// <summary>469 /// Get the list of jobs that are currently available in this470 /// store.471 /// </summary>472 /// <returns>Collection of job objects.</returns>473 public abstract IList<Job2> GetJobs();474 475 /// <summary>476 /// Get list of jobs that matches the specified names.477 /// </summary>478 /// <param name="name">names to match, can support479 /// wildcard if the store supports</param>480 /// <param name="recurse"></param>481 /// <returns>Collection of jobs that match the specified482 /// criteria.</returns>483 public abstract IList<Job2> GetJobsByName(string name, bool recurse);484 485 /// <summary>486 /// Get list of jobs that run the specified command.487 /// </summary>488 /// <param name="command">Command to match.</param>489 /// <param name="recurse"></param>490 /// <returns>Collection of jobs that match the specified491 /// criteria.</returns>492 public abstract IList<Job2> GetJobsByCommand(string command, bool recurse);493 494 /// <summary>495 /// Get list of jobs that has the specified id.496 /// </summary>497 /// <param name="instanceId">Guid to match.</param>498 /// <param name="recurse"></param>499 /// <returns>Job with the specified guid.</returns>500 public abstract Job2 GetJobByInstanceId(Guid instanceId, bool recurse);501 502 /// <summary>503 /// Get job that has specific session id.504 /// </summary>505 /// <param name="id">Id to match.</param>506 /// <param name="recurse"></param>507 /// <returns>Job with the specified id.</returns>508 public abstract Job2 GetJobBySessionId(int id, bool recurse);509 510 /// <summary>511 /// Get list of jobs that are in the specified state.512 /// </summary>513 /// <param name="state">State to match.</param>514 /// <param name="recurse"></param>515 /// <returns>Collection of jobs with the specified516 /// state.</returns>517 public abstract IList<Job2> GetJobsByState(JobState state, bool recurse);518 519 /// <summary>520 /// Get list of jobs based on the adapter specific521 /// filter parameters.522 /// </summary>523 /// <param name="filter">dictionary containing name value524 /// pairs for adapter specific filters</param>525 /// <param name="recurse"></param>526 /// <returns>Collection of jobs that match the527 /// specified criteria.</returns>528 public abstract IList<Job2> GetJobsByFilter(Dictionary<string, object> filter, bool recurse);529 530 /// <summary>531 /// Remove a job from the store.532 /// </summary>533 /// <param name="job">Job object to remove.</param>534 public abstract void RemoveJob(Job2 job);535 536 /// <summary>537 /// Saves the job to a persisted store.538 /// </summary>539 /// <param name="job">Job2 type job to persist.</param>540 public virtual void PersistJob(Job2 job)541 {542 // Implemented only if job needs to be told when to persist.543 }544 }545}546 