|
| 1 | +// File must be "stand-alone"; it's included by |
| 2 | +// `tools/remap-mam-json-to-xml` |
| 3 | + |
| 4 | +#nullable enable |
| 5 | + |
| 6 | +using System; |
| 7 | +using System.Collections.Generic; |
| 8 | +using System.Globalization; |
| 9 | +using System.IO; |
| 10 | +using System.Xml; |
| 11 | + |
| 12 | +using ReplacementTypesDict = System.Collections.Generic.Dictionary<string, string>; |
| 13 | +using ReplacementMethodsDict = System.Collections.Generic.Dictionary< |
| 14 | + (string SourceType, string SourceName, string? SourceSignature), |
| 15 | + (string? TargetType, string? TargetName, string? TargetSignature, int? ParamCount, bool IsStatic) |
| 16 | +>; |
| 17 | + |
| 18 | +namespace Android.Runtime { |
| 19 | + |
| 20 | + class MamXmlParser { |
| 21 | + |
| 22 | + public static (ReplacementTypesDict ReplacementTypes, ReplacementMethodsDict ReplacementMethods) Parse (string xml) |
| 23 | + { |
| 24 | + var replacementTypes = new ReplacementTypesDict (); |
| 25 | + var replacementMethods = new ReplacementMethodsDict (); |
| 26 | + |
| 27 | + using var t = new StringReader (xml); |
| 28 | + using var reader = XmlReader.Create (t, new XmlReaderSettings { XmlResolver = null }); |
| 29 | + while (reader.Read ()) { |
| 30 | + if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment) { |
| 31 | + continue; |
| 32 | + } |
| 33 | + if (!reader.IsStartElement ()) { |
| 34 | + continue; |
| 35 | + } |
| 36 | + if (!reader.HasAttributes) { |
| 37 | + continue; |
| 38 | + } |
| 39 | + switch (reader.LocalName) { |
| 40 | + case "replace-type": |
| 41 | + ParseReplaceTypeAttributes (replacementTypes, reader); |
| 42 | + break; |
| 43 | + case "replace-method": |
| 44 | + ParseReplaceMethodAttributes (replacementMethods, reader); |
| 45 | + break; |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + return (replacementTypes, replacementMethods); |
| 50 | + } |
| 51 | + |
| 52 | + static void ParseReplaceTypeAttributes (ReplacementTypesDict replacementTypes, XmlReader reader) |
| 53 | + { |
| 54 | + // <replace-type |
| 55 | + // from="android/app/Activity"' |
| 56 | + // to="com/microsoft/intune/mam/client/app/MAMActivity" |
| 57 | + // /> |
| 58 | + string? from = null; |
| 59 | + string? to = null; |
| 60 | + while (reader.MoveToNextAttribute ()) { |
| 61 | + switch (reader.LocalName) { |
| 62 | + case "from": |
| 63 | + from = reader.Value; |
| 64 | + break; |
| 65 | + case "to": |
| 66 | + to = reader.Value; |
| 67 | + break; |
| 68 | + } |
| 69 | + } |
| 70 | + if (string.IsNullOrEmpty (from) || string.IsNullOrEmpty (to)) { |
| 71 | + return; |
| 72 | + } |
| 73 | + replacementTypes [from] = to; |
| 74 | + } |
| 75 | + |
| 76 | + static void ParseReplaceMethodAttributes (ReplacementMethodsDict replacementMethods, XmlReader reader) |
| 77 | + { |
| 78 | + // <replace-method |
| 79 | + // source-type="jni-simple-type" |
| 80 | + // source-method-name="method-name" |
| 81 | + // source-method-signature="jni-method-signature" |
| 82 | + // target-type="jni-simple-type" |
| 83 | + // target-method-name="method-name" |
| 84 | + // target-method-signature="jni-method-signature" |
| 85 | + // target-method-parameter-count="int" |
| 86 | + // target-method-instance-to-static="bool" |
| 87 | + // /> |
| 88 | + |
| 89 | + string? sourceType = null; |
| 90 | + string? sourceMethod = null; |
| 91 | + string? sourceMethodSig = null; |
| 92 | + string? targetType = null; |
| 93 | + string? targetMethod = null; |
| 94 | + string? targetMethodSig = null; |
| 95 | + int? targetMethodParamCount = null; |
| 96 | + bool targetMethodInstanceToStatic = false; |
| 97 | + |
| 98 | + while (reader.MoveToNextAttribute ()) { |
| 99 | + switch (reader.LocalName) { |
| 100 | + case "source-type": |
| 101 | + sourceType = reader.Value; |
| 102 | + break; |
| 103 | + case "source-method-name": |
| 104 | + sourceMethod = reader.Value; |
| 105 | + break; |
| 106 | + case "source-method-signature": |
| 107 | + sourceMethodSig = reader.Value; |
| 108 | + break; |
| 109 | + case "target-type": |
| 110 | + targetType = reader.Value; |
| 111 | + break; |
| 112 | + case "target-method-name": |
| 113 | + targetMethod = reader.Value; |
| 114 | + break; |
| 115 | + case "target-method-signature": |
| 116 | + targetMethodSig = reader.Value; |
| 117 | + break; |
| 118 | + case "target-method-parameter-count": |
| 119 | + if (int.TryParse (reader.Value, 0, CultureInfo.InvariantCulture, out var v)) { |
| 120 | + targetMethodParamCount = v; |
| 121 | + } |
| 122 | + break; |
| 123 | + case "target-method-instance-to-static": |
| 124 | + targetMethodInstanceToStatic = reader.Value == "true"; |
| 125 | + break; |
| 126 | + } |
| 127 | + } |
| 128 | + if (string.IsNullOrEmpty (sourceType) || string.IsNullOrEmpty (sourceMethod)) { |
| 129 | + return; |
| 130 | + } |
| 131 | + replacementMethods [(sourceType, sourceMethod, sourceMethodSig)] |
| 132 | + = (targetType, targetMethod, targetMethodSig, targetMethodParamCount, targetMethodInstanceToStatic); |
| 133 | + } |
| 134 | + } |
| 135 | +} |
0 commit comments