001package org.apache.maven.resolver.examples.util; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.IOException; 023import java.io.UncheckedIOException; 024import java.nio.charset.StandardCharsets; 025import java.nio.file.Files; 026import java.nio.file.Path; 027import java.util.ListIterator; 028import java.util.Objects; 029 030import org.eclipse.aether.AbstractRepositoryListener; 031import org.eclipse.aether.RepositoryEvent; 032import org.eclipse.aether.RequestTrace; 033import org.eclipse.aether.artifact.Artifact; 034import org.eclipse.aether.collection.CollectStepData; 035import org.eclipse.aether.graph.Dependency; 036import org.eclipse.aether.graph.DependencyNode; 037 038import static java.util.Objects.requireNonNull; 039 040/** 041 * A demo class building reverse tree using {@link CollectStepData} trace data provided in {@link RepositoryEvent} 042 * events fired during collection. 043 */ 044public class ReverseTreeRepositoryListener 045 extends AbstractRepositoryListener 046{ 047 private static final String EOL = System.lineSeparator(); 048 049 @Override 050 public void artifactResolved( RepositoryEvent event ) 051 { 052 requireNonNull( event, "event cannot be null" ); 053 054 RequestTrace trace = event.getTrace(); 055 CollectStepData collectStepTrace = null; 056 while ( trace != null ) 057 { 058 if ( trace.getData() instanceof CollectStepData ) 059 { 060 collectStepTrace = (CollectStepData) trace.getData(); 061 break; 062 } 063 trace = trace.getParent(); 064 } 065 066 if ( collectStepTrace == null ) 067 { 068 return; 069 } 070 071 Artifact resolvedArtifact = event.getArtifact(); 072 Artifact nodeArtifact = collectStepTrace.getNode().getArtifact(); 073 074 if ( isInScope( resolvedArtifact, nodeArtifact ) ) 075 { 076 Dependency node = collectStepTrace.getNode(); 077 String trackingData = node + " (" + collectStepTrace.getContext() + ")" + EOL; 078 String indent = ""; 079 ListIterator<DependencyNode> iter = collectStepTrace.getPath() 080 .listIterator( collectStepTrace.getPath().size() ); 081 while ( iter.hasPrevious() ) 082 { 083 DependencyNode curr = iter.previous(); 084 indent += " "; 085 trackingData += indent + curr + " (" + collectStepTrace.getContext() + ")" + EOL; 086 } 087 try 088 { 089 Path trackingDir = resolvedArtifact.getFile().getParentFile().toPath().resolve( ".tracking" ); 090 Files.createDirectories( trackingDir ); 091 Path trackingFile = trackingDir.resolve( collectStepTrace.getPath().get( 0 ) 092 .getArtifact().toString().replace( ":", "_" ) ); 093 Files.write( trackingFile, trackingData.getBytes( StandardCharsets.UTF_8 ) ); 094 System.out.println( trackingData ); 095 } 096 catch ( IOException e ) 097 { 098 throw new UncheckedIOException( e ); 099 } 100 } 101 } 102 103 /** 104 * The event "artifact resolved" if fired WHENEVER an artifact is resolved, BUT it happens also when an artifact 105 * descriptor (model, the POM) is being built, and parent (and parent of parent...) is being asked for. Hence, this 106 * method "filters" out in WHICH artifact are we interested in, but it intentionally neglects extension as 107 * ArtifactDescriptorReader modifies extension to "pom" during collect. So all we have to rely on is GAV only. 108 */ 109 private boolean isInScope( Artifact artifact, Artifact nodeArtifact ) 110 { 111 return Objects.equals( artifact.getGroupId(), nodeArtifact.getGroupId() ) 112 && Objects.equals( artifact.getArtifactId(), nodeArtifact.getArtifactId() ) 113 && Objects.equals( artifact.getVersion(), nodeArtifact.getVersion() ); 114 } 115}