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.nio.file.Path;
22  import java.time.Instant;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.NoSuchElementException;
27  import java.util.Objects;
28  import java.util.concurrent.ConcurrentHashMap;
29  import java.util.function.Supplier;
30  
31  import org.apache.maven.RepositoryUtils;
32  import org.apache.maven.api.DependencyCoordinate;
33  import org.apache.maven.api.LocalRepository;
34  import org.apache.maven.api.Project;
35  import org.apache.maven.api.RemoteRepository;
36  import org.apache.maven.api.Service;
37  import org.apache.maven.api.Session;
38  import org.apache.maven.api.SessionData;
39  import org.apache.maven.api.annotations.Nonnull;
40  import org.apache.maven.api.annotations.Nullable;
41  import org.apache.maven.api.services.MavenException;
42  import org.apache.maven.api.settings.Settings;
43  import org.apache.maven.artifact.repository.ArtifactRepository;
44  import org.apache.maven.bridge.MavenRepositorySystem;
45  import org.apache.maven.execution.MavenSession;
46  import org.apache.maven.plugin.MojoExecution;
47  import org.apache.maven.plugin.descriptor.MojoDescriptor;
48  import org.apache.maven.plugin.descriptor.PluginDescriptor;
49  import org.apache.maven.rtinfo.RuntimeInformation;
50  import org.codehaus.plexus.PlexusContainer;
51  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
52  import org.eclipse.aether.DefaultRepositorySystemSession;
53  import org.eclipse.aether.RepositorySystem;
54  import org.eclipse.aether.RepositorySystemSession;
55  
56  import static org.apache.maven.internal.impl.Utils.map;
57  import static org.apache.maven.internal.impl.Utils.nonNull;
58  
59  public class DefaultSession extends AbstractSession {
60  
61      private final MavenSession mavenSession;
62      private final RepositorySystemSession session;
63      private final RepositorySystem repositorySystem;
64      private final List<RemoteRepository> repositories;
65      private final MavenRepositorySystem mavenRepositorySystem;
66      private final PlexusContainer container;
67      private final RuntimeInformation runtimeInformation;
68      private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>();
69  
70      @SuppressWarnings("checkstyle:ParameterNumber")
71      public DefaultSession(
72              @Nonnull MavenSession session,
73              @Nonnull RepositorySystem repositorySystem,
74              @Nullable List<RemoteRepository> repositories,
75              @Nonnull MavenRepositorySystem mavenRepositorySystem,
76              @Nonnull PlexusContainer container,
77              @Nonnull RuntimeInformation runtimeInformation) {
78          this.mavenSession = nonNull(session);
79          this.session = mavenSession.getRepositorySession();
80          this.repositorySystem = nonNull(repositorySystem);
81          this.repositories = repositories != null
82                  ? repositories
83                  : map(
84                          mavenSession.getRequest().getRemoteRepositories(),
85                          r -> getRemoteRepository(RepositoryUtils.toRepo(r)));
86          this.mavenRepositorySystem = mavenRepositorySystem;
87          this.container = container;
88          this.runtimeInformation = runtimeInformation;
89      }
90  
91      public MavenSession getMavenSession() {
92          return mavenSession;
93      }
94  
95      @Nonnull
96      @Override
97      public LocalRepository getLocalRepository() {
98          return new DefaultLocalRepository(session.getLocalRepository());
99      }
100 
101     @Nonnull
102     @Override
103     public List<RemoteRepository> getRemoteRepositories() {
104         return Collections.unmodifiableList(repositories);
105     }
106 
107     @Nonnull
108     @Override
109     public Settings getSettings() {
110         return mavenSession.getSettings().getDelegate();
111     }
112 
113     @Nonnull
114     @Override
115     public Map<String, String> getUserProperties() {
116         return new PropertiesAsMap(mavenSession.getUserProperties());
117     }
118 
119     @Nonnull
120     @Override
121     public Map<String, String> getSystemProperties() {
122         return new PropertiesAsMap(mavenSession.getSystemProperties());
123     }
124 
125     @Nonnull
126     @Override
127     public String getMavenVersion() {
128         return runtimeInformation.getMavenVersion();
129     }
130 
131     @Override
132     public int getDegreeOfConcurrency() {
133         return mavenSession.getRequest().getDegreeOfConcurrency();
134     }
135 
136     @Nonnull
137     @Override
138     public Instant getStartTime() {
139         return mavenSession.getStartTime().toInstant();
140     }
141 
142     @Override
143     public Path getRootDirectory() {
144         return mavenSession.getRequest().getRootDirectory();
145     }
146 
147     @Override
148     public Path getTopDirectory() {
149         return mavenSession.getRequest().getTopDirectory();
150     }
151 
152     @Nonnull
153     @Override
154     public List<Project> getProjects() {
155         return getProjects(mavenSession.getProjects());
156     }
157 
158     @Nonnull
159     @Override
160     public Map<String, Object> getPluginContext(Project project) {
161         nonNull(project, "project");
162         try {
163             MojoExecution mojoExecution = container.lookup(MojoExecution.class);
164             MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
165             PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
166             return mavenSession.getPluginContext(pluginDescriptor, ((DefaultProject) project).getProject());
167         } catch (ComponentLookupException e) {
168             throw new MavenException("The PluginContext is only available during a mojo execution", e);
169         }
170     }
171 
172     @Nonnull
173     @Override
174     public SessionData getData() {
175         org.eclipse.aether.SessionData data = session.getData();
176         return new SessionData() {
177             @Override
178             public void set(@Nonnull Object key, @Nullable Object value) {
179                 data.set(key, value);
180             }
181 
182             @Override
183             public boolean set(@Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue) {
184                 return data.set(key, oldValue, newValue);
185             }
186 
187             @Nullable
188             @Override
189             public Object get(@Nonnull Object key) {
190                 return data.get(key);
191             }
192 
193             @Nullable
194             @Override
195             public Object computeIfAbsent(@Nonnull Object key, @Nonnull Supplier<Object> supplier) {
196                 return data.computeIfAbsent(key, supplier);
197             }
198         };
199     }
200 
201     @Nonnull
202     @Override
203     public Session withLocalRepository(@Nonnull LocalRepository localRepository) {
204         nonNull(localRepository, "localRepository");
205         if (session.getLocalRepository() != null
206                 && Objects.equals(session.getLocalRepository().getBasedir().toPath(), localRepository.getPath())) {
207             return this;
208         }
209         org.eclipse.aether.repository.LocalRepository repository = toRepository(localRepository);
210         org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager =
211                 repositorySystem.newLocalRepositoryManager(session, repository);
212 
213         RepositorySystemSession repoSession =
214                 new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
215         MavenSession newSession = new MavenSession(repoSession, mavenSession.getRequest(), mavenSession.getResult());
216         return new DefaultSession(
217                 newSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation);
218     }
219 
220     @Nonnull
221     @Override
222     public Session withRemoteRepositories(@Nonnull List<RemoteRepository> repositories) {
223         return new DefaultSession(
224                 mavenSession, repositorySystem, repositories, mavenRepositorySystem, container, runtimeInformation);
225     }
226 
227     @Nonnull
228     @Override
229     @SuppressWarnings("unchecked")
230     public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementException {
231         T t = (T) services.computeIfAbsent(clazz, this::lookup);
232         if (t == null) {
233             throw new NoSuchElementException(clazz.getName());
234         }
235         return t;
236     }
237 
238     private Service lookup(Class<? extends Service> c) {
239         try {
240             return container.lookup(c);
241         } catch (ComponentLookupException e) {
242             NoSuchElementException nsee = new NoSuchElementException(c.getName());
243             e.initCause(e);
244             throw nsee;
245         }
246     }
247 
248     @Nonnull
249     public RepositorySystemSession getSession() {
250         return session;
251     }
252 
253     @Nonnull
254     public RepositorySystem getRepositorySystem() {
255         return repositorySystem;
256     }
257 
258     public ArtifactRepository toArtifactRepository(RemoteRepository repository) {
259         if (repository instanceof DefaultRemoteRepository) {
260             org.eclipse.aether.repository.RemoteRepository rr = ((DefaultRemoteRepository) repository).getRepository();
261 
262             try {
263                 return mavenRepositorySystem.createRepository(
264                         rr.getUrl(),
265                         rr.getId(),
266                         rr.getPolicy(false).isEnabled(),
267                         rr.getPolicy(false).getUpdatePolicy(),
268                         rr.getPolicy(true).isEnabled(),
269                         rr.getPolicy(true).getUpdatePolicy(),
270                         rr.getPolicy(false).getChecksumPolicy());
271 
272             } catch (Exception e) {
273                 throw new RuntimeException("Unable to create repository", e);
274             }
275         } else {
276             // TODO
277             throw new UnsupportedOperationException("Not yet implemented");
278         }
279     }
280 
281     public org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency) {
282         if (dependency instanceof DefaultDependencyCoordinate) {
283             return ((DefaultDependencyCoordinate) dependency).getDependency();
284         } else {
285             return new org.eclipse.aether.graph.Dependency(
286                     new org.eclipse.aether.artifact.DefaultArtifact(
287                             dependency.getGroupId(),
288                             dependency.getArtifactId(),
289                             dependency.getClassifier(),
290                             dependency.getType().getExtension(),
291                             dependency.getVersion().toString(),
292                             null),
293                     dependency.getScope().id());
294         }
295     }
296 }