1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package io.earcam.instrumental.lade.jpms;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.lang.module.ModuleDescriptor;
24 import java.lang.module.ModuleFinder;
25 import java.lang.module.ModuleReference;
26 import java.net.URI;
27 import java.net.URL;
28 import java.util.Enumeration;
29 import java.util.HashSet;
30 import java.util.Optional;
31 import java.util.Set;
32 import java.util.stream.Collectors;
33
34 import io.earcam.instrumental.lade.InMemoryClassLoader;
35 import io.earcam.unexceptional.CheckedFunction;
36 import io.earcam.unexceptional.Closing;
37 import io.earcam.unexceptional.Exceptional;
38
39 public final class InMemoryModuleFinder implements ModuleFinder {
40
41 private static final String MODULE_INFO_CLASS = "module-info.class";
42 private final InMemoryClassLoader loader;
43
44
45 public InMemoryModuleFinder(InMemoryClassLoader loader)
46 {
47 this.loader = loader;
48 }
49
50
51 @Override
52 public Optional<ModuleReference> find(String name)
53 {
54 return findAll().stream()
55 .filter(m -> name.equals(m.descriptor().name()))
56 .findAny();
57 }
58
59
60 @Override
61 public Set<ModuleReference> findAll()
62 {
63 Enumeration<URL> resources = loader.getResources(MODULE_INFO_CLASS, false);
64
65 Set<ModuleReference> references = new HashSet<>();
66 while(resources.hasMoreElements()) {
67 URL moduleInfo = resources.nextElement();
68 ModuleDescriptor descriptor = parseModuleInfoByteCode(moduleInfo);
69 URI uri = extractBaseUri(moduleInfo);
70 Set<String> list = resourcesForThisModule(uri);
71 references.add(new InMemoryModuleReference(descriptor, uri, list));
72
73 }
74 return references;
75 }
76
77
78 private Set<String> resourcesForThisModule(URI baseUri)
79 {
80 return loader.resources()
81 .map(Object::toString)
82 .filter(r -> r.startsWith(baseUri.toString()))
83 .collect(Collectors.toSet());
84 }
85
86
87 private URI extractBaseUri(URL moduleInfo)
88 {
89 String url = moduleInfo.toString();
90 url = url.substring(0, url.length() - MODULE_INFO_CLASS.length());
91 return Exceptional.uri(url);
92 }
93
94
95 private ModuleDescriptor parseModuleInfoByteCode(URL moduleInfo)
96 {
97 CheckedFunction<InputStream, ModuleDescriptor, IOException> converter = ModuleDescriptor::read;
98 return Closing.closeAfterApplying(
99 URL::openStream,
100 moduleInfo,
101 converter);
102 }
103 }