File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\maven-plugin\src\main\java\hudson\maven\Maven3Builder.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy, CloudBees, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.maven;
25
26 import hudson.maven.MavenBuild.ProxyImpl2;
27 import hudson.maven.reporters.TestFailureDetector;
28 import hudson.maven.util.ExecutionEventLogger;
29 import hudson.model.BuildListener;
30 import hudson.model.Result;
31 import hudson.remoting.Channel;
32 import hudson.remoting.DelegatingCallable;
33 import hudson.util.IOException2;
34 import org.apache.maven.cli.PrintStreamLogger;
35 import org.apache.maven.execution.AbstractExecutionListener;
36 import org.apache.maven.execution.ExecutionEvent;
37 import org.apache.maven.execution.ExecutionListener;
38 import org.apache.maven.plugin.MojoExecution;
39 import org.apache.maven.plugin.MojoExecutionException;
40 import org.apache.maven.project.MavenProject;
41 import org.jvnet.hudson.maven3.agent.Maven3Main;
42 import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
43 import org.jvnet.hudson.maven3.listeners.HudsonMavenExecutionResult;
44
45 import java.io.IOException;
46 import java.io.PrintStream;
47 import java.io.Serializable;
48 import java.lang.reflect.InvocationTargetException;
49 import java.text.NumberFormat;
50 import java.util.Collection;
51 import java.util.HashMap;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Map.Entry;
55 import java.util.concurrent.ConcurrentHashMap;
56 import java.util.concurrent.CopyOnWriteArrayList;
57 import java.util.concurrent.atomic.AtomicBoolean;
58 import java.util.logging.Logger;
59
60 import static hudson.Util.*;
61
62 /**
63 * @author Olivier Lamy
64 * @author Kohsuke Kawaguchi
65 */
66 public class Maven3Builder extends AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
67
68 /**
69 * Flag needs to be set at the constructor, so that this reflects
70 * the setting at master.
71 */
72 private final boolean profile = MavenProcessFactory.profile;
73
74 HudsonMavenExecutionResult mavenExecutionResult;
75
76 protected Maven3Builder(BuildListener listener,Map<ModuleName,ProxyImpl2> proxies, Collection<MavenModule> modules, List<String> goals, Map<String, String> systemProps, MavenBuildInformation mavenBuildInformation) {
77 super( listener, modules, goals, systemProps );
78 this.sourceProxies.putAll(proxies);
79 this.proxies = new HashMap<ModuleName, FilterImpl>();
80 for (Entry<ModuleName,ProxyImpl2> e : this.sourceProxies.entrySet()) {
81 this.proxies.put(e.getKey(), new FilterImpl(e.getValue(), mavenBuildInformation));
82 }
83 }
84
85 public Result call() throws IOException {
86
87 try {
88 initializeAsynchronousExecutions();
89
90 MavenExecutionListener mavenExecutionListener = new MavenExecutionListener( this );
91 Maven3Launcher.setMavenExecutionListener( mavenExecutionListener );
92
93 markAsSuccess = false;
94
95 registerSystemProperties();
96
97 listener.getLogger().println(formatArgs(goals));
98
99
100 int r = Maven3Main.launch( goals.toArray(new String[goals.size()]));
101
102 // now check the completion status of async ops
103 long startTime = System.nanoTime();
104
105 Result waitForAsyncExecutionsResult = waitForAsynchronousExecutions();
106 if (waitForAsyncExecutionsResult != null) {
107 return waitForAsyncExecutionsResult;
108 }
109
110 mavenExecutionListener.overheadTime += System.nanoTime()-startTime;
111
112 if(profile) {
113 NumberFormat n = NumberFormat.getInstance();
114 PrintStream logger = listener.getLogger();
115 logger.println("Total overhead was "+format(n,mavenExecutionListener.overheadTime)+"ms");
116 Channel ch = Channel.current();
117 logger.println("Class loading " +format(n,ch.classLoadingTime.get()) +"ms, "+ch.classLoadingCount+" classes");
118 logger.println("Resource loading "+format(n,ch.resourceLoadingTime.get())+"ms, "+ch.resourceLoadingCount+" times");
119 }
120
121 mavenExecutionResult = Maven3Launcher.getMavenExecutionResult();
122
123 PrintStream logger = listener.getLogger();
124
125 if(r==0 && mavenExecutionResult.getThrowables().isEmpty()) {
126 if(mavenExecutionListener.hasTestFailures()){
127 return Result.UNSTABLE;
128 }
129 return Result.SUCCESS;
130 }
131
132 if (!mavenExecutionResult.getThrowables().isEmpty()) {
133 logger.println( "mavenExecutionResult exceptions not empty");
134 for(Throwable throwable : mavenExecutionResult.getThrowables()) {
135 logger.println("message : " + throwable.getMessage());
136 if (throwable.getCause()!=null) {
137 logger.println("cause : " + throwable.getCause().getMessage());
138 }
139 logger.println("Stack trace : ");
140 throwable.printStackTrace( logger );
141 }
142
143 }
144
145 if(markAsSuccess) {
146 listener.getLogger().println(Messages.MavenBuilder_Failed());
147 if(mavenExecutionListener.hasTestFailures()){
148 return Result.UNSTABLE;
149 }
150 return Result.SUCCESS;
151 }
152 return Result.FAILURE;
153 } catch (NoSuchMethodException e) {
154 throw new IOException2(e);
155 } catch (IllegalAccessException e) {
156 throw new IOException2(e);
157 } catch (InvocationTargetException e) {
158 throw new IOException2(e);
159 } catch (ClassNotFoundException e) {
160 throw new IOException2(e);
161 } catch (Exception e) {
162 throw new IOException2(e);
163 }
164 }
165
166 private static final class MavenExecutionListener extends AbstractExecutionListener implements Serializable, ExecutionListener {
167
168 private static final long serialVersionUID = 4942789836756366116L;
169
170 private final AbstractMavenBuilder maven3Builder;
171
172 private AtomicBoolean hasTestFailures = new AtomicBoolean();
173
174 /**
175 * Number of total nanoseconds {@link Maven3Builder} spent.
176 */
177 long overheadTime;
178
179
180 private final Map<ModuleName,FilterImpl> proxies;
181
182 private final Map<ModuleName,List<ExecutedMojo>> executedMojosPerModule = new ConcurrentHashMap<ModuleName, List<ExecutedMojo>>();
183
184 private final Map<ModuleName,List<MavenReporter>> reporters;
185
186 private final Map<ModuleName, Long> currentMojoStartPerModuleName = new ConcurrentHashMap<ModuleName, Long>();
187
188 private ExecutionEventLogger eventLogger;
189
190 public MavenExecutionListener(AbstractMavenBuilder maven3Builder) {
191 this.maven3Builder = maven3Builder;
192 this.proxies = new ConcurrentHashMap<ModuleName, FilterImpl>(maven3Builder.proxies);
193 for (ModuleName name : this.proxies.keySet()) {
194 executedMojosPerModule.put( name, new CopyOnWriteArrayList<ExecutedMojo>() );
195 }
196 this.reporters = new ConcurrentHashMap<ModuleName, List<MavenReporter>>(maven3Builder.reporters);
197
198 // TODO: we should think about reusing the code in org.apache.maven.cli.DefaultMavenExecutionRequestBuilder#logging?
199 // E.g. there's also the option to redirect logging to a file which is handled there, but not here.
200 PrintStreamLogger logger = new PrintStreamLogger( maven3Builder.listener.getLogger() );
201 if (maven3Builder.isDebug()) {
202 logger.setThreshold(PrintStreamLogger.LEVEL_DEBUG);
203 } else if (maven3Builder.isQuiet()) {
204 logger.setThreshold(PrintStreamLogger.LEVEL_ERROR);
205 }
206
207 this.eventLogger = new ExecutionEventLogger( logger );
208 }
209
210 /**
211 * Whether there where test failures detected during the build.
212 * @since 1.496
213 */
214 public boolean hasTestFailures(){
215 return hasTestFailures.get();
216 }
217
218 private MavenBuildProxy2 getMavenBuildProxy2(MavenProject mavenProject) {
219 for (Entry<ModuleName,FilterImpl> entry : proxies.entrySet()) {
220 if (entry.getKey().compareTo( new ModuleName( mavenProject ) ) == 0) {
221 return entry.getValue();
222 }
223 }
224 return null;
225 }
226
227 private List<MavenReporter> getMavenReporters(MavenProject mavenProject) {
228 return reporters.get( new ModuleName( mavenProject ) );
229 }
230
231 private long initMojoStartTime( MavenProject mavenProject) {
232 long mojoStartTime = System.currentTimeMillis();
233 this.currentMojoStartPerModuleName.put( new ModuleName( mavenProject), mojoStartTime);
234 return mojoStartTime;
235 }
236
237 private Long getMojoStartTime(MavenProject mavenProject) {
238 return currentMojoStartPerModuleName.get( new ModuleName(mavenProject) );
239 }
240
241 /**
242 * @see org.apache.maven.execution.ExecutionListener#projectDiscoveryStarted(org.apache.maven.execution.ExecutionEvent)
243 */
244 public void projectDiscoveryStarted( ExecutionEvent event ) {
245 this.eventLogger.projectDiscoveryStarted( event );
246 }
247
248 /**
249 * @see org.apache.maven.execution.ExecutionListener#sessionStarted(org.apache.maven.execution.ExecutionEvent)
250 */
251 public void sessionStarted( ExecutionEvent event ) {
252 this.eventLogger.sessionStarted(event);
253
254 Map<ModuleName, MavenProject> buildingProjects = getSessionProjects(event);
255
256 for (Entry<ModuleName,FilterImpl> e : this.proxies.entrySet()) {
257 MavenProject project = buildingProjects.get(e.getKey());
258 if (project!=null) {
259 for (MavenReporter mavenReporter : fixNull(reporters.get(e.getKey()))) {
260 try {
261 mavenReporter.preBuild( e.getValue() ,project, maven3Builder.listener);
262 } catch ( InterruptedException x ) {
263 x.printStackTrace();
264 } catch ( IOException x ) {
265 x.printStackTrace();
266 }
267 }
268 } else {
269 // set all modules which are not actually being build (in incremental builds) to NOT_BUILD (JENKINS-9072)
270 LOGGER.fine("Project " + e.getKey() + " needs not be build");
271
272 MavenBuildProxy2 proxy = e.getValue();
273 proxy.start();
274 proxy.setResult(Result.NOT_BUILT);
275 proxy.end();
276 }
277 }
278 }
279
280 /**
281 * @see org.apache.maven.execution.ExecutionListener#sessionEnded(org.apache.maven.execution.ExecutionEvent)
282 */
283 public void sessionEnded( ExecutionEvent event ) {
284 debug( "sessionEnded" );
285 this.eventLogger.sessionEnded( event );
286
287 Map<ModuleName, MavenProject> buildingProjects = getSessionProjects(event);
288
289 for (Entry<ModuleName,FilterImpl> e : fixNull(this.proxies.entrySet())) {
290 MavenProject project = buildingProjects.get(e.getKey());
291 if (project!=null) {
292 for (MavenReporter mavenReporter : reporters.get(e.getKey())) {
293 try {
294 mavenReporter.postBuild( e.getValue() ,project, maven3Builder.listener);
295 } catch ( InterruptedException x ) {
296 x.printStackTrace();
297 } catch ( IOException x ) {
298 x.printStackTrace();
299 }
300 }
301 }
302 }
303 }
304
305 /**
306 * All {@link MavenProject}s in the current session, keyed by their names.
307 */
308 private Map<ModuleName, MavenProject> getSessionProjects(ExecutionEvent event) {
309 List<MavenProject> projects = event.getSession().getProjects();
310 debug("Projects to build: " + projects);
311 Map<ModuleName,MavenProject> buildingProjects = new HashMap<ModuleName,MavenProject>();
312 for (MavenProject p : projects) {
313 buildingProjects.put(new ModuleName(p), p);
314 }
315 return buildingProjects;
316 }
317
318 /**
319 * @see org.apache.maven.execution.ExecutionListener#projectSkipped(org.apache.maven.execution.ExecutionEvent)
320 */
321 public void projectSkipped( ExecutionEvent event ) {
322 debug("projectSkipped " + gav(event.getProject()));
323 this.eventLogger.projectSkipped( event );
324 }
325
326 /**
327 * @see org.apache.maven.execution.ExecutionListener#projectStarted(org.apache.maven.execution.ExecutionEvent)
328 */
329 public void projectStarted( ExecutionEvent event ) {
330 debug( "projectStarted " + gav(event.getProject()));
331 recordProjectStarted(event);
332 this.eventLogger.projectStarted( event );
333
334 }
335
336 private void recordProjectStarted(ExecutionEvent event) {
337 MavenProject mavenProject = event.getProject();
338 List<MavenReporter> mavenReporters = getMavenReporters( mavenProject );
339
340 MavenBuildProxy2 mavenBuildProxy2 = getMavenBuildProxy2( mavenProject );
341 mavenBuildProxy2.start();
342
343
344 for (MavenReporter mavenReporter : fixNull(mavenReporters)) {
345 try {
346 mavenReporter.enterModule( mavenBuildProxy2 ,mavenProject, maven3Builder.listener);
347 } catch ( InterruptedException e ) {
348 e.printStackTrace();
349 } catch ( IOException e ) {
350 e.printStackTrace();
351 }
352 }
353 }
354
355 /**
356 * @see org.apache.maven.execution.ExecutionListener#projectSucceeded(org.apache.maven.execution.ExecutionEvent)
357 */
358 public void projectSucceeded( ExecutionEvent event ) {
359 debug( "projectSucceeded "+gav(event.getProject()));
360 recordProjectEnded(event,Result.SUCCESS);
361 this.eventLogger.projectSucceeded( event );
362 }
363
364 /**
365 * @see org.apache.maven.execution.ExecutionListener#projectFailed(org.apache.maven.execution.ExecutionEvent)
366 */
367 public void projectFailed( ExecutionEvent event ) {
368 debug("projectFailed " + gav(event.getProject()));
369 recordProjectEnded(event,Result.FAILURE);
370 this.eventLogger.projectFailed(event);
371 }
372
373 private void recordProjectEnded(ExecutionEvent event, Result result) {
374 MavenBuildProxy2 mavenBuildProxy2 = getMavenBuildProxy2( event.getProject() );
375 mavenBuildProxy2.setResult(result);
376
377 List<MavenReporter> mavenReporters = getMavenReporters( event.getProject() );
378
379 for ( MavenReporter mavenReporter : fixNull(mavenReporters)) {
380 try {
381 mavenReporter.leaveModule( mavenBuildProxy2, event.getProject(), maven3Builder.listener);
382 } catch ( InterruptedException e ) {
383 e.printStackTrace();
384 } catch ( IOException e ) {
385 e.printStackTrace();
386 }
387 }
388
389 mavenBuildProxy2.end();
390 }
391
392 /**
393 * @see org.apache.maven.execution.ExecutionListener#mojoSkipped(org.apache.maven.execution.ExecutionEvent)
394 */
395 public void mojoSkipped( ExecutionEvent event ) {
396 debug("mojoSkipped " + mojoExec(event));
397 this.eventLogger.mojoSkipped( event );
398 }
399
400 /**
401 * @see org.apache.maven.execution.ExecutionListener#mojoStarted(org.apache.maven.execution.ExecutionEvent)
402 */
403 public void mojoStarted( ExecutionEvent event ) {
404 debug("mojoStarted " + mojoExec(event));
405 recordMojoStarted(event);
406 this.eventLogger.mojoStarted( event );
407 }
408
409 private void recordMojoStarted(ExecutionEvent event) {
410 long startTime = initMojoStartTime( event.getProject() );
411
412 MavenProject mavenProject = event.getProject();
413 MojoInfo mojoInfo = new MojoInfo(event,startTime);
414
415 List<MavenReporter> mavenReporters = getMavenReporters( mavenProject );
416
417 MavenBuildProxy2 mavenBuildProxy2 = getMavenBuildProxy2( mavenProject );
418
419 for (MavenReporter mavenReporter : fixNull(mavenReporters)) {
420 try {
421 mavenReporter.preExecute( mavenBuildProxy2, mavenProject, mojoInfo, maven3Builder.listener);
422 } catch ( InterruptedException e ) {
423 e.printStackTrace();
424 } catch ( IOException e ) {
425 e.printStackTrace();
426 }
427 }
428 }
429
430 /**
431 * @see org.apache.maven.execution.ExecutionListener#mojoSucceeded(org.apache.maven.execution.ExecutionEvent)
432 */
433 public void mojoSucceeded( ExecutionEvent event ) {
434 debug("mojoSucceeded " + mojoExec(event));
435 recordMojoEnded(event,null);
436 this.eventLogger.mojoSucceeded( event );
437 }
438
439 private void recordMojoEnded(ExecutionEvent event, Exception problem) {
440 MavenProject mavenProject = event.getProject();
441 MojoInfo mojoInfo = new MojoInfo(event,getMojoStartTime(event.getProject()));
442
443 recordExecutionTime(event,mojoInfo);
444
445 List<MavenReporter> mavenReporters = getMavenReporters( mavenProject );
446
447 MavenBuildProxy2 mavenBuildProxy2 = getMavenBuildProxy2( mavenProject );
448
449 mavenBuildProxy2.setExecutedMojos( this.executedMojosPerModule.get( new ModuleName(event) ) );
450
451 for (MavenReporter mavenReporter : fixNull(mavenReporters)) {
452 try {
453 mavenReporter.postExecute( mavenBuildProxy2, mavenProject, mojoInfo, maven3Builder.listener, problem);
454 if (mavenReporter instanceof TestFailureDetector) {
455 if(((TestFailureDetector) mavenReporter).hasTestFailures()) {
456 hasTestFailures.compareAndSet(false, true);
457 }
458 }
459 } catch ( InterruptedException e ) {
460 e.printStackTrace();
461 } catch ( IOException e ) {
462 e.printStackTrace();
463 }
464 }
465 }
466
467 /**
468 * Record how long it took to run this mojo.
469 */
470 private void recordExecutionTime(ExecutionEvent event, MojoInfo mojoInfo) {
471 MavenProject p = event.getProject();
472 List<ExecutedMojo> m = executedMojosPerModule.get(new ModuleName(p));
473 if (m==null) // defensive check
474 executedMojosPerModule.put(new ModuleName(p), m=new CopyOnWriteArrayList<ExecutedMojo>());
475
476 Long startTime = getMojoStartTime( event.getProject() );
477 m.add(new ExecutedMojo( mojoInfo, startTime == null ? 0 : System.currentTimeMillis() - startTime ));
478 }
479
480 /**
481 * @see org.apache.maven.execution.ExecutionListener#mojoFailed(org.apache.maven.execution.ExecutionEvent)
482 */
483 public void mojoFailed( ExecutionEvent event ) {
484 debug("mojoFailed " + mojoExec(event));
485 recordMojoEnded(event, getExecutionException(event));
486 this.eventLogger.mojoFailed( event );
487 }
488
489 private void debug(String msg) {
490 LOGGER.fine(msg);
491 }
492
493
494 private Exception getExecutionException(ExecutionEvent event) {
495 // http://issues.jenkins-ci.org/browse/JENKINS-8493
496 // with maven 3.0.2 see http://jira.codehaus.org/browse/MNG-4922
497 // catch NoSuchMethodError if folks not using 3.0.2+
498 try {
499 return event.getException();
500 } catch (NoSuchMethodError e) {
501 return new MojoExecutionException(event.getMojoExecution()+" failed");
502 }
503 }
504
505 /**
506 * @see org.apache.maven.execution.ExecutionListener#forkStarted(org.apache.maven.execution.ExecutionEvent)
507 */
508 public void forkStarted( ExecutionEvent event ) {
509 LOGGER.fine("mojo forkStarted " + mojoExec(event));
510 recordMojoStarted(event);
511 }
512
513 /**
514 * @see org.apache.maven.execution.ExecutionListener#forkSucceeded(org.apache.maven.execution.ExecutionEvent)
515 */
516 public void forkSucceeded( ExecutionEvent event ) {
517 LOGGER.fine("mojo forkSucceeded " + mojoExec(event));
518 recordMojoEnded(event,null);
519 }
520
521 /**
522 * @see org.apache.maven.execution.ExecutionListener#forkFailed(org.apache.maven.execution.ExecutionEvent)
523 */
524 public void forkFailed( ExecutionEvent event ) {
525 LOGGER.fine("mojo forkFailed " + mojoExec(event));
526 recordMojoEnded(event, getExecutionException(event));
527 }
528
529 /*
530 Forked life cycle handling
531 --------------------------
532
533 As discussed in MavenBuildProxy2, Jenkins has a simplistic view of Maven build sequence,
534 and in particular it doesn't recognize the forked life cycle as a first-class citizen.
535 So to map the reality with the Jenkins' simplified model, we don't report forked project as
536 a separate module start/end.
537
538 Doing so would require that we remember the nesting, and when the forking is over, we need to
539 tell MavenBuildProxy2 of the right module that its build has resumed.
540 */
541
542 public void forkedProjectStarted( ExecutionEvent event ) {
543 debug("forkedProjectStarted " + gav(event.getProject()));
544 // recordProjectStarted(event);
545 this.eventLogger.forkedProjectStarted( event );
546 }
547
548 public void forkedProjectSucceeded( ExecutionEvent event ) {
549 debug("forkedProjectSucceeded " +gav(event.getProject()));
550 // recordProjectEnded(event,Result.SUCCESS);
551 this.eventLogger.forkedProjectSucceeded(event);
552 }
553
554 public void forkedProjectFailed( ExecutionEvent event ) {
555 debug("forkedProjectFailed " +gav(event.getProject()));
556 // recordProjectEnded(event,Result.FAILURE);
557 }
558
559 private String gav(MavenProject p) {
560 return String.format("%s:%s:%s", p.getGroupId(), p.getArtifactId(), p.getVersion());
561 }
562
563 private String mojoExec(ExecutionEvent event) {
564 MojoExecution me = event.getMojoExecution();
565 return String.format("%s:%s:%s(%s)", me.getGroupId(), me.getArtifactId(), me.getVersion(), me.getExecutionId());
566 }
567 }
568
569 public static boolean markAsSuccess;
570
571 private static final long serialVersionUID = 1L;
572
573 private static final Logger LOGGER = Logger.getLogger(Maven3Builder.class.getName());
574 }
575