Skip to content

Commit

Permalink
Get licenses from embedded schema, skip bad modules in deserialize
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Jan 26, 2022
1 parent 6a3eba7 commit a54c49b
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 144 deletions.
35 changes: 35 additions & 0 deletions CKAN.schema
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,41 @@
"open-source", "restricted", "unrestricted", "unknown"
]
},
"redistributable_license": {
"description" : "A license that grants us the right to redistribute.",
"enum" : [
"public-domain",
"Apache", "Apache-1.0", "Apache-2.0",
"Artistic", "Artistic-1.0", "Artistic-2.0",
"BSD-2-clause", "BSD-3-clause", "BSD-4-clause",
"ISC",
"CC-BY", "CC-BY-1.0", "CC-BY-2.0", "CC-BY-2.5", "CC-BY-3.0", "CC-BY-4.0",
"CC-BY-SA", "CC-BY-SA-1.0", "CC-BY-SA-2.0", "CC-BY-SA-2.5", "CC-BY-SA-3.0", "CC-BY-SA-4.0",
"CC-BY-NC", "CC-BY-NC-1.0", "CC-BY-NC-2.0", "CC-BY-NC-2.5", "CC-BY-NC-3.0", "CC-BY-NC-4.0",
"CC-BY-NC-SA", "CC-BY-NC-SA-1.0", "CC-BY-NC-SA-2.0", "CC-BY-NC-SA-2.5", "CC-BY-NC-SA-3.0", "CC-BY-NC-SA-4.0",
"CC-BY-NC-ND", "CC-BY-NC-ND-1.0", "CC-BY-NC-ND-2.0", "CC-BY-NC-ND-2.5", "CC-BY-NC-ND-3.0", "CC-BY-NC-ND-4.0",
"CC-BY-ND", "CC-BY-ND-1.0", "CC-BY-ND-2.0", "CC-BY-ND-2.5", "CC-BY-ND-3.0", "CC-BY-ND-4.0",
"CC0",
"CDDL", "CPL",
"EFL-1.0", "EFL-2.0",
"Expat", "MIT",
"GPL-1.0", "GPL-2.0", "GPL-3.0",
"LGPL-2.0", "LGPL-2.1", "LGPL-3.0",
"GFDL-1.0", "GFDL-1.1", "GFDL-1.2", "GFDL-1.3",
"GFDL-NIV-1.0", "GFDL-NIV-1.1", "GFDL-NIV-1.2", "GFDL-NIV-1.3",
"LPPL-1.0", "LPPL-1.1", "LPPL-1.2", "LPPL-1.3c",
"MPL-1.1", "MPL-2.0",
"Perl",
"Python-2.0",
"QPL-1.0",
"W3C",
"Zlib",
"Zope",
"WTFPL",
"Unlicense",
"open-source", "unrestricted"
]
},
"licenses" : {
"description" : "A license, or array of licenses",
"anyOf" : [
Expand Down
4 changes: 4 additions & 0 deletions Core/CKAN-core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<PackageReference Include="SharpZipLib" Version="1.3.1" />
<PackageReference Include="log4net" Version="2.0.10" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="NJsonSchema" Version="10.0.27" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<PackageReference Include="ChinhDo.Transactions.FileManager" Version="1.2.0" />
Expand All @@ -64,6 +65,9 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="builds.json" />
<EmbeddedResource Include="..\CKAN.schema">
<LogicalName>CKAN.Core.CKAN.schema</LogicalName>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="log4net.xml">
Expand Down
64 changes: 64 additions & 0 deletions Core/Converters/JsonLeakySortedDictionaryConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;

using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CKAN
{
/// <summary>
/// [De]serializes a dictionary that might have some questionably
/// valid data in it.
/// If exceptions are thrown for any key/value pair, leave it out.
/// Removes CkanModule objects from AvailableModule.module_version
/// if License throws BadMetadataKraken.
/// </summary>
public class JsonLeakySortedDictionaryConverter<K, V> : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var dict = new SortedDictionary<K, V>();
foreach (var kvp in JObject.Load(reader))
{
try
{
dict.Add(
(K)Activator.CreateInstance(typeof(K), kvp.Key),
kvp.Value.ToObject<V>());
}
catch (Exception exc)
{
log.WarnFormat($"Failed to deserialize {kvp.Key}", exc);
}
}
return dict;
}

/// <summary>
/// Use default serializer for writing
/// </summary>
public override bool CanWrite => false;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

/// <summary>
/// We *only* want to be triggered for types that have explicitly
/// set an attribute in their class saying they can be converted.
/// By returning false here, we declare we're not interested in participating
/// in any other conversions.
/// </summary>
/// <returns>
/// false
/// </returns>
public override bool CanConvert(Type objectType)
{
return false;
}

private static readonly ILog log = LogManager.GetLogger(typeof(JsonLeakySortedDictionaryConverter<K, V>));
}
}
34 changes: 20 additions & 14 deletions Core/Converters/JsonSimpleStringConverter.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
using System;
using Newtonsoft.Json;

namespace CKAN {
// A lovely class for serialising things that can be converted
// to simple strings and back.

public class JsonSimpleStringConverter : JsonConverter {
using Newtonsoft.Json;

namespace CKAN
{
/// <summary>
/// Serialises things that can be converted
/// to simple strings and back.
/// </summary>
public class JsonSimpleStringConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue (value.ToString ());
writer.WriteValue(value.ToString());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{

// If we find a null, then that might be okay, so we pass it down to our
// activator. Otherwise we convert to string, since that's our job.
string value = reader.Value == null ? null : reader.Value.ToString();
return Activator.CreateInstance (objectType, value);
return Activator.CreateInstance(objectType, reader.Value?.ToString());
}

/// <summary>
/// We *only* want to be triggered for types that have explicitly
/// set an attribute in their class saying they can be converted.
/// By returning false here, we declare we're not interested in participating
/// in any other conversions.
/// </summary>
/// <returns>
/// false
/// </returns>
public override bool CanConvert(Type objectType)
{
// We *only* want to be triggered for types that have explicitly
// set an attribute in their class saying they can be converted.
// By returning false here, we declare we're not interested in participating
// in any other conversions.
return false;
}
}
Expand Down
38 changes: 20 additions & 18 deletions Core/Converters/JsonSingleOrArrayConverter.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
using System;
using System.Collections.Generic;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CKAN
{

// With thanks to
// https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n

/// <summary>
/// With thanks to
/// https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n
/// </summary>
public class JsonSingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type object_type)
{
// We *only* want to be triggered for types that have explicitly
// set an attribute in their class saying they can be converted.
// By returning false here, we declare we're not interested in participating
// in any other conversions.
return false;
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
Expand All @@ -32,15 +24,25 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
return token.ToObject<T>() == null ? null : new List<T> { token.ToObject<T>() };
}

public override bool CanWrite
{
get { return false; }
}
public override bool CanWrite => false;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}

/// <summary>
/// We *only* want to be triggered for types that have explicitly
/// set an attribute in their class saying they can be converted.
/// By returning false here, we declare we're not interested in participating
/// in any other conversions.
/// </summary>
/// <returns>
/// false
/// </returns>
public override bool CanConvert(Type object_type)
{
return false;
}
}
}

13 changes: 7 additions & 6 deletions Core/Registry/AvailableModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using CKAN.Extensions;
using CKAN.Versioning;

using log4net;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

using CKAN.Extensions;
using CKAN.Versioning;

namespace CKAN
{
/// <summary>
Expand All @@ -32,10 +34,8 @@ private AvailableModule()
[OnDeserialized]
internal void DeserialisationFixes(StreamingContext context)
{
// Set identifier
var mod = module_version.Values.LastOrDefault();
identifier = mod.identifier;
Debug.Assert(module_version.Values.All(m=>identifier.Equals(m.identifier)));
identifier = module_version.Values.LastOrDefault()?.identifier;
Debug.Assert(module_version.Values.All(m => identifier.Equals(m.identifier)));
}

/// <param name="identifier">The module to keep track of</param>
Expand All @@ -49,6 +49,7 @@ public AvailableModule(string identifier)
// The map of versions -> modules, that's what we're about!
// First element is the oldest version, last is the newest.
[JsonProperty]
[JsonConverter(typeof(JsonLeakySortedDictionaryConverter<ModuleVersion, CkanModule>))]
internal SortedDictionary<ModuleVersion, CkanModule> module_version =
new SortedDictionary<ModuleVersion, CkanModule>();

Expand Down
5 changes: 3 additions & 2 deletions Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ namespace CKAN
public class Registry : IEnlistmentNotification, IRegistryQuerier
{
[JsonIgnore] private const int LATEST_REGISTRY_VERSION = 3;
[JsonIgnore] private static readonly ILog log = LogManager.GetLogger(typeof (Registry));
[JsonIgnore] private static readonly ILog log = LogManager.GetLogger(typeof(Registry));

[JsonProperty] private int registry_version;

// name => Repository
[JsonProperty("sorted_repositories")]
private SortedDictionary<string, Repository> repositories; // name => Repository
private SortedDictionary<string, Repository> repositories;

// TODO: These may be good as custom types, especially those which process
// paths (and flip from absolute to relative, and vice-versa).
Expand Down
Loading

0 comments on commit a54c49b

Please sign in to comment.