Skip to content

Commit

Permalink
Modified code from Microsot.Extensions.Configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
isra-fel committed Mar 24, 2022
1 parent c5e438d commit 8efa0f9
Show file tree
Hide file tree
Showing 30 changed files with 2,246 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/Accounts/Authentication/Config/Internal/BinderOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// 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.
// ----------------------------------------------------------------------------------

namespace Microsoft.Azure.Commands.Common.Authentication.Config.Internal
{
/// <summary>
/// Options class used by the <see cref="ConfigurationBinder"/>.
/// </summary>
internal class BinderOptions
{
/// <summary>
/// When false (the default), the binder will only attempt to set public properties.
/// If true, the binder will attempt to set all non read-only properties.
/// </summary>
public bool BindNonPublicProperties { get; set; }
}
}
587 changes: 587 additions & 0 deletions src/Accounts/Authentication/Config/Internal/ConfigurationBinder.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// 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.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.Common.Authentication.Config.Internal.Interfaces;
using System;
using System.Collections.Generic;

namespace Microsoft.Azure.Commands.Common.Authentication.Config.Internal
{
/// <summary>
/// Used to build key/value based configuration settings for use in an application.
/// </summary>
internal class ConfigurationBuilder : IConfigurationBuilder
{
/// <summary>
/// Returns the sources used to obtain configuration values.
/// </summary>
public IList<IConfigurationSource> Sources { get; } = new List<IConfigurationSource>();

private IDictionary<IConfigurationSource, string> _ids = new Dictionary<IConfigurationSource, string>();

/// <summary>
/// Gets a key/value collection that can be used to share data between the <see cref="IConfigurationBuilder"/>
/// and the registered <see cref="IConfigurationProvider"/>s.
/// </summary>
public IDictionary<string, object> Properties { get; } = new Dictionary<string, object>();

/// <summary>
/// Adds a new configuration source.
/// </summary>
/// <param name="source">The configuration source to add.</param>
/// <returns>The same <see cref="IConfigurationBuilder"/>.</returns>
public IConfigurationBuilder Add(string id, IConfigurationSource source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}

Sources.Add(source);
_ids[source] = id;
return this;
}

/// <summary>
/// Builds an <see cref="IConfiguration"/> with keys and values from the set of providers registered in
/// <see cref="Sources"/>.
/// </summary>
/// <returns>An <see cref="IConfigurationRoot"/> with keys and values from the registered providers.</returns>
public IConfigurationRoot Build()
{
var providers = new List<IConfigurationProvider>();
foreach (IConfigurationSource source in Sources)
{
IConfigurationProvider provider = source.Build(this, _ids[source]);
providers.Add(provider);
}
return new ConfigurationRoot(providers);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// 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.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Commands.Common.Authentication.Config.Internal.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Azure.Commands.Common.Authentication.Config.Internal
{
/// <summary>
/// Extension methods for configuration classes./>.
/// </summary>
internal static class ConfigurationExtensions
{
/// <summary>
/// Adds a new configuration source.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="configureSource">Configures the source secrets.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder Add<TSource>(this IConfigurationBuilder builder, string id, Action<TSource> configureSource) where TSource : IConfigurationSource, new()
{
var source = new TSource();
configureSource?.Invoke(source);
return builder.Add(id, source);
}

/// <summary>
/// Shorthand for GetSection("ConnectionStrings")[name].
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="name">The connection string key.</param>
/// <returns>The connection string.</returns>
public static string GetConnectionString(this IConfiguration configuration, string name)
{
return configuration?.GetSection("ConnectionStrings")?[name];
}

/// <summary>
/// Get the enumeration of key value pairs within the <see cref="IConfiguration" />
/// </summary>
/// <param name="configuration">The <see cref="IConfiguration"/> to enumerate.</param>
/// <returns>An enumeration of key value pairs.</returns>
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this IConfiguration configuration) => configuration.AsEnumerable(makePathsRelative: false);

/// <summary>
/// Get the enumeration of key value pairs within the <see cref="IConfiguration" />
/// </summary>
/// <param name="configuration">The <see cref="IConfiguration"/> to enumerate.</param>
/// <param name="makePathsRelative">If true, the child keys returned will have the current configuration's Path trimmed from the front.</param>
/// <returns>An enumeration of key value pairs.</returns>
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this IConfiguration configuration, bool makePathsRelative)
{
var stack = new Stack<IConfiguration>();
stack.Push(configuration);
var rootSection = configuration as IConfigurationSection;
int prefixLength = (makePathsRelative && rootSection != null) ? rootSection.Path.Length + 1 : 0;
while (stack.Count > 0)
{
IConfiguration config = stack.Pop();
// Don't include the sections value if we are removing paths, since it will be an empty key
if (config is IConfigurationSection section && (!makePathsRelative || config != configuration))
{
yield return new KeyValuePair<string, string>(section.Path.Substring(prefixLength), section.Value);
}
foreach (IConfigurationSection child in config.GetChildren())
{
stack.Push(child);
}
}
}

/// <summary>
/// Determines whether the section has a <see cref="IConfigurationSection.Value"/> or has children
/// </summary>
public static bool Exists(this IConfigurationSection section)
{
if (section == null)
{
return false;
}
return section.Value != null || section.GetChildren().Any();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// 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.
// ----------------------------------------------------------------------------------

using System;
using System.Collections.Generic;

namespace Microsoft.Azure.Commands.Common.Authentication.Config.Internal
{
internal class ConfigurationKeyComparer : IComparer<string>
{
private static readonly string[] _keyDelimiterArray = new[] { ConfigurationPath.KeyDelimiter };

/// <summary>
/// The default instance.
/// </summary>
public static ConfigurationKeyComparer Instance { get; } = new ConfigurationKeyComparer();

/// <summary>
/// Compares two strings.
/// </summary>
/// <param name="x">First string.</param>
/// <param name="y">Second string.</param>
/// <returns>Less than 0 if x is less than y, 0 if x is equal to y and greater than 0 if x is greater than y.</returns>
public int Compare(string x, string y)
{
string[] xParts = x?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
string[] yParts = y?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();

// Compare each part until we get two parts that are not equal
for (int i = 0; i < Math.Min(xParts.Length, yParts.Length); i++)
{
x = xParts[i];
y = yParts[i];

int value1 = 0;
int value2 = 0;

bool xIsInt = x != null && int.TryParse(x, out value1);
bool yIsInt = y != null && int.TryParse(y, out value2);

int result;

if (!xIsInt && !yIsInt)
{
// Both are strings
result = string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
}
else if (xIsInt && yIsInt)
{
// Both are int
result = value1 - value2;
}
else
{
// Only one of them is int
result = xIsInt ? -1 : 1;
}

if (result != 0)
{
// One of them is different
return result;
}
}

// If we get here, the common parts are equal.
// If they are of the same length, then they are totally identical
return xParts.Length - yParts.Length;
}
}
}
90 changes: 90 additions & 0 deletions src/Accounts/Authentication/Config/Internal/ConfigurationPath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// 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.
// ----------------------------------------------------------------------------------

using System;
using System.Collections.Generic;

namespace Microsoft.Azure.Commands.Common.Authentication.Config.Internal
{
/// <summary>
/// Utility methods and constants for manipulating Configuration paths
/// </summary>
internal static class ConfigurationPath
{
/// <summary>
/// The delimiter ":" used to separate individual keys in a path.
/// </summary>
public static readonly string KeyDelimiter = ":";

/// <summary>
/// Combines path segments into one path.
/// </summary>
/// <param name="pathSegments">The path segments to combine.</param>
/// <returns>The combined path.</returns>
public static string Combine(params string[] pathSegments)
{
if (pathSegments == null)
{
throw new ArgumentNullException(nameof(pathSegments));
}
return string.Join(KeyDelimiter, pathSegments);
}

/// <summary>
/// Combines path segments into one path.
/// </summary>
/// <param name="pathSegments">The path segments to combine.</param>
/// <returns>The combined path.</returns>
public static string Combine(IEnumerable<string> pathSegments)
{
if (pathSegments == null)
{
throw new ArgumentNullException(nameof(pathSegments));
}
return string.Join(KeyDelimiter, pathSegments);
}

/// <summary>
/// Extracts the last path segment from the path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>The last path segment of the path.</returns>
public static string GetSectionKey(string path)
{
if (string.IsNullOrEmpty(path))
{
return path;
}

int lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase);
return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1);
}

/// <summary>
/// Extracts the path corresponding to the parent node for a given path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>The original path minus the last individual segment found in it. Null if the original path corresponds to a top level node.</returns>
public static string GetParentPath(string path)
{
if (string.IsNullOrEmpty(path))
{
return null;
}

int lastDelimiterIndex = path.LastIndexOf(KeyDelimiter, StringComparison.OrdinalIgnoreCase);
return lastDelimiterIndex == -1 ? null : path.Substring(0, lastDelimiterIndex);
}
}
}
Loading

0 comments on commit 8efa0f9

Please sign in to comment.