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