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