View Javadoc

1   package org.apache.maven.lifecycle.internal;
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 org.apache.maven.InternalErrorException;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.execution.BuildFailure;
25  import org.apache.maven.execution.ExecutionEvent;
26  import org.apache.maven.execution.MavenExecutionRequest;
27  import org.apache.maven.execution.MavenSession;
28  import org.apache.maven.lifecycle.LifecycleExecutionException;
29  import org.apache.maven.lifecycle.LifecycleNotFoundException;
30  import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException;
31  import org.apache.maven.lifecycle.MavenExecutionPlan;
32  import org.apache.maven.model.Plugin;
33  import org.apache.maven.plugin.InvalidPluginDescriptorException;
34  import org.apache.maven.plugin.MojoNotFoundException;
35  import org.apache.maven.plugin.PluginDescriptorParsingException;
36  import org.apache.maven.plugin.PluginNotFoundException;
37  import org.apache.maven.plugin.PluginResolutionException;
38  import org.apache.maven.plugin.descriptor.MojoDescriptor;
39  import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
40  import org.apache.maven.plugin.version.PluginVersionResolutionException;
41  import org.apache.maven.project.MavenProject;
42  import org.codehaus.plexus.classworlds.realm.ClassRealm;
43  import org.codehaus.plexus.component.annotations.Component;
44  import org.codehaus.plexus.component.annotations.Requirement;
45  import org.codehaus.plexus.logging.Logger;
46  
47  import java.util.Set;
48  
49  /**
50   * Common code that is shared by the LifecycleModuleBuilder and the LifeCycleWeaveBuilder
51   *
52   * @since 3.0
53   * @author Kristian Rosenvold
54   *         Builds one or more lifecycles for a full module
55   *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
56   */
57  @Component( role = BuilderCommon.class )
58  public class BuilderCommon
59  {
60      @Requirement
61      private LifecycleDebugLogger lifecycleDebugLogger;
62  
63      @Requirement
64      private LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator;
65  
66      @Requirement
67      private ExecutionEventCatapult eventCatapult;
68  
69      @Requirement
70      private Logger logger;
71  
72  
73      public BuilderCommon()
74      {
75      }
76  
77      public BuilderCommon( LifecycleDebugLogger lifecycleDebugLogger,
78                            LifecycleExecutionPlanCalculator lifeCycleExecutionPlanCalculator, Logger logger )
79      {
80          this.lifecycleDebugLogger = lifecycleDebugLogger;
81          this.lifeCycleExecutionPlanCalculator = lifeCycleExecutionPlanCalculator;
82          this.logger = logger;
83      }
84  
85      public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject project, TaskSegment taskSegment,
86                                                  Set<Artifact> projectArtifacts )
87          throws PluginNotFoundException, PluginResolutionException, LifecyclePhaseNotFoundException,
88          PluginDescriptorParsingException, MojoNotFoundException, InvalidPluginDescriptorException,
89          NoPluginFoundForPrefixException, LifecycleNotFoundException, PluginVersionResolutionException,
90          LifecycleExecutionException
91      {
92          MavenExecutionPlan executionPlan =
93              lifeCycleExecutionPlanCalculator.calculateExecutionPlan( session, project, taskSegment.getTasks() );
94  
95          lifecycleDebugLogger.debugProjectPlan( project, executionPlan );
96  
97          if ( session.getRequest().isThreadConfigurationPresent() )
98          {
99              final Set<Plugin> unsafePlugins = executionPlan.getNonThreadSafePlugins();
100             if ( !unsafePlugins.isEmpty() )
101             {
102                 logger.warn( "*****************************************************************" );
103                 logger.warn( "* Your build is requesting parallel execution, but project      *" );
104                 logger.warn( "* contains the following plugin(s) that have goals not marked   *" );
105                 logger.warn( "* as @threadSafe to support parallel building.                  *" );
106                 logger.warn( "* While this /may/ work fine, please look for plugin updates    *" );
107                 logger.warn( "* and/or request plugins be made thread-safe.                   *" );
108                 logger.warn( "* If reporting an issue, report it against the plugin in        *" );
109                 logger.warn( "* question, not against maven-core                              *" );
110                 logger.warn( "*****************************************************************" );
111                 if ( logger.isDebugEnabled() )
112                 {
113                     final Set<MojoDescriptor> unsafeGoals = executionPlan.getNonThreadSafeMojos();
114                     logger.warn( "The following goals are not marked @threadSafe in " + project.getName() + ":" );
115                     for ( MojoDescriptor unsafeGoal : unsafeGoals )
116                     {
117                         logger.warn( unsafeGoal.getId() );
118                     }
119                 }
120                 else
121                 {
122                     logger.warn( "The following plugins are not marked @threadSafe in " + project.getName() + ":" );
123                     for ( Plugin unsafePlugin : unsafePlugins )
124                     {
125                         logger.warn( unsafePlugin.getId() );
126                     }
127                     logger.warn( "Enable debug to see more precisely which goals are not marked @threadSafe." );
128                 }
129                 logger.warn( "*****************************************************************" );
130             }
131         }
132 
133         return executionPlan;
134     }
135 
136     public void handleBuildError( final ReactorContext buildContext, final MavenSession rootSession,
137                                   final MavenSession currentSession, final MavenProject mavenProject, Exception e,
138                                   final long buildStartTime )
139     {
140         if ( e instanceof RuntimeException )
141         {
142             e = new InternalErrorException( "Internal error: " + e, e );
143         }
144 
145         buildContext.getResult().addException( e );
146 
147         long buildEndTime = System.currentTimeMillis();
148 
149         buildContext.getResult().addBuildSummary( new BuildFailure( mavenProject, buildEndTime - buildStartTime, e ) );
150 
151         eventCatapult.fire( ExecutionEvent.Type.ProjectFailed, currentSession, null, e );
152 
153         if ( MavenExecutionRequest.REACTOR_FAIL_NEVER.equals( rootSession.getReactorFailureBehavior() ) )
154         {
155             // continue the build
156         }
157         else if ( MavenExecutionRequest.REACTOR_FAIL_AT_END.equals( rootSession.getReactorFailureBehavior() ) )
158         {
159             // continue the build but ban all projects that depend on the failed one
160             buildContext.getReactorBuildStatus().blackList( mavenProject );
161         }
162         else if ( MavenExecutionRequest.REACTOR_FAIL_FAST.equals( rootSession.getReactorFailureBehavior() ) )
163         {
164             buildContext.getReactorBuildStatus().halt();
165         }
166         else
167         {
168             throw new IllegalArgumentException(
169                 "invalid reactor failure behavior " + rootSession.getReactorFailureBehavior() );
170         }
171     }
172 
173     public static void attachToThread( MavenProject currentProject )
174     {
175         ClassRealm projectRealm = currentProject.getClassRealm();
176         if ( projectRealm != null )
177         {
178             Thread.currentThread().setContextClassLoader( projectRealm );
179         }
180     }
181 
182     // Todo: I'm really wondering where this method belongs; smells like it should be on MavenProject, but for some reason
183     // it isn't ? This localization is kind-of a code smell.
184 
185     public static String getKey( MavenProject project )
186     {
187         return project.getGroupId() + ':' + project.getArtifactId() + ':' + project.getVersion();
188     }
189 
190 }