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