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