winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

ConfigurationSetProcessorBase.cs (10614B)


      1 // -----------------------------------------------------------------------------
      2 // <copyright file="ConfigurationSetProcessorBase.cs" company="Microsoft Corporation">
      3 //     Copyright (c) Microsoft Corporation. Licensed under the MIT License.
      4 // </copyright>
      5 // -----------------------------------------------------------------------------
      6 
      7 namespace Microsoft.Management.Configuration.Processor.Set
      8 {
      9     using System;
     10     using System.Collections.Generic;
     11     using System.Runtime.CompilerServices;
     12     using Microsoft.Management.Configuration.Processor.Extensions;
     13     using Microsoft.Management.Configuration.Processor.Factory;
     14     using Microsoft.Management.Configuration.Processor.Unit;
     15 
     16     /// <summary>
     17     /// IConfigurationSetProcessor base implementation.
     18     /// </summary>
     19     internal abstract partial class ConfigurationSetProcessorBase
     20     {
     21         private readonly ConfigurationSet? configurationSet;
     22         private List<ConfigurationUnit> limitUnitList = new List<ConfigurationUnit>();
     23 
     24         /// <summary>
     25         /// Initializes a new instance of the <see cref="ConfigurationSetProcessorBase"/> class.
     26         /// </summary>
     27         /// <param name="configurationSet">Configuration set.</param>
     28         /// <param name="isLimitMode">Whether the set processor should work in limitation mode.</param>
     29         public ConfigurationSetProcessorBase(ConfigurationSet? configurationSet, bool isLimitMode)
     30         {
     31             this.configurationSet = configurationSet;
     32             this.IsLimitMode = isLimitMode;
     33 
     34             // In limit mode, configurationSet is the limitation set to be used. It cannot be null.
     35             if (this.IsLimitMode)
     36             {
     37                 if (this.configurationSet == null)
     38                 {
     39                     throw new ArgumentNullException(nameof(configurationSet), "configurationSet is required in limit mode.");
     40                 }
     41 
     42                 foreach (var unit in this.configurationSet.Units)
     43                 {
     44                     this.limitUnitList.Add(unit);
     45                 }
     46             }
     47         }
     48 
     49         /// <summary>
     50         /// Gets or initializes the set processor factory.
     51         /// </summary>
     52         internal ConfigurationSetProcessorFactoryBase? SetProcessorFactory { get; init; }
     53 
     54         /// <summary>
     55         /// Gets a value indicating whether the set processor is running in limit mode.
     56         /// </summary>
     57         internal bool IsLimitMode { get; private set; }
     58 
     59         /// <summary>
     60         /// Gets the configuration set for this processor.
     61         /// </summary>
     62         protected ConfigurationSet? ConfigurationSet
     63         {
     64             get { return this.configurationSet; }
     65         }
     66 
     67         /// <summary>
     68         /// Creates a configuration unit processor for the given unit.
     69         /// </summary>
     70         /// <param name="incomingUnit">Configuration unit.</param>
     71         /// <returns>A configuration unit processor.</returns>
     72         public IConfigurationUnitProcessor CreateUnitProcessor(ConfigurationUnit incomingUnit)
     73         {
     74             try
     75             {
     76                 this.OnDiagnostics(DiagnosticLevel.Informational, $"GetUnitProcessorDetails is running in limit mode: {this.IsLimitMode}.");
     77 
     78                 // CreateUnitProcessor can only be called once on each configuration unit in limit mode.
     79                 var unit = this.GetConfigurationUnit(incomingUnit, true);
     80 
     81                 IConfigurationUnitProcessor result = this.CreateUnitProcessorInternal(unit);
     82 
     83                 this.OnDiagnostics(DiagnosticLevel.Verbose, "... done creating unit processor.");
     84 
     85                 return result;
     86             }
     87             catch (Exception ex)
     88             {
     89                 this.OnDiagnostics(DiagnosticLevel.Error, ex.ToString());
     90                 throw;
     91             }
     92         }
     93 
     94         /// <summary>
     95         /// Gets the configuration unit processor details for the given unit.
     96         /// </summary>
     97         /// <param name="incomingUnit">Configuration unit.</param>
     98         /// <param name="detailFlags">Detail flags.</param>
     99         /// <returns>Configuration unit processor details.</returns>
    100         public IConfigurationUnitProcessorDetails? GetUnitProcessorDetails(ConfigurationUnit incomingUnit, ConfigurationUnitDetailFlags detailFlags)
    101         {
    102             try
    103             {
    104                 this.OnDiagnostics(DiagnosticLevel.Informational, $"GetUnitProcessorDetails is running in limit mode: {this.IsLimitMode}.");
    105 
    106                 // GetUnitProcessorDetails can be invoked multiple times on each configuration unit in limit mode.
    107                 var unit = this.GetConfigurationUnit(incomingUnit);
    108 
    109                 return this.GetUnitProcessorDetailsInternal(unit, detailFlags);
    110             }
    111             catch (Exception ex)
    112             {
    113                 this.OnDiagnostics(DiagnosticLevel.Error, ex.ToString());
    114                 throw;
    115             }
    116         }
    117 
    118         /// <summary>
    119         /// Gets all configuration units for the given unit type.
    120         /// Returned units may be of types other than the one passed in.
    121         /// </summary>
    122         /// <param name="findOptions">Find unit processors options.</param>
    123         /// <returns>A list of unit processor details.</returns>
    124         public IList<IConfigurationUnitProcessorDetails> FindUnitProcessors(FindUnitProcessorsOptions findOptions)
    125         {
    126             try
    127             {
    128                 this.OnDiagnostics(DiagnosticLevel.Verbose, $"Invoking `FindUnitProcessors` ...");
    129 
    130                 return this.FindUnitProcessorsInternal(findOptions);
    131             }
    132             catch (Exception ex)
    133             {
    134                 this.OnDiagnostics(DiagnosticLevel.Error, ex.ToString());
    135                 throw;
    136             }
    137         }
    138 
    139         /// <summary>
    140         /// Creates a configuration unit processor for the given unit.
    141         /// </summary>
    142         /// <param name="unit">Configuration unit.</param>
    143         /// <returns>A configuration unit processor.</returns>
    144         protected abstract IConfigurationUnitProcessor CreateUnitProcessorInternal(ConfigurationUnit unit);
    145 
    146         /// <summary>
    147         /// Gets the configuration unit processor details for the given unit.
    148         /// </summary>
    149         /// <param name="unit">Configuration unit.</param>
    150         /// <param name="detailFlags">Detail flags.</param>
    151         /// <returns>Configuration unit processor details.</returns>
    152         protected abstract IConfigurationUnitProcessorDetails? GetUnitProcessorDetailsInternal(ConfigurationUnit unit, ConfigurationUnitDetailFlags detailFlags);
    153 
    154         /// <summary>
    155         /// Finds unit processors based on the input FindUnitProcessorsOptions.
    156         /// Derive from IFindUnitProcessorsSetProcessor and implement an override to support this.
    157         /// </summary>
    158         /// <param name="findOptions">Find unit processors options.</param>
    159         /// <returns>A list of unit processor details.</returns>
    160         protected virtual IList<IConfigurationUnitProcessorDetails> FindUnitProcessorsInternal(FindUnitProcessorsOptions findOptions)
    161         {
    162             throw new NotImplementedException("Configuration set processor did not implement FindUnitProcessorsInternal.");
    163         }
    164 
    165         /// <summary>
    166         /// Sends diagnostics to factory.
    167         /// </summary>
    168         /// <param name="level">The level of this diagnostic message.</param>
    169         /// <param name="message">The diagnostic message.</param>
    170         protected void OnDiagnostics(DiagnosticLevel level, string message)
    171         {
    172             this.SetProcessorFactory?.OnDiagnostics(level, message);
    173         }
    174 
    175         private static bool ConfigurationUnitEquals(ConfigurationUnit first, ConfigurationUnit second)
    176         {
    177             var firstIdentifier = first.Identifier;
    178             var firstIntent = first.Intent;
    179             var firstType = first.Type;
    180             var secondIdentifier = second.Identifier;
    181             var secondType = second.Type;
    182             var secondIntent = second.Intent;
    183 
    184             if (firstIdentifier != secondIdentifier ||
    185                 firstType != secondType ||
    186                 firstIntent != secondIntent)
    187             {
    188                 return false;
    189             }
    190 
    191             var firstEnvironment = first.Environment;
    192             var secondEnvironment = second.Environment;
    193             if (firstEnvironment.Context != secondEnvironment.Context ||
    194                 firstEnvironment.ProcessorIdentifier != secondEnvironment.ProcessorIdentifier ||
    195                 !firstEnvironment.ProcessorProperties.ContentEquals(secondEnvironment.ProcessorProperties))
    196             {
    197                 return false;
    198             }
    199 
    200             if (!first.Settings.ContentEquals(second.Settings))
    201             {
    202                 return false;
    203             }
    204 
    205             if (!first.Metadata.ContentEquals(second.Metadata))
    206             {
    207                 return false;
    208             }
    209 
    210             // Note: Consider group units logic when group units are supported.
    211             return true;
    212         }
    213 
    214         [MethodImpl(MethodImplOptions.Synchronized)]
    215         private ConfigurationUnit GetConfigurationUnit(ConfigurationUnit incomingUnit, bool useLimitList = false)
    216         {
    217             if (this.IsLimitMode)
    218             {
    219                 if (this.configurationSet == null)
    220                 {
    221                     throw new InvalidOperationException("Configuration set should not be null in limit mode.");
    222                 }
    223 
    224                 var unitList = useLimitList ? this.limitUnitList : this.configurationSet.Units;
    225 
    226                 for (int i = 0; i < unitList.Count; i++)
    227                 {
    228                     var unit = unitList[i];
    229                     if (ConfigurationUnitEquals(incomingUnit, unit))
    230                     {
    231                         if (useLimitList)
    232                         {
    233                             this.limitUnitList.RemoveAt(i);
    234                         }
    235 
    236                         return unit;
    237                     }
    238 
    239                     // Note: Consider group units logic when group units are supported.
    240                 }
    241 
    242                 this.OnDiagnostics(DiagnosticLevel.Error, "Configuration unit not found in limit mode.");
    243                 throw new InvalidOperationException("Configuration unit not found in limit mode.");
    244             }
    245             else
    246             {
    247                 return incomingUnit;
    248             }
    249         }
    250     }
    251 }