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.project;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.File;
26  import java.util.ArrayList;
27  import java.util.Arrays;
28  import java.util.List;
29  import java.util.Properties;
30  
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.artifact.InvalidRepositoryException;
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
35  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
36  import org.apache.maven.execution.MavenExecutionRequest;
37  import org.apache.maven.execution.MavenSession;
38  import org.apache.maven.model.Repository;
39  import org.apache.maven.model.building.ModelBuildingException;
40  import org.apache.maven.model.building.ModelBuildingRequest;
41  import org.apache.maven.model.building.ModelSource;
42  import org.apache.maven.model.building.UrlModelSource;
43  import org.apache.maven.plugin.LegacySupport;
44  import org.apache.maven.profiles.ProfileManager;
45  import org.apache.maven.properties.internal.EnvironmentUtils;
46  import org.apache.maven.repository.RepositorySystem;
47  import org.apache.maven.wagon.events.TransferListener;
48  
49  /**
50   */
51  @Deprecated
52  @Named
53  @Singleton
54  public class DefaultMavenProjectBuilder implements MavenProjectBuilder {
55  
56      @Inject
57      private ProjectBuilder projectBuilder;
58  
59      @Inject
60      private RepositorySystem repositorySystem;
61  
62      @Inject
63      private LegacySupport legacySupport;
64  
65      // ----------------------------------------------------------------------
66      // MavenProjectBuilder Implementation
67      // ----------------------------------------------------------------------
68  
69      private ProjectBuildingRequest toRequest(ProjectBuilderConfiguration configuration) {
70          DefaultProjectBuildingRequest request = new DefaultProjectBuildingRequest();
71  
72          request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0);
73          request.setResolveDependencies(false);
74  
75          request.setLocalRepository(configuration.getLocalRepository());
76          request.setBuildStartTime(configuration.getBuildStartTime());
77          request.setUserProperties(configuration.getUserProperties());
78          request.setSystemProperties(configuration.getExecutionProperties());
79  
80          ProfileManager profileManager = configuration.getGlobalProfileManager();
81          if (profileManager != null) {
82              request.setActiveProfileIds(profileManager.getExplicitlyActivatedIds());
83              request.setInactiveProfileIds(profileManager.getExplicitlyDeactivatedIds());
84          } else {
85              /*
86               * MNG-4900: Hack to workaround deficiency of legacy API which makes it impossible for plugins to access the
87               * global profile manager which is required to build a POM like a CLI invocation does. Failure to consider
88               * the activated profiles can cause repo declarations to be lost which in turn will result in artifact
89               * resolution failures, in particular when using the enhanced local repo which guards access to local files
90               * based on the configured remote repos.
91               */
92              MavenSession session = legacySupport.getSession();
93              if (session != null) {
94                  MavenExecutionRequest req = session.getRequest();
95                  if (req != null) {
96                      request.setActiveProfileIds(req.getActiveProfiles());
97                      request.setInactiveProfileIds(req.getInactiveProfiles());
98                  }
99              }
100         }
101 
102         return request;
103     }
104 
105     private ProjectBuildingRequest injectSession(ProjectBuildingRequest request) {
106         MavenSession session = legacySupport.getSession();
107         if (session != null) {
108             request.setRepositorySession(session.getRepositorySession());
109             request.setSystemProperties(session.getSystemProperties());
110             if (request.getUserProperties().isEmpty()) {
111                 request.setUserProperties(session.getUserProperties());
112             }
113 
114             MavenExecutionRequest req = session.getRequest();
115             if (req != null) {
116                 request.setRemoteRepositories(req.getRemoteRepositories());
117             }
118         } else {
119             Properties props = new Properties();
120             EnvironmentUtils.addEnvVars(props);
121             props.putAll(System.getProperties());
122             request.setSystemProperties(props);
123         }
124 
125         return request;
126     }
127 
128     @SuppressWarnings("unchecked")
129     private List<ArtifactRepository> normalizeToArtifactRepositories(
130             List<?> repositories, ProjectBuildingRequest request) throws ProjectBuildingException {
131         /*
132          * This provides backward-compat with 2.x that allowed plugins like the maven-remote-resources-plugin:1.0 to
133          * populate the builder configuration with model repositories instead of artifact repositories.
134          */
135 
136         if (repositories != null) {
137             boolean normalized = false;
138 
139             List<ArtifactRepository> repos = new ArrayList<>(repositories.size());
140 
141             for (Object repository : repositories) {
142                 if (repository instanceof Repository) {
143                     try {
144                         ArtifactRepository repo = repositorySystem.buildArtifactRepository((Repository) repository);
145                         repositorySystem.injectMirror(request.getRepositorySession(), Arrays.asList(repo));
146                         repositorySystem.injectProxy(request.getRepositorySession(), Arrays.asList(repo));
147                         repositorySystem.injectAuthentication(request.getRepositorySession(), Arrays.asList(repo));
148                         repos.add(repo);
149                     } catch (InvalidRepositoryException e) {
150                         throw new ProjectBuildingException("", "Invalid remote repository " + repository, e);
151                     }
152                     normalized = true;
153                 } else {
154                     repos.add((ArtifactRepository) repository);
155                 }
156             }
157 
158             if (normalized) {
159                 return repos;
160             }
161         }
162 
163         return (List<ArtifactRepository>) repositories;
164     }
165 
166     private ProjectBuildingException transformError(ProjectBuildingException e) {
167         if (e.getCause() instanceof ModelBuildingException) {
168             return new InvalidProjectModelException(e.getProjectId(), e.getMessage(), e.getPomFile());
169         }
170 
171         return e;
172     }
173 
174     public MavenProject build(File pom, ProjectBuilderConfiguration configuration) throws ProjectBuildingException {
175         ProjectBuildingRequest request = injectSession(toRequest(configuration));
176 
177         try {
178             return projectBuilder.build(pom, request).getProject();
179         } catch (ProjectBuildingException e) {
180             throw transformError(e);
181         }
182     }
183 
184     // This is used by the SITE plugin.
185     public MavenProject build(File pom, ArtifactRepository localRepository, ProfileManager profileManager)
186             throws ProjectBuildingException {
187         ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
188         configuration.setLocalRepository(localRepository);
189         configuration.setGlobalProfileManager(profileManager);
190 
191         return build(pom, configuration);
192     }
193 
194     public MavenProject buildFromRepository(
195             Artifact artifact,
196             List<ArtifactRepository> remoteRepositories,
197             ProjectBuilderConfiguration configuration,
198             boolean allowStubModel)
199             throws ProjectBuildingException {
200         ProjectBuildingRequest request = injectSession(toRequest(configuration));
201         request.setRemoteRepositories(normalizeToArtifactRepositories(remoteRepositories, request));
202         request.setProcessPlugins(false);
203         request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
204 
205         try {
206             return projectBuilder.build(artifact, allowStubModel, request).getProject();
207         } catch (ProjectBuildingException e) {
208             throw transformError(e);
209         }
210     }
211 
212     public MavenProject buildFromRepository(
213             Artifact artifact,
214             List<ArtifactRepository> remoteRepositories,
215             ArtifactRepository localRepository,
216             boolean allowStubModel)
217             throws ProjectBuildingException {
218         ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
219         configuration.setLocalRepository(localRepository);
220 
221         return buildFromRepository(artifact, remoteRepositories, configuration, allowStubModel);
222     }
223 
224     public MavenProject buildFromRepository(
225             Artifact artifact, List<ArtifactRepository> remoteRepositories, ArtifactRepository localRepository)
226             throws ProjectBuildingException {
227         return buildFromRepository(artifact, remoteRepositories, localRepository, true);
228     }
229 
230     /**
231      * This is used for pom-less execution like running archetype:generate. I am taking out the profile handling and the
232      * interpolation of the base directory until we spec this out properly.
233      */
234     public MavenProject buildStandaloneSuperProject(ProjectBuilderConfiguration configuration)
235             throws ProjectBuildingException {
236         ProjectBuildingRequest request = injectSession(toRequest(configuration));
237         request.setProcessPlugins(false);
238         request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
239 
240         ModelSource modelSource = new UrlModelSource(getClass().getResource("standalone.xml"));
241 
242         MavenProject project = projectBuilder.build(modelSource, request).getProject();
243         project.setExecutionRoot(true);
244         return project;
245     }
246 
247     public MavenProject buildStandaloneSuperProject(ArtifactRepository localRepository)
248             throws ProjectBuildingException {
249         return buildStandaloneSuperProject(localRepository, null);
250     }
251 
252     public MavenProject buildStandaloneSuperProject(ArtifactRepository localRepository, ProfileManager profileManager)
253             throws ProjectBuildingException {
254         ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
255         configuration.setLocalRepository(localRepository);
256         configuration.setGlobalProfileManager(profileManager);
257 
258         return buildStandaloneSuperProject(configuration);
259     }
260 
261     public MavenProject buildWithDependencies(
262             File pom,
263             ArtifactRepository localRepository,
264             ProfileManager profileManager,
265             TransferListener transferListener)
266             throws ProjectBuildingException, ArtifactResolutionException, ArtifactNotFoundException {
267         ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
268         configuration.setLocalRepository(localRepository);
269         configuration.setGlobalProfileManager(profileManager);
270 
271         ProjectBuildingRequest request = injectSession(toRequest(configuration));
272 
273         request.setResolveDependencies(true);
274 
275         try {
276             return projectBuilder.build(pom, request).getProject();
277         } catch (ProjectBuildingException e) {
278             throw transformError(e);
279         }
280     }
281 
282     public MavenProject buildWithDependencies(
283             File pom, ArtifactRepository localRepository, ProfileManager profileManager)
284             throws ProjectBuildingException, ArtifactResolutionException, ArtifactNotFoundException {
285         return buildWithDependencies(pom, localRepository, profileManager, null);
286     }
287 }