mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-19 16:47:06 +01:00
Make some classes internal + chnage some files to file-scoped namespaces
This commit is contained in:
@@ -1,35 +1,34 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace WireMock.Exceptions
|
||||
namespace WireMock.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
/// WireMockException
|
||||
/// </summary>
|
||||
/// <seealso cref="Exception" />
|
||||
public class WireMockException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// WireMockException
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <seealso cref="Exception" />
|
||||
public class WireMockException : Exception
|
||||
public WireMockException()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
public WireMockException()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public WireMockException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public WireMockException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="inner">The inner.</param>
|
||||
public WireMockException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="inner">The inner.</param>
|
||||
public WireMockException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -3,179 +3,178 @@ using System.IO;
|
||||
using WireMock.Util;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Handlers
|
||||
namespace WireMock.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation for a handler to interact with the local file system to read and write static mapping files.
|
||||
/// </summary>
|
||||
public class LocalFileSystemHandler : IFileSystemHandler
|
||||
{
|
||||
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
|
||||
private static readonly string UnmatchedRequestsFolder = Path.Combine("requests", "unmatched");
|
||||
|
||||
private readonly string _rootFolder;
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation for a handler to interact with the local file system to read and write static mapping files.
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
public class LocalFileSystemHandler : IFileSystemHandler
|
||||
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
|
||||
{
|
||||
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
|
||||
private static readonly string UnmatchedRequestsFolder = Path.Combine("requests", "unmatched");
|
||||
}
|
||||
|
||||
private readonly string _rootFolder;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="rootFolder">The root folder.</param>
|
||||
public LocalFileSystemHandler(string rootFolder)
|
||||
{
|
||||
_rootFolder = rootFolder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
|
||||
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
|
||||
public virtual bool FolderExists(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
|
||||
public virtual void CreateFolder(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||
public virtual IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||
public virtual string GetMappingFolder()
|
||||
{
|
||||
return Path.Combine(_rootFolder, AdminMappingsFolder);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
|
||||
public virtual string ReadMappingFile(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile(string, string)"/>
|
||||
public virtual void WriteMappingFile(string path, string text)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
Guard.NotNull(text, nameof(text));
|
||||
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public virtual byte[] ReadResponseBodyAsFile(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
path = PathUtils.CleanPath(path);
|
||||
// If the file exists at the given path relative to the MappingsFolder, then return that.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
||||
public virtual string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
path = PathUtils.CleanPath(path);
|
||||
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public virtual bool FileExists(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
|
||||
return File.Exists(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void WriteFile(string filename, byte[] bytes)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
Guard.NotNull(bytes);
|
||||
|
||||
File.WriteAllBytes(AdjustPathForMappingFolder(filename), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void WriteFile(string folder, string filename, byte[] bytes)
|
||||
{
|
||||
Guard.NotNullOrEmpty(folder);
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
Guard.NotNull(bytes);
|
||||
|
||||
File.WriteAllBytes(PathUtils.Combine(folder, filename), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
||||
public virtual void DeleteFile(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
|
||||
File.Delete(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
||||
public virtual byte[] ReadFile(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
|
||||
return File.ReadAllBytes(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
|
||||
public virtual string ReadFileAsString(string filename)
|
||||
{
|
||||
return File.ReadAllText(AdjustPathForMappingFolder(Guard.NotNullOrEmpty(filename, nameof(filename))));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetUnmatchedRequestsFolder"/>
|
||||
public virtual string GetUnmatchedRequestsFolder()
|
||||
{
|
||||
return Path.Combine(_rootFolder, UnmatchedRequestsFolder);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteUnmatchedRequest"/>
|
||||
public virtual void WriteUnmatchedRequest(string filename, string text)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
Guard.NotNull(text);
|
||||
|
||||
var folder = GetUnmatchedRequestsFolder();
|
||||
if (!FolderExists(folder))
|
||||
{
|
||||
CreateFolder(folder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="rootFolder">The root folder.</param>
|
||||
public LocalFileSystemHandler(string rootFolder)
|
||||
{
|
||||
_rootFolder = rootFolder;
|
||||
}
|
||||
File.WriteAllText(Path.Combine(folder, filename), text);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
|
||||
public virtual bool FolderExists(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
|
||||
public virtual void CreateFolder(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||
public virtual IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||
public virtual string GetMappingFolder()
|
||||
{
|
||||
return Path.Combine(_rootFolder, AdminMappingsFolder);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
|
||||
public virtual string ReadMappingFile(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile(string, string)"/>
|
||||
public virtual void WriteMappingFile(string path, string text)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
Guard.NotNull(text, nameof(text));
|
||||
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public virtual byte[] ReadResponseBodyAsFile(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
path = PathUtils.CleanPath(path);
|
||||
// If the file exists at the given path relative to the MappingsFolder, then return that.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
||||
public virtual string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path, nameof(path));
|
||||
path = PathUtils.CleanPath(path);
|
||||
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public virtual bool FileExists(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
return File.Exists(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void WriteFile(string filename, byte[] bytes)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
||||
Guard.NotNull(bytes, nameof(bytes));
|
||||
|
||||
File.WriteAllBytes(AdjustPathForMappingFolder(filename), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void WriteFile(string folder, string filename, byte[] bytes)
|
||||
{
|
||||
Guard.NotNullOrEmpty(folder);
|
||||
Guard.NotNullOrEmpty(filename);
|
||||
Guard.NotNull(bytes);
|
||||
|
||||
File.WriteAllBytes(PathUtils.Combine(folder, filename), bytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
||||
public virtual void DeleteFile(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
File.Delete(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
||||
public virtual byte[] ReadFile(string filename)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
||||
|
||||
return File.ReadAllBytes(AdjustPathForMappingFolder(filename));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
|
||||
public virtual string ReadFileAsString(string filename)
|
||||
{
|
||||
return File.ReadAllText(AdjustPathForMappingFolder(Guard.NotNullOrEmpty(filename, nameof(filename))));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.GetUnmatchedRequestsFolder"/>
|
||||
public virtual string GetUnmatchedRequestsFolder()
|
||||
{
|
||||
return Path.Combine(_rootFolder, UnmatchedRequestsFolder);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.WriteUnmatchedRequest"/>
|
||||
public virtual void WriteUnmatchedRequest(string filename, string text)
|
||||
{
|
||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
||||
Guard.NotNull(text, nameof(text));
|
||||
|
||||
var folder = GetUnmatchedRequestsFolder();
|
||||
if (!FolderExists(folder))
|
||||
{
|
||||
CreateFolder(folder);
|
||||
}
|
||||
|
||||
File.WriteAllText(Path.Combine(folder, filename), text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the path to the MappingFolder.
|
||||
/// </summary>
|
||||
/// <param name="filename">The path.</param>
|
||||
/// <returns>Adjusted path</returns>
|
||||
private string AdjustPathForMappingFolder(string filename)
|
||||
{
|
||||
return Path.Combine(GetMappingFolder(), filename);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adjusts the path to the MappingFolder.
|
||||
/// </summary>
|
||||
/// <param name="filename">The path.</param>
|
||||
/// <returns>Adjusted path</returns>
|
||||
private string AdjustPathForMappingFolder(string filename)
|
||||
{
|
||||
return Path.Combine(GetMappingFolder(), filename);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Net.Http.Headers;
|
||||
using AnyOfTypes;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.Models
|
||||
namespace WireMock.Models;
|
||||
|
||||
/// <summary>
|
||||
/// TimeSettingsModel: Start, End and TTL
|
||||
/// </summary>
|
||||
public class TimeSettings : ITimeSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// TimeSettingsModel: Start, End and TTL
|
||||
/// </summary>
|
||||
public class TimeSettings : ITimeSettings
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public DateTime? Start { get; set; }
|
||||
/// <inheritdoc />
|
||||
public DateTime? Start { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime? End { get; set; }
|
||||
/// <inheritdoc />
|
||||
public DateTime? End { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? TTL { get; set; }
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public int? TTL { get; set; }
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace WireMock.Util;
|
||||
/// http://www.unicode.org/versions/corrigendum1.html
|
||||
/// http://www.ietf.org/rfc/rfc2279.txt
|
||||
/// </summary>
|
||||
public static class BytesEncodingUtils
|
||||
internal static class BytesEncodingUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries the get the Encoding from an array of bytes.
|
||||
|
||||
@@ -1,86 +1,85 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Util
|
||||
namespace WireMock.Util;
|
||||
|
||||
/// <summary>
|
||||
/// A special Collection that overrides methods of <see cref="ObservableCollection{T}"/> to make them thread safe.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of elements in the collection.</typeparam>
|
||||
/// <inheritdoc cref="ObservableCollection{T}" />
|
||||
internal class ConcurrentObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
private readonly object _lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:WireMock.Util.ConcurrentObservableCollection`1" /> class.
|
||||
/// </summary>
|
||||
public ConcurrentObservableCollection() { }
|
||||
|
||||
/// <summary>
|
||||
/// A special Collection that overrides methods of <see cref="ObservableCollection{T}"/> to make them thread safe.
|
||||
/// Initializes a new instance of the <see cref="ConcurrentObservableCollection{T}"/> class that contains elements copied from the specified list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of elements in the collection.</typeparam>
|
||||
/// <inheritdoc cref="ObservableCollection{T}" />
|
||||
internal class ConcurrentObservableCollection<T> : ObservableCollection<T>
|
||||
/// <param name="list">The list from which the elements are copied.</param>
|
||||
public ConcurrentObservableCollection(List<T> list) : base(list) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConcurrentObservableCollection{T}"/> class that contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection from which the elements are copied.</param>
|
||||
public ConcurrentObservableCollection(IEnumerable<T> collection) : base(collection) { }
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.ClearItems"/>
|
||||
protected override void ClearItems()
|
||||
{
|
||||
private readonly object _lockObject = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:WireMock.Util.ConcurrentObservableCollection`1" /> class.
|
||||
/// </summary>
|
||||
public ConcurrentObservableCollection() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConcurrentObservableCollection{T}"/> class that contains elements copied from the specified list.
|
||||
/// </summary>
|
||||
/// <param name="list">The list from which the elements are copied.</param>
|
||||
public ConcurrentObservableCollection(List<T> list) : base(list) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConcurrentObservableCollection{T}"/> class that contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">The collection from which the elements are copied.</param>
|
||||
public ConcurrentObservableCollection(IEnumerable<T> collection) : base(collection) { }
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.ClearItems"/>
|
||||
protected override void ClearItems()
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.ClearItems();
|
||||
}
|
||||
base.ClearItems();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.RemoveItem"/>
|
||||
protected override void RemoveItem(int index)
|
||||
/// <inheritdoc cref="ObservableCollection{T}.RemoveItem"/>
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.InsertItem"/>
|
||||
protected override void InsertItem(int index, T item)
|
||||
/// <inheritdoc cref="ObservableCollection{T}.InsertItem"/>
|
||||
protected override void InsertItem(int index, T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
base.InsertItem(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.SetItem"/>
|
||||
protected override void SetItem(int index, T item)
|
||||
/// <inheritdoc cref="ObservableCollection{T}.SetItem"/>
|
||||
protected override void SetItem(int index, T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
base.SetItem(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ObservableCollection{T}.MoveItem"/>
|
||||
protected override void MoveItem(int oldIndex, int newIndex)
|
||||
/// <inheritdoc cref="ObservableCollection{T}.MoveItem"/>
|
||||
protected override void MoveItem(int oldIndex, int newIndex)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
base.MoveItem(oldIndex, newIndex);
|
||||
}
|
||||
base.MoveItem(oldIndex, newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> ToList()
|
||||
public List<T> ToList()
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
return Items.ToList();
|
||||
}
|
||||
return Items.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,251 +4,250 @@ using System.IO;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Util
|
||||
namespace WireMock.Util;
|
||||
|
||||
/// <summary>
|
||||
/// An EnhancedFileSystemWatcher, which can be used to suppress duplicate events that fire on a single change to the file.
|
||||
/// </summary>
|
||||
/// <seealso cref="FileSystemWatcher" />
|
||||
public class EnhancedFileSystemWatcher : FileSystemWatcher
|
||||
{
|
||||
#region Private Members
|
||||
// Default Watch Interval in Milliseconds
|
||||
private const int DefaultWatchInterval = 100;
|
||||
|
||||
// This Dictionary keeps the track of when an event occurred last for a particular file
|
||||
private ConcurrentDictionary<string, DateTime> _lastFileEvent = new();
|
||||
|
||||
// Watch Interval in Milliseconds
|
||||
private int _interval;
|
||||
|
||||
// Timespan created when interval is set
|
||||
private TimeSpan _recentTimeSpan;
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// An EnhancedFileSystemWatcher, which can be used to suppress duplicate events that fire on a single change to the file.
|
||||
/// Interval, in milliseconds, within which events are considered "recent".
|
||||
/// </summary>
|
||||
/// <seealso cref="FileSystemWatcher" />
|
||||
public class EnhancedFileSystemWatcher : FileSystemWatcher
|
||||
[PublicAPI]
|
||||
public int Interval
|
||||
{
|
||||
#region Private Members
|
||||
// Default Watch Interval in Milliseconds
|
||||
private const int DefaultWatchInterval = 100;
|
||||
|
||||
// This Dictionary keeps the track of when an event occurred last for a particular file
|
||||
private ConcurrentDictionary<string, DateTime> _lastFileEvent = new();
|
||||
|
||||
// Watch Interval in Milliseconds
|
||||
private int _interval;
|
||||
|
||||
// Timespan created when interval is set
|
||||
private TimeSpan _recentTimeSpan;
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
/// <summary>
|
||||
/// Interval, in milliseconds, within which events are considered "recent".
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public int Interval
|
||||
get => _interval;
|
||||
set
|
||||
{
|
||||
get => _interval;
|
||||
set
|
||||
{
|
||||
_interval = value;
|
||||
_interval = value;
|
||||
|
||||
// Set timespan based on the value passed
|
||||
_recentTimeSpan = new TimeSpan(0, 0, 0, 0, value);
|
||||
}
|
||||
// Set timespan based on the value passed
|
||||
_recentTimeSpan = new TimeSpan(0, 0, 0, 0, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows user to set whether to filter recent events.
|
||||
/// If this is set a false, this class behaves like System.IO.FileSystemWatcher class.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool FilterRecentEvents { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(int interval = DefaultWatchInterval)
|
||||
{
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(string path, int interval = DefaultWatchInterval) : base(path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
|
||||
/// <param name="filter">The type of files to watch. For example, "*.txt" watches for changes to all text files.</param>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(string path, string filter, int interval = DefaultWatchInterval) : base(path, filter)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
Guard.NotNullOrEmpty(filter);
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
// These events hide the events from the base class.
|
||||
// We want to raise these events appropriately and we do not want the
|
||||
// users of this class subscribing to these events of the base class accidentally
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is changed.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Changed;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is created.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Created;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is deleted.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Deleted;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is renamed.
|
||||
/// </summary>
|
||||
public new event RenamedEventHandler? Renamed;
|
||||
#endregion
|
||||
|
||||
#region Protected Methods to raise the Events for this class
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Changed" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnChanged(FileSystemEventArgs e)
|
||||
{
|
||||
Changed?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Created" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnCreated(FileSystemEventArgs e)
|
||||
{
|
||||
Created?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Deleted" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnDeleted(FileSystemEventArgs e)
|
||||
{
|
||||
Deleted?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Renamed" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.RenamedEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnRenamed(RenamedEventArgs e)
|
||||
{
|
||||
Renamed?.Invoke(this, e);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// This Method Initializes the private members.
|
||||
/// Interval is set to its default value of 100 millisecond.
|
||||
/// FilterRecentEvents is set to true, _lastFileEvent dictionary is initialized.
|
||||
/// We subscribe to the base class events.
|
||||
/// </summary>
|
||||
private void InitializeMembers(int interval = 100)
|
||||
{
|
||||
Interval = interval;
|
||||
FilterRecentEvents = true;
|
||||
_lastFileEvent = new ConcurrentDictionary<string, DateTime>();
|
||||
|
||||
base.Created += OnCreated;
|
||||
base.Changed += OnChanged;
|
||||
base.Deleted += OnDeleted;
|
||||
base.Renamed += OnRenamed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method searches the dictionary to find out when the last event occurred
|
||||
/// for a particular file. If that event occurred within the specified timespan
|
||||
/// it returns true, else false
|
||||
/// </summary>
|
||||
/// <param name="fileName">The filename to be checked</param>
|
||||
/// <returns>True if an event has occurred within the specified interval, False otherwise</returns>
|
||||
private bool HasAnotherFileEventOccurredRecently(string fileName)
|
||||
{
|
||||
// Check dictionary only if user wants to filter recent events otherwise return value stays false.
|
||||
if (!FilterRecentEvents)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool retVal = false;
|
||||
if (_lastFileEvent.ContainsKey(fileName))
|
||||
{
|
||||
// If dictionary contains the filename, check how much time has elapsed
|
||||
// since the last event occurred. If the timespan is less that the
|
||||
// specified interval, set return value to true
|
||||
// and store current datetime in dictionary for this file
|
||||
DateTime lastEventTime = _lastFileEvent[fileName];
|
||||
DateTime currentTime = DateTime.Now;
|
||||
TimeSpan timeSinceLastEvent = currentTime - lastEventTime;
|
||||
retVal = timeSinceLastEvent < _recentTimeSpan;
|
||||
_lastFileEvent[fileName] = currentTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If dictionary does not contain the filename,
|
||||
// no event has occurred in past for this file, so set return value to false
|
||||
// and append filename along with current datetime to the dictionary
|
||||
_lastFileEvent.TryAdd(fileName, DateTime.Now);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#region FileSystemWatcher EventHandlers
|
||||
// Base class Event Handlers. Check if an event has occurred recently and call method
|
||||
// to raise appropriate event only if no recent event is detected
|
||||
private void OnChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCreated(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnCreated(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDeleted(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnDeleted(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRenamed(object sender, RenamedEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.OldFullPath))
|
||||
{
|
||||
OnRenamed(e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows user to set whether to filter recent events.
|
||||
/// If this is set a false, this class behaves like System.IO.FileSystemWatcher class.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool FilterRecentEvents { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(int interval = DefaultWatchInterval)
|
||||
{
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(string path, int interval = DefaultWatchInterval) : base(path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EnhancedFileSystemWatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
|
||||
/// <param name="filter">The type of files to watch. For example, "*.txt" watches for changes to all text files.</param>
|
||||
/// <param name="interval">The interval.</param>
|
||||
public EnhancedFileSystemWatcher(string path, string filter, int interval = DefaultWatchInterval) : base(path, filter)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
Guard.NotNullOrEmpty(filter);
|
||||
Guard.Condition(interval, i => i >= 0);
|
||||
|
||||
InitializeMembers(interval);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
// These events hide the events from the base class.
|
||||
// We want to raise these events appropriately and we do not want the
|
||||
// users of this class subscribing to these events of the base class accidentally
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is changed.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Changed;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is created.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Created;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is deleted.
|
||||
/// </summary>
|
||||
public new event FileSystemEventHandler? Deleted;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is renamed.
|
||||
/// </summary>
|
||||
public new event RenamedEventHandler? Renamed;
|
||||
#endregion
|
||||
|
||||
#region Protected Methods to raise the Events for this class
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Changed" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnChanged(FileSystemEventArgs e)
|
||||
{
|
||||
Changed?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Created" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnCreated(FileSystemEventArgs e)
|
||||
{
|
||||
Created?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Deleted" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.FileSystemEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnDeleted(FileSystemEventArgs e)
|
||||
{
|
||||
Deleted?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.IO.FileSystemWatcher.Renamed" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">A <see cref="T:System.IO.RenamedEventArgs" /> that contains the event data.</param>
|
||||
protected new virtual void OnRenamed(RenamedEventArgs e)
|
||||
{
|
||||
Renamed?.Invoke(this, e);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
/// <summary>
|
||||
/// This Method Initializes the private members.
|
||||
/// Interval is set to its default value of 100 millisecond.
|
||||
/// FilterRecentEvents is set to true, _lastFileEvent dictionary is initialized.
|
||||
/// We subscribe to the base class events.
|
||||
/// </summary>
|
||||
private void InitializeMembers(int interval = 100)
|
||||
{
|
||||
Interval = interval;
|
||||
FilterRecentEvents = true;
|
||||
_lastFileEvent = new ConcurrentDictionary<string, DateTime>();
|
||||
|
||||
base.Created += OnCreated;
|
||||
base.Changed += OnChanged;
|
||||
base.Deleted += OnDeleted;
|
||||
base.Renamed += OnRenamed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method searches the dictionary to find out when the last event occurred
|
||||
/// for a particular file. If that event occurred within the specified timespan
|
||||
/// it returns true, else false
|
||||
/// </summary>
|
||||
/// <param name="fileName">The filename to be checked</param>
|
||||
/// <returns>True if an event has occurred within the specified interval, False otherwise</returns>
|
||||
private bool HasAnotherFileEventOccurredRecently(string fileName)
|
||||
{
|
||||
// Check dictionary only if user wants to filter recent events otherwise return value stays false.
|
||||
if (!FilterRecentEvents)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool retVal = false;
|
||||
if (_lastFileEvent.ContainsKey(fileName))
|
||||
{
|
||||
// If dictionary contains the filename, check how much time has elapsed
|
||||
// since the last event occurred. If the timespan is less that the
|
||||
// specified interval, set return value to true
|
||||
// and store current datetime in dictionary for this file
|
||||
DateTime lastEventTime = _lastFileEvent[fileName];
|
||||
DateTime currentTime = DateTime.Now;
|
||||
TimeSpan timeSinceLastEvent = currentTime - lastEventTime;
|
||||
retVal = timeSinceLastEvent < _recentTimeSpan;
|
||||
_lastFileEvent[fileName] = currentTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If dictionary does not contain the filename,
|
||||
// no event has occurred in past for this file, so set return value to false
|
||||
// and append filename along with current datetime to the dictionary
|
||||
_lastFileEvent.TryAdd(fileName, DateTime.Now);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#region FileSystemWatcher EventHandlers
|
||||
// Base class Event Handlers. Check if an event has occurred recently and call method
|
||||
// to raise appropriate event only if no recent event is detected
|
||||
private void OnChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCreated(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnCreated(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDeleted(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.FullPath))
|
||||
{
|
||||
OnDeleted(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRenamed(object sender, RenamedEventArgs e)
|
||||
{
|
||||
if (!HasAnotherFileEventOccurredRecently(e.OldFullPath))
|
||||
{
|
||||
OnRenamed(e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace WireMock.Util;
|
||||
/// <summary>
|
||||
/// Port Utility class
|
||||
/// </summary>
|
||||
public static class PortUtils
|
||||
internal static class PortUtils
|
||||
{
|
||||
private static readonly Regex UrlDetailsRegex = new(@"^((?<proto>\w+)://)(?<host>[^/]+?):(?<port>\d+)\/?$", RegexOptions.Compiled);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user