Skip to content

Commit

Permalink
nopSolutions#88 Extracted File IO Functions
Browse files Browse the repository at this point in the history
  • Loading branch information
skoshelev committed Apr 28, 2018
1 parent fba6eea commit 69ecaba
Show file tree
Hide file tree
Showing 56 changed files with 1,683 additions and 786 deletions.
74 changes: 4 additions & 70 deletions src/Libraries/Nop.Core/CommonHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Threading;
using Nop.Core.Infrastructure;

namespace Nop.Core
{
Expand All @@ -34,29 +33,6 @@ static CommonHelper()

#endregion

#region Utilities

private static void DeleteDirectoryRecursive(string path)
{
Directory.Delete(path, true);
const int maxIterationToWait = 10;
var curIteration = 0;

//according to the documentation(https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa365488.aspx)
//System.IO.Directory.Delete method ultimately (after removing the files) calls native
//RemoveDirectory function which marks the directory as "deleted". That's why we wait until
//the directory is actually deleted. For more details see https://stackoverflow.com/a/4245121
while (Directory.Exists(path))
{
curIteration += 1;
if (curIteration > maxIterationToWait)
return;
Thread.Sleep(100);
}
}

#endregion

#region Methods

/// <summary>
Expand Down Expand Up @@ -338,17 +314,6 @@ public static int GetDifferenceInYears(DateTime startDate, DateTime endDate)
return age;
}

/// <summary>
/// Maps a virtual path to a physical disk path.
/// </summary>
/// <param name="path">The path to map. E.g. "~/bin"</param>
/// <returns>The physical path. E.g. "c:\inetpub\wwwroot\bin"</returns>
public static string MapPath(string path)
{
path = path.Replace("~/", "").TrimStart('/').Replace('/', '\\');
return Path.Combine(BaseDirectory??string.Empty, path);
}

/// <summary>
/// Get private fields property value
/// </summary>
Expand Down Expand Up @@ -387,46 +352,15 @@ public static object GetPrivateFieldValue(object target, string fieldName)
return fi.GetValue(target);
}

/// <summary>
/// Depth-first recursive delete, with handling for descendant directories open in Windows Explorer.
/// </summary>
/// <param name="path">Directory path</param>
public static void DeleteDirectory(string path)
{
if (string.IsNullOrEmpty(path))
throw new ArgumentNullException(path);

//find more info about directory deletion
//and why we use this approach at https://stackoverflow.com/questions/329355/cannot-delete-directory-with-directory-deletepath-true

foreach (var directory in Directory.GetDirectories(path))
{
DeleteDirectory(directory);
}

try
{
DeleteDirectoryRecursive(path);
}
catch (IOException)
{
DeleteDirectoryRecursive(path);
}
catch (UnauthorizedAccessException)
{
DeleteDirectoryRecursive(path);
}
}

#endregion

#region Properties

/// <summary>
/// Gets or sets application base path
/// Gets or sets the default file provider
/// </summary>
internal static string BaseDirectory { get; set; }
public static INopFileProvider DefaultFileProvider { get; set; }

#endregion
}
}
13 changes: 7 additions & 6 deletions src/Libraries/Nop.Core/Data/DataSettingsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ public partial class DataSettingsHelper
/// <returns></returns>
public static bool DatabaseIsInstalled()
{
if (!_databaseIsInstalled.HasValue)
{
var manager = new DataSettingsManager();
var settings = manager.LoadSettings(reloadSettings:true);
_databaseIsInstalled = settings != null && !string.IsNullOrEmpty(settings.DataConnectionString);
}
if (_databaseIsInstalled.HasValue)
return _databaseIsInstalled.Value;

var manager = new DataSettingsManager();

var settings = manager.LoadSettings(reloadSettings:true);
_databaseIsInstalled = !string.IsNullOrEmpty(settings?.DataConnectionString);
return _databaseIsInstalled.Value;
}

Expand Down
50 changes: 31 additions & 19 deletions src/Libraries/Nop.Core/Data/DataSettingsManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Nop.Core.Infrastructure;

Expand All @@ -12,8 +13,14 @@ public partial class DataSettingsManager
{
#region Const

private const string ObsoleteDataSettingsFilePath = "~/App_Data/Settings.txt";
private const string DataSettingsFilePath_ = "~/App_Data/dataSettings.json";
private const string OBSOLETE_DATA_SETTINGS_FILE_PATH = "~/App_Data/Settings.txt";
private const string DATA_SETTINGS_FILE_PATH_ = "~/App_Data/dataSettings.json";

#endregion

#region Fields

protected INopFileProvider _fileProvider;

#endregion

Expand All @@ -22,7 +29,16 @@ public partial class DataSettingsManager
/// <summary>
/// Gets the path to file that contains data settings
/// </summary>
public static string DataSettingsFilePath => DataSettingsFilePath_;
public static string DataSettingsFilePath => DATA_SETTINGS_FILE_PATH_;

#endregion

#region Ctor

public DataSettingsManager(INopFileProvider fileProvider = null)
{
this._fileProvider = fileProvider ?? CommonHelper.DefaultFileProvider;
}

#endregion

Expand All @@ -39,21 +55,21 @@ public virtual DataSettings LoadSettings(string filePath = null, bool reloadSett
if (!reloadSettings && Singleton<DataSettings>.Instance != null)
return Singleton<DataSettings>.Instance;

filePath = filePath ?? CommonHelper.MapPath(DataSettingsFilePath);
filePath = filePath ?? _fileProvider.MapPath(DataSettingsFilePath);

//check whether file exists
if (!File.Exists(filePath))
if (!_fileProvider.FileExists(filePath))
{
//if not, try to parse the file that was used in previous nopCommerce versions
filePath = CommonHelper.MapPath(ObsoleteDataSettingsFilePath);
if (!File.Exists(filePath))
filePath = _fileProvider.MapPath(OBSOLETE_DATA_SETTINGS_FILE_PATH);
if (!_fileProvider.FileExists(filePath))
return new DataSettings();

//get data settings from the old txt file
var dataSettings = new DataSettings();
using (var reader = new StringReader(File.ReadAllText(filePath)))
using (var reader = new StringReader(_fileProvider.ReadAllText(filePath, Encoding.UTF8)))
{
var settingsLine = string.Empty;
string settingsLine;
while ((settingsLine = reader.ReadLine()) != null)
{
var separatorIndex = settingsLine.IndexOf(':');
Expand Down Expand Up @@ -82,13 +98,13 @@ public virtual DataSettings LoadSettings(string filePath = null, bool reloadSett
SaveSettings(dataSettings);

//and delete the old one
File.Delete(filePath);
_fileProvider.DeleteFile(filePath);

Singleton<DataSettings>.Instance = dataSettings;
return Singleton<DataSettings>.Instance;
}

var text = File.ReadAllText(filePath);
var text = _fileProvider.ReadAllText(filePath, Encoding.UTF8);
if (string.IsNullOrEmpty(text))
return new DataSettings();

Expand All @@ -104,19 +120,15 @@ public virtual DataSettings LoadSettings(string filePath = null, bool reloadSett
public virtual void SaveSettings(DataSettings settings)
{
Singleton<DataSettings>.Instance = settings ?? throw new ArgumentNullException(nameof(settings));

var filePath = CommonHelper.MapPath(DataSettingsFilePath);
var filePath = _fileProvider.MapPath(DataSettingsFilePath);

//create file if not exists
if (!File.Exists(filePath))
{
//we use 'using' to close the file after it's created
using (File.Create(filePath)) { }
}
_fileProvider.CreateFile(filePath);

//save data settings to the file
var text = JsonConvert.SerializeObject(Singleton<DataSettings>.Instance, Formatting.Indented);
File.WriteAllText(filePath, text);
_fileProvider.WriteAllText(filePath, text, Encoding.UTF8);
}

#endregion
Expand Down
48 changes: 19 additions & 29 deletions src/Libraries/Nop.Core/Infrastructure/AppDomainTypeFinder.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

Expand All @@ -17,11 +16,17 @@ public class AppDomainTypeFinder : ITypeFinder
{
#region Fields

private bool ignoreReflectionErrors = true;
private bool loadAppDomainAssemblies = true;
private string assemblySkipLoadingPattern = "^System|^mscorlib|^Microsoft|^AjaxControlToolkit|^Antlr3|^Autofac|^AutoMapper|^Castle|^ComponentArt|^CppCodeProvider|^DotNetOpenAuth|^EntityFramework|^EPPlus|^FluentValidation|^ImageResizer|^itextsharp|^log4net|^MaxMind|^MbUnit|^MiniProfiler|^Mono.Math|^MvcContrib|^Newtonsoft|^NHibernate|^nunit|^Org.Mentalis|^PerlRegex|^QuickGraph|^Recaptcha|^Remotion|^RestSharp|^Rhino|^Telerik|^Iesi|^TestDriven|^TestFu|^UserAgentStringLibrary|^VJSharpCodeProvider|^WebActivator|^WebDev|^WebGrease";
private string assemblyRestrictToLoadingPattern = ".*";
private IList<string> assemblyNames = new List<string>();
private bool _ignoreReflectionErrors = true;
protected INopFileProvider _fileProvider;

#endregion

#region Ctor

public AppDomainTypeFinder(INopFileProvider fileProvider = null)
{
this._fileProvider = fileProvider ?? CommonHelper.DefaultFileProvider;
}

#endregion

Expand Down Expand Up @@ -106,17 +111,18 @@ protected virtual bool Matches(string assemblyFullName, string pattern)
protected virtual void LoadMatchingAssemblies(string directoryPath)
{
var loadedAssemblyNames = new List<string>();

foreach (var a in GetAssemblies())
{
loadedAssemblyNames.Add(a.FullName);
}

if (!Directory.Exists(directoryPath))
if (!_fileProvider.DirectoryExists(directoryPath))
{
return;
}

foreach (var dllPath in Directory.GetFiles(directoryPath, "*.dll"))
foreach (var dllPath in _fileProvider.GetFiles(directoryPath, "*.dll"))
{
try
{
Expand Down Expand Up @@ -228,7 +234,7 @@ public IEnumerable<Type> FindClassesOfType(Type assignTypeFrom, IEnumerable<Asse
catch
{
//Entity Framework 6 doesn't allow getting types (throws an exception)
if (!ignoreReflectionErrors)
if (!_ignoreReflectionErrors)
{
throw;
}
Expand Down Expand Up @@ -299,33 +305,17 @@ public virtual AppDomain App
}

/// <summary>Gets or sets whether Nop should iterate assemblies in the app domain when loading Nop types. Loading patterns are applied when loading these assemblies.</summary>
public bool LoadAppDomainAssemblies
{
get { return loadAppDomainAssemblies; }
set { loadAppDomainAssemblies = value; }
}
public bool LoadAppDomainAssemblies { get; set; } = true;

/// <summary>Gets or sets assemblies loaded a startup in addition to those loaded in the AppDomain.</summary>
public IList<string> AssemblyNames
{
get { return assemblyNames; }
set { assemblyNames = value; }
}
public IList<string> AssemblyNames { get; set; } = new List<string>();

/// <summary>Gets the pattern for dlls that we know don't need to be investigated.</summary>
public string AssemblySkipLoadingPattern
{
get { return assemblySkipLoadingPattern; }
set { assemblySkipLoadingPattern = value; }
}
public string AssemblySkipLoadingPattern { get; set; } = "^System|^mscorlib|^Microsoft|^AjaxControlToolkit|^Antlr3|^Autofac|^AutoMapper|^Castle|^ComponentArt|^CppCodeProvider|^DotNetOpenAuth|^EntityFramework|^EPPlus|^FluentValidation|^ImageResizer|^itextsharp|^log4net|^MaxMind|^MbUnit|^MiniProfiler|^Mono.Math|^MvcContrib|^Newtonsoft|^NHibernate|^nunit|^Org.Mentalis|^PerlRegex|^QuickGraph|^Recaptcha|^Remotion|^RestSharp|^Rhino|^Telerik|^Iesi|^TestDriven|^TestFu|^UserAgentStringLibrary|^VJSharpCodeProvider|^WebActivator|^WebDev|^WebGrease";

/// <summary>Gets or sets the pattern for dll that will be investigated. For ease of use this defaults to match all but to increase performance you might want to configure a pattern that includes assemblies and your own.</summary>
/// <remarks>If you change this so that Nop assemblies aren't investigated (e.g. by not including something like "^Nop|..." you may break core functionality.</remarks>
public string AssemblyRestrictToLoadingPattern
{
get { return assemblyRestrictToLoadingPattern; }
set { assemblyRestrictToLoadingPattern = value; }
}
public string AssemblyRestrictToLoadingPattern { get; set; } = ".*";

#endregion

Expand Down
Loading

0 comments on commit 69ecaba

Please sign in to comment.