IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
VfsAssemblyDirectory.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2007-2011 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Collections.Concurrent;
26using System.Linq;
27using System.Reflection;
28using System.Text;
29
30namespace IKVM.Runtime.Vfs
31{
32
36 internal sealed class VfsAssemblyDirectory : VfsDirectory
37 {
38
39 readonly ConcurrentDictionary<Assembly, VfsDirectory> directories = new ConcurrentDictionary<Assembly, VfsDirectory>();
40
45 public VfsAssemblyDirectory(VfsContext context) :
46 base(context)
47 {
48
49 }
50
56 AssemblyName ParseDirectoryName(string directoryName)
57 {
58 try
59 {
60 var assemblyName = new AssemblyName();
61 var sb = new ValueStringBuilder();
62 var part = 0;
63 for (var i = 0; i <= directoryName.Length; i++)
64 {
65 if (i == directoryName.Length || directoryName[i] == '_')
66 {
67 if (i < directoryName.Length - 1 && directoryName[i + 1] == '!')
68 {
69 sb.Append('_');
70 i++;
71 }
72 else if (i == directoryName.Length || directoryName[i + 1] == '_')
73 {
74 switch (part++)
75 {
76 case 0:
77 assemblyName.Name = sb.ToString();
78 break;
79 case 1:
80 assemblyName.Version = Version.Parse(sb.ToString());
81 break;
82 case 2:
83 assemblyName.SetPublicKeyToken(StringToByteArray(sb.ToString()));
84 break;
85 case 3:
86 assemblyName.CultureName = sb.ToString();
87 break;
88 case 4:
89 return null;
90 }
91
92 sb.Length = 0;
93 i++;
94 }
95 else
96 {
97 int start = i + 1;
98 int end = start;
99 while ('0' <= directoryName[end] && directoryName[end] <= '9')
100 end++;
101
102#if NETFRAMEWORK
103 if (directoryName[end] != '_' || !int.TryParse(directoryName.Substring(start, end - start), out int repeatCount))
104#else
105 if (directoryName[end] != '_' || !int.TryParse(directoryName.AsSpan(start, end - start), out int repeatCount))
106#endif
107 return null;
108
109 sb.Append('_', repeatCount);
110 i = end;
111 }
112 }
113 else
114 {
115 sb.Append(directoryName[i]);
116 }
117 }
118
119 return assemblyName;
120 }
121 catch
122 {
123 return null;
124 }
125 }
126
132 public override VfsEntry GetEntry(string name)
133 {
134 // search for a directory by MVID
135 if (Guid.TryParse(name, out var guid))
136 {
137 foreach (var assemblyName in Context.GetAssemblyNames())
138 if (Context.GetAssembly(assemblyName) is Assembly assembly)
139 if (assembly.ManifestModule.ModuleVersionId == guid && assembly.IsDynamic == false)
140 return directories.GetOrAdd(assembly, CreateAssemblyDirectory);
141
142 return null;
143 }
144 else
145 {
146 // search for a directory for the given full name
147 var assemblyName = ParseDirectoryName(name);
148 if (assemblyName != null)
149 {
150 var assembly = Context.GetAssembly(assemblyName);
151 if (assembly != null && assembly.IsDynamic == false && name == VfsTable.GetAssemblyDirectoryName(Context, assembly))
152 return directories.GetOrAdd(assembly, CreateAssemblyDirectory);
153 }
154
155 return null;
156 }
157 }
158
164 VfsDirectory CreateAssemblyDirectory(Assembly assembly)
165 {
166 var d = new VfsEntryDirectory(Context);
167 d.AddEntry("resources", new VfsAssemblyResourceDirectory(Context, assembly));
168 d.AddEntry("classes", new VfsAssemblyClassDirectory(Context, assembly, ""));
169 return d;
170 }
171
176 public override string[] List()
177 {
178 return Array.Empty<string>();
179 }
180
187 byte[] StringToByteArray(string hex)
188 {
189 if (hex.Length % 2 == 1)
190 throw new Exception("The binary key cannot have an odd number of digits");
191
192 var arr = new byte[hex.Length >> 1];
193 for (int i = 0; i < hex.Length >> 1; ++i)
194 arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
195
196 return arr;
197
198 static int GetHexVal(char hex) => (int)hex - ((int)hex < 58 ? 48 : ((int)hex < 97 ? 55 : 87));
199 }
200
201 }
202
203}
IKVM.Reflection.Assembly Assembly
IKVM.Reflection.AssemblyName AssemblyName