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