001package org.apache.maven.project;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.List;
026import java.util.Properties;
027
028import org.apache.maven.artifact.Artifact;
029import org.apache.maven.artifact.InvalidRepositoryException;
030import org.apache.maven.artifact.repository.ArtifactRepository;
031import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
032import org.apache.maven.artifact.resolver.ArtifactResolutionException;
033import org.apache.maven.execution.MavenExecutionRequest;
034import org.apache.maven.execution.MavenSession;
035import org.apache.maven.model.Repository;
036import org.apache.maven.model.building.ModelBuildingException;
037import org.apache.maven.model.building.ModelBuildingRequest;
038import org.apache.maven.model.building.ModelSource;
039import org.apache.maven.model.building.UrlModelSource;
040import org.apache.maven.plugin.LegacySupport;
041import org.apache.maven.profiles.ProfileManager;
042import org.apache.maven.properties.internal.EnvironmentUtils;
043import org.apache.maven.repository.RepositorySystem;
044import org.apache.maven.wagon.events.TransferListener;
045import org.codehaus.plexus.component.annotations.Component;
046import org.codehaus.plexus.component.annotations.Requirement;
047
048/**
049 */
050@Component( role = MavenProjectBuilder.class )
051@Deprecated
052public class DefaultMavenProjectBuilder
053    implements MavenProjectBuilder
054{
055
056    @Requirement
057    private ProjectBuilder projectBuilder;
058
059    @Requirement
060    private RepositorySystem repositorySystem;
061
062    @Requirement
063    private LegacySupport legacySupport;
064
065    // ----------------------------------------------------------------------
066    // MavenProjectBuilder Implementation
067    // ----------------------------------------------------------------------
068
069    private ProjectBuildingRequest toRequest( ProjectBuilderConfiguration configuration )
070    {
071        DefaultProjectBuildingRequest request = new DefaultProjectBuildingRequest();
072
073        request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 );
074        request.setResolveDependencies( false );
075
076        request.setLocalRepository( configuration.getLocalRepository() );
077        request.setBuildStartTime( configuration.getBuildStartTime() );
078        request.setUserProperties( configuration.getUserProperties() );
079        request.setSystemProperties( configuration.getExecutionProperties() );
080
081        ProfileManager profileManager = configuration.getGlobalProfileManager();
082        if ( profileManager != null )
083        {
084            request.setActiveProfileIds( profileManager.getExplicitlyActivatedIds() );
085            request.setInactiveProfileIds( profileManager.getExplicitlyDeactivatedIds() );
086        }
087        else
088        {
089            /*
090             * MNG-4900: Hack to workaround deficiency of legacy API which makes it impossible for plugins to access the
091             * global profile manager which is required to build a POM like a CLI invocation does. Failure to consider
092             * the activated profiles can cause repo declarations to be lost which in turn will result in artifact
093             * resolution failures, in particular when using the enhanced local repo which guards access to local files
094             * based on the configured remote repos.
095             */
096            MavenSession session = legacySupport.getSession();
097            if ( session != null )
098            {
099                MavenExecutionRequest req = session.getRequest();
100                if ( req != null )
101                {
102                    request.setActiveProfileIds( req.getActiveProfiles() );
103                    request.setInactiveProfileIds( req.getInactiveProfiles() );
104                }
105            }
106        }
107
108        return request;
109    }
110
111    private ProjectBuildingRequest injectSession( ProjectBuildingRequest request )
112    {
113        MavenSession session = legacySupport.getSession();
114        if ( session != null )
115        {
116            request.setRepositorySession( session.getRepositorySession() );
117            request.setSystemProperties( session.getSystemProperties() );
118            if ( request.getUserProperties().isEmpty() )
119            {
120                request.setUserProperties( session.getUserProperties() );
121            }
122
123            MavenExecutionRequest req = session.getRequest();
124            if ( req != null )
125            {
126                request.setRemoteRepositories( req.getRemoteRepositories() );
127            }
128        }
129        else
130        {
131            Properties props = new Properties();
132            EnvironmentUtils.addEnvVars( props );
133            props.putAll( System.getProperties() );
134            request.setSystemProperties( props );
135        }
136
137        return request;
138    }
139
140    @SuppressWarnings( "unchecked" )
141    private List<ArtifactRepository> normalizeToArtifactRepositories( List<?> repositories,
142                                                                      ProjectBuildingRequest request )
143        throws ProjectBuildingException
144    {
145        /*
146         * This provides backward-compat with 2.x that allowed plugins like the maven-remote-resources-plugin:1.0 to
147         * populate the builder configuration with model repositories instead of artifact repositories.
148         */
149
150        if ( repositories != null )
151        {
152            boolean normalized = false;
153
154            List<ArtifactRepository> repos = new ArrayList<ArtifactRepository>( repositories.size() );
155
156            for ( Object repository : repositories )
157            {
158                if ( repository instanceof Repository )
159                {
160                    try
161                    {
162                        ArtifactRepository repo = repositorySystem.buildArtifactRepository( (Repository) repository );
163                        repositorySystem.injectMirror( request.getRepositorySession(), Arrays.asList( repo ) );
164                        repositorySystem.injectProxy( request.getRepositorySession(), Arrays.asList( repo ) );
165                        repositorySystem.injectAuthentication( request.getRepositorySession(), Arrays.asList( repo ) );
166                        repos.add( repo );
167                    }
168                    catch ( InvalidRepositoryException e )
169                    {
170                        throw new ProjectBuildingException( "", "Invalid remote repository " + repository, e );
171                    }
172                    normalized = true;
173                }
174                else
175                {
176                    repos.add( (ArtifactRepository) repository );
177                }
178            }
179
180            if ( normalized )
181            {
182                return repos;
183            }
184        }
185
186        return (List<ArtifactRepository>) repositories;
187    }
188
189    private ProjectBuildingException transformError( ProjectBuildingException e )
190    {
191        if ( e.getCause() instanceof ModelBuildingException )
192        {
193            return new InvalidProjectModelException( e.getProjectId(), e.getMessage(), e.getPomFile() );
194        }
195
196        return e;
197    }
198
199    public MavenProject build( File pom, ProjectBuilderConfiguration configuration )
200        throws ProjectBuildingException
201    {
202        ProjectBuildingRequest request = injectSession( toRequest( configuration ) );
203
204        try
205        {
206            return projectBuilder.build( pom, request ).getProject();
207        }
208        catch ( ProjectBuildingException e )
209        {
210            throw transformError( e );
211        }
212    }
213
214    // This is used by the SITE plugin.
215    public MavenProject build( File pom, ArtifactRepository localRepository, ProfileManager profileManager )
216        throws ProjectBuildingException
217    {
218        ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
219        configuration.setLocalRepository( localRepository );
220        configuration.setGlobalProfileManager( profileManager );
221
222        return build( pom, configuration );
223    }
224
225    public MavenProject buildFromRepository( Artifact artifact, List<ArtifactRepository> remoteRepositories,
226                                             ProjectBuilderConfiguration configuration, boolean allowStubModel )
227        throws ProjectBuildingException
228    {
229        ProjectBuildingRequest request = injectSession( toRequest( configuration ) );
230        request.setRemoteRepositories( normalizeToArtifactRepositories( remoteRepositories, request ) );
231        request.setProcessPlugins( false );
232        request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
233
234        try
235        {
236            return projectBuilder.build( artifact, allowStubModel, request ).getProject();
237        }
238        catch ( ProjectBuildingException e )
239        {
240            throw transformError( e );
241        }
242    }
243
244    public MavenProject buildFromRepository( Artifact artifact, List<ArtifactRepository> remoteRepositories,
245                                             ArtifactRepository localRepository, boolean allowStubModel )
246        throws ProjectBuildingException
247    {
248        ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
249        configuration.setLocalRepository( localRepository );
250
251        return buildFromRepository( artifact, remoteRepositories, configuration, allowStubModel );
252    }
253
254    public MavenProject buildFromRepository( Artifact artifact, List<ArtifactRepository> remoteRepositories,
255                                             ArtifactRepository localRepository )
256        throws ProjectBuildingException
257    {
258        return buildFromRepository( artifact, remoteRepositories, localRepository, true );
259    }
260
261    /**
262     * This is used for pom-less execution like running archetype:generate. I am taking out the profile handling and the
263     * interpolation of the base directory until we spec this out properly.
264     */
265    public MavenProject buildStandaloneSuperProject( ProjectBuilderConfiguration configuration )
266        throws ProjectBuildingException
267    {
268        ProjectBuildingRequest request = injectSession( toRequest( configuration ) );
269        request.setProcessPlugins( false );
270        request.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
271
272        ModelSource modelSource = new UrlModelSource( getClass().getResource( "standalone.xml" ) );
273
274        MavenProject project = projectBuilder.build( modelSource, request ).getProject();
275        project.setExecutionRoot( true );
276        return project;
277    }
278
279    public MavenProject buildStandaloneSuperProject( ArtifactRepository localRepository )
280        throws ProjectBuildingException
281    {
282        return buildStandaloneSuperProject( localRepository, null );
283    }
284
285    public MavenProject buildStandaloneSuperProject( ArtifactRepository localRepository, ProfileManager profileManager )
286        throws ProjectBuildingException
287    {
288        ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
289        configuration.setLocalRepository( localRepository );
290        configuration.setGlobalProfileManager( profileManager );
291
292        return buildStandaloneSuperProject( configuration );
293    }
294
295    public MavenProject buildWithDependencies( File pom, ArtifactRepository localRepository,
296                                               ProfileManager profileManager, TransferListener transferListener )
297        throws ProjectBuildingException, ArtifactResolutionException, ArtifactNotFoundException
298    {
299        ProjectBuilderConfiguration configuration = new DefaultProjectBuilderConfiguration();
300        configuration.setLocalRepository( localRepository );
301        configuration.setGlobalProfileManager( profileManager );
302
303        ProjectBuildingRequest request = injectSession( toRequest( configuration ) );
304
305        request.setResolveDependencies( true );
306
307        try
308        {
309            return projectBuilder.build( pom, request ).getProject();
310        }
311        catch ( ProjectBuildingException e )
312        {
313            throw transformError( e );
314        }
315    }
316
317    public MavenProject buildWithDependencies( File pom, ArtifactRepository localRepository,
318                                               ProfileManager profileManager )
319        throws ProjectBuildingException, ArtifactResolutionException, ArtifactNotFoundException
320    {
321        return buildWithDependencies( pom, localRepository, profileManager, null );
322    }
323
324}