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