View Javadoc
1   package org.apache.maven;
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.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Objects;
29  import java.util.Optional;
30  import java.util.stream.Collectors;
31  
32  import org.apache.maven.artifact.handler.ArtifactHandler;
33  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
34  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
35  import org.apache.maven.artifact.repository.ArtifactRepository;
36  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
37  import org.eclipse.aether.RepositorySystemSession;
38  import org.eclipse.aether.artifact.Artifact;
39  import org.eclipse.aether.artifact.ArtifactProperties;
40  import org.eclipse.aether.artifact.ArtifactType;
41  import org.eclipse.aether.artifact.ArtifactTypeRegistry;
42  import org.eclipse.aether.artifact.DefaultArtifact;
43  import org.eclipse.aether.artifact.DefaultArtifactType;
44  import org.eclipse.aether.graph.Dependency;
45  import org.eclipse.aether.graph.DependencyFilter;
46  import org.eclipse.aether.graph.DependencyNode;
47  import org.eclipse.aether.graph.Exclusion;
48  import org.eclipse.aether.repository.Authentication;
49  import org.eclipse.aether.repository.Proxy;
50  import org.eclipse.aether.repository.RemoteRepository;
51  import org.eclipse.aether.repository.RepositoryPolicy;
52  import org.eclipse.aether.repository.WorkspaceReader;
53  import org.eclipse.aether.repository.WorkspaceRepository;
54  import org.eclipse.aether.util.repository.AuthenticationBuilder;
55  
56  /**
57   * <strong>Warning:</strong> This is an internal utility class that is only public for technical reasons, it is not part
58   * of the public API. In particular, this class can be changed or deleted without prior notice.
59   *
60   * @author Benjamin Bentmann
61   */
62  public class RepositoryUtils
63  {
64  
65      private static String nullify( String string )
66      {
67          return ( string == null || string.length() <= 0 ) ? null : string;
68      }
69  
70      private static org.apache.maven.artifact.Artifact toArtifact( Dependency dependency )
71      {
72          if ( dependency == null )
73          {
74              return null;
75          }
76  
77          org.apache.maven.artifact.Artifact result = toArtifact( dependency.getArtifact() );
78          result.setScope( dependency.getScope() );
79          result.setOptional( dependency.isOptional() );
80  
81          return result;
82      }
83  
84      public static org.apache.maven.artifact.Artifact toArtifact( Artifact artifact )
85      {
86          if ( artifact == null )
87          {
88              return null;
89          }
90  
91          ArtifactHandler handler = newHandler( artifact );
92  
93          /*
94           * NOTE: From Artifact.hasClassifier(), an empty string and a null both denote "no classifier". However, some
95           * plugins only check for null, so be sure to nullify an empty classifier.
96           */
97          org.apache.maven.artifact.Artifact result =
98              new org.apache.maven.artifact.DefaultArtifact( artifact.getGroupId(), artifact.getArtifactId(),
99                                                             artifact.getVersion(), null,
100                                                            artifact.getProperty( ArtifactProperties.TYPE,
101                                                                                  artifact.getExtension() ),
102                                                            nullify( artifact.getClassifier() ), handler );
103 
104         result.setFile( artifact.getFile() );
105         result.setResolved( artifact.getFile() != null );
106 
107         List<String> trail = new ArrayList<>( 1 );
108         trail.add( result.getId() );
109         result.setDependencyTrail( trail );
110 
111         return result;
112     }
113 
114     public static void toArtifacts( Collection<org.apache.maven.artifact.Artifact> artifacts,
115                                     Collection<? extends DependencyNode> nodes, List<String> trail,
116                                     DependencyFilter filter )
117     {
118         for ( DependencyNode node : nodes )
119         {
120             org.apache.maven.artifact.Artifact artifact = toArtifact( node.getDependency() );
121 
122             List<String> nodeTrail = new ArrayList<>( trail.size() + 1 );
123             nodeTrail.addAll( trail );
124             nodeTrail.add( artifact.getId() );
125 
126             if ( filter == null || filter.accept( node, Collections.emptyList() ) )
127             {
128                 artifact.setDependencyTrail( nodeTrail );
129                 artifacts.add( artifact );
130             }
131 
132             toArtifacts( artifacts, node.getChildren(), nodeTrail, filter );
133         }
134     }
135 
136     public static Artifact toArtifact( org.apache.maven.artifact.Artifact artifact )
137     {
138         if ( artifact == null )
139         {
140             return null;
141         }
142 
143         String version = artifact.getVersion();
144         if ( version == null && artifact.getVersionRange() != null )
145         {
146             version = artifact.getVersionRange().toString();
147         }
148 
149         Map<String, String> props = null;
150         if ( org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
151         {
152             String localPath = ( artifact.getFile() != null ) ? artifact.getFile().getPath() : "";
153             props = Collections.singletonMap( ArtifactProperties.LOCAL_PATH, localPath );
154         }
155 
156         Artifact result =
157             new DefaultArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getClassifier(),
158                                  artifact.getArtifactHandler().getExtension(), version, props,
159                                  newArtifactType( artifact.getType(), artifact.getArtifactHandler() ) );
160         result = result.setFile( artifact.getFile() );
161 
162         return result;
163     }
164 
165     public static Dependency toDependency( org.apache.maven.artifact.Artifact artifact,
166                                            Collection<org.apache.maven.model.Exclusion> exclusions )
167     {
168         if ( artifact == null )
169         {
170             return null;
171         }
172 
173         Artifact result = toArtifact( artifact );
174 
175         List<Exclusion> excl = Optional.ofNullable( exclusions )
176                 .orElse( Collections.emptyList() )
177                 .stream()
178                 .map( RepositoryUtils::toExclusion )
179                 .collect( Collectors.toList() );
180         return new Dependency( result, artifact.getScope(), artifact.isOptional(), excl );
181     }
182 
183     public static List<RemoteRepository> toRepos( List<ArtifactRepository> repos )
184     {
185         return Optional.ofNullable( repos )
186                 .orElse( Collections.emptyList() )
187                 .stream()
188                 .map( RepositoryUtils::toRepo )
189                 .collect( Collectors.toList() );
190     }
191 
192     public static RemoteRepository toRepo( ArtifactRepository repo )
193     {
194         RemoteRepository result = null;
195         if ( repo != null )
196         {
197             RemoteRepository.Builder builder =
198                 new RemoteRepository.Builder( repo.getId(), getLayout( repo ), repo.getUrl() );
199             builder.setSnapshotPolicy( toPolicy( repo.getSnapshots() ) );
200             builder.setReleasePolicy( toPolicy( repo.getReleases() ) );
201             builder.setAuthentication( toAuthentication( repo.getAuthentication() ) );
202             builder.setProxy( toProxy( repo.getProxy() ) );
203             builder.setMirroredRepositories( toRepos( repo.getMirroredRepositories() ) );
204             builder.setBlocked( repo.isBlocked() );
205             result = builder.build();
206         }
207         return result;
208     }
209 
210     public static String getLayout( ArtifactRepository repo )
211     {
212         try
213         {
214             return repo.getLayout().getId();
215         }
216         catch ( LinkageError e )
217         {
218             /*
219              * NOTE: getId() was added in 3.x and is as such not implemented by plugins compiled against 2.x APIs.
220              */
221             String className = repo.getLayout().getClass().getSimpleName();
222             if ( className.endsWith( "RepositoryLayout" ) )
223             {
224                 String layout = className.substring( 0, className.length() - "RepositoryLayout".length() );
225                 if ( layout.length() > 0 )
226                 {
227                     layout = Character.toLowerCase( layout.charAt( 0 ) ) + layout.substring( 1 );
228                     return layout;
229                 }
230             }
231             return "";
232         }
233     }
234 
235     private static RepositoryPolicy toPolicy( ArtifactRepositoryPolicy policy )
236     {
237         RepositoryPolicy result = null;
238         if ( policy != null )
239         {
240             result = new RepositoryPolicy( policy.isEnabled(), policy.getUpdatePolicy(), policy.getChecksumPolicy() );
241         }
242         return result;
243     }
244 
245     private static Authentication toAuthentication( org.apache.maven.artifact.repository.Authentication auth )
246     {
247         Authentication result = null;
248         if ( auth != null )
249         {
250             AuthenticationBuilder authBuilder = new AuthenticationBuilder();
251             authBuilder.addUsername( auth.getUsername() ).addPassword( auth.getPassword() );
252             authBuilder.addPrivateKey( auth.getPrivateKey(), auth.getPassphrase() );
253             result = authBuilder.build();
254         }
255         return result;
256     }
257 
258     private static Proxy toProxy( org.apache.maven.repository.Proxy proxy )
259     {
260         Proxy result = null;
261         if ( proxy != null )
262         {
263             AuthenticationBuilder authBuilder = new AuthenticationBuilder();
264             authBuilder.addUsername( proxy.getUserName() ).addPassword( proxy.getPassword() );
265             result = new Proxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), authBuilder.build() );
266         }
267         return result;
268     }
269 
270     public static ArtifactHandler newHandler( Artifact artifact )
271     {
272         String type = artifact.getProperty( ArtifactProperties.TYPE, artifact.getExtension() );
273         return new DefaultArtifactHandler(
274             type,
275             artifact.getExtension(),
276             null,
277             null,
278             null,
279             Boolean.parseBoolean( artifact.getProperty( ArtifactProperties.INCLUDES_DEPENDENCIES, "" ) ),
280             artifact.getProperty( ArtifactProperties.LANGUAGE, null ),
281             Boolean.parseBoolean( artifact.getProperty( ArtifactProperties.CONSTITUTES_BUILD_PATH, "" ) )
282         );
283     }
284 
285     public static ArtifactType newArtifactType( String id, ArtifactHandler handler )
286     {
287         return new DefaultArtifactType( id, handler.getExtension(), handler.getClassifier(), handler.getLanguage(),
288                                         handler.isAddedToClasspath(), handler.isIncludesDependencies() );
289     }
290 
291     public static Dependency toDependency( org.apache.maven.model.Dependency dependency,
292                                            ArtifactTypeRegistry stereotypes )
293     {
294         ArtifactType stereotype = stereotypes.get( dependency.getType() );
295         if ( stereotype == null )
296         {
297             stereotype = new DefaultArtifactType( dependency.getType() );
298         }
299 
300         boolean system = dependency.getSystemPath() != null && dependency.getSystemPath().length() > 0;
301 
302         Map<String, String> props = null;
303         if ( system )
304         {
305             props = Collections.singletonMap( ArtifactProperties.LOCAL_PATH, dependency.getSystemPath() );
306         }
307 
308         Artifact artifact =
309             new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), null,
310                                  dependency.getVersion(), props, stereotype );
311 
312         List<Exclusion> exclusions =
313                 dependency.getExclusions().stream().map( RepositoryUtils::toExclusion ).collect( Collectors.toList() );
314 
315         return new Dependency( artifact,
316                                             dependency.getScope(),
317                                             dependency.getOptional() != null
318                                                 ? dependency.isOptional()
319                                                 : null,
320                                             exclusions );
321     }
322 
323     private static Exclusion toExclusion( org.apache.maven.model.Exclusion exclusion )
324     {
325         return new Exclusion( exclusion.getGroupId(), exclusion.getArtifactId(), "*", "*" );
326     }
327 
328     public static ArtifactTypeRegistry newArtifactTypeRegistry( ArtifactHandlerManager handlerManager )
329     {
330         return new MavenArtifactTypeRegistry( handlerManager );
331     }
332 
333     static class MavenArtifactTypeRegistry
334         implements ArtifactTypeRegistry
335     {
336 
337         private final ArtifactHandlerManager handlerManager;
338 
339         MavenArtifactTypeRegistry( ArtifactHandlerManager handlerManager )
340         {
341             this.handlerManager = handlerManager;
342         }
343 
344         public ArtifactType get( String stereotypeId )
345         {
346             ArtifactHandler handler = handlerManager.getArtifactHandler( stereotypeId );
347             return newArtifactType( stereotypeId, handler );
348         }
349 
350     }
351 
352     public static Collection<Artifact> toArtifacts( Collection<org.apache.maven.artifact.Artifact> artifactsToConvert )
353     {
354         return artifactsToConvert.stream().map( RepositoryUtils::toArtifact ).collect( Collectors.toList() );
355     }
356 
357     public static WorkspaceRepository getWorkspace( RepositorySystemSession session )
358     {
359         WorkspaceReader reader = session.getWorkspaceReader();
360         return ( reader != null ) ? reader.getRepository() : null;
361     }
362 
363     public static boolean repositoriesEquals( List<RemoteRepository> r1, List<RemoteRepository> r2 )
364     {
365         if ( r1.size() != r2.size() )
366         {
367             return false;
368         }
369 
370         for ( Iterator<RemoteRepository> it1 = r1.iterator(), it2 = r2.iterator(); it1.hasNext(); )
371         {
372             if ( !repositoryEquals( it1.next(), it2.next() ) )
373             {
374                 return false;
375             }
376         }
377 
378         return true;
379     }
380 
381     public static int repositoriesHashCode( List<RemoteRepository> repositories )
382     {
383         int result = 17;
384         for ( RemoteRepository repository : repositories )
385         {
386             result = 31 * result + repositoryHashCode( repository );
387         }
388         return result;
389     }
390 
391     private static int repositoryHashCode( RemoteRepository repository )
392     {
393         int result = 17;
394         Object obj = repository.getUrl();
395         result = 31 * result + ( obj != null ? obj.hashCode() : 0 );
396         return result;
397     }
398 
399     private static boolean policyEquals( RepositoryPolicy p1, RepositoryPolicy p2 )
400     {
401         if ( p1 == p2 )
402         {
403             return true;
404         }
405         // update policy doesn't affect contents
406         return p1.isEnabled() == p2.isEnabled() && Objects.equals( p1.getChecksumPolicy(), p2.getChecksumPolicy() );
407     }
408 
409     private static boolean repositoryEquals( RemoteRepository r1, RemoteRepository r2 )
410     {
411         if ( r1 == r2 )
412         {
413             return true;
414         }
415 
416         return Objects.equals( r1.getId(), r2.getId() ) && Objects.equals( r1.getUrl(), r2.getUrl() )
417             && policyEquals( r1.getPolicy( false ), r2.getPolicy( false ) )
418             && policyEquals( r1.getPolicy( true ), r2.getPolicy( true ) );
419     }
420 }