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, String, String, String, String, String)
226      */
227     @Override
228     public ArtifactCoordinate createArtifactCoordinate(
229             String groupId, String artifactId, String version, String classifier, String extension, String type) {
230         return getService(ArtifactCoordinateFactory.class)
231                 .create(this, groupId, artifactId, version, classifier, extension, type);
232     }
233 
234     /**
235      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
236      *
237      * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String)
238      */
239     @Override
240     public ArtifactCoordinate createArtifactCoordinate(Artifact artifact) {
241         return getService(ArtifactCoordinateFactory.class)
242                 .create(
243                         this,
244                         artifact.getGroupId(),
245                         artifact.getArtifactId(),
246                         artifact.getVersion().asString(),
247                         artifact.getClassifier(),
248                         artifact.getExtension(),
249                         null);
250     }
251 
252     /**
253      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
254      *
255      * @see ArtifactFactory#create(Session, String, String, String, String)
256      */
257     @Override
258     public Artifact createArtifact(String groupId, String artifactId, String version, String extension) {
259         return getService(ArtifactFactory.class).create(this, groupId, artifactId, version, extension);
260     }
261 
262     /**
263      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
264      *
265      * @see ArtifactFactory#create(Session, String, String, String, String, String, String)
266      */
267     @Override
268     public Artifact createArtifact(
269             String groupId, String artifactId, String version, String classifier, String extension, String type) {
270         return getService(ArtifactFactory.class)
271                 .create(this, groupId, artifactId, version, classifier, extension, type);
272     }
273 
274     /**
275      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
276      *
277      * @throws ArtifactResolverException if the artifact resolution failed
278      * @see ArtifactResolver#resolve(Session, Collection)
279      */
280     @Override
281     public Map.Entry<Artifact, Path> resolveArtifact(ArtifactCoordinate coordinate) {
282         return getService(ArtifactResolver.class)
283                 .resolve(this, Collections.singletonList(coordinate))
284                 .getArtifacts()
285                 .entrySet()
286                 .iterator()
287                 .next();
288     }
289 
290     /**
291      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
292      *
293      * @throws ArtifactResolverException if the artifact resolution failed
294      * @see ArtifactResolver#resolve(Session, Collection)
295      */
296     @Override
297     public Map<Artifact, Path> resolveArtifacts(ArtifactCoordinate... coordinates) {
298         return resolveArtifacts(Arrays.asList(coordinates));
299     }
300 
301     /**
302      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
303      *
304      * @throws ArtifactResolverException if the artifact resolution failed
305      * @see ArtifactResolver#resolve(Session, Collection)
306      */
307     @Override
308     public Map<Artifact, Path> resolveArtifacts(Collection<? extends ArtifactCoordinate> coordinates) {
309         return getService(ArtifactResolver.class).resolve(this, coordinates).getArtifacts();
310     }
311 
312     /**
313      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
314      *
315      * @throws ArtifactResolverException if the artifact resolution failed
316      * @see ArtifactResolver#resolve(Session, Collection)
317      */
318     @Override
319     public Map.Entry<Artifact, Path> resolveArtifact(Artifact artifact) {
320         ArtifactCoordinate coordinate =
321                 getService(ArtifactCoordinateFactory.class).create(this, artifact);
322         return resolveArtifact(coordinate);
323     }
324 
325     @Override
326     public Map<Artifact, Path> resolveArtifacts(Artifact... artifacts) {
327         ArtifactCoordinateFactory acf = getService(ArtifactCoordinateFactory.class);
328         List<ArtifactCoordinate> coords = map(Arrays.asList(artifacts), a -> acf.create(this, a));
329         return resolveArtifacts(coords);
330     }
331 
332     /**
333      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
334      *
335      * @throws ArtifactInstallerException if the artifacts installation failed
336      * @see ArtifactInstaller#install(Session, Collection)
337      */
338     @Override
339     public void installArtifacts(Artifact... artifacts) {
340         installArtifacts(Arrays.asList(artifacts));
341     }
342 
343     /**
344      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
345      *
346      * @throws ArtifactInstallerException if the artifacts installation failed
347      * @see ArtifactInstaller#install(Session, Collection)
348      */
349     @Override
350     public void installArtifacts(Collection<Artifact> artifacts) {
351         getService(ArtifactInstaller.class).install(this, artifacts);
352     }
353 
354     /**
355      * Shortcut for <code>getService(ArtifactDeployer.class).deploy(...)</code>
356      *
357      * @throws ArtifactDeployerException if the artifacts deployment failed
358      * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection)
359      */
360     @Override
361     public void deployArtifact(RemoteRepository repository, Artifact... artifacts) {
362         getService(ArtifactDeployer.class).deploy(this, repository, Arrays.asList(artifacts));
363     }
364 
365     /**
366      * Shortcut for <code>getService(ArtifactManager.class).setPath(...)</code>
367      *
368      * @see ArtifactManager#setPath(Artifact, Path)
369      */
370     @Override
371     public void setArtifactPath(@Nonnull Artifact artifact, @Nonnull Path path) {
372         getService(ArtifactManager.class).setPath(artifact, path);
373     }
374 
375     /**
376      * Shortcut for <code>getService(ArtifactManager.class).getPath(...)</code>
377      *
378      * @see ArtifactManager#getPath(Artifact)
379      */
380     @Nonnull
381     @Override
382     public Optional<Path> getArtifactPath(@Nonnull Artifact artifact) {
383         return getService(ArtifactManager.class).getPath(artifact);
384     }
385 
386     /**
387      * Shortcut for <code>getService(VersionParser.class).isSnapshot(...)</code>
388      *
389      * @see VersionParser#isSnapshot(String)
390      */
391     @Override
392     public boolean isVersionSnapshot(@Nonnull String version) {
393         return getService(VersionParser.class).isSnapshot(version);
394     }
395 
396     /**
397      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
398      *
399      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
400      */
401     @Nonnull
402     @Override
403     public DependencyCoordinate createDependencyCoordinate(@Nonnull ArtifactCoordinate coordinate) {
404         return getService(DependencyCoordinateFactory.class).create(this, coordinate);
405     }
406 
407     /**
408      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
409      *
410      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
411      */
412     @Nonnull
413     public DependencyCoordinate createDependencyCoordinate(@Nonnull Dependency dependency) {
414         return getService(DependencyCoordinateFactory.class).create(this, dependency);
415     }
416 
417     /**
418      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
419      *
420      * @throws DependencyCollectorException if the dependency collection failed
421      * @see DependencyCollector#collect(Session, Artifact)
422      */
423     @Nonnull
424     @Override
425     public Node collectDependencies(@Nonnull Artifact artifact) {
426         return getService(DependencyCollector.class).collect(this, artifact).getRoot();
427     }
428 
429     /**
430      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
431      *
432      * @throws DependencyCollectorException if the dependency collection failed
433      * @see DependencyCollector#collect(Session, Project)
434      */
435     @Nonnull
436     @Override
437     public Node collectDependencies(@Nonnull Project project) {
438         return getService(DependencyCollector.class).collect(this, project).getRoot();
439     }
440 
441     /**
442      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
443      *
444      * @throws DependencyCollectorException if the dependency collection failed
445      * @see DependencyCollector#collect(Session, DependencyCoordinate)
446      */
447     @Nonnull
448     @Override
449     public Node collectDependencies(@Nonnull DependencyCoordinate dependency) {
450         return getService(DependencyCollector.class).collect(this, dependency).getRoot();
451     }
452 
453     @Nonnull
454     @Override
455     public List<Node> flattenDependencies(@Nonnull Node node, @Nonnull ResolutionScope scope) {
456         return getService(DependencyResolver.class).flatten(this, node, scope);
457     }
458 
459     @Override
460     public List<Path> resolveDependencies(DependencyCoordinate dependency) {
461         return getService(DependencyResolver.class).resolve(this, dependency).getPaths();
462     }
463 
464     @Override
465     public List<Path> resolveDependencies(List<DependencyCoordinate> dependencies) {
466         return getService(DependencyResolver.class).resolve(this, dependencies).getPaths();
467     }
468 
469     @Override
470     public List<Path> resolveDependencies(Project project, ResolutionScope scope) {
471         return getService(DependencyResolver.class)
472                 .resolve(this, project, scope)
473                 .getPaths();
474     }
475 
476     @Override
477     public Path getPathForLocalArtifact(@Nonnull Artifact artifact) {
478         return getService(LocalRepositoryManager.class).getPathForLocalArtifact(this, getLocalRepository(), artifact);
479     }
480 
481     @Override
482     public Path getPathForRemoteArtifact(RemoteRepository remote, Artifact artifact) {
483         return getService(LocalRepositoryManager.class)
484                 .getPathForRemoteArtifact(this, getLocalRepository(), remote, artifact);
485     }
486 
487     @Override
488     public Version parseVersion(String version) {
489         return getService(VersionParser.class).parseVersion(version);
490     }
491 
492     @Override
493     public VersionRange parseVersionRange(String versionRange) {
494         return getService(VersionParser.class).parseVersionRange(versionRange);
495     }
496 
497     @Override
498     public Version resolveVersion(ArtifactCoordinate artifact) {
499         return getService(VersionResolver.class).resolve(this, artifact).getVersion();
500     }
501 
502     @Override
503     public List<Version> resolveVersionRange(ArtifactCoordinate artifact) {
504         return getService(VersionRangeResolver.class).resolve(this, artifact).getVersions();
505     }
506 }