Plugin tool: ensure URIs are absolute URIs (#340)
* Plugin tool: ensure URIs are absolute URIs * Check if GetAboutInfo is overridden
This commit is contained in:
Родитель
98bea7d6de
Коммит
774b642add
|
@ -30,21 +30,6 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
this.PhoneNumbers = phoneNumbers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContactInfo"/> class from a <see cref="SDK.Processing.ContactInfo"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="contactInfo">
|
||||
/// The <see cref="SDK.Processing.ContactInfo"/> instance to copy.
|
||||
/// </param>
|
||||
public ContactInfo(SDK.Processing.ContactInfo contactInfo)
|
||||
: this(
|
||||
contactInfo?.Name,
|
||||
contactInfo?.Address,
|
||||
contactInfo?.EmailAddresses?.ToArray(),
|
||||
contactInfo?.PhoneNumbers?.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the contact, if any.
|
||||
/// </summary>
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
[JsonConstructor]
|
||||
public LicenseInfo(
|
||||
string name,
|
||||
string uri,
|
||||
Uri uri,
|
||||
string text)
|
||||
{
|
||||
this.Name = name;
|
||||
|
@ -27,17 +27,6 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
this.Text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LicenseInfo"/> class from a <see cref="SDK.Processing.LicenseInfo"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="licenseInfo">
|
||||
/// The license info to copy.
|
||||
/// </param>
|
||||
public LicenseInfo(SDK.Processing.LicenseInfo licenseInfo)
|
||||
: this(licenseInfo?.Name, licenseInfo?.Uri, licenseInfo?.Text)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the license.
|
||||
/// </summary>
|
||||
|
@ -46,7 +35,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
/// <summary>
|
||||
/// Gets the URI where the license text may be found.
|
||||
/// </summary>
|
||||
public string Uri { get; }
|
||||
public Uri Uri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full text of the license, if desired.
|
||||
|
@ -74,7 +63,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
}
|
||||
|
||||
return string.Equals(this.Name, other.Name, StringComparison.Ordinal)
|
||||
&& string.Equals(this.Uri, other.Uri, StringComparison.Ordinal)
|
||||
&& string.Equals(this.Uri.OriginalString, other.Uri.OriginalString, StringComparison.Ordinal)
|
||||
&& string.Equals(this.Text, other.Text, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,20 +32,6 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
this.AdditionalInformation = additionalInformation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProcessingSourceInfo"/> class from a <see cref="SDK.Processing.ProcessingSourceInfo"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
public ProcessingSourceInfo(SDK.Processing.ProcessingSourceInfo other)
|
||||
: this(
|
||||
other?.Owners?.Select(x => new ContactInfo(x)).ToArray(),
|
||||
new ProjectInfo(other?.ProjectInfo),
|
||||
new LicenseInfo(other?.LicenseInfo),
|
||||
other?.CopyrightNotice,
|
||||
other?.AdditionalInformation?.ToArray())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the contact information of the owners
|
||||
/// of the <see cref="IProcessingSource"/>.
|
||||
|
@ -68,7 +54,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
public string CopyrightNotice { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets any additional information about the <see cref="IProcessingSource"/> to convey to the user.
|
||||
/// Gets any additional information about the <see cref="IProcessingSource"/> to convey to the user.
|
||||
/// Each entry in the array is logically a new paragraph.
|
||||
/// </summary>
|
||||
public string[] AdditionalInformation { get; }
|
||||
|
|
|
@ -19,24 +19,15 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
/// The URI to the page for this project.
|
||||
/// </param>
|
||||
[JsonConstructor]
|
||||
public ProjectInfo(string uri)
|
||||
public ProjectInfo(Uri uri)
|
||||
{
|
||||
this.Uri = uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProjectInfo"/> class from a <see cref="SDK.Processing.ProjectInfo"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="projectInfo"></param>
|
||||
public ProjectInfo(SDK.Processing.ProjectInfo projectInfo)
|
||||
: this(projectInfo?.Uri)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URI to the page for this project.
|
||||
/// </summary>
|
||||
public string Uri { get; }
|
||||
public Uri Uri { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
|
@ -57,7 +48,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Core.Metadata
|
|||
return true;
|
||||
}
|
||||
|
||||
return string.Equals(this.Uri, other.Uri, StringComparison.Ordinal);
|
||||
return string.Equals(this.Uri.OriginalString, other.Uri.OriginalString, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
@ -56,6 +56,12 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Manifest
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!pluginManifest.ProjectUrl.IsAbsoluteUri)
|
||||
{
|
||||
this.logger.LogError($"Manifest {manifestFilePath} is invalid: project URL {pluginManifest.ProjectUrl.OriginalString} is not an absolute URI.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Performance.SDK;
|
||||
using Microsoft.Performance.SDK.Processing;
|
||||
|
@ -41,7 +42,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
/// <inheritdoc />
|
||||
public bool TryProcess(PluginArtifacts artifacts, [NotNullWhen(true)] out ProcessedPluginResult? processedPlugin)
|
||||
{
|
||||
processedPlugin = null;
|
||||
processedPlugin = null;
|
||||
if (!TryProcessSourceDir(artifacts.SourceDirectoryFullPath, out ProcessedPluginSourceDirectory? processedDir))
|
||||
{
|
||||
this.logger.LogError($"Failed to process source directory {artifacts.SourceDirectoryFullPath}.");
|
||||
|
@ -77,7 +78,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
x => new SandboxPreloadValidator(x, versionChecker),
|
||||
Logger.Create<PluginsLoader>());
|
||||
|
||||
bool loadSuccess = pluginsLoader.TryLoadPlugin(processedDir.FullPath, out ErrorInfo errorInfo);
|
||||
bool loadSuccess = pluginsLoader.TryLoadPlugin(processedDir.FullPath, out ErrorInfo errorInfo);
|
||||
if (!loadSuccess)
|
||||
{
|
||||
// TODO: Check error codes and throw more specific exceptions
|
||||
|
@ -121,10 +122,10 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
if (!loadSuccess || !isVersionSupported)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PluginMetadata metadata = GenerateMetadata(processedDir, manifest, pluginSDKversion);
|
||||
|
||||
|
||||
if (!TryGenerateContentsMetadata(pluginsLoader, out PluginContentsMetadata? contentsMetadata))
|
||||
{
|
||||
this.logger.LogError($"Failed to generate contents metadata for plugin.");
|
||||
|
@ -177,7 +178,7 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
filesToPack,
|
||||
manifestFilePath,
|
||||
totalSize);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -204,7 +205,18 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
|
||||
private bool TryGenerateContentsMetadata(PluginsLoader pluginsLoader, out PluginContentsMetadata? contentsMetadata)
|
||||
{
|
||||
var processingSourcesMetadata = pluginsLoader.LoadedProcessingSources.Select(x => CreateProcessingSourceMetadata(x)).ToList();
|
||||
HashSet<ProcessingSourceMetadata> processingSourcesMetadata = new();
|
||||
|
||||
foreach (ProcessingSourceReference psr in pluginsLoader.LoadedProcessingSources)
|
||||
{
|
||||
if (!TryCreateProcessingSourceMetadata(psr, out var metadata))
|
||||
{
|
||||
contentsMetadata = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
processingSourcesMetadata.Add(metadata);
|
||||
}
|
||||
|
||||
// TODO: #294 Figure out how to extract description of a datacooker.
|
||||
var dataCookers = pluginsLoader.Extensions.SourceDataCookers
|
||||
|
@ -220,12 +232,12 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
x.TableDescriptor.Category,
|
||||
x.TableDescriptor.IsMetadataTable))
|
||||
.ToList();
|
||||
|
||||
|
||||
contentsMetadata = new(processingSourcesMetadata, dataCookers, tables);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ProcessingSourceMetadata CreateProcessingSourceMetadata(ProcessingSourceReference psr)
|
||||
private bool TryCreateProcessingSourceMetadata(ProcessingSourceReference psr, [NotNullWhen(true)] out ProcessingSourceMetadata? metadata)
|
||||
{
|
||||
// Tables
|
||||
IEnumerable<TableMetadata> dataTables = psr.Instance.DataTables.Select(x => new TableMetadata(
|
||||
|
@ -264,16 +276,65 @@ namespace Microsoft.Performance.Toolkit.Plugins.Cli.Processing
|
|||
}
|
||||
}
|
||||
|
||||
ProcessingSourceMetadata metadata = new(
|
||||
if (!TryGetAboutInfo(psr, out ProcessingSourceInfo? aboutInfo))
|
||||
{
|
||||
metadata = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
metadata = new(
|
||||
version: Version.Parse(psr.Version),
|
||||
name: psr.Name,
|
||||
description: psr.Description,
|
||||
guid: psr.Instance.TryGetGuid(),
|
||||
aboutInfo: new ProcessingSourceInfo(psr.Instance.GetAboutInfo()),
|
||||
aboutInfo: aboutInfo,
|
||||
availableTables: dataTables.Concat(metadataTables),
|
||||
supportedDataSources: dataSourcesMetadata);
|
||||
|
||||
return metadata;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetAboutInfo(ProcessingSourceReference psr, [NotNullWhen(true)] out ProcessingSourceInfo? processingSourceInfo)
|
||||
{
|
||||
processingSourceInfo = null;
|
||||
|
||||
var aboutInfo = psr.Instance.GetAboutInfo();
|
||||
|
||||
if (aboutInfo == null)
|
||||
{
|
||||
this.logger.LogError($"Unable to generate processing source info: {psr.Name} does not contain about info.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the GetAboutInfo method is overridden
|
||||
MethodInfo? methodInfo = psr.Instance.GetType().GetMethod(nameof(ProcessingSource.GetAboutInfo));
|
||||
if (methodInfo == null || methodInfo.DeclaringType == typeof(ProcessingSource))
|
||||
{
|
||||
this.logger.LogError($"Unable to generate processing source info: {psr.Name} does not override the virtual method {nameof(ProcessingSource)}.{nameof(ProcessingSource.GetAboutInfo)}.");
|
||||
}
|
||||
|
||||
var owners = aboutInfo.Owners
|
||||
.Select(o => new Core.Metadata.ContactInfo(o.Name, o.Address, o.EmailAddresses, o.PhoneNumbers))
|
||||
.ToArray();
|
||||
|
||||
if (!Uri.TryCreate(aboutInfo.ProjectInfo.Uri, UriKind.Absolute, out Uri? projectUri))
|
||||
{
|
||||
this.logger.LogError($"Unable to generate processing source info: {aboutInfo.ProjectInfo.Uri} is not an absolute URI.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Core.Metadata.ProjectInfo projectInfo = new(projectUri);
|
||||
|
||||
if (!Uri.TryCreate(aboutInfo.LicenseInfo.Uri, UriKind.Absolute, out Uri? licenseUri))
|
||||
{
|
||||
this.logger.LogError($"Unable to generate processing source info: {aboutInfo.LicenseInfo.Uri} is not an absolute URI.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Core.Metadata.LicenseInfo licenseInfo = new(aboutInfo.LicenseInfo.Name, licenseUri, aboutInfo.LicenseInfo.Text);
|
||||
|
||||
processingSourceInfo = new ProcessingSourceInfo(owners, projectInfo, licenseInfo, aboutInfo.CopyrightNotice, aboutInfo.AdditionalInformation);
|
||||
return true;
|
||||
}
|
||||
|
||||
private record ProcessedPluginSourceDirectory(
|
||||
|
|
Загрузка…
Ссылка в новой задаче