4646import org .graalvm .buildtools .gradle .internal .GraalVMReachabilityMetadataService ;
4747import org .gradle .api .DefaultTask ;
4848import org .gradle .api .artifacts .Configuration ;
49- import org .gradle .api .artifacts .ResolvedArtifact ;
50- import org .gradle .api .artifacts .ResolvedDependency ;
49+ import org .gradle .api .artifacts .component .ModuleComponentIdentifier ;
50+ import org .gradle .api .artifacts .result .DependencyResult ;
51+ import org .gradle .api .artifacts .result .ResolvedArtifactResult ;
52+ import org .gradle .api .artifacts .result .ResolvedComponentResult ;
53+ import org .gradle .api .artifacts .result .ResolvedDependencyResult ;
5154import org .gradle .api .file .RegularFileProperty ;
5255import org .gradle .api .provider .Property ;
56+ import org .gradle .api .provider .SetProperty ;
5357import org .gradle .api .tasks .Internal ;
5458import org .gradle .api .tasks .OutputFile ;
5559import org .gradle .api .tasks .TaskAction ;
6064import java .nio .file .Files ;
6165import java .nio .file .Path ;
6266import java .util .HashMap ;
63- import java .util .HashSet ;
6467import java .util .LinkedHashSet ;
6568import java .util .Map ;
6669import java .util .Optional ;
@@ -83,8 +86,16 @@ public abstract class GenerateDynamicAccessMetadata extends DefaultTask {
8386 private static final String METADATA_PROVIDER = "metadataProvider" ;
8487 private static final String PROVIDES_FOR = "providesFor" ;
8588
89+ public void setClasspath (Configuration classpath ) {
90+ getRuntimeClasspathGraph ().set (classpath .getIncoming ().getResolutionResult ().getRootComponent ());
91+ getRuntimeClasspathArtifacts ().set (classpath .getIncoming ().getArtifacts ().getResolvedArtifacts ());
92+ }
93+
94+ @ Internal
95+ public abstract Property <ResolvedComponentResult > getRuntimeClasspathGraph ();
96+
8697 @ Internal
87- public abstract Property < Configuration > getRuntimeClasspath ();
98+ public abstract SetProperty < ResolvedArtifactResult > getRuntimeClasspathArtifacts ();
8899
89100 @ Internal
90101 public abstract Property <GraalVMReachabilityMetadataService > getMetadataService ();
@@ -110,16 +121,21 @@ public void generate() {
110121 try {
111122 Set <String > artifactsToInclude = readArtifacts (jsonFile );
112123
113- Configuration runtimeClasspathConfig = getRuntimeClasspath ().get ();
114- Set <File > classpathEntries = runtimeClasspathConfig .getFiles ();
124+ Map <String , String > coordinatesToPath = new HashMap <>();
125+ for (ResolvedArtifactResult artifact : getRuntimeClasspathArtifacts ().get ()) {
126+ if (artifact .getId ().getComponentIdentifier () instanceof ModuleComponentIdentifier mci ) {
127+ String coordinates = mci .getGroup () + ":" + mci .getModule ();
128+ coordinatesToPath .put (coordinates , artifact .getFile ().getAbsolutePath ());
129+ }
130+ }
115131
116- Map <String , Set <String >> exportMap = buildExportMap (
117- runtimeClasspathConfig .getResolvedConfiguration ().getFirstLevelModuleDependencies (),
118- artifactsToInclude ,
119- classpathEntries
120- );
132+ ResolvedComponentResult root = getRuntimeClasspathGraph ().get ();
133+
134+ Map <String , Set <String >> exportMap = buildExportMap (root , artifactsToInclude , coordinatesToPath );
121135
122136 writeMapToJson (getOutputJson ().getAsFile ().get (), exportMap );
137+
138+ GraalVMLogger .of (getLogger ()).log ("Dynamic Access Metadata written into " + getOutputJson ().get ());
123139 } catch (IOException e ) {
124140 GraalVMLogger .of (getLogger ()).log ("Failed to generate dynamic access metadata: {}" , e );
125141 }
@@ -147,40 +163,61 @@ private Set<String> readArtifacts(File inputFile) throws IOException {
147163 * exists in the {@value #LIBRARY_AND_FRAMEWORK_LIST} file, to the set of all of its
148164 * transitive dependency entry paths.
149165 */
150- private Map <String , Set <String >> buildExportMap (Set < ResolvedDependency > dependencies , Set <String > artifactsToInclude , Set < File > classpathEntries ) {
166+ private Map <String , Set <String >> buildExportMap (ResolvedComponentResult root , Set <String > artifactsToInclude , Map < String , String > coordinatesToPath ) {
151167 Map <String , Set <String >> exportMap = new HashMap <>();
152- for (ResolvedDependency dependency : dependencies ) {
153- String dependencyCoordinates = dependency .getModuleGroup () + ":" + dependency .getModuleName ();
154- if (!artifactsToInclude .contains (dependencyCoordinates )) {
155- continue ;
156- }
168+ Map <String , Set <String >> dependencyMap = new HashMap <>();
157169
158- for (ResolvedArtifact artifact : dependency .getModuleArtifacts ()) {
159- File file = artifact .getFile ();
160- if (classpathEntries .contains (file )) {
161- Set <String > files = new LinkedHashSet <>();
162- collectDependencies (dependency , files , classpathEntries );
163- exportMap .put (file .getAbsolutePath (), files );
170+ collectDependencies (root , dependencyMap , new LinkedHashSet <>(), coordinatesToPath );
171+
172+ for (Map .Entry <String , Set <String >> entry : dependencyMap .entrySet ()) {
173+ String coordinates = entry .getKey ();
174+ if (artifactsToInclude .contains (coordinates )) {
175+ String absolutePath = coordinatesToPath .get (coordinates );
176+ if (absolutePath != null ) {
177+ exportMap .put (absolutePath , entry .getValue ());
164178 }
165179 }
166180 }
181+
167182 return exportMap ;
168183 }
169184
170185 /**
171186 * Recursively collects all classpath entry paths for the given dependency and its transitive dependencies.
172187 */
173- private void collectDependencies (ResolvedDependency dep , Set <String > collector , Set <File > classpathEntries ) {
174- for (ResolvedArtifact artifact : dep .getModuleArtifacts ()) {
175- File file = artifact .getFile ();
176- if (classpathEntries .contains (file )) {
177- collector .add (file .getAbsolutePath ());
178- }
188+ private void collectDependencies (ResolvedComponentResult node , Map <String , Set <String >> dependencyMap , Set <String > visited , Map <String , String > coordinatesToPath ) {
189+ String coordinates = null ;
190+ if (node .getId () instanceof ModuleComponentIdentifier mci ) {
191+ coordinates = mci .getGroup () + ":" + mci .getModule ();
179192 }
180193
181- for (ResolvedDependency child : dep .getChildren ()) {
182- collectDependencies (child , collector , classpathEntries );
194+ if (coordinates != null && !visited .add (coordinates )) {
195+ return ;
196+ }
197+
198+ Set <String > dependencies = new LinkedHashSet <>();
199+ for (DependencyResult dep : node .getDependencies ()) {
200+ if (dep instanceof ResolvedDependencyResult resolved ) {
201+ ResolvedComponentResult target = resolved .getSelected ();
202+
203+ if (target .getId () instanceof ModuleComponentIdentifier targetMci ) {
204+ String dependencyCoordinates = targetMci .getGroup () + ":" + targetMci .getModule ();
205+ String dependencyPath = coordinatesToPath .get (dependencyCoordinates );
206+
207+ if (dependencyPath != null ) {
208+ dependencies .add (dependencyPath );
209+ }
210+
211+ collectDependencies (target , dependencyMap , visited , coordinatesToPath );
212+
213+ Set <String > transitiveDependencies = dependencyMap .get (dependencyCoordinates );
214+ if (transitiveDependencies != null ) {
215+ dependencies .addAll (transitiveDependencies );
216+ }
217+ }
218+ }
183219 }
220+ dependencyMap .put (coordinates , dependencies );
184221 }
185222
186223 /**
0 commit comments