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.internal.impl;
20  
21  import java.io.File;
22  import java.nio.file.Path;
23  import java.util.Arrays;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Objects;
29  import java.util.Optional;
30  import java.util.WeakHashMap;
31  import java.util.concurrent.CopyOnWriteArrayList;
32  
33  import org.apache.maven.api.*;
34  import org.apache.maven.api.annotations.Nonnull;
35  import org.apache.maven.api.model.Repository;
36  import org.apache.maven.api.services.*;
37  import org.apache.maven.artifact.repository.ArtifactRepository;
38  import org.apache.maven.project.MavenProject;
39  
40  import static org.apache.maven.internal.impl.Utils.map;
41  import static org.apache.maven.internal.impl.Utils.nonNull;
42  
43  public abstract class AbstractSession implements InternalSession {
44  
45      private final List<Listener> listeners = new CopyOnWriteArrayList<>();
46      private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes =
47              Collections.synchronizedMap(new WeakHashMap<>());
48      private final Map<org.eclipse.aether.artifact.Artifact, Artifact> allArtifacts =
49              Collections.synchronizedMap(new WeakHashMap<>());
50      private final Map<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories =
51              Collections.synchronizedMap(new WeakHashMap<>());
52      private final Map<String, Project> allProjects = Collections.synchronizedMap(new WeakHashMap<>());
53      private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies =
54              Collections.synchronizedMap(new WeakHashMap<>());
55  
56      public RemoteRepository getRemoteRepository(org.eclipse.aether.repository.RemoteRepository repository) {
57          return allRepositories.computeIfAbsent(repository, DefaultRemoteRepository::new);
58      }
59  
60      public Node getNode(org.eclipse.aether.graph.DependencyNode node) {
61          return getNode(node, false);
62      }
63  
64      public Node getNode(org.eclipse.aether.graph.DependencyNode node, boolean verbose) {
65          return allNodes.computeIfAbsent(node, n -> new DefaultNode(this, n, verbose));
66      }
67  
68      @Nonnull
69      public Artifact getArtifact(@Nonnull org.eclipse.aether.artifact.Artifact artifact) {
70          return allArtifacts.computeIfAbsent(artifact, a -> new DefaultArtifact(this, a));
71      }
72  
73      @Nonnull
74      public Dependency getDependency(@Nonnull org.eclipse.aether.graph.Dependency dependency) {
75          return allDependencies.computeIfAbsent(dependency, d -> new DefaultDependency(this, d));
76      }
77  
78      public List<Project> getProjects(List<MavenProject> projects) {
79          return projects == null ? null : map(projects, this::getProject);
80      }
81  
82      public Project getProject(MavenProject project) {
83          return allProjects.computeIfAbsent(project.getId(), id -> new DefaultProject(this, project));
84      }
85  
86      public List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories) {
87          return repositories == null ? null : map(repositories, this::toRepository);
88      }
89  
90      public org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository) {
91          if (repository instanceof DefaultRemoteRepository) {
92              return ((DefaultRemoteRepository) repository).getRepository();
93          } else {
94              // TODO
95              throw new UnsupportedOperationException("Not implemented yet");
96          }
97      }
98  
99      public org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository repository) {
100         if (repository instanceof DefaultLocalRepository) {
101             return ((DefaultLocalRepository) repository).getRepository();
102         } else {
103             // TODO
104             throw new UnsupportedOperationException("Not implemented yet");
105         }
106     }
107 
108     public List<ArtifactRepository> toArtifactRepositories(List<RemoteRepository> repositories) {
109         return repositories == null ? null : map(repositories, this::toArtifactRepository);
110     }
111 
112     public abstract ArtifactRepository toArtifactRepository(RemoteRepository repository);
113 
114     public List<org.eclipse.aether.graph.Dependency> toDependencies(Collection<DependencyCoordinate> dependencies) {
115         return dependencies == null ? null : map(dependencies, this::toDependency);
116     }
117 
118     public abstract org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency);
119 
120     public List<org.eclipse.aether.artifact.Artifact> toArtifacts(Collection<Artifact> artifacts) {
121         return artifacts == null ? null : map(artifacts, this::toArtifact);
122     }
123 
124     public org.eclipse.aether.artifact.Artifact toArtifact(Artifact artifact) {
125         File file = getService(ArtifactManager.class)
126                 .getPath(artifact)
127                 .map(Path::toFile)
128                 .orElse(null);
129         if (artifact instanceof DefaultArtifact) {
130             org.eclipse.aether.artifact.Artifact a = ((DefaultArtifact) artifact).getArtifact();
131             if (Objects.equals(file, a.getFile())) {
132                 return a;
133             }
134         }
135         return new org.eclipse.aether.artifact.DefaultArtifact(
136                 artifact.getGroupId(),
137                 artifact.getArtifactId(),
138                 artifact.getClassifier(),
139                 artifact.getExtension(),
140                 artifact.getVersion().toString(),
141                 null,
142                 file);
143     }
144 
145     public org.eclipse.aether.artifact.Artifact toArtifact(ArtifactCoordinate coord) {
146         if (coord instanceof DefaultArtifactCoordinate) {
147             return ((DefaultArtifactCoordinate) coord).getCoordinate();
148         }
149         return new org.eclipse.aether.artifact.DefaultArtifact(
150                 coord.getGroupId(),
151                 coord.getArtifactId(),
152                 coord.getClassifier(),
153                 coord.getExtension(),
154                 coord.getVersion().toString(),
155                 null,
156                 (File) null);
157     }
158 
159     @Override
160     public void registerListener(@Nonnull Listener listener) {
161         listeners.add(nonNull(listener));
162     }
163 
164     @Override
165     public void unregisterListener(@Nonnull Listener listener) {
166         listeners.remove(nonNull(listener));
167     }
168 
169     @Nonnull
170     @Override
171     public Collection<Listener> getListeners() {
172         return Collections.unmodifiableCollection(listeners);
173     }
174 
175     //
176     // Shortcut implementations
177     //
178 
179     /**
180      * Shortcut for <code>getService(RepositoryFactory.class).createLocal(...)</code>
181      *
182      * @see RepositoryFactory#createLocal(Path)
183      */
184     @Override
185     public LocalRepository createLocalRepository(Path path) {
186         return getService(RepositoryFactory.class).createLocal(path);
187     }
188 
189     /**
190      * Shortcut for <code>getService(RepositoryFactory.class).createRemote(...)</code>
191      *
192      * @see RepositoryFactory#createRemote(String, String)
193      */
194     @Nonnull
195     @Override
196     public RemoteRepository createRemoteRepository(@Nonnull String id, @Nonnull String url) {
197         return getService(RepositoryFactory.class).createRemote(id, url);
198     }
199 
200     /**
201      * Shortcut for <code>getService(RepositoryFactory.class).createRemote(...)</code>
202      *
203      * @see RepositoryFactory#createRemote(Repository)
204      */
205     @Nonnull
206     @Override
207     public RemoteRepository createRemoteRepository(@Nonnull Repository repository) {
208         return getService(RepositoryFactory.class).createRemote(repository);
209     }
210 
211     /**
212      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
213      *
214      * @see ArtifactFactory#create(Session, String, String, String, String)
215      */
216     @Override
217     public ArtifactCoordinate createArtifactCoordinate(
218             String groupId, String artifactId, String version, String extension) {
219         return getService(ArtifactCoordinateFactory.class).create(this, groupId, artifactId, version, extension);
220     }
221 
222     /**
223      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
224      *
225      * @see ArtifactCoordinateFactory#create(Session, String)
226      */
227     @Override
228     public ArtifactCoordinate createArtifactCoordinate(String coordString) {
229         return getService(ArtifactCoordinateFactory.class).create(this, coordString);
230     }
231 
232     /**
233      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
234      *
235      * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String)
236      */
237     @Override
238     public ArtifactCoordinate createArtifactCoordinate(
239             String groupId, String artifactId, String version, String classifier, String extension, String type) {
240         return getService(ArtifactCoordinateFactory.class)
241                 .create(this, groupId, artifactId, version, classifier, extension, type);
242     }
243 
244     /**
245      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
246      *
247      * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String)
248      */
249     @Override
250     public ArtifactCoordinate createArtifactCoordinate(Artifact artifact) {
251         return getService(ArtifactCoordinateFactory.class)
252                 .create(
253                         this,
254                         artifact.getGroupId(),
255                         artifact.getArtifactId(),
256                         artifact.getVersion().asString(),
257                         artifact.getClassifier(),
258                         artifact.getExtension(),
259                         null);
260     }
261 
262     /**
263      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
264      *
265      * @see ArtifactFactory#create(Session, String, String, String, String)
266      */
267     @Override
268     public Artifact createArtifact(String groupId, String artifactId, String version, String extension) {
269         return getService(ArtifactFactory.class).create(this, groupId, artifactId, version, extension);
270     }
271 
272     /**
273      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
274      *
275      * @see ArtifactFactory#create(Session, String, String, String, String, String, String)
276      */
277     @Override
278     public Artifact createArtifact(
279             String groupId, String artifactId, String version, String classifier, String extension, String type) {
280         return getService(ArtifactFactory.class)
281                 .create(this, groupId, artifactId, version, classifier, extension, type);
282     }
283 
284     /**
285      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
286      *
287      * @throws ArtifactResolverException if the artifact resolution failed
288      * @see ArtifactResolver#resolve(Session, Collection)
289      */
290     @Override
291     public Map.Entry<Artifact, Path> resolveArtifact(ArtifactCoordinate coordinate) {
292         return getService(ArtifactResolver.class)
293                 .resolve(this, Collections.singletonList(coordinate))
294                 .getArtifacts()
295                 .entrySet()
296                 .iterator()
297                 .next();
298     }
299 
300     /**
301      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
302      *
303      * @throws ArtifactResolverException if the artifact resolution failed
304      * @see ArtifactResolver#resolve(Session, Collection)
305      */
306     @Override
307     public Map<Artifact, Path> resolveArtifacts(ArtifactCoordinate... coordinates) {
308         return resolveArtifacts(Arrays.asList(coordinates));
309     }
310 
311     /**
312      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
313      *
314      * @throws ArtifactResolverException if the artifact resolution failed
315      * @see ArtifactResolver#resolve(Session, Collection)
316      */
317     @Override
318     public Map<Artifact, Path> resolveArtifacts(Collection<? extends ArtifactCoordinate> coordinates) {
319         return getService(ArtifactResolver.class).resolve(this, coordinates).getArtifacts();
320     }
321 
322     /**
323      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
324      *
325      * @throws ArtifactResolverException if the artifact resolution failed
326      * @see ArtifactResolver#resolve(Session, Collection)
327      */
328     @Override
329     public Map.Entry<Artifact, Path> resolveArtifact(Artifact artifact) {
330         ArtifactCoordinate coordinate =
331                 getService(ArtifactCoordinateFactory.class).create(this, artifact);
332         return resolveArtifact(coordinate);
333     }
334 
335     @Override
336     public Map<Artifact, Path> resolveArtifacts(Artifact... artifacts) {
337         ArtifactCoordinateFactory acf = getService(ArtifactCoordinateFactory.class);
338         List<ArtifactCoordinate> coords = map(Arrays.asList(artifacts), a -> acf.create(this, a));
339         return resolveArtifacts(coords);
340     }
341 
342     /**
343      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
344      *
345      * @throws ArtifactInstallerException if the artifacts installation failed
346      * @see ArtifactInstaller#install(Session, Collection)
347      */
348     @Override
349     public void installArtifacts(Artifact... artifacts) {
350         installArtifacts(Arrays.asList(artifacts));
351     }
352 
353     /**
354      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
355      *
356      * @throws ArtifactInstallerException if the artifacts installation failed
357      * @see ArtifactInstaller#install(Session, Collection)
358      */
359     @Override
360     public void installArtifacts(Collection<Artifact> artifacts) {
361         getService(ArtifactInstaller.class).install(this, artifacts);
362     }
363 
364     /**
365      * Shortcut for <code>getService(ArtifactDeployer.class).deploy(...)</code>
366      *
367      * @throws ArtifactDeployerException if the artifacts deployment failed
368      * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection)
369      */
370     @Override
371     public void deployArtifact(RemoteRepository repository, Artifact... artifacts) {
372         getService(ArtifactDeployer.class).deploy(this, repository, Arrays.asList(artifacts));
373     }
374 
375     /**
376      * Shortcut for <code>getService(ArtifactManager.class).setPath(...)</code>
377      *
378      * @see ArtifactManager#setPath(Artifact, Path)
379      */
380     @Override
381     public void setArtifactPath(@Nonnull Artifact artifact, @Nonnull Path path) {
382         getService(ArtifactManager.class).setPath(artifact, path);
383     }
384 
385     /**
386      * Shortcut for <code>getService(ArtifactManager.class).getPath(...)</code>
387      *
388      * @see ArtifactManager#getPath(Artifact)
389      */
390     @Nonnull
391     @Override
392     public Optional<Path> getArtifactPath(@Nonnull Artifact artifact) {
393         return getService(ArtifactManager.class).getPath(artifact);
394     }
395 
396     /**
397      * Shortcut for <code>getService(VersionParser.class).isSnapshot(...)</code>
398      *
399      * @see VersionParser#isSnapshot(String)
400      */
401     @Override
402     public boolean isVersionSnapshot(@Nonnull String version) {
403         return getService(VersionParser.class).isSnapshot(version);
404     }
405 
406     /**
407      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
408      *
409      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
410      */
411     @Nonnull
412     @Override
413     public DependencyCoordinate createDependencyCoordinate(@Nonnull ArtifactCoordinate coordinate) {
414         return getService(DependencyCoordinateFactory.class).create(this, coordinate);
415     }
416 
417     /**
418      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
419      *
420      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
421      */
422     @Nonnull
423     public DependencyCoordinate createDependencyCoordinate(@Nonnull Dependency dependency) {
424         return getService(DependencyCoordinateFactory.class).create(this, dependency);
425     }
426 
427     /**
428      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
429      *
430      * @throws DependencyCollectorException if the dependency collection failed
431      * @see DependencyCollector#collect(Session, Artifact)
432      */
433     @Nonnull
434     @Override
435     public Node collectDependencies(@Nonnull Artifact artifact) {
436         return getService(DependencyCollector.class).collect(this, artifact).getRoot();
437     }
438 
439     /**
440      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
441      *
442      * @throws DependencyCollectorException if the dependency collection failed
443      * @see DependencyCollector#collect(Session, Project)
444      */
445     @Nonnull
446     @Override
447     public Node collectDependencies(@Nonnull Project project) {
448         return getService(DependencyCollector.class).collect(this, project).getRoot();
449     }
450 
451     /**
452      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
453      *
454      * @throws DependencyCollectorException if the dependency collection failed
455      * @see DependencyCollector#collect(Session, DependencyCoordinate)
456      */
457     @Nonnull
458     @Override
459     public Node collectDependencies(@Nonnull DependencyCoordinate dependency) {
460         return getService(DependencyCollector.class).collect(this, dependency).getRoot();
461     }
462 
463     @Nonnull
464     @Override
465     public List<Node> flattenDependencies(@Nonnull Node node, @Nonnull ResolutionScope scope) {
466         return getService(DependencyResolver.class).flatten(this, node, scope);
467     }
468 
469     @Override
470     public List<Path> resolveDependencies(DependencyCoordinate dependency) {
471         return getService(DependencyResolver.class).resolve(this, dependency).getPaths();
472     }
473 
474     @Override
475     public List<Path> resolveDependencies(List<DependencyCoordinate> dependencies) {
476         return getService(DependencyResolver.class).resolve(this, dependencies).getPaths();
477     }
478 
479     @Override
480     public List<Path> resolveDependencies(Project project, ResolutionScope scope) {
481         return getService(DependencyResolver.class)
482                 .resolve(this, project, scope)
483                 .getPaths();
484     }
485 
486     @Override
487     public Path getPathForLocalArtifact(@Nonnull Artifact artifact) {
488         return getService(LocalRepositoryManager.class).getPathForLocalArtifact(this, getLocalRepository(), artifact);
489     }
490 
491     @Override
492     public Path getPathForRemoteArtifact(RemoteRepository remote, Artifact artifact) {
493         return getService(LocalRepositoryManager.class)
494                 .getPathForRemoteArtifact(this, getLocalRepository(), remote, artifact);
495     }
496 
497     @Override
498     public Version parseVersion(String version) {
499         return getService(VersionParser.class).parseVersion(version);
500     }
501 
502     @Override
503     public VersionRange parseVersionRange(String versionRange) {
504         return getService(VersionParser.class).parseVersionRange(versionRange);
505     }
506 
507     @Override
508     public Version resolveVersion(ArtifactCoordinate artifact) {
509         return getService(VersionResolver.class).resolve(this, artifact).getVersion();
510     }
511 
512     @Override
513     public List<Version> resolveVersionRange(ArtifactCoordinate artifact) {
514         return getService(VersionRangeResolver.class).resolve(this, artifact).getVersions();
515     }
516 }