View Javadoc

1   package org.apache.maven.report.projectinfo.dependencies;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.net.UnknownHostException;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.artifact.ArtifactUtils;
28  import org.apache.maven.artifact.factory.ArtifactFactory;
29  import org.apache.maven.artifact.manager.WagonConfigurationException;
30  import org.apache.maven.artifact.manager.WagonManager;
31  import org.apache.maven.artifact.metadata.ArtifactMetadata;
32  import org.apache.maven.artifact.repository.ArtifactRepository;
33  import org.apache.maven.artifact.repository.metadata.Metadata;
34  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
35  import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
36  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
37  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
38  import org.apache.maven.artifact.resolver.ArtifactResolver;
39  import org.apache.maven.plugin.logging.Log;
40  import org.apache.maven.project.MavenProject;
41  import org.apache.maven.project.MavenProjectBuilder;
42  import org.apache.maven.project.ProjectBuildingException;
43  import org.apache.maven.settings.Proxy;
44  import org.apache.maven.settings.Settings;
45  import org.apache.maven.wagon.ConnectionException;
46  import org.apache.maven.wagon.TransferFailedException;
47  import org.apache.maven.wagon.UnsupportedProtocolException;
48  import org.apache.maven.wagon.Wagon;
49  import org.apache.maven.wagon.authentication.AuthenticationException;
50  import org.apache.maven.wagon.authentication.AuthenticationInfo;
51  import org.apache.maven.wagon.authorization.AuthorizationException;
52  import org.apache.maven.wagon.observers.Debug;
53  import org.apache.maven.wagon.proxy.ProxyInfo;
54  import org.apache.maven.wagon.repository.Repository;
55  import org.codehaus.plexus.util.StringUtils;
56  
57  /**
58   * Utilities methods to play with repository
59   *
60   * @version $Id: RepositoryUtils.java 1042031 2010-12-03 22:22:51Z vsiveton $
61   * @since 2.1
62   */
63  public class RepositoryUtils
64  {
65      private static final List<String> UNKNOWN_HOSTS = new ArrayList<String>();
66  
67      private final Log log;
68  
69      private final WagonManager wagonManager;
70  
71      private final Settings settings;
72  
73      private final MavenProjectBuilder mavenProjectBuilder;
74  
75      private final ArtifactFactory factory;
76  
77      private final List<ArtifactRepository> remoteRepositories;
78  
79      private final List<ArtifactRepository> pluginRepositories;
80  
81      private final ArtifactResolver resolver;
82  
83      private final ArtifactRepository localRepository;
84  
85      /**
86       * @param log
87       * @param wagonManager
88       * @param settings
89       * @param mavenProjectBuilder
90       * @param factory
91       * @param resolver
92       * @param remoteRepositories
93       * @param pluginRepositories
94       * @param localRepository
95       * @param repositoryMetadataManager
96       */
97      public RepositoryUtils( Log log, WagonManager wagonManager, Settings settings,
98                              MavenProjectBuilder mavenProjectBuilder, ArtifactFactory factory,
99                              ArtifactResolver resolver, List<ArtifactRepository> remoteRepositories,
100                             List<ArtifactRepository> pluginRepositories, ArtifactRepository localRepository,
101                             RepositoryMetadataManager repositoryMetadataManager )
102     {
103         this.log = log;
104         this.wagonManager = wagonManager;
105         this.settings = settings;
106         this.mavenProjectBuilder = mavenProjectBuilder;
107         this.factory = factory;
108         this.resolver = resolver;
109         this.remoteRepositories = remoteRepositories;
110         this.pluginRepositories = pluginRepositories;
111         this.localRepository = localRepository;
112     }
113 
114     /**
115      * @return localrepo
116      */
117     public ArtifactRepository getLocalRepository()
118     {
119         return localRepository;
120     }
121 
122     /**
123      * @return remote artifact repo
124      */
125     public List<ArtifactRepository> getRemoteArtifactRepositories()
126     {
127         return remoteRepositories;
128     }
129 
130     /**
131      * @return plugin artifact repo
132      */
133     public List<ArtifactRepository> getPluginArtifactRepositories()
134     {
135         return pluginRepositories;
136     }
137 
138     /**
139      * @param artifact not null
140      * @throws ArtifactResolutionException if any
141      * @throws ArtifactNotFoundException if any
142      * @see ArtifactResolver#resolve(Artifact, List, ArtifactRepository)
143      */
144     public void resolve( Artifact artifact )
145         throws ArtifactResolutionException, ArtifactNotFoundException
146     {
147         List<ArtifactRepository> repos =
148             new ArrayList<ArtifactRepository>( pluginRepositories.size() + remoteRepositories.size() );
149         repos.addAll( pluginRepositories );
150         repos.addAll( remoteRepositories );
151 
152         resolver.resolve( artifact, repos, localRepository );
153     }
154 
155     /**
156      * @param repo not null
157      * @param artifact not null
158      * @return <code>true</code> if the artifact exists in the given repo, <code>false</code> otherwise or if
159      * the repo is blacklisted.
160      */
161     public boolean dependencyExistsInRepo( ArtifactRepository repo, Artifact artifact )
162     {
163         if ( repo.isBlacklisted() )
164         {
165             if ( log.isDebugEnabled() )
166             {
167                 log.debug( "The repo '" + repo.getId() + "' is black listed - Ignored it" );
168             }
169             return false;
170         }
171 
172         if ( UNKNOWN_HOSTS.contains( repo.getUrl() ) )
173         {
174             if ( log.isDebugEnabled() )
175             {
176                 log.debug( "The repo url '" + repo.getUrl() + "' is unknowned - Ignored it" );
177             }
178             return false;
179         }
180 
181         repo = wagonManager.getMirrorRepository( repo );
182 
183         String id = repo.getId();
184         Repository repository = new Repository( id, repo.getUrl() );
185 
186         Wagon wagon;
187         try
188         {
189             wagon = wagonManager.getWagon( repository );
190         }
191         catch ( UnsupportedProtocolException e )
192         {
193             log.error( "Unsupported protocol: '" + repo.getProtocol() + "'", e );
194             return false;
195         }
196         catch ( WagonConfigurationException e )
197         {
198             log.error( "Unsupported protocol: '" + repo.getProtocol() + "'", e );
199             return false;
200         }
201 
202         wagon.setTimeout( 1000 );
203 
204         if ( log.isDebugEnabled() )
205         {
206             Debug debug = new Debug();
207 
208             wagon.addSessionListener( debug );
209             wagon.addTransferListener( debug );
210         }
211 
212         try
213         {
214             // FIXME when upgrading to maven 3.x : this must be changed.
215             AuthenticationInfo auth = wagonManager.getAuthenticationInfo( repo.getId() );
216 
217             ProxyInfo proxyInfo = getProxyInfo();
218             if ( proxyInfo != null )
219             {
220                 wagon.connect( repository, auth, proxyInfo );
221             }
222             else
223             {
224                 wagon.connect( repository, auth );
225             }
226 
227             return wagon.resourceExists( StringUtils.replace( getDependencyUrlFromRepository( artifact, repo ),
228                                                               repo.getUrl(), "" ) );
229         }
230         catch ( ConnectionException e )
231         {
232             if ( log.isDebugEnabled() )
233             {
234                 log.error( "Unable to connect to: " + repo.getUrl(), e );
235             }
236             else
237             {
238                 log.error( "Unable to connect to: " + repo.getUrl() );
239             }
240             return false;
241         }
242         catch ( AuthenticationException e )
243         {
244             if ( log.isDebugEnabled() )
245             {
246                 log.error( "Unable to connect to: " + repo.getUrl(), e );
247             }
248             else
249             {
250                 log.error( "Unable to connect to: " + repo.getUrl() );
251             }
252             return false;
253         }
254         catch ( TransferFailedException e )
255         {
256             if ( e.getCause() instanceof UnknownHostException )
257             {
258                 log.error( "Unknown host " + e.getCause().getMessage() + " - ignored it" );
259                 UNKNOWN_HOSTS.add( repo.getUrl() );
260             }
261             else
262             {
263                 if ( log.isDebugEnabled() )
264                 {
265                     log.error( "Unable to determine if resource " + artifact + " exists in " + repo.getUrl(), e );
266                 }
267                 else
268                 {
269                     log.error( "Unable to determine if resource " + artifact + " exists in " + repo.getUrl() );
270                 }
271             }
272             return false;
273         }
274         catch ( AuthorizationException e )
275         {
276             if ( log.isDebugEnabled() )
277             {
278                 log.error( "Unable to connect to: " + repo.getUrl(), e );
279             }
280             else
281             {
282                 log.error( "Unable to connect to: " + repo.getUrl() );
283             }
284             return false;
285         }
286         catch ( AbstractMethodError e )
287         {
288             log.error( "Wagon " + wagon.getClass().getName() + " does not support the resourceExists method" );
289             return false;
290         }
291         finally
292         {
293             try
294             {
295                 wagon.disconnect();
296             }
297             catch ( ConnectionException e )
298             {
299                 if ( log.isDebugEnabled() )
300                 {
301                     log.error( "Error disconnecting wagon - ignored", e );
302                 }
303                 else
304                 {
305                     log.error( "Error disconnecting wagon - ignored" );
306                 }
307             }
308         }
309     }
310 
311     /**
312      * Get the <code>Maven project</code> from the repository depending the <code>Artifact</code> given.
313      *
314      * @param artifact an artifact
315      * @return the Maven project for the given artifact
316      * @throws ProjectBuildingException if any
317      */
318     public MavenProject getMavenProjectFromRepository( Artifact artifact )
319         throws ProjectBuildingException
320     {
321         Artifact projectArtifact = artifact;
322 
323         boolean allowStubModel = false;
324         if ( !"pom".equals( artifact.getType() ) )
325         {
326             projectArtifact = factory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(),
327                                                              artifact.getVersion(), artifact.getScope() );
328             allowStubModel = true;
329         }
330 
331         // TODO: we should use the MavenMetadataSource instead
332         return mavenProjectBuilder.buildFromRepository( projectArtifact, remoteRepositories, localRepository,
333                                                         allowStubModel );
334     }
335 
336     /**
337      * @param artifact not null
338      * @param repo not null
339      * @return the artifact url in the given repo for the given artifact. If it is a snapshot artifact, the version
340      * will be the timestamp and the build number from the metadata. Could return null if the repo is blacklisted.
341      */
342     public String getDependencyUrlFromRepository( Artifact artifact, ArtifactRepository repo )
343     {
344         if ( repo.isBlacklisted() )
345         {
346             return null;
347         }
348 
349         Artifact copyArtifact = ArtifactUtils.copyArtifact( artifact );
350         // Try to get the last artifact repo name depending the snapshot version
351         if ( ( artifact.isSnapshot() && repo.getSnapshots().isEnabled() ) )
352         {
353             if ( artifact.getBaseVersion().equals( artifact.getVersion() ) )
354             {
355                 // Try to resolve it if not already done
356                 if ( artifact.getMetadataList() == null || artifact.getMetadataList().isEmpty() )
357                 {
358                     try
359                     {
360                         resolve( artifact );
361                     }
362                     catch ( ArtifactResolutionException e )
363                     {
364                         log.error( "Artifact: " + artifact.getId() + " could not be resolved." );
365                     }
366                     catch ( ArtifactNotFoundException e )
367                     {
368                         log.error( "Artifact: " + artifact.getId() + " was not found." );
369                     }
370                 }
371 
372                 for ( ArtifactMetadata m : artifact.getMetadataList() )
373                 {
374                     if ( m instanceof SnapshotArtifactRepositoryMetadata )
375                     {
376                         SnapshotArtifactRepositoryMetadata snapshotMetadata = (SnapshotArtifactRepositoryMetadata) m;
377 
378                         Metadata metadata = snapshotMetadata.getMetadata();
379                         if ( metadata.getVersioning() == null || metadata.getVersioning().getSnapshot() == null
380                             || metadata.getVersioning().getSnapshot().isLocalCopy()
381                             || metadata.getVersioning().getSnapshot().getTimestamp() == null )
382                         {
383                             continue;
384                         }
385 
386                         // create the version according SnapshotTransformation
387                         String version =
388                             StringUtils.replace( copyArtifact.getVersion(), Artifact.SNAPSHOT_VERSION,
389                                                  metadata.getVersioning().getSnapshot().getTimestamp() )
390                                 + "-" + metadata.getVersioning().getSnapshot().getBuildNumber();
391                         copyArtifact.setVersion( version );
392                     }
393                 }
394             }
395         }
396 
397         return repo.getUrl() + "/" + repo.pathOf( copyArtifact );
398     }
399 
400     // ----------------------------------------------------------------------
401     // Private methods
402     // ----------------------------------------------------------------------
403 
404     /**
405      * Convenience method to map a <code>Proxy</code> object from the user system settings to a <code>ProxyInfo</code>
406      * object.
407      *
408      * @return a proxyInfo object instanced or null if no active proxy is define in the settings.xml
409      */
410     private ProxyInfo getProxyInfo()
411     {
412         ProxyInfo proxyInfo = null;
413         if ( settings != null && settings.getActiveProxy() != null )
414         {
415             Proxy settingsProxy = settings.getActiveProxy();
416 
417             proxyInfo = new ProxyInfo();
418             proxyInfo.setHost( settingsProxy.getHost() );
419             proxyInfo.setType( settingsProxy.getProtocol() );
420             proxyInfo.setPort( settingsProxy.getPort() );
421             proxyInfo.setNonProxyHosts( settingsProxy.getNonProxyHosts() );
422             proxyInfo.setUserName( settingsProxy.getUsername() );
423             proxyInfo.setPassword( settingsProxy.getPassword() );
424         }
425 
426         return proxyInfo;
427     }
428 }