View Javadoc
1   package org.apache.maven.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.nio.file.Path;
24  import java.util.Arrays;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Objects;
30  import java.util.Optional;
31  import java.util.WeakHashMap;
32  import java.util.concurrent.CopyOnWriteArrayList;
33  import java.util.stream.Collectors;
34  import java.util.stream.Stream;
35  
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  import static org.apache.maven.internal.impl.Utils.nonNull;
69  
70  public abstract class AbstractSession implements Session
71  {
72  
73      private final List<Listener> listeners = new CopyOnWriteArrayList<>();
74      private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes
75              = Collections.synchronizedMap( new WeakHashMap<>() );
76      private final Map<org.eclipse.aether.artifact.Artifact, Artifact> allArtifacts
77              = Collections.synchronizedMap( new WeakHashMap<>() );
78      private final Map<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories
79              = Collections.synchronizedMap( new WeakHashMap<>() );
80      private final Map<String, Project> allProjects
81              = Collections.synchronizedMap( new WeakHashMap<>() );
82      private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies
83              = Collections.synchronizedMap( new WeakHashMap<>() );
84  
85      public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository )
86      {
87          return allRepositories.computeIfAbsent( repository, DefaultRemoteRepository::new );
88      }
89  
90      public Node getNode( org.eclipse.aether.graph.DependencyNode node )
91      {
92          return getNode( node, false );
93      }
94  
95      public Node getNode( org.eclipse.aether.graph.DependencyNode node, boolean verbose )
96      {
97          return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n, verbose ) );
98      }
99  
100     @Nonnull
101     public Artifact getArtifact( @Nonnull org.eclipse.aether.artifact.Artifact artifact )
102     {
103         return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) );
104     }
105 
106     @Nonnull
107     public Dependency getDependency( @Nonnull org.eclipse.aether.graph.Dependency dependency )
108     {
109         return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) );
110     }
111 
112     public List<Project> getProjects( List<MavenProject> projects )
113     {
114         return projects == null ? null : projects.stream()
115                 .map( this::getProject )
116                 .collect( Collectors.toList() );
117     }
118 
119     public Project getProject( MavenProject project )
120     {
121         return allProjects.computeIfAbsent( project.getId(), id -> new DefaultProject( this, project ) );
122     }
123 
124     public List<org.eclipse.aether.repository.RemoteRepository> toRepositories( List<RemoteRepository> repositories )
125     {
126         return repositories == null ? null : repositories.stream()
127                 .map( this::toRepository )
128                 .collect( Collectors.toList() );
129     }
130 
131     public org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repository )
132     {
133         if ( repository instanceof DefaultRemoteRepository )
134         {
135             return ( (DefaultRemoteRepository) repository ).getRepository();
136         }
137         else
138         {
139             // TODO
140             throw new UnsupportedOperationException( "Not implemented yet" );
141         }
142     }
143 
144     public org.eclipse.aether.repository.LocalRepository toRepository( LocalRepository repository )
145     {
146         if ( repository instanceof DefaultLocalRepository )
147         {
148             return ( (DefaultLocalRepository) repository ).getRepository();
149         }
150         else
151         {
152             // TODO
153             throw new UnsupportedOperationException( "Not implemented yet" );
154         }
155     }
156 
157     public List<ArtifactRepository> toArtifactRepositories( List<RemoteRepository> repositories )
158     {
159         return repositories == null ? null : repositories.stream()
160                 .map( this::toArtifactRepository )
161                 .collect( Collectors.toList() );
162     }
163 
164     public abstract ArtifactRepository toArtifactRepository( RemoteRepository repository );
165 
166     public List<org.eclipse.aether.graph.Dependency> toDependencies( Collection<DependencyCoordinate> dependencies )
167     {
168         return dependencies == null ? null : dependencies.stream()
169                 .map( this::toDependency )
170                 .collect( Collectors.toList() );
171     }
172 
173     public abstract org.eclipse.aether.graph.Dependency toDependency( DependencyCoordinate dependency );
174 
175     public List<org.eclipse.aether.artifact.Artifact> toArtifacts( Collection<Artifact> artifacts )
176     {
177         return artifacts == null ? null : artifacts.stream()
178                 .map( this::toArtifact )
179                 .collect( Collectors.toList() );
180     }
181 
182     public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact )
183     {
184         File file = getService( ArtifactManager.class ).getPath( artifact ).map( Path::toFile ).orElse( null );
185         if ( artifact instanceof DefaultArtifact )
186         {
187             org.eclipse.aether.artifact.Artifact a = ( (DefaultArtifact) artifact ).getArtifact();
188             if ( Objects.equals( file, a.getFile() ) )
189             {
190                 return a;
191             }
192         }
193         return new org.eclipse.aether.artifact.DefaultArtifact(
194                 artifact.getGroupId(),
195                 artifact.getArtifactId(),
196                 artifact.getClassifier(),
197                 artifact.getExtension(),
198                 artifact.getVersion().toString(),
199                 null,
200                 file
201         );
202     }
203 
204     public org.eclipse.aether.artifact.Artifact toArtifact( ArtifactCoordinate coord )
205     {
206         if ( coord instanceof DefaultArtifactCoordinate )
207         {
208             return ( (DefaultArtifactCoordinate) coord ).getCoordinate();
209         }
210         return new org.eclipse.aether.artifact.DefaultArtifact(
211                 coord.getGroupId(),
212                 coord.getArtifactId(),
213                 coord.getClassifier(),
214                 coord.getExtension(),
215                 coord.getVersion().toString(),
216                 null,
217                 (File) null
218         );
219     }
220 
221     @Override
222     public void registerListener( @Nonnull Listener listener )
223     {
224         listeners.add( nonNull( listener ) );
225     }
226 
227     @Override
228     public void unregisterListener( @Nonnull Listener listener )
229     {
230         listeners.remove( nonNull( listener ) );
231     }
232 
233     @Nonnull
234     @Override
235     public Collection<Listener> getListeners()
236     {
237         return Collections.unmodifiableCollection( listeners );
238     }
239 
240     //
241     // Shortcut implementations
242     //
243 
244     /**
245      * Shortcut for <code>getService(RepositoryFactory.class).createLocal(...)</code>
246      *
247      * @see RepositoryFactory#createLocal(Path)
248      */
249     @Override
250     public LocalRepository createLocalRepository( Path path )
251     {
252         return getService( RepositoryFactory.class ).createLocal( path );
253     }
254 
255     /**
256      * Shortcut for <code>getService(RepositoryFactory.class).createRemote(...)</code>
257      *
258      * @see RepositoryFactory#createRemote(String, String)
259      */
260     @Nonnull
261     @Override
262     public RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url )
263     {
264         return getService( RepositoryFactory.class )
265                 .createRemote( id, url );
266     }
267 
268     /**
269      * Shortcut for <code>getService(RepositoryFactory.class).createRemote(...)</code>
270      *
271      * @see RepositoryFactory#createRemote(Repository)
272      */
273     @Nonnull
274     @Override
275     public RemoteRepository createRemoteRepository( @Nonnull Repository repository )
276     {
277         return getService( RepositoryFactory.class )
278                 .createRemote( repository );
279     }
280 
281     /**
282      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
283      *
284      * @see ArtifactFactory#create(Session, String, String, String, String)
285      */
286     @Override
287     public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId,
288                                                         String version, String extension )
289     {
290         return getService( ArtifactCoordinateFactory.class )
291                 .create( this, groupId, artifactId, version, extension );
292     }
293 
294     /**
295      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
296      *
297      * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String)
298      */
299     @Override
300     public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version,
301                                                         String classifier, String extension, String type )
302     {
303         return getService( ArtifactCoordinateFactory.class )
304                 .create( this, groupId, artifactId, version, classifier, extension, type );
305     }
306 
307     /**
308      * Shortcut for <code>getService(CoordinateFactory.class).create(...)</code>
309      *
310      * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String)
311      */
312     @Override
313     public ArtifactCoordinate createArtifactCoordinate( Artifact artifact )
314     {
315         return getService( ArtifactCoordinateFactory.class )
316                 .create( this, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(),
317                          artifact.getClassifier(), artifact.getExtension(), null );
318     }
319 
320     /**
321      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
322      *
323      * @see ArtifactFactory#create(Session, String, String, String, String)
324      */
325     @Override
326     public Artifact createArtifact( String groupId, String artifactId, String version, String extension )
327     {
328         return getService( ArtifactFactory.class )
329                 .create( this, groupId, artifactId, version, extension );
330     }
331 
332     /**
333      * Shortcut for <code>getService(ArtifactFactory.class).create(...)</code>
334      *
335      * @see ArtifactFactory#create(Session, String, String, String, String, String, String)
336      */
337     @Override
338     public Artifact createArtifact( String groupId, String artifactId, String version, String classifier,
339                                     String extension, String type )
340     {
341         return getService( ArtifactFactory.class )
342                 .create( this, groupId, artifactId, version, classifier, extension, type );
343     }
344 
345     /**
346      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
347      *
348      * @throws ArtifactResolverException if the artifact resolution failed
349      * @see ArtifactResolver#resolve(Session, Collection)
350      */
351     @Override
352     public Artifact resolveArtifact( ArtifactCoordinate coordinate )
353     {
354         return getService( ArtifactResolver.class )
355                 .resolve( this, Collections.singletonList( coordinate ) )
356                 .getArtifacts().keySet().iterator().next();
357     }
358 
359     /**
360      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
361      *
362      * @throws ArtifactResolverException if the artifact resolution failed
363      * @see ArtifactResolver#resolve(Session, Collection)
364      */
365     @Override
366     public Collection<Artifact> resolveArtifacts( ArtifactCoordinate... coordinates )
367     {
368         return resolveArtifacts( Arrays.asList( coordinates ) );
369     }
370 
371     /**
372      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
373      *
374      * @throws ArtifactResolverException if the artifact resolution failed
375      * @see ArtifactResolver#resolve(Session, Collection)
376      */
377     @Override
378     public Collection<Artifact> resolveArtifacts( Collection<? extends ArtifactCoordinate> coordinates )
379     {
380         return getService( ArtifactResolver.class )
381                 .resolve( this, coordinates )
382                 .getArtifacts().keySet();
383     }
384 
385     /**
386      * Shortcut for <code>getService(ArtifactResolver.class).resolve(...)</code>
387      *
388      * @throws ArtifactResolverException if the artifact resolution failed
389      * @see ArtifactResolver#resolve(Session, Collection)
390      */
391     @Override
392     public Artifact resolveArtifact( Artifact artifact )
393     {
394         ArtifactCoordinate coordinate = getService( ArtifactCoordinateFactory.class )
395                 .create( this, artifact );
396         return resolveArtifact( coordinate );
397     }
398 
399     @Override
400     public Collection<Artifact> resolveArtifacts( Artifact... artifacts )
401     {
402         ArtifactCoordinateFactory acf = getService( ArtifactCoordinateFactory.class );
403         ArtifactCoordinate[] coords = Stream.of( artifacts )
404                 .map( a -> acf.create( this, a ) )
405                 .toArray( ArtifactCoordinate[]::new );
406         return resolveArtifacts( coords );
407     }
408 
409     /**
410      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
411      *
412      * @throws ArtifactInstallerException if the artifacts installation failed
413      * @see ArtifactInstaller#install(Session, Collection)
414      */
415     @Override
416     public void installArtifacts( Artifact... artifacts )
417     {
418         installArtifacts( Arrays.asList( artifacts ) );
419     }
420 
421     /**
422      * Shortcut for {@code getService(ArtifactInstaller.class).install(...)}
423      *
424      * @throws ArtifactInstallerException if the artifacts installation failed
425      * @see ArtifactInstaller#install(Session, Collection)
426      */
427     @Override
428     public void installArtifacts( Collection<Artifact> artifacts )
429     {
430         getService( ArtifactInstaller.class )
431                 .install( this, artifacts );
432     }
433 
434     /**
435      * Shortcut for <code>getService(ArtifactDeployer.class).deploy(...)</code>
436      *
437      * @throws ArtifactDeployerException if the artifacts deployment failed
438      * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection)
439      */
440     @Override
441     public void deployArtifact( RemoteRepository repository, Artifact... artifacts )
442     {
443         getService( ArtifactDeployer.class )
444                 .deploy( this, repository, Arrays.asList( artifacts ) );
445     }
446 
447     /**
448      * Shortcut for <code>getService(ArtifactManager.class).setPath(...)</code>
449      *
450      * @see ArtifactManager#setPath(Artifact, Path)
451      */
452     @Override
453     public void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path )
454     {
455         getService( ArtifactManager.class )
456                 .setPath( artifact, path );
457     }
458 
459     /**
460      * Shortcut for <code>getService(ArtifactManager.class).getPath(...)</code>
461      *
462      * @see ArtifactManager#getPath(Artifact)
463      */
464     @Nonnull
465     @Override
466     public Optional<Path> getArtifactPath( @Nonnull Artifact artifact )
467     {
468         return getService( ArtifactManager.class )
469                 .getPath( artifact );
470     }
471 
472     /**
473      * Shortcut for <code>getService(VersionParser.class).isSnapshot(...)</code>
474      *
475      * @see VersionParser#isSnapshot(String)
476      */
477     @Override
478     public boolean isVersionSnapshot( @Nonnull String version )
479     {
480         return getService( VersionParser.class )
481                 .isSnapshot( version );
482     }
483 
484     /**
485      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
486      *
487      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
488      */
489     @Nonnull
490     @Override
491     public DependencyCoordinate createDependencyCoordinate( @Nonnull ArtifactCoordinate coordinate )
492     {
493         return getService( DependencyCoordinateFactory.class )
494                 .create( this, coordinate );
495     }
496 
497     /**
498      * Shortcut for <code>getService(DependencyFactory.class).create(...)</code>
499      *
500      * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate)
501      */
502     @Nonnull
503     public DependencyCoordinate createDependencyCoordinate( @Nonnull Dependency dependency )
504     {
505         return getService( DependencyCoordinateFactory.class )
506                 .create( this, dependency );
507     }
508 
509     /**
510      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
511      *
512      * @throws DependencyCollectorException if the dependency collection failed
513      * @see DependencyCollector#collect(Session, Artifact)
514      */
515     @Nonnull
516     @Override
517     public Node collectDependencies( @Nonnull Artifact artifact )
518     {
519         return getService( DependencyCollector.class )
520                 .collect( this, artifact )
521                 .getRoot();
522     }
523 
524     /**
525      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
526      *
527      * @throws DependencyCollectorException if the dependency collection failed
528      * @see DependencyCollector#collect(Session, Project)
529      */
530     @Nonnull
531     @Override
532     public Node collectDependencies( @Nonnull Project project )
533     {
534         return getService( DependencyCollector.class )
535                 .collect( this, project )
536                 .getRoot();
537     }
538 
539     /**
540      * Shortcut for <code>getService(DependencyCollector.class).collect(...)</code>
541      *
542      * @throws DependencyCollectorException if the dependency collection failed
543      * @see DependencyCollector#collect(Session, DependencyCoordinate)
544      */
545     @Nonnull
546     @Override
547     public Node collectDependencies( @Nonnull DependencyCoordinate dependency )
548     {
549         return getService( DependencyCollector.class )
550                 .collect( this, dependency )
551                 .getRoot();
552     }
553 
554     @Override
555     public Path getPathForLocalArtifact( @Nonnull Artifact artifact )
556     {
557         return getService( LocalRepositoryManager.class )
558                 .getPathForLocalArtifact( this, getLocalRepository(), artifact );
559     }
560 
561     @Override
562     public Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact )
563     {
564         return getService( LocalRepositoryManager.class )
565                 .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact );
566     }
567 
568     @Override
569     public Version parseVersion( String version )
570     {
571         return getService( VersionParser.class )
572                 .parseVersion( version );
573     }
574 
575     @Override
576     public VersionRange parseVersionRange( String versionRange )
577     {
578         return getService( VersionParser.class )
579                 .parseVersionRange( versionRange );
580     }
581 }