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