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.execution.MavenSession;
23  import org.apache.maven.project.MavenProject;
24  import org.codehaus.plexus.component.annotations.Component;
25  import org.codehaus.plexus.component.annotations.Requirement;
26  import org.codehaus.plexus.logging.Logger;
27  
28  import java.util.List;
29  import java.util.Map;
30  import java.util.concurrent.Callable;
31  import java.util.concurrent.CompletionService;
32  import java.util.concurrent.ExecutionException;
33  import java.util.concurrent.Future;
34  
35  /**
36   * Builds the full lifecycle in weave-mode (phase by phase as opposed to project-by-project)
37   * 
38   * @since 3.0
39   * @author Kristian Rosenvold
40   *         Builds one or more lifecycles for a full module
41   *         <p/>
42   *         NOTE: This class is not part of any public api and can be changed or deleted without prior notice.
43   */
44  @Component( role = LifecycleThreadedBuilder.class )
45  public class LifecycleThreadedBuilder
46  {
47  
48      @Requirement
49      private Logger logger;
50  
51      @Requirement
52      private LifecycleModuleBuilder lifecycleModuleBuilder;
53  
54  
55      @SuppressWarnings( { "UnusedDeclaration" } )
56      public LifecycleThreadedBuilder()
57      {
58      }
59  
60      public void build( MavenSession session, ReactorContext reactorContext, ProjectBuildList projectBuilds,
61                         List<TaskSegment> currentTaskSegment, ConcurrencyDependencyGraph analyzer,
62                         CompletionService<ProjectSegment> service )
63      {
64  
65          // Currently disabled
66          ThreadOutputMuxer muxer = null; // new ThreadOutputMuxer( analyzer.getProjectBuilds(), System.out );
67  
68          for ( TaskSegment taskSegment : currentTaskSegment )
69          {
70              Map<MavenProject, ProjectSegment> projectBuildMap = projectBuilds.selectSegment( taskSegment );
71                  try
72                  {
73                  multiThreadedProjectTaskSegmentBuild( analyzer, reactorContext, session, service, taskSegment,
74                                                        projectBuildMap, muxer );
75                      if ( reactorContext.getReactorBuildStatus().isHalted( ) )
76                      {
77                          break;
78                      }
79                  }
80                  catch ( Exception e )
81                  {
82                      break;  // Why are we just ignoring this exception? Are exceptions are being used for flow control
83                  }
84  
85          }
86      }
87  
88      private void multiThreadedProjectTaskSegmentBuild( ConcurrencyDependencyGraph analyzer,
89                                                         ReactorContext reactorContext, MavenSession rootSession,
90                                                         CompletionService<ProjectSegment> service,
91                                                         TaskSegment taskSegment,
92                                                         Map<MavenProject, ProjectSegment> projectBuildList,
93                                                         ThreadOutputMuxer muxer )
94      {
95  
96          // schedule independent projects
97          for ( MavenProject mavenProject : analyzer.getRootSchedulableBuilds() )
98          {
99              ProjectSegment projectSegment = projectBuildList.get( mavenProject );
100             logger.debug( "Scheduling: " + projectSegment.getProject() );
101             Callable<ProjectSegment> cb =
102                 createBuildCallable( rootSession, projectSegment, reactorContext, taskSegment, muxer );
103             service.submit( cb );
104         }
105 
106         // for each finished project
107         for ( int i = 0; i < analyzer.getNumberOfBuilds(); i++ )
108         {
109             try
110             {
111                 ProjectSegment projectBuild = service.take().get();
112                 if ( reactorContext.getReactorBuildStatus().isHalted() )
113                 {
114                     break;
115                 }
116                 final List<MavenProject> newItemsThatCanBeBuilt =
117                     analyzer.markAsFinished( projectBuild.getProject() );
118                 for ( MavenProject mavenProject : newItemsThatCanBeBuilt )
119                 {
120                     ProjectSegment scheduledDependent = projectBuildList.get( mavenProject );
121                     logger.debug( "Scheduling: " + scheduledDependent );
122                     Callable<ProjectSegment> cb =
123                         createBuildCallable( rootSession, scheduledDependent, reactorContext, taskSegment, muxer );
124                     service.submit( cb );
125                 }
126             }
127             catch ( InterruptedException e )
128             {
129                 break;
130             }
131             catch ( ExecutionException e )
132             {
133                 break;
134             }
135         }
136 
137         // cancel outstanding builds (if any)  - this can happen if an exception is thrown in above block
138 
139         Future<ProjectSegment> unprocessed;
140         while ( ( unprocessed = service.poll() ) != null )
141         {
142             try
143             {
144                 unprocessed.get();
145             }
146             catch ( InterruptedException e )
147             {
148                 throw new RuntimeException( e );
149             }
150             catch ( ExecutionException e )
151             {
152                 throw new RuntimeException( e );
153             }
154         }
155     }
156 
157     private Callable<ProjectSegment> createBuildCallable( final MavenSession rootSession,
158                                                           final ProjectSegment projectBuild,
159                                                           final ReactorContext reactorContext,
160                                                           final TaskSegment taskSegment, final ThreadOutputMuxer muxer )
161     {
162         return new Callable<ProjectSegment>()
163         {
164             public ProjectSegment call()
165             {
166                 // muxer.associateThreadWithProjectSegment( projectBuild );
167                 lifecycleModuleBuilder.buildProject( projectBuild.getSession(), rootSession, reactorContext,
168                                                      projectBuild.getProject(), taskSegment );
169                 // muxer.setThisModuleComplete( projectBuild );
170 
171                 return projectBuild;
172             }
173         };
174     }
175 }