This project has retired. For details please refer to its Attic page.
Maven3DependencyTreeBuilder xref
View Javadoc
1   package org.apache.archiva.dependency.tree.maven2;
2   /*
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  
21  
22  import org.apache.archiva.admin.model.RepositoryAdminException;
23  import org.apache.archiva.admin.model.beans.NetworkProxy;
24  import org.apache.archiva.admin.model.beans.ProxyConnector;
25  import org.apache.archiva.admin.model.networkproxy.NetworkProxyAdmin;
26  import org.apache.archiva.admin.model.proxyconnector.ProxyConnectorAdmin;
27  import org.apache.archiva.common.plexusbridge.PlexusSisuBridge;
28  import org.apache.archiva.common.plexusbridge.PlexusSisuBridgeException;
29  import org.apache.archiva.common.utils.VersionUtil;
30  import org.apache.archiva.maven2.metadata.MavenMetadataReader;
31  import org.apache.archiva.maven2.model.TreeEntry;
32  import org.apache.archiva.metadata.repository.storage.RepositoryPathTranslator;
33  import org.apache.archiva.model.ArchivaRepositoryMetadata;
34  import org.apache.archiva.repository.ManagedRepository;
35  import org.apache.archiva.repository.RemoteRepository;
36  import org.apache.archiva.repository.RepositoryRegistry;
37  import org.apache.archiva.repository.maven2.MavenSystemManager;
38  import org.apache.archiva.repository.metadata.base.MetadataTools;
39  import org.apache.archiva.repository.storage.StorageAsset;
40  import org.apache.archiva.xml.XMLException;
41  import org.apache.commons.lang3.StringUtils;
42  import org.apache.maven.artifact.Artifact;
43  import org.apache.maven.bridge.MavenRepositorySystem;
44  import org.eclipse.aether.RepositorySystem;
45  import org.eclipse.aether.RepositorySystemSession;
46  import org.eclipse.aether.artifact.DefaultArtifact;
47  import org.eclipse.aether.collection.CollectRequest;
48  import org.eclipse.aether.collection.CollectResult;
49  import org.eclipse.aether.collection.DependencyCollectionException;
50  import org.eclipse.aether.graph.Dependency;
51  import org.eclipse.aether.graph.DependencyVisitor;
52  import org.slf4j.Logger;
53  import org.slf4j.LoggerFactory;
54  import org.springframework.stereotype.Service;
55  
56  import javax.annotation.PostConstruct;
57  import javax.inject.Inject;
58  import javax.inject.Named;
59  import java.io.IOException;
60  import java.util.ArrayList;
61  import java.util.HashMap;
62  import java.util.List;
63  import java.util.Map;
64  
65  /**
66   * @author Olivier Lamy
67   * @since 1.4-M3
68   */
69  @Service("dependencyTreeBuilder#maven3")
70  public class Maven3DependencyTreeBuilder
71      implements DependencyTreeBuilder
72  {
73      private Logger log = LoggerFactory.getLogger( Maven3DependencyTreeBuilder.class );
74  
75      @Inject
76      private PlexusSisuBridge plexusSisuBridge;
77  
78      private MavenRepositorySystem mavenRepositorySystem;
79  
80      @Inject
81      @Named( "repositoryPathTranslator#maven2" )
82      private RepositoryPathTranslator pathTranslator;
83  
84      @Inject
85      private ProxyConnectorAdmin proxyConnectorAdmin;
86  
87      @Inject
88      private NetworkProxyAdmin networkProxyAdmin;
89  
90      @Inject
91      RepositoryRegistry repositoryRegistry;
92  
93      @Inject
94      MavenSystemManager mavenSystemManager;
95  
96  
97      @PostConstruct
98      public void initialize()
99          throws PlexusSisuBridgeException
100     {
101         mavenRepositorySystem = plexusSisuBridge.lookup(MavenRepositorySystem.class);
102     }
103 
104 
105 
106     public void buildDependencyTree( List<String> repositoryIds, String groupId, String artifactId, String version,
107                                      DependencyVisitor dependencyVisitor )
108         throws DependencyTreeBuilderException
109     {
110 
111         Artifact projectArtifact = mavenRepositorySystem.createProjectArtifact(groupId, artifactId, version);
112         ManagedRepository repository = findArtifactInRepositories( repositoryIds, projectArtifact );
113 
114         if ( repository == null )
115         {
116             // metadata could not be resolved
117             log.info("Did not find repository with artifact {}/{}/{}", groupId, artifactId, version);
118             return;
119         }
120 
121         List<org.apache.archiva.repository.RemoteRepository> remoteRepositories = new ArrayList<>();
122         Map<String, NetworkProxy> networkProxies = new HashMap<>();
123 
124         try
125         {
126             // MRM-1411
127             // TODO: this is a workaround for a lack of proxy capability in the resolvers - replace when it can all be
128             //       handled there. It doesn't cache anything locally!
129 
130             Map<String, List<ProxyConnector>> proxyConnectorsMap = proxyConnectorAdmin.getProxyConnectorAsMap();
131             List<ProxyConnector> proxyConnectors = proxyConnectorsMap.get( repository.getId() );
132             if ( proxyConnectors != null )
133             {
134                 for ( ProxyConnector proxyConnector : proxyConnectors )
135                 {
136                     remoteRepositories.add(
137                         repositoryRegistry.getRemoteRepository( proxyConnector.getTargetRepoId() ) );
138 
139                     NetworkProxy networkProxyConfig = networkProxyAdmin.getNetworkProxy( proxyConnector.getProxyId() );
140 
141                     if ( networkProxyConfig != null )
142                     {
143                         // key/value: remote repo ID/proxy info
144                         networkProxies.put( proxyConnector.getTargetRepoId(), networkProxyConfig );
145                     }
146                 }
147             }
148         }
149         catch ( RepositoryAdminException e )
150         {
151             throw new DependencyTreeBuilderException( e.getMessage(), e );
152         }
153 
154         // FIXME take care of relative path
155         ResolveRequest resolveRequest = new ResolveRequest();
156         resolveRequest.dependencyVisitor = dependencyVisitor;
157         resolveRequest.localRepoDir = repository.getContent().getRepoRoot();
158         resolveRequest.groupId = groupId;
159         resolveRequest.artifactId = artifactId;
160         resolveRequest.version = version;
161         resolveRequest.remoteRepositories = remoteRepositories;
162         resolveRequest.networkProxies = networkProxies;
163         resolve( resolveRequest );
164     }
165 
166 
167     @Override
168     public List<TreeEntry> buildDependencyTree( List<String> repositoryIds, String groupId, String artifactId,
169                                                 String version )
170         throws DependencyTreeBuilderException
171     {
172 
173         List<TreeEntry> treeEntries = new ArrayList<>();
174         TreeDependencyNodeVisitorVisitor.html#TreeDependencyNodeVisitor">TreeDependencyNodeVisitor treeDependencyNodeVisitor = new TreeDependencyNodeVisitor( treeEntries );
175 
176         buildDependencyTree( repositoryIds, groupId, artifactId, version, treeDependencyNodeVisitor );
177 
178         log.debug( "treeEntries: {}", treeEntries );
179         return treeEntries;
180     }
181 
182     private static class ResolveRequest
183     {
184         String localRepoDir, groupId, artifactId, version;
185 
186         DependencyVisitor dependencyVisitor;
187 
188         List<org.apache.archiva.repository.RemoteRepository> remoteRepositories;
189 
190         Map<String, NetworkProxy> networkProxies;
191 
192     }
193 
194 
195     private void resolve( ResolveRequest resolveRequest )
196     {
197 
198         RepositorySystem system = mavenSystemManager.getRepositorySystem();
199         RepositorySystemSession session = MavenSystemManager.newRepositorySystemSession( resolveRequest.localRepoDir );
200 
201         org.eclipse.aether.artifact.Artifact artifact = new DefaultArtifact(
202             resolveRequest.groupId + ":" + resolveRequest.artifactId + ":" + resolveRequest.version );
203 
204         CollectRequest collectRequest = new CollectRequest();
205         collectRequest.setRoot( new Dependency( artifact, "" ) );
206 
207         // add remote repositories
208         for ( RemoteRepository remoteRepository : resolveRequest.remoteRepositories )
209         {
210             org.eclipse.aether.repository.RemoteRepository repo = new org.eclipse.aether.repository.RemoteRepository.Builder( remoteRepository.getId( ), "default", remoteRepository.getLocation( ).toString() ).build( );
211             collectRequest.addRepository(repo);
212         }
213         collectRequest.setRequestContext( "project" );
214 
215         //collectRequest.addRepository( repo );
216 
217         try
218         {
219             CollectResult collectResult = system.collectDependencies( session, collectRequest );
220             collectResult.getRoot().accept( resolveRequest.dependencyVisitor );
221             log.debug("Collected dependency results for resolve");
222         }
223         catch ( DependencyCollectionException e )
224         {
225             log.error( "Error while collecting dependencies (resolve): {}", e.getMessage(), e );
226         }
227 
228 
229 
230     }
231 
232     private ManagedRepository findArtifactInRepositories( List<String> repositoryIds, Artifact projectArtifact ) {
233         for ( String repoId : repositoryIds )
234         {
235             ManagedRepository managedRepo = repositoryRegistry.getManagedRepository(repoId);
236             StorageAsset repoDir = managedRepo.getAsset("");
237 
238             StorageAsset file = pathTranslator.toFile( repoDir, projectArtifact.getGroupId(), projectArtifact.getArtifactId(),
239                                                projectArtifact.getBaseVersion(),
240                                                projectArtifact.getArtifactId() + "-" + projectArtifact.getVersion()
241                                                    + ".pom" );
242 
243             if ( file.exists() )
244             {
245                 return managedRepo;
246             }
247             // try with snapshot version
248             if ( StringUtils.endsWith( projectArtifact.getBaseVersion(), VersionUtil.SNAPSHOT ) )
249             {
250                 StorageAsset metadataFile = file.getParent().resolve( MetadataTools.MAVEN_METADATA );
251                 if ( metadataFile.exists() )
252                 {
253                     try
254                     {
255                         ArchivaRepositoryMetadata archivaRepositoryMetadata = MavenMetadataReader.read( metadataFile);
256                         int buildNumber = archivaRepositoryMetadata.getSnapshotVersion().getBuildNumber();
257                         String timeStamp = archivaRepositoryMetadata.getSnapshotVersion().getTimestamp();
258                         // rebuild file name with timestamped version and build number
259                         String timeStampFileName =
260                             new StringBuilder( projectArtifact.getArtifactId() ).append( '-' ).append(
261                                 StringUtils.remove( projectArtifact.getBaseVersion(),
262                                                     "-" + VersionUtil.SNAPSHOT ) ).append( '-' ).append(
263                                 timeStamp ).append( '-' ).append( Integer.toString( buildNumber ) ).append(
264                                 ".pom" ).toString();
265                         StorageAsset timeStampFile = file.getParent().resolve( timeStampFileName );
266                         log.debug( "try to find timestamped snapshot version file: {}", timeStampFile);
267                         if ( timeStampFile.exists() )
268                         {
269                             return managedRepo;
270                         }
271                     }
272                     catch (XMLException | IOException e )
273                     {
274                         log.warn( "skip fail to find timestamped snapshot pom: {}", e.getMessage() );
275                     }
276                 }
277             }
278         }
279         return null;
280     }
281 
282 }