Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/Gemstone/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
Expand Down Expand Up @@ -616,7 +615,10 @@ public static ulong GetTotalPhysicalMemory()
{
if (IsPosixEnvironment)
{
string output = Command.Execute("awk", "'/MemTotal/ {print $2}' /proc/meminfo").StandardOutput;
// Pass the awk program as a single argument using double quotes (which the .NET argument tokenizer
// groups and strips); single quotes are shell-only syntax and, since the command is executed without
// a shell, would be passed to awk literally - causing "awk: unexpected character '''".
string output = Command.Execute("awk", "\"/MemTotal/ {print $2}\" /proc/meminfo").StandardOutput;
return ulong.Parse(output) * SI2.Kilo;
}

Expand All @@ -632,7 +634,9 @@ public static ulong GetAvailablePhysicalMemory()
{
if (IsPosixEnvironment)
{
string output = Command.Execute("awk", "'/MemAvailable/ {print $2}' /proc/meminfo").StandardOutput;
// Double-quote the awk program so it is passed as a single argument; single quotes are shell-only
// syntax and would reach awk literally when executed without a shell (see GetTotalPhysicalMemory).
string output = Command.Execute("awk", "\"/MemAvailable/ {print $2}\" /proc/meminfo").StandardOutput;
return ulong.Parse(output) * SI2.Kilo;
}

Expand Down
5 changes: 0 additions & 5 deletions src/Gemstone/Identity/UserInfoUnix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,8 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;
using Gemstone.Collections.CollectionExtensions;
using Gemstone.Console;
Expand Down
1 change: 0 additions & 1 deletion src/Gemstone/Identity/UserInfoWindows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -793,7 +792,7 @@
string getGroupPrefix(string accountName)
{
string[] parts = accountName.Split('\\');
return parts.Length == 2 ? parts[0].Trim() : null;

Check warning on line 795 in src/Gemstone/Identity/UserInfoWindows.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Possible null reference return.
}

//using (Logger.SuppressFirstChanceExceptionLogMessages())
Expand All @@ -812,7 +811,7 @@
// Don't include "BUILTIN\" prefix for group names so they are easily comparable
builtInGroups.Add(groupAccount.ToString().Substring((BuiltInGroupName ?? "BUILTIN").Length + 1));
}
catch (IdentityNotMappedException ex)

Check warning on line 814 in src/Gemstone/Identity/UserInfoWindows.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

The variable 'ex' is declared but never used
{
// TODO: Exposes as captured exception event
//Logger.SwallowException(ex, "WindowsUserInfo.cs Static Constructor: Failed to lookup identity", builtInSid.ToString());
Expand Down Expand Up @@ -868,8 +867,8 @@
{
Type type = largeInteger.GetType();

int highPart = (int)type.InvokeMember("HighPart", BindingFlags.GetProperty, null, largeInteger, null);

Check warning on line 870 in src/Gemstone/Identity/UserInfoWindows.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Unboxing a possibly null value.
int lowPart = (int)type.InvokeMember("LowPart", BindingFlags.GetProperty, null, largeInteger, null);

Check warning on line 871 in src/Gemstone/Identity/UserInfoWindows.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Unboxing a possibly null value.

return (long)highPart << 32 | (uint)lowPart;
}
Expand Down Expand Up @@ -1008,7 +1007,7 @@
}
catch (COMException)
{
accountEntry = null;

Check warning on line 1010 in src/Gemstone/Identity/UserInfoWindows.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Cannot convert null literal to non-nullable reference type.
return false;
}
}
Expand Down
74 changes: 55 additions & 19 deletions src/Gemstone/Serialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,29 +73,28 @@ private class LegacySerializationBinder : SerializationBinder
// Perform namespace transformations that occurred when migrating to the Grid Solutions Framework
// from various older versions of code with different namespaces
string newTypeName = typeName
.Replace("TVA.", "Gemstone.")
.Replace("GSF.TimeSeries.", "Gemstone.Timeseries.")
.Replace("GSF.", "Gemstone.")
.Replace("TimeSeriesFramework.", "Gemstone.Timeseries.")
.Replace(".TimeSeries.", ".Timeseries.") // Updated Gemstone casing for timeseries namespace
.Replace("GSF.Units.EE", "Gemstone.Numeric.EE") // Gemstone assembly relocation of EE namespace
.Replace("TVA.Units.EE", "Gemstone.Numeric.EE") // Gemstone assembly relocation of EE namespace
.Replace("TimeSeriesFramework.", "Gemstone.Timeseries.") // 2007 TVA Code Library "TimeSeriesFramework" namespace
.Replace("ConnectionTester.", "Gemstone.PhasorProtocols.") // PMU Connection Tester namespace
.Replace("TVA.Phasors.", "Gemstone.PhasorProtocols.") // 2007 TVA Code Library namespace
.Replace("Tva.Phasors.", "Gemstone.PhasorProtocols.") // 2008 TVA Code Library namespace
.Replace("BpaPdcStream", "BPAPDCstream") // 2013 GSF uppercase phasor protocol namespace
.Replace("FNet", "FNET") // 2013 GSF uppercase phasor protocol namespace
.Replace("Iec61850_90_5", "IEC61850_90_5") // 2013 GSF uppercase phasor protocol namespace
.Replace("Ieee1344", "IEEE1344") // 2013 GSF uppercase phasor protocol namespace
.Replace("IeeeC37_118", "IEEEC37_118"); // 2013 GSF uppercase phasor protocol namespace
.Replace("TVA.Phasors.", "Gemstone.PhasorProtocols.") // 2007 TVA Code Library "Phasors" namespace
.Replace("Tva.Phasors.", "Gemstone.PhasorProtocols.") // 2008 TVA Code Library "Phasors" namespace
.Replace("GSF.", "Gemstone.") // 2013+ GSF root namespace
.Replace("TVA.", "Gemstone.") // 2007 TVA Code Library root namespace
.Replace("Tva.", "Gemstone.") // 2008 TVA Code Library root namespace
.Replace("BpaPdcStream", "BPAPDCstream") // 2013 updated GSF casing for phasor protocol namespace
.Replace("FNet", "FNET") // 2013 updated GSF casing for phasor protocol namespace
.Replace("Iec61850_90_5", "IEC61850_90_5") // 2013 updated GSF casing for phasor protocol namespace
.Replace("Ieee1344", "IEEE1344") // 2013 updated GSF casing for phasor protocol namespace
.Replace("IeeeC37_118", "IEEEC37_118"); // 2013 updated GSF casing for phasor protocol namespace

// Check for 2009 TVA Code Library namespace
// Check for 2009 TVA Code Library "PhasorProtocols" namespace
if (newTypeName.StartsWith("PhasorProtocols", StringComparison.Ordinal))
newTypeName = "Gemstone." + newTypeName;

// Check for 2014 LineFrequency type
if (newTypeName.Equals("GSF.PhasorProtocols.LineFrequency", StringComparison.Ordinal))
newTypeName = "Gemstone.Numeric.EE.LineFrequency";

// Check for GSF LineFrequency type
if (newTypeName.Equals("GSF.Units.EE.LineFrequency", StringComparison.Ordinal))
// Check for 2014 LineFrequency type (note: already replaced GSF with Gemstone here)
if (newTypeName.Equals("Gemstone.PhasorProtocols.LineFrequency", StringComparison.Ordinal))
newTypeName = "Gemstone.Numeric.EE.LineFrequency";

try
Expand Down Expand Up @@ -128,8 +127,45 @@ private class LegacySerializationBinder : SerializationBinder
// No type found; return null
return null;
}

/// <summary>
/// Controls the binding of a serialized object to a type name and assembly name during serialization.
/// </summary>
/// <remarks>
/// Maps current Gemstone types back to their legacy GSF names so that XML written by Gemstone code
/// remains readable by .NET Framework consumers (PMU Connection Tester, older openPDC builds, etc.)
/// that only know the GSF-era types. The Gemstone-side reader translates these names back via
/// <see cref="BindToType(string, string)"/>, so round-trip identity is preserved.
/// </remarks>
/// <param name="serializedType">The runtime type being serialized.</param>
/// <param name="assemblyName">On return, the legacy assembly name to emit.</param>
/// <param name="typeName">On return, the legacy fully-qualified type name to emit.</param>
public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName)
{
string fullName = serializedType.FullName ?? serializedType.Name;
string typeNamespace = serializedType.Namespace ?? string.Empty;
string runtimeAssembly = serializedType.Assembly.GetName().Name ?? string.Empty;

// Special case: Gemstone.Numeric.EE.* types (LineFrequency, PhasorType, etc.) historically
// lived in the GSF.Units.EE namespace inside the GSF.Core assembly.
if (typeNamespace == "Gemstone.Numeric.EE" || typeNamespace.StartsWith("Gemstone.Numeric.EE.", StringComparison.Ordinal))
{
typeName = fullName.Replace("Gemstone.Numeric.EE", "GSF.Units.EE", StringComparison.Ordinal);
assemblyName = "GSF.Core";
return;
}

// General case: Gemstone.* → GSF.* (and Timeseries → TimeSeries casing flip).
typeName = fullName
.Replace("Gemstone.Timeseries.", "GSF.TimeSeries.", StringComparison.Ordinal)
.Replace("Gemstone.", "GSF.", StringComparison.Ordinal);

assemblyName = runtimeAssembly
.Replace("Gemstone.Timeseries", "GSF.TimeSeries", StringComparison.Ordinal)
.Replace("Gemstone.", "GSF.", StringComparison.Ordinal);
}
}

/// <summary>
/// Gets <see cref="SerializationInfo"/> value for specified <paramref name="name"/>; otherwise <paramref name="defaultValue"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
//
//******************************************************************************************************

using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;

Expand Down
10 changes: 7 additions & 3 deletions src/Gemstone/StringExtensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,19 @@ public static T ConvertToType<T>(this string? value, CultureInfo? culture)
/// </remarks>
public static object? ConvertToType(this string? value, Type type, CultureInfo? culture, bool suppressException = true)
{
// Don't proceed further if string is empty.
// Handle the trivial string-to-string conversion
if (type == typeof(string))
return value;

// Don't proceed further if string is empty
if (string.IsNullOrEmpty(value))
return null;

// Initialize return type if not specified.
// There is no way to guess what type the user intended to convert to
if (type is null)
throw new ArgumentNullException(nameof(type));

// Initialize culture info if not specified.
// Initialize culture info if not specified
culture ??= CultureInfo.InvariantCulture;

// Handle array types as a special case
Expand Down
Loading