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