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