Code quality changes

This commit is contained in:
Robin 2016-09-22 20:40:13 +02:00
parent f07ed83722
commit 610f45d082
189 changed files with 4609 additions and 5203 deletions

View file

@ -28,55 +28,50 @@ using log4net;
namespace Greenshot.IniFile {
public class IniConfig {
private static readonly ILog LOG = LogManager.GetLogger(typeof(IniConfig));
private const string INI_EXTENSION = ".ini";
private const string DEFAULTS_POSTFIX = "-defaults";
private const string FIXED_POSTFIX = "-fixed";
private static readonly ILog Log = LogManager.GetLogger(typeof(IniConfig));
private const string IniExtension = ".ini";
private const string DefaultsPostfix = "-defaults";
private const string FixedPostfix = "-fixed";
/// <summary>
/// A lock object for the ini file saving
/// </summary>
private static readonly object iniLock = new object();
private static readonly object IniLock = new object();
/// <summary>
/// As the ini implementation is kept someone generic, for reusing, this holds the name of the application
/// </summary>
private static string applicationName;
private static string _applicationName;
/// <summary>
/// As the ini implementation is kept someone generic, for reusing, this holds the name of the configuration
/// </summary>
private static string configName;
private static string _configName;
/// <summary>
/// A Dictionary with all the sections stored by section name
/// </summary>
private static readonly Dictionary<string, IniSection> sectionMap = new Dictionary<string, IniSection>();
private static readonly Dictionary<string, IniSection> SectionMap = new Dictionary<string, IniSection>();
/// <summary>
/// A Dictionary with the properties for a section stored by section name
/// </summary>
private static Dictionary<string, Dictionary<string, string>> sections = new Dictionary<string, Dictionary<string, string>>();
private static Dictionary<string, Dictionary<string, string>> _sections = new Dictionary<string, Dictionary<string, string>>();
/// <summary>
/// A Dictionary with the fixed-properties for a section stored by section name
/// </summary>
private static Dictionary<string, Dictionary<string, string>> fixedProperties;
private static Dictionary<string, Dictionary<string, string>> _fixedProperties;
/// <summary>
/// Stores if we checked for portable
/// </summary>
private static bool portableCheckMade;
private static bool _portableCheckMade;
/// <summary>
/// Is the configuration portable (meaning we don't store it in the AppData directory)
/// </summary>
private static bool portable;
public static bool IsPortable {
get {
return portable;
}
}
public static bool IsPortable { get; private set; }
/// <summary>
/// Config directory when set from external
@ -92,34 +87,34 @@ namespace Greenshot.IniFile {
/// <param name="appName"></param>
/// <param name="configName"></param>
public static void Init(string appName, string configName) {
applicationName = appName;
IniConfig.configName = configName;
_applicationName = appName;
_configName = configName;
Reload();
}
/// <summary>
/// Checks if we initialized the ini
/// </summary>
public static bool isInitialized {
get {
return applicationName != null && configName != null && sectionMap.Count > 0;
}
}
public static bool IsInitialized => _applicationName != null && _configName != null && SectionMap.Count > 0;
/// <summary>
/// This forces the ini to be stored in the startup path, used for portable applications
/// </summary>
public static void ForceIniInStartupPath() {
if (portableCheckMade) {
if (_portableCheckMade) {
throw new Exception("ForceLocal should be called before any file is read");
}
portable = false;
portableCheckMade = true;
IsPortable = false;
_portableCheckMade = true;
string applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
if (applicationName == null || configName == null) {
if (_applicationName == null || _configName == null) {
Init();
}
string forcedIni = Path.Combine(applicationStartupPath, applicationName + INI_EXTENSION);
if (applicationStartupPath == null)
{
return;
}
string forcedIni = Path.Combine(applicationStartupPath, _applicationName + IniExtension);
if (!File.Exists(forcedIni)) {
using (File.Create(forcedIni)) {}
}
@ -130,9 +125,9 @@ namespace Greenshot.IniFile {
/// </summary>
public static void Init() {
AssemblyProductAttribute[] assemblyProductAttributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false) as AssemblyProductAttribute[];
if (assemblyProductAttributes.Length > 0) {
if (assemblyProductAttributes != null && assemblyProductAttributes.Length > 0) {
string productName = assemblyProductAttributes[0].Product;
LOG.InfoFormat("Using ProductName {0}", productName);
Log.InfoFormat("Using ProductName {0}", productName);
Init(productName, productName);
} else {
throw new InvalidOperationException("Assembly ProductName not set.");
@ -144,8 +139,8 @@ namespace Greenshot.IniFile {
/// </summary>
public static string ConfigLocation {
get {
if (isInitialized) {
return CreateIniLocation(configName + INI_EXTENSION, false);
if (IsInitialized) {
return CreateIniLocation(_configName + IniExtension, false);
}
throw new InvalidOperationException("Ini configuration was not initialized!");
}
@ -155,7 +150,7 @@ namespace Greenshot.IniFile {
/// Create the location of the configuration file
/// </summary>
private static string CreateIniLocation(string configFilename, bool isReadOnly) {
if (applicationName == null || configName == null) {
if (_applicationName == null || _configName == null) {
throw new InvalidOperationException("IniConfig.Init not called!");
}
string iniFilePath = null;
@ -174,53 +169,60 @@ namespace Greenshot.IniFile {
iniFilePath = null;
}
} catch (Exception exception) {
LOG.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message);
Log.WarnFormat("The ini-directory {0} can't be used due to: {1}", IniDirectory, exception.Message);
}
string applicationStartupPath = "";
string applicationStartupPath;
try {
applicationStartupPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
} catch (Exception exception) {
LOG.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message);
Log.WarnFormat("Problem retrieving the AssemblyLocation: {0} (Designer mode?)", exception.Message);
applicationStartupPath = @".";
}
string pafPath = Path.Combine(applicationStartupPath, @"App\" + applicationName);
if (applicationStartupPath != null)
{
string pafPath = Path.Combine(applicationStartupPath, @"App\" + _applicationName);
if (portable || !portableCheckMade) {
if (!portable) {
LOG.Info("Checking for portable mode.");
portableCheckMade = true;
if (Directory.Exists(pafPath)) {
portable = true;
LOG.Info("Portable mode active!");
}
}
if (portable) {
string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings");
try {
if (!Directory.Exists(pafConfigPath)) {
Directory.CreateDirectory(pafConfigPath);
if (IsPortable || !_portableCheckMade) {
if (!IsPortable) {
Log.Info("Checking for portable mode.");
_portableCheckMade = true;
if (Directory.Exists(pafPath)) {
IsPortable = true;
Log.Info("Portable mode active!");
}
}
if (IsPortable) {
string pafConfigPath = Path.Combine(applicationStartupPath, @"Data\Settings");
try {
if (!Directory.Exists(pafConfigPath)) {
Directory.CreateDirectory(pafConfigPath);
}
iniFilePath = Path.Combine(pafConfigPath, configFilename);
} catch(Exception e) {
Log.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message);
}
iniFilePath = Path.Combine(pafConfigPath, configFilename);
} catch(Exception e) {
LOG.InfoFormat("Portable mode NOT possible, couldn't create directory '{0}'! Reason: {1}", pafConfigPath, e.Message);
}
}
}
if (iniFilePath == null) {
if (iniFilePath == null)
{
// check if file is in the same location as started from, if this is the case
// we will use this file instead of the ApplicationData folder
// Done for Feature Request #2741508
iniFilePath = Path.Combine(applicationStartupPath, configFilename);
if (applicationStartupPath != null)
{
iniFilePath = Path.Combine(applicationStartupPath, configFilename);
}
if (!File.Exists(iniFilePath)) {
string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), applicationName);
string iniDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), _applicationName);
if (!Directory.Exists(iniDirectory)) {
Directory.CreateDirectory(iniDirectory);
}
iniFilePath = Path.Combine(iniDirectory, configFilename);
}
}
LOG.InfoFormat("Using ini file {0}", iniFilePath);
Log.InfoFormat("Using ini file {0}", iniFilePath);
return iniFilePath;
}
@ -229,25 +231,25 @@ namespace Greenshot.IniFile {
/// </summary>
public static void Reload() {
// Clear the current properties
sections = new Dictionary<string, Dictionary<string, string>>();
_sections = new Dictionary<string, Dictionary<string, string>>();
// Load the defaults
Read(CreateIniLocation(configName + DEFAULTS_POSTFIX + INI_EXTENSION, true));
Read(CreateIniLocation(_configName + DefaultsPostfix + IniExtension, true));
// Load the normal
Read(CreateIniLocation(configName + INI_EXTENSION, false));
Read(CreateIniLocation(_configName + IniExtension, false));
// Load the fixed settings
fixedProperties = Read(CreateIniLocation(configName + FIXED_POSTFIX + INI_EXTENSION, true));
_fixedProperties = Read(CreateIniLocation(_configName + FixedPostfix + IniExtension, true));
foreach (IniSection section in sectionMap.Values) {
foreach (IniSection section in SectionMap.Values) {
try {
section.Fill(PropertiesForSection(section));
FixProperties(section);
} catch (Exception ex) {
string sectionName = "unknown";
if (section != null && section.IniSectionAttribute != null && section.IniSectionAttribute.Name != null) {
if (section?.IniSectionAttribute?.Name != null) {
sectionName = section.IniSectionAttribute.Name;
}
LOG.WarnFormat("Problem reading the ini section {0}", sectionName);
LOG.Warn("Exception", ex);
Log.WarnFormat("Problem reading the ini section {0}", sectionName);
Log.Warn("Exception", ex);
}
}
}
@ -258,14 +260,18 @@ namespace Greenshot.IniFile {
/// <param name="section">IniSection</param>
private static void FixProperties(IniSection section) {
// Make properties unchangeable
if (fixedProperties != null) {
Dictionary<string, string> fixedPropertiesForSection = null;
if (fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out fixedPropertiesForSection)) {
foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) {
if (section.Values.ContainsKey(fixedPropertyKey)) {
section.Values[fixedPropertyKey].IsFixed = true;
}
}
if (_fixedProperties == null)
{
return;
}
Dictionary<string, string> fixedPropertiesForSection;
if (!_fixedProperties.TryGetValue(section.IniSectionAttribute.Name, out fixedPropertiesForSection))
{
return;
}
foreach (string fixedPropertyKey in fixedPropertiesForSection.Keys) {
if (section.Values.ContainsKey(fixedPropertyKey)) {
section.Values[fixedPropertyKey].IsFixed = true;
}
}
}
@ -276,21 +282,21 @@ namespace Greenshot.IniFile {
/// <param name="iniLocation">Path & Filename of ini file</param>
private static Dictionary<string, Dictionary<string, string>> Read(string iniLocation) {
if (!File.Exists(iniLocation)) {
LOG.Info("Can't find file: " + iniLocation);
Log.Info("Can't find file: " + iniLocation);
return null;
}
LOG.InfoFormat("Loading ini-file: {0}", iniLocation);
Log.InfoFormat("Loading ini-file: {0}", iniLocation);
//LOG.Info("Reading ini-properties from file: " + iniLocation);
Dictionary<string, Dictionary<string, string>> newSections = IniReader.read(iniLocation, Encoding.UTF8);
// Merge the newly loaded properties to the already available
foreach(string section in newSections.Keys) {
Dictionary<string, string> newProperties = newSections[section];
if (!sections.ContainsKey(section)) {
if (!_sections.ContainsKey(section)) {
// This section is not yet loaded, simply add the complete section
sections.Add(section, newProperties);
_sections.Add(section, newProperties);
} else {
// Overwrite or add every property from the newly loaded section to the available one
Dictionary<string, string> currentProperties = sections[section];
Dictionary<string, string> currentProperties = _sections[section];
foreach(string propertyName in newProperties.Keys) {
string propertyValue = newProperties[propertyName];
if (currentProperties.ContainsKey(propertyName)) {
@ -308,7 +314,7 @@ namespace Greenshot.IniFile {
public static IEnumerable<string> IniSectionNames {
get {
foreach (string sectionName in sectionMap.Keys) {
foreach (string sectionName in SectionMap.Keys) {
yield return sectionName;
}
}
@ -321,7 +327,7 @@ namespace Greenshot.IniFile {
/// <returns></returns>
public static IniSection GetIniSection(string sectionName) {
IniSection returnValue;
sectionMap.TryGetValue(sectionName, out returnValue);
SectionMap.TryGetValue(sectionName, out returnValue);
return returnValue;
}
@ -345,20 +351,20 @@ namespace Greenshot.IniFile {
Type iniSectionType = typeof(T);
string sectionName = IniSection.GetIniSectionAttribute(iniSectionType).Name;
if (sectionMap.ContainsKey(sectionName)) {
if (SectionMap.ContainsKey(sectionName)) {
//LOG.Debug("Returning pre-mapped section " + sectionName);
section = (T)sectionMap[sectionName];
section = (T)SectionMap[sectionName];
} else {
// Create instance of this type
section = (T)Activator.CreateInstance(iniSectionType);
// Store for later save & retrieval
sectionMap.Add(sectionName, section);
SectionMap.Add(sectionName, section);
section.Fill(PropertiesForSection(section));
FixProperties(section);
}
if (allowSave && section.IsDirty) {
LOG.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
Log.DebugFormat("Section {0} is marked dirty, saving!", sectionName);
Save();
}
return section;
@ -373,11 +379,11 @@ namespace Greenshot.IniFile {
string sectionName = section.IniSectionAttribute.Name;
// Get the properties for the section
IDictionary<string, string> properties;
if (sections.ContainsKey(sectionName)) {
properties = sections[sectionName];
if (_sections.ContainsKey(sectionName)) {
properties = _sections[sectionName];
} else {
sections.Add(sectionName, new Dictionary<string, string>());
properties = sections[sectionName];
_sections.Add(sectionName, new Dictionary<string, string>());
properties = _sections[sectionName];
}
return properties;
}
@ -388,23 +394,23 @@ namespace Greenshot.IniFile {
public static void Save() {
bool acquiredLock = false;
try {
acquiredLock = Monitor.TryEnter(iniLock, TimeSpan.FromMilliseconds(200));
acquiredLock = Monitor.TryEnter(IniLock, TimeSpan.FromMilliseconds(200));
if (acquiredLock) {
// Code that accesses resources that are protected by the lock.
string iniLocation = CreateIniLocation(configName + INI_EXTENSION, false);
string iniLocation = CreateIniLocation(_configName + IniExtension, false);
try {
SaveInternally(iniLocation);
} catch (Exception ex) {
LOG.Error("A problem occured while writing the configuration file to: " + iniLocation);
LOG.Error(ex);
Log.Error("A problem occured while writing the configuration file to: " + iniLocation);
Log.Error(ex);
}
} else {
// Code to deal with the fact that the lock was not acquired.
LOG.Warn("A second thread tried to save the ini-file, we blocked as the first took too long.");
Log.Warn("A second thread tried to save the ini-file, we blocked as the first took too long.");
}
} finally {
if (acquiredLock) {
Monitor.Exit(iniLock);
Monitor.Exit(IniLock);
}
}
}
@ -414,13 +420,15 @@ namespace Greenshot.IniFile {
/// </summary>
/// <param name="iniLocation"></param>
private static void SaveInternally(string iniLocation) {
LOG.Info("Saving configuration to: " + iniLocation);
if (!Directory.Exists(Path.GetDirectoryName(iniLocation))) {
Directory.CreateDirectory(Path.GetDirectoryName(iniLocation));
Log.Info("Saving configuration to: " + iniLocation);
var iniPath = Path.GetDirectoryName(iniLocation);
if (iniPath != null && !Directory.Exists(iniPath))
{
Directory.CreateDirectory(iniPath);
}
using (MemoryStream memoryStream = new MemoryStream()) {
using (var memoryStream = new MemoryStream()) {
using (TextWriter writer = new StreamWriter(memoryStream, Encoding.UTF8)) {
foreach (IniSection section in sectionMap.Values) {
foreach (var section in SectionMap.Values) {
section.Write(writer, false);
// Add empty line after section
writer.WriteLine();
@ -428,20 +436,22 @@ namespace Greenshot.IniFile {
}
writer.WriteLine();
// Write left over properties
foreach (string sectionName in sections.Keys) {
foreach (string sectionName in _sections.Keys) {
// Check if the section is one that is "registered", if so skip it!
if (!sectionMap.ContainsKey(sectionName)) {
writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName);
writer.WriteLine("; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", sectionName);
// Write section name
writer.WriteLine("[{0}]", sectionName);
Dictionary<string, string> properties = sections[sectionName];
// Loop and write properties
foreach (string propertyName in properties.Keys) {
writer.WriteLine("{0}={1}", propertyName, properties[propertyName]);
}
writer.WriteLine();
if (SectionMap.ContainsKey(sectionName))
{
continue;
}
writer.WriteLine("; The section {0} hasn't been 'claimed' since the last start of Greenshot, therefor it doesn't have additional information here!", sectionName);
writer.WriteLine("; The reason could be that the section {0} just hasn't been used, a plugin has an error and can't claim it or maybe the whole section {0} is obsolete.", sectionName);
// Write section name
writer.WriteLine("[{0}]", sectionName);
Dictionary<string, string> properties = _sections[sectionName];
// Loop and write properties
foreach (string propertyName in properties.Keys) {
writer.WriteLine("{0}={1}", propertyName, properties[propertyName]);
}
writer.WriteLine();
}
// Don't forget to flush the buffer
writer.Flush();