|
47 | 47 | import org.graalvm.reachability.internal.index.artifacts.SingleModuleJsonVersionToConfigDirectoryIndex; |
48 | 48 | import org.graalvm.reachability.internal.index.artifacts.VersionToConfigDirectoryIndex; |
49 | 49 | import org.graalvm.reachability.internal.index.modules.FileSystemModuleToConfigDirectoryIndex; |
| 50 | +import org.graalvm.reachability.internal.index.modules.ModuleConfigurationDirectory; |
50 | 51 |
|
51 | 52 | import java.nio.file.Path; |
| 53 | +import java.util.Collections; |
| 54 | +import java.util.LinkedHashMap; |
| 55 | +import java.util.LinkedHashSet; |
| 56 | +import java.util.List; |
52 | 57 | import java.util.Map; |
53 | 58 | import java.util.Optional; |
54 | 59 | import java.util.Set; |
55 | 60 | import java.util.concurrent.ConcurrentHashMap; |
56 | 61 | import java.util.function.Consumer; |
57 | 62 | import java.util.function.Supplier; |
58 | | -import java.util.stream.Collectors; |
59 | 63 |
|
60 | 64 | /** |
61 | 65 | * Queries an unpacked reachability metadata repository. §FS-common-libraries.5. |
@@ -99,90 +103,109 @@ public static boolean isSupportedArchiveFormat(String path) { |
99 | 103 | public Set<DirectoryConfiguration> findConfigurationsFor(Consumer<? super Query> queryBuilder) { |
100 | 104 | DefaultQuery query = new DefaultQuery(); |
101 | 105 | queryBuilder.accept(query); |
102 | | - return query.getArtifacts() |
103 | | - .stream() |
104 | | - .flatMap(artifactQuery -> { |
105 | | - String groupId = artifactQuery.getGroupId(); |
106 | | - String artifactId = artifactQuery.getArtifactId(); |
107 | | - String version = artifactQuery.getVersion(); |
108 | | - return moduleIndex.findConfigurationDirectories(groupId, artifactId) |
109 | | - .stream() |
110 | | - .map(dir -> { |
111 | | - VersionToConfigDirectoryIndex index = artifactIndexes.computeIfAbsent(dir, |
112 | | - SingleModuleJsonVersionToConfigDirectoryIndex::new); |
113 | | - if (artifactQuery.getForcedConfig().isPresent()) { |
114 | | - String configVersion = artifactQuery.getForcedConfig().get(); |
115 | | - logger.log(groupId, artifactId, version, "Configuration is forced to version " + configVersion); |
116 | | - return index.findConfiguration(groupId, artifactId, configVersion); |
117 | | - } |
118 | | - Optional<DirectoryConfiguration> configuration = index.findConfiguration(groupId, artifactId, version); |
119 | | - if (!configuration.isPresent() && artifactQuery.isUseLatestVersion()) { |
120 | | - logger.log(groupId, artifactId, version, "Configuration directory not found. Trying latest version."); |
121 | | - configuration = index.findLatestConfigurationFor(groupId, artifactId, version); |
122 | | - if (!configuration.isPresent()) { |
123 | | - logger.log(groupId, artifactId, version, "Latest version not found!"); |
124 | | - } |
125 | | - } |
126 | | - Optional<DirectoryConfiguration> finalConfigurationDirectory = configuration; |
127 | | - logger.log(groupId, artifactId, version, () -> { |
128 | | - if (finalConfigurationDirectory.isPresent()) { |
129 | | - Path path = finalConfigurationDirectory.get().getDirectory(); |
130 | | - return "Configuration directory is " + rootDirectory.relativize(path); |
131 | | - } |
132 | | - return "missing."; |
133 | | - }); |
134 | | - return configuration; |
135 | | - }) |
136 | | - .filter(Optional::isPresent) |
137 | | - .map(Optional::get); |
138 | | - }) |
139 | | - .collect(Collectors.toSet()); |
| 106 | + List<DefaultArtifactQuery> artifacts = query.getArtifacts(); |
| 107 | + Set<String> directlyQueriedModules = directlyQueriedModules(artifacts); |
| 108 | + Map<String, DirectoryConfiguration> configurations = new LinkedHashMap<>(); |
| 109 | + // Select the complete query as one graph so requires never preempts a direct module query. §FS-common-libraries.5.1. |
| 110 | + for (DefaultArtifactQuery artifactQuery : artifacts) { |
| 111 | + for (ModuleConfigurationDirectory candidate : moduleIndex.findConfigurationDirectories( |
| 112 | + artifactQuery.getGroupId(), artifactQuery.getArtifactId())) { |
| 113 | + boolean direct = isSameModule(candidate, artifactQuery); |
| 114 | + if (!direct && directlyQueriedModules.contains(moduleKey(candidate.getGroupId(), candidate.getArtifactId()))) { |
| 115 | + continue; |
| 116 | + } |
| 117 | + Optional<String> forcedConfig = direct ? artifactQuery.getForcedConfig() : Optional.empty(); |
| 118 | + selectConfiguration(candidate, artifactQuery.getVersion(), artifactQuery.isUseLatestVersion(), forcedConfig) |
| 119 | + .ifPresent(configuration -> configurations.putIfAbsent(configurationKey(configuration), configuration)); |
| 120 | + } |
| 121 | + } |
| 122 | + return Collections.unmodifiableSet(new LinkedHashSet<>(configurations.values())); |
140 | 123 | } |
141 | 124 |
|
142 | 125 | @Override |
143 | 126 | public boolean isCoveredByRepository(Consumer<? super Query> queryBuilder) { |
144 | 127 | DefaultQuery query = new DefaultQuery(); |
145 | 128 | queryBuilder.accept(query); |
146 | | - return query.getArtifacts() |
147 | | - .stream() |
148 | | - .anyMatch(artifactQuery -> { |
149 | | - String groupId = artifactQuery.getGroupId(); |
150 | | - String artifactId = artifactQuery.getArtifactId(); |
151 | | - String version = artifactQuery.getVersion(); |
152 | | - return moduleIndex.findConfigurationDirectories(groupId, artifactId) |
153 | | - .stream() |
154 | | - .anyMatch(dir -> { |
155 | | - VersionToConfigDirectoryIndex index = artifactIndexes.computeIfAbsent(dir, SingleModuleJsonVersionToConfigDirectoryIndex::new); |
156 | | - Optional<DirectoryConfiguration> configuration; |
157 | | - if (artifactQuery.getForcedConfig().isPresent()) { |
158 | | - String configVersion = artifactQuery.getForcedConfig().get(); |
159 | | - logger.log(groupId, artifactId, version, "Configuration is forced to version " + configVersion); |
160 | | - configuration = index.findConfiguration(groupId, artifactId, configVersion); |
161 | | - } else { |
162 | | - configuration = index.findConfiguration(groupId, artifactId, version); |
163 | | - if (!configuration.isPresent() && artifactQuery.isUseLatestVersion()) { |
164 | | - logger.log(groupId, artifactId, version, |
165 | | - "Configuration directory not found. Trying latest version."); |
166 | | - configuration = index.findLatestConfigurationFor(groupId, artifactId, version); |
167 | | - if (!configuration.isPresent()) { |
168 | | - logger.log(groupId, artifactId, version, "Latest version not found!"); |
169 | | - } |
170 | | - } |
171 | | - } |
172 | | - if (configuration.isPresent()) { |
173 | | - Path path = configuration.get().getDirectory(); |
174 | | - logger.log(groupId, artifactId, version, |
175 | | - "Configuration directory is " + rootDirectory.relativize(path)); |
176 | | - return true; |
177 | | - } |
178 | | - if (index.isNotForNativeImage(groupId, artifactId, version)) { |
179 | | - logger.log(groupId, artifactId, version, "Artifact is marked as not for native-image."); |
180 | | - return true; |
181 | | - } |
182 | | - logger.log(groupId, artifactId, version, "missing."); |
183 | | - return false; |
184 | | - }); |
185 | | - }); |
| 129 | + List<DefaultArtifactQuery> artifacts = query.getArtifacts(); |
| 130 | + Set<String> directlyQueriedModules = directlyQueriedModules(artifacts); |
| 131 | + // Check the complete query as one graph so requires never preempts a direct module query. §FS-common-libraries.5.1. |
| 132 | + for (DefaultArtifactQuery artifactQuery : artifacts) { |
| 133 | + for (ModuleConfigurationDirectory candidate : moduleIndex.findConfigurationDirectories( |
| 134 | + artifactQuery.getGroupId(), artifactQuery.getArtifactId())) { |
| 135 | + boolean direct = isSameModule(candidate, artifactQuery); |
| 136 | + if (!direct && directlyQueriedModules.contains(moduleKey(candidate.getGroupId(), candidate.getArtifactId()))) { |
| 137 | + continue; |
| 138 | + } |
| 139 | + Optional<String> forcedConfig = direct ? artifactQuery.getForcedConfig() : Optional.empty(); |
| 140 | + if (isCovered(candidate, artifactQuery.getVersion(), artifactQuery.isUseLatestVersion(), forcedConfig)) { |
| 141 | + return true; |
| 142 | + } |
| 143 | + } |
| 144 | + } |
| 145 | + return false; |
| 146 | + } |
| 147 | + |
| 148 | + private Optional<DirectoryConfiguration> selectConfiguration(ModuleConfigurationDirectory candidate, |
| 149 | + String version, boolean useLatestVersion, Optional<String> forcedConfig) { |
| 150 | + String groupId = candidate.getGroupId(); |
| 151 | + String artifactId = candidate.getArtifactId(); |
| 152 | + VersionToConfigDirectoryIndex index = artifactIndexes.computeIfAbsent(candidate.getDirectory(), |
| 153 | + SingleModuleJsonVersionToConfigDirectoryIndex::new); |
| 154 | + Optional<DirectoryConfiguration> configuration; |
| 155 | + if (forcedConfig.isPresent()) { |
| 156 | + String configVersion = forcedConfig.get(); |
| 157 | + logger.log(groupId, artifactId, version, "Configuration is forced to version " + configVersion); |
| 158 | + configuration = index.findConfiguration(groupId, artifactId, configVersion); |
| 159 | + } else { |
| 160 | + configuration = index.findConfiguration(groupId, artifactId, version); |
| 161 | + if (!configuration.isPresent() && useLatestVersion) { |
| 162 | + logger.log(groupId, artifactId, version, "Configuration directory not found. Trying latest version."); |
| 163 | + configuration = index.findLatestConfigurationFor(groupId, artifactId, version); |
| 164 | + if (!configuration.isPresent()) { |
| 165 | + logger.log(groupId, artifactId, version, "Latest version not found!"); |
| 166 | + } |
| 167 | + } |
| 168 | + } |
| 169 | + Optional<DirectoryConfiguration> result = configuration; |
| 170 | + logger.log(groupId, artifactId, version, () -> result |
| 171 | + .map(value -> "Configuration directory is " + rootDirectory.relativize(value.getDirectory())) |
| 172 | + .orElse("missing.")); |
| 173 | + return configuration; |
| 174 | + } |
| 175 | + |
| 176 | + private boolean isCovered(ModuleConfigurationDirectory candidate, String version, boolean useLatestVersion, |
| 177 | + Optional<String> forcedConfig) { |
| 178 | + Optional<DirectoryConfiguration> configuration = selectConfiguration(candidate, version, useLatestVersion, forcedConfig); |
| 179 | + if (configuration.isPresent()) { |
| 180 | + return true; |
| 181 | + } |
| 182 | + VersionToConfigDirectoryIndex index = artifactIndexes.get(candidate.getDirectory()); |
| 183 | + if (index.isNotForNativeImage(candidate.getGroupId(), candidate.getArtifactId(), version)) { |
| 184 | + logger.log(candidate.getGroupId(), candidate.getArtifactId(), version, "Artifact is marked as not for native-image."); |
| 185 | + return true; |
| 186 | + } |
| 187 | + return false; |
| 188 | + } |
| 189 | + |
| 190 | + private static Set<String> directlyQueriedModules(List<DefaultArtifactQuery> artifacts) { |
| 191 | + Set<String> modules = new LinkedHashSet<>(); |
| 192 | + for (DefaultArtifactQuery artifact : artifacts) { |
| 193 | + modules.add(moduleKey(artifact.getGroupId(), artifact.getArtifactId())); |
| 194 | + } |
| 195 | + return modules; |
| 196 | + } |
| 197 | + |
| 198 | + private static boolean isSameModule(ModuleConfigurationDirectory candidate, DefaultArtifactQuery artifact) { |
| 199 | + return candidate.getGroupId().equals(artifact.getGroupId()) && candidate.getArtifactId().equals(artifact.getArtifactId()); |
| 200 | + } |
| 201 | + |
| 202 | + private static String moduleKey(String groupId, String artifactId) { |
| 203 | + return groupId + ':' + artifactId; |
| 204 | + } |
| 205 | + |
| 206 | + private static String configurationKey(DirectoryConfiguration configuration) { |
| 207 | + return moduleKey(configuration.getGroupId(), configuration.getArtifactId()) + ':' + configuration.getVersion() |
| 208 | + + ':' + configuration.getDirectory().normalize() + ':' + configuration.isOverride(); |
186 | 209 | } |
187 | 210 |
|
188 | 211 | public Path getRootDirectory() { |
|
0 commit comments