1 package org.apache.maven.plugin.internal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintStream;
29 import java.io.Reader;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.jar.JarFile;
38 import java.util.zip.ZipEntry;
39
40 import org.apache.maven.RepositoryUtils;
41 import org.apache.maven.artifact.Artifact;
42 import org.apache.maven.classrealm.ClassRealmManager;
43 import org.apache.maven.execution.MavenSession;
44 import org.apache.maven.model.Plugin;
45 import org.apache.maven.monitor.logging.DefaultLog;
46 import org.apache.maven.plugin.ContextEnabled;
47 import org.apache.maven.plugin.DebugConfigurationListener;
48 import org.apache.maven.plugin.InvalidPluginDescriptorException;
49 import org.apache.maven.plugin.MavenPluginManager;
50 import org.apache.maven.plugin.MavenPluginValidator;
51 import org.apache.maven.plugin.Mojo;
52 import org.apache.maven.plugin.MojoExecution;
53 import org.apache.maven.plugin.MojoNotFoundException;
54 import org.apache.maven.plugin.PluginConfigurationException;
55 import org.apache.maven.plugin.PluginContainerException;
56 import org.apache.maven.plugin.PluginDescriptorCache;
57 import org.apache.maven.plugin.PluginDescriptorParsingException;
58 import org.apache.maven.plugin.PluginIncompatibleException;
59 import org.apache.maven.plugin.PluginParameterException;
60 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
61 import org.apache.maven.plugin.PluginRealmCache;
62 import org.apache.maven.plugin.PluginResolutionException;
63 import org.apache.maven.plugin.descriptor.MojoDescriptor;
64 import org.apache.maven.plugin.descriptor.Parameter;
65 import org.apache.maven.plugin.descriptor.PluginDescriptor;
66 import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
67 import org.apache.maven.project.MavenProject;
68 import org.apache.maven.rtinfo.RuntimeInformation;
69 import org.codehaus.plexus.PlexusContainer;
70 import org.codehaus.plexus.classworlds.realm.ClassRealm;
71 import org.codehaus.plexus.component.annotations.Component;
72 import org.codehaus.plexus.component.annotations.Requirement;
73 import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
74 import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
75 import org.codehaus.plexus.component.configurator.ComponentConfigurator;
76 import org.codehaus.plexus.component.configurator.ConfigurationListener;
77 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
78 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
79 import org.codehaus.plexus.component.repository.ComponentDescriptor;
80 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
81 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
82 import org.codehaus.plexus.configuration.PlexusConfiguration;
83 import org.codehaus.plexus.configuration.PlexusConfigurationException;
84 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
85 import org.codehaus.plexus.logging.Logger;
86 import org.codehaus.plexus.util.IOUtil;
87 import org.codehaus.plexus.util.ReaderFactory;
88 import org.codehaus.plexus.util.StringUtils;
89 import org.codehaus.plexus.util.xml.Xpp3Dom;
90 import org.sonatype.aether.RepositorySystemSession;
91 import org.sonatype.aether.graph.DependencyFilter;
92 import org.sonatype.aether.graph.DependencyNode;
93 import org.sonatype.aether.repository.RemoteRepository;
94 import org.sonatype.aether.util.filter.AndDependencyFilter;
95 import org.sonatype.aether.util.graph.PreorderNodeListGenerator;
96
97
98
99
100
101
102
103
104
105 @Component( role = MavenPluginManager.class )
106 public class DefaultMavenPluginManager
107 implements MavenPluginManager
108 {
109
110 @Requirement
111 private Logger logger;
112
113 @Requirement
114 private PlexusContainer container;
115
116 @Requirement
117 private ClassRealmManager classRealmManager;
118
119 @Requirement
120 private PluginDescriptorCache pluginDescriptorCache;
121
122 @Requirement
123 private PluginRealmCache pluginRealmCache;
124
125 @Requirement
126 private PluginDependenciesResolver pluginDependenciesResolver;
127
128 @Requirement
129 private RuntimeInformation runtimeInformation;
130
131 private PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
132
133 public synchronized PluginDescriptor getPluginDescriptor( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session )
134 throws PluginResolutionException, PluginDescriptorParsingException, InvalidPluginDescriptorException
135 {
136 PluginDescriptorCache.Key cacheKey = pluginDescriptorCache.createKey( plugin, repositories, session );
137
138 PluginDescriptor pluginDescriptor = pluginDescriptorCache.get( cacheKey );
139
140 if ( pluginDescriptor == null )
141 {
142 org.sonatype.aether.artifact.Artifact artifact =
143 pluginDependenciesResolver.resolve( plugin, repositories, session );
144
145 Artifact pluginArtifact = RepositoryUtils.toArtifact( artifact );
146
147 pluginDescriptor = extractPluginDescriptor( pluginArtifact, plugin );
148
149 pluginDescriptor.setRequiredMavenVersion( artifact.getProperty( "requiredMavenVersion", null ) );
150
151 pluginDescriptorCache.put( cacheKey, pluginDescriptor );
152 }
153
154 pluginDescriptor.setPlugin( plugin );
155
156 return pluginDescriptor;
157 }
158
159 private PluginDescriptor extractPluginDescriptor( Artifact pluginArtifact, Plugin plugin )
160 throws PluginDescriptorParsingException, InvalidPluginDescriptorException
161 {
162 PluginDescriptor pluginDescriptor = null;
163
164 File pluginFile = pluginArtifact.getFile();
165
166 try
167 {
168 if ( pluginFile.isFile() )
169 {
170 JarFile pluginJar = new JarFile( pluginFile, false );
171 try
172 {
173 ZipEntry pluginDescriptorEntry = pluginJar.getEntry( getPluginDescriptorLocation() );
174
175 if ( pluginDescriptorEntry != null )
176 {
177 InputStream is = pluginJar.getInputStream( pluginDescriptorEntry );
178
179 pluginDescriptor = parsePluginDescriptor( is, plugin, pluginFile.getAbsolutePath() );
180 }
181 }
182 finally
183 {
184 pluginJar.close();
185 }
186 }
187 else
188 {
189 File pluginXml = new File( pluginFile, getPluginDescriptorLocation() );
190
191 if ( pluginXml.isFile() )
192 {
193 InputStream is = new BufferedInputStream( new FileInputStream( pluginXml ) );
194 try
195 {
196 pluginDescriptor = parsePluginDescriptor( is, plugin, pluginXml.getAbsolutePath() );
197 }
198 finally
199 {
200 IOUtil.close( is );
201 }
202 }
203 }
204
205 if ( pluginDescriptor == null )
206 {
207 throw new IOException( "No plugin descriptor found at " + getPluginDescriptorLocation() );
208 }
209 }
210 catch ( IOException e )
211 {
212 throw new PluginDescriptorParsingException( plugin, pluginFile.getAbsolutePath(), e );
213 }
214
215 MavenPluginValidator validator = new MavenPluginValidator( pluginArtifact );
216
217 validator.validate( pluginDescriptor );
218
219 if ( validator.hasErrors() )
220 {
221 throw new InvalidPluginDescriptorException( "Invalid plugin descriptor for " + plugin.getId() + " ("
222 + pluginFile + ")", validator.getErrors() );
223 }
224
225 pluginDescriptor.setPluginArtifact( pluginArtifact );
226
227 return pluginDescriptor;
228 }
229
230 private String getPluginDescriptorLocation()
231 {
232 return "META-INF/maven/plugin.xml";
233 }
234
235 private PluginDescriptor parsePluginDescriptor( InputStream is, Plugin plugin, String descriptorLocation )
236 throws PluginDescriptorParsingException
237 {
238 try
239 {
240 Reader reader = ReaderFactory.newXmlReader( is );
241
242 PluginDescriptor pluginDescriptor = builder.build( reader, descriptorLocation );
243
244 return pluginDescriptor;
245 }
246 catch ( IOException e )
247 {
248 throw new PluginDescriptorParsingException( plugin, descriptorLocation, e );
249 }
250 catch ( PlexusConfigurationException e )
251 {
252 throw new PluginDescriptorParsingException( plugin, descriptorLocation, e );
253 }
254 }
255
256 public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List<RemoteRepository> repositories,
257 RepositorySystemSession session )
258 throws MojoNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
259 InvalidPluginDescriptorException
260 {
261 PluginDescriptor pluginDescriptor = getPluginDescriptor( plugin, repositories, session );
262
263 MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( goal );
264
265 if ( mojoDescriptor == null )
266 {
267 throw new MojoNotFoundException( goal, pluginDescriptor );
268 }
269
270 return mojoDescriptor;
271 }
272
273 public void checkRequiredMavenVersion( PluginDescriptor pluginDescriptor )
274 throws PluginIncompatibleException
275 {
276 String requiredMavenVersion = pluginDescriptor.getRequiredMavenVersion();
277 if ( StringUtils.isNotBlank( requiredMavenVersion ) )
278 {
279 try
280 {
281 if ( !runtimeInformation.isMavenVersion( requiredMavenVersion ) )
282 {
283 throw new PluginIncompatibleException( pluginDescriptor.getPlugin(), "The plugin "
284 + pluginDescriptor.getId() + " requires Maven version " + requiredMavenVersion );
285 }
286 }
287 catch ( RuntimeException e )
288 {
289 logger.warn( "Could not verify plugin's Maven prerequisite: " + e.getMessage() );
290 }
291 }
292 }
293
294 public synchronized void setupPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session,
295 ClassLoader parent, List<String> imports, DependencyFilter filter )
296 throws PluginResolutionException, PluginContainerException
297 {
298 Plugin plugin = pluginDescriptor.getPlugin();
299
300 MavenProject project = session.getCurrentProject();
301
302 PluginRealmCache.Key cacheKey =
303 pluginRealmCache.createKey( plugin, parent, imports, filter, project.getRemotePluginRepositories(),
304 session.getRepositorySession() );
305
306 PluginRealmCache.CacheRecord cacheRecord = pluginRealmCache.get( cacheKey );
307
308 if ( cacheRecord != null )
309 {
310 pluginDescriptor.setClassRealm( cacheRecord.realm );
311 pluginDescriptor.setArtifacts( new ArrayList<Artifact>( cacheRecord.artifacts ) );
312 }
313 else
314 {
315 createPluginRealm( pluginDescriptor, session, parent, imports, filter );
316
317 cacheRecord =
318 pluginRealmCache.put( cacheKey, pluginDescriptor.getClassRealm(), pluginDescriptor.getArtifacts() );
319 }
320
321 pluginRealmCache.register( project, cacheRecord );
322 }
323
324 private void createPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent,
325 List<String> imports, DependencyFilter filter )
326 throws PluginResolutionException, PluginContainerException
327 {
328 Plugin plugin = pluginDescriptor.getPlugin();
329
330 if ( plugin == null )
331 {
332 throw new IllegalArgumentException( "incomplete plugin descriptor, plugin missing" );
333 }
334
335 Artifact pluginArtifact = pluginDescriptor.getPluginArtifact();
336
337 if ( pluginArtifact == null )
338 {
339 throw new IllegalArgumentException( "incomplete plugin descriptor, plugin artifact missing" );
340 }
341
342 MavenProject project = session.getCurrentProject();
343
344 DependencyFilter dependencyFilter = project.getExtensionDependencyFilter();
345 dependencyFilter = AndDependencyFilter.newInstance( dependencyFilter, filter );
346
347 DependencyNode root =
348 pluginDependenciesResolver.resolve( plugin, RepositoryUtils.toArtifact( pluginArtifact ), dependencyFilter,
349 project.getRemotePluginRepositories(), session.getRepositorySession() );
350
351 PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
352 root.accept( nlg );
353
354 List<Artifact> exposedPluginArtifacts = new ArrayList<Artifact>( nlg.getNodes().size() );
355 RepositoryUtils.toArtifacts( exposedPluginArtifacts, Collections.singleton( root ),
356 Collections.<String> emptyList(), null );
357 for ( Iterator<Artifact> it = exposedPluginArtifacts.iterator(); it.hasNext(); )
358 {
359 Artifact artifact = it.next();
360 if ( artifact.getFile() == null )
361 {
362 it.remove();
363 }
364 }
365
366 List<org.sonatype.aether.artifact.Artifact> pluginArtifacts = nlg.getArtifacts( true );
367
368 Map<String, ClassLoader> foreignImports = calcImports( project, parent, imports );
369
370 ClassRealm pluginRealm =
371 classRealmManager.createPluginRealm( plugin, parent, null, foreignImports, pluginArtifacts );
372
373 pluginDescriptor.setClassRealm( pluginRealm );
374 pluginDescriptor.setArtifacts( exposedPluginArtifacts );
375
376 try
377 {
378 for ( ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents() )
379 {
380 componentDescriptor.setRealm( pluginRealm );
381 container.addComponentDescriptor( componentDescriptor );
382 }
383
384 container.discoverComponents( pluginRealm );
385 }
386 catch ( PlexusConfigurationException e )
387 {
388 throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin "
389 + plugin.getId() + ": " + e.getMessage(), e );
390 }
391 catch ( CycleDetectedInComponentGraphException e )
392 {
393 throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin "
394 + plugin.getId() + ": " + e.getMessage(), e );
395 }
396 }
397
398 private Map<String, ClassLoader> calcImports( MavenProject project, ClassLoader parent, List<String> imports )
399 {
400 Map<String, ClassLoader> foreignImports = new HashMap<String, ClassLoader>();
401
402 ClassLoader projectRealm = project.getClassRealm();
403 if ( projectRealm != null )
404 {
405 foreignImports.put( "", projectRealm );
406 }
407 else
408 {
409 foreignImports.put( "", classRealmManager.getMavenApiRealm() );
410 }
411
412 if ( parent != null && imports != null )
413 {
414 for ( String parentImport : imports )
415 {
416 foreignImports.put( parentImport, parent );
417 }
418 }
419
420 return foreignImports;
421 }
422
423 public <T> T getConfiguredMojo( Class<T> mojoInterface, MavenSession session, MojoExecution mojoExecution )
424 throws PluginConfigurationException, PluginContainerException
425 {
426 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
427
428 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor();
429
430 ClassRealm pluginRealm = pluginDescriptor.getClassRealm();
431
432 if ( logger.isDebugEnabled() )
433 {
434 logger.debug( "Configuring mojo " + mojoDescriptor.getId() + " from plugin realm " + pluginRealm );
435 }
436
437
438
439
440 ClassRealm oldLookupRealm = container.setLookupRealm( pluginRealm );
441
442 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
443 Thread.currentThread().setContextClassLoader( pluginRealm );
444
445 try
446 {
447 T mojo;
448
449 try
450 {
451 mojo = container.lookup( mojoInterface, mojoDescriptor.getRoleHint() );
452 }
453 catch ( ComponentLookupException e )
454 {
455 Throwable cause = e.getCause();
456 while ( cause != null && !( cause instanceof LinkageError )
457 && !( cause instanceof ClassNotFoundException ) )
458 {
459 cause = cause.getCause();
460 }
461
462 if ( ( cause instanceof NoClassDefFoundError ) || ( cause instanceof ClassNotFoundException ) )
463 {
464 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 );
465 PrintStream ps = new PrintStream( os );
466 ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
467 + pluginDescriptor.getId() + "'. A required class is missing: " + cause.getMessage() );
468 pluginRealm.display( ps );
469
470 throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause );
471 }
472 else if ( cause instanceof LinkageError )
473 {
474 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 );
475 PrintStream ps = new PrintStream( os );
476 ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '"
477 + pluginDescriptor.getId() + "' due to an API incompatibility: " + e.getClass().getName()
478 + ": " + cause.getMessage() );
479 pluginRealm.display( ps );
480
481 throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause );
482 }
483
484 throw new PluginContainerException( mojoDescriptor, pluginRealm, "Unable to load the mojo '"
485 + mojoDescriptor.getGoal() + "' (or one of its required components) from the plugin '"
486 + pluginDescriptor.getId() + "'", e );
487 }
488
489 if ( mojo instanceof ContextEnabled )
490 {
491 MavenProject project = session.getCurrentProject();
492
493 Map<String, Object> pluginContext = session.getPluginContext( pluginDescriptor, project );
494
495 if ( pluginContext != null )
496 {
497 pluginContext.put( "project", project );
498
499 pluginContext.put( "pluginDescriptor", pluginDescriptor );
500
501 ( (ContextEnabled) mojo ).setPluginContext( pluginContext );
502 }
503 }
504
505 if ( mojo instanceof Mojo )
506 {
507 ( (Mojo) mojo ).setLog( new DefaultLog( logger ) );
508 }
509
510 Xpp3Dom dom = mojoExecution.getConfiguration();
511
512 PlexusConfiguration pomConfiguration;
513
514 if ( dom == null )
515 {
516 pomConfiguration = new XmlPlexusConfiguration( "configuration" );
517 }
518 else
519 {
520 pomConfiguration = new XmlPlexusConfiguration( dom );
521 }
522
523 ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution );
524
525 populatePluginFields( mojo, mojoDescriptor, pluginRealm, pomConfiguration, expressionEvaluator );
526
527 return mojo;
528 }
529 finally
530 {
531 Thread.currentThread().setContextClassLoader( oldClassLoader );
532 container.setLookupRealm( oldLookupRealm );
533 }
534 }
535
536 private void populatePluginFields( Object mojo, MojoDescriptor mojoDescriptor, ClassRealm pluginRealm,
537 PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator )
538 throws PluginConfigurationException
539 {
540 ComponentConfigurator configurator = null;
541
542 String configuratorId = mojoDescriptor.getComponentConfigurator();
543
544 if ( StringUtils.isEmpty( configuratorId ) )
545 {
546 configuratorId = "basic";
547 }
548
549 try
550 {
551
552
553 configurator = container.lookup( ComponentConfigurator.class, configuratorId );
554
555 ConfigurationListener listener = new DebugConfigurationListener( logger );
556
557 ValidatingConfigurationListener validator =
558 new ValidatingConfigurationListener( mojo, mojoDescriptor, listener );
559
560 logger.debug( "Configuring mojo '" + mojoDescriptor.getId() + "' with " + configuratorId
561 + " configurator -->" );
562
563 configurator.configureComponent( mojo, configuration, expressionEvaluator, pluginRealm, validator );
564
565 logger.debug( "-- end configuration --" );
566
567 Collection<Parameter> missingParameters = validator.getMissingParameters();
568 if ( !missingParameters.isEmpty() )
569 {
570 if ( "basic".equals( configuratorId ) )
571 {
572 throw new PluginParameterException( mojoDescriptor, new ArrayList<Parameter>( missingParameters ) );
573 }
574 else
575 {
576
577
578
579
580 validateParameters( mojoDescriptor, configuration, expressionEvaluator );
581 }
582 }
583 }
584 catch ( ComponentConfigurationException e )
585 {
586 String message = "Unable to parse configuration of mojo " + mojoDescriptor.getId();
587 if ( e.getFailedConfiguration() != null )
588 {
589 message += " for parameter " + e.getFailedConfiguration().getName();
590 }
591 message += ": " + e.getMessage();
592
593 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), message, e );
594 }
595 catch ( ComponentLookupException e )
596 {
597 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(),
598 "Unable to retrieve component configurator " + configuratorId
599 + " for configuration of mojo " + mojoDescriptor.getId(), e );
600 }
601 catch ( NoClassDefFoundError e )
602 {
603 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 );
604 PrintStream ps = new PrintStream( os );
605 ps.println( "A required class was missing during configuration of mojo " + mojoDescriptor.getId() + ": "
606 + e.getMessage() );
607 pluginRealm.display( ps );
608
609 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e );
610 }
611 catch ( LinkageError e )
612 {
613 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 );
614 PrintStream ps = new PrintStream( os );
615 ps.println( "An API incompatibility was encountered during configuration of mojo " + mojoDescriptor.getId()
616 + ": " + e.getClass().getName() + ": " + e.getMessage() );
617 pluginRealm.display( ps );
618
619 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e );
620 }
621 finally
622 {
623 if ( configurator != null )
624 {
625 try
626 {
627 container.release( configurator );
628 }
629 catch ( ComponentLifecycleException e )
630 {
631 logger.debug( "Failed to release mojo configurator - ignoring." );
632 }
633 }
634 }
635 }
636
637 private void validateParameters( MojoDescriptor mojoDescriptor, PlexusConfiguration configuration,
638 ExpressionEvaluator expressionEvaluator )
639 throws ComponentConfigurationException, PluginParameterException
640 {
641 if ( mojoDescriptor.getParameters() == null )
642 {
643 return;
644 }
645
646 List<Parameter> invalidParameters = new ArrayList<Parameter>();
647
648 for ( Parameter parameter : mojoDescriptor.getParameters() )
649 {
650 if ( !parameter.isRequired() )
651 {
652 continue;
653 }
654
655 Object value = null;
656
657 PlexusConfiguration config = configuration.getChild( parameter.getName(), false );
658 if ( config != null )
659 {
660 String expression = config.getValue( null );
661
662 try
663 {
664 value = expressionEvaluator.evaluate( expression );
665
666 if ( value == null )
667 {
668 value = config.getAttribute( "default-value", null );
669 }
670 }
671 catch ( ExpressionEvaluationException e )
672 {
673 String msg =
674 "Error evaluating the expression '" + expression + "' for configuration value '"
675 + configuration.getName() + "'";
676 throw new ComponentConfigurationException( configuration, msg, e );
677 }
678 }
679
680 if ( value == null && ( config == null || config.getChildCount() <= 0 ) )
681 {
682 invalidParameters.add( parameter );
683 }
684 }
685
686 if ( !invalidParameters.isEmpty() )
687 {
688 throw new PluginParameterException( mojoDescriptor, invalidParameters );
689 }
690 }
691
692 public void releaseMojo( Object mojo, MojoExecution mojoExecution )
693 {
694 if ( mojo != null )
695 {
696 try
697 {
698 container.release( mojo );
699 }
700 catch ( ComponentLifecycleException e )
701 {
702 String goalExecId = mojoExecution.getGoal();
703
704 if ( mojoExecution.getExecutionId() != null )
705 {
706 goalExecId += " {execution: " + mojoExecution.getExecutionId() + "}";
707 }
708
709 logger.debug( "Error releasing mojo for " + goalExecId, e );
710 }
711 }
712 }
713
714 }