001 package org.apache.maven.plugin.internal; 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 022 import java.io.BufferedInputStream; 023 import java.io.ByteArrayOutputStream; 024 import java.io.File; 025 import java.io.FileInputStream; 026 import java.io.IOException; 027 import java.io.InputStream; 028 import java.io.PrintStream; 029 import java.io.Reader; 030 import java.util.ArrayList; 031 import java.util.Collection; 032 import java.util.Collections; 033 import java.util.HashMap; 034 import java.util.Iterator; 035 import java.util.List; 036 import java.util.Map; 037 import java.util.jar.JarFile; 038 import java.util.zip.ZipEntry; 039 040 import org.apache.maven.RepositoryUtils; 041 import org.apache.maven.artifact.Artifact; 042 import org.apache.maven.classrealm.ClassRealmManager; 043 import org.apache.maven.execution.MavenSession; 044 import org.apache.maven.model.Plugin; 045 import org.apache.maven.monitor.logging.DefaultLog; 046 import org.apache.maven.plugin.ContextEnabled; 047 import org.apache.maven.plugin.DebugConfigurationListener; 048 import org.apache.maven.plugin.InvalidPluginDescriptorException; 049 import org.apache.maven.plugin.MavenPluginManager; 050 import org.apache.maven.plugin.MavenPluginValidator; 051 import org.apache.maven.plugin.Mojo; 052 import org.apache.maven.plugin.MojoExecution; 053 import org.apache.maven.plugin.MojoNotFoundException; 054 import org.apache.maven.plugin.PluginConfigurationException; 055 import org.apache.maven.plugin.PluginContainerException; 056 import org.apache.maven.plugin.PluginDescriptorCache; 057 import org.apache.maven.plugin.PluginDescriptorParsingException; 058 import org.apache.maven.plugin.PluginIncompatibleException; 059 import org.apache.maven.plugin.PluginParameterException; 060 import org.apache.maven.plugin.PluginParameterExpressionEvaluator; 061 import org.apache.maven.plugin.PluginRealmCache; 062 import org.apache.maven.plugin.PluginResolutionException; 063 import org.apache.maven.plugin.descriptor.MojoDescriptor; 064 import org.apache.maven.plugin.descriptor.Parameter; 065 import org.apache.maven.plugin.descriptor.PluginDescriptor; 066 import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder; 067 import org.apache.maven.project.MavenProject; 068 import org.apache.maven.rtinfo.RuntimeInformation; 069 import org.codehaus.plexus.PlexusContainer; 070 import org.codehaus.plexus.classworlds.realm.ClassRealm; 071 import org.codehaus.plexus.component.annotations.Component; 072 import org.codehaus.plexus.component.annotations.Requirement; 073 import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException; 074 import org.codehaus.plexus.component.configurator.ComponentConfigurationException; 075 import org.codehaus.plexus.component.configurator.ComponentConfigurator; 076 import org.codehaus.plexus.component.configurator.ConfigurationListener; 077 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; 078 import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; 079 import org.codehaus.plexus.component.repository.ComponentDescriptor; 080 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; 081 import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 082 import org.codehaus.plexus.configuration.PlexusConfiguration; 083 import org.codehaus.plexus.configuration.PlexusConfigurationException; 084 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; 085 import org.codehaus.plexus.logging.Logger; 086 import org.codehaus.plexus.util.IOUtil; 087 import org.codehaus.plexus.util.ReaderFactory; 088 import org.codehaus.plexus.util.StringUtils; 089 import org.codehaus.plexus.util.xml.Xpp3Dom; 090 import org.sonatype.aether.RepositorySystemSession; 091 import org.sonatype.aether.graph.DependencyFilter; 092 import org.sonatype.aether.graph.DependencyNode; 093 import org.sonatype.aether.repository.RemoteRepository; 094 import org.sonatype.aether.util.filter.AndDependencyFilter; 095 import org.sonatype.aether.util.graph.PreorderNodeListGenerator; 096 097 /** 098 * Provides basic services to manage Maven plugins and their mojos. This component is kept general in its design such 099 * that the plugins/mojos can be used in arbitrary contexts. In particular, the mojos can be used for ordinary build 100 * plugins as well as special purpose plugins like reports. 101 * 102 * @since 3.0 103 * @author Benjamin Bentmann 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 Map<String, ClassLoader> foreignImports = calcImports( project, parent, imports ); 303 304 PluginRealmCache.Key cacheKey = 305 pluginRealmCache.createKey( plugin, parent, foreignImports, filter, project.getRemotePluginRepositories(), 306 session.getRepositorySession() ); 307 308 PluginRealmCache.CacheRecord cacheRecord = pluginRealmCache.get( cacheKey ); 309 310 if ( cacheRecord != null ) 311 { 312 pluginDescriptor.setClassRealm( cacheRecord.realm ); 313 pluginDescriptor.setArtifacts( new ArrayList<Artifact>( cacheRecord.artifacts ) ); 314 for ( ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents() ) 315 { 316 componentDescriptor.setRealm( cacheRecord.realm ); 317 } 318 } 319 else 320 { 321 createPluginRealm( pluginDescriptor, session, parent, foreignImports, filter ); 322 323 cacheRecord = 324 pluginRealmCache.put( cacheKey, pluginDescriptor.getClassRealm(), pluginDescriptor.getArtifacts() ); 325 } 326 327 pluginRealmCache.register( project, cacheRecord ); 328 } 329 330 private void createPluginRealm( PluginDescriptor pluginDescriptor, MavenSession session, ClassLoader parent, 331 Map<String, ClassLoader> foreignImports, DependencyFilter filter ) 332 throws PluginResolutionException, PluginContainerException 333 { 334 Plugin plugin = pluginDescriptor.getPlugin(); 335 336 if ( plugin == null ) 337 { 338 throw new IllegalArgumentException( "incomplete plugin descriptor, plugin missing" ); 339 } 340 341 Artifact pluginArtifact = pluginDescriptor.getPluginArtifact(); 342 343 if ( pluginArtifact == null ) 344 { 345 throw new IllegalArgumentException( "incomplete plugin descriptor, plugin artifact missing" ); 346 } 347 348 MavenProject project = session.getCurrentProject(); 349 350 DependencyFilter dependencyFilter = project.getExtensionDependencyFilter(); 351 dependencyFilter = AndDependencyFilter.newInstance( dependencyFilter, filter ); 352 353 DependencyNode root = 354 pluginDependenciesResolver.resolve( plugin, RepositoryUtils.toArtifact( pluginArtifact ), dependencyFilter, 355 project.getRemotePluginRepositories(), session.getRepositorySession() ); 356 357 PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); 358 root.accept( nlg ); 359 360 List<Artifact> exposedPluginArtifacts = new ArrayList<Artifact>( nlg.getNodes().size() ); 361 RepositoryUtils.toArtifacts( exposedPluginArtifacts, Collections.singleton( root ), 362 Collections.<String> emptyList(), null ); 363 for ( Iterator<Artifact> it = exposedPluginArtifacts.iterator(); it.hasNext(); ) 364 { 365 Artifact artifact = it.next(); 366 if ( artifact.getFile() == null ) 367 { 368 it.remove(); 369 } 370 } 371 372 List<org.sonatype.aether.artifact.Artifact> pluginArtifacts = nlg.getArtifacts( true ); 373 374 ClassRealm pluginRealm = 375 classRealmManager.createPluginRealm( plugin, parent, null, foreignImports, pluginArtifacts ); 376 377 pluginDescriptor.setClassRealm( pluginRealm ); 378 pluginDescriptor.setArtifacts( exposedPluginArtifacts ); 379 380 try 381 { 382 for ( ComponentDescriptor<?> componentDescriptor : pluginDescriptor.getComponents() ) 383 { 384 componentDescriptor.setRealm( pluginRealm ); 385 container.addComponentDescriptor( componentDescriptor ); 386 } 387 388 container.discoverComponents( pluginRealm ); 389 } 390 catch ( PlexusConfigurationException e ) 391 { 392 throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin " 393 + plugin.getId() + ": " + e.getMessage(), e ); 394 } 395 catch ( CycleDetectedInComponentGraphException e ) 396 { 397 throw new PluginContainerException( plugin, pluginRealm, "Error in component graph of plugin " 398 + plugin.getId() + ": " + e.getMessage(), e ); 399 } 400 } 401 402 private Map<String, ClassLoader> calcImports( MavenProject project, ClassLoader parent, List<String> imports ) 403 { 404 Map<String, ClassLoader> foreignImports = new HashMap<String, ClassLoader>(); 405 406 ClassLoader projectRealm = project.getClassRealm(); 407 if ( projectRealm != null ) 408 { 409 foreignImports.put( "", projectRealm ); 410 } 411 else 412 { 413 foreignImports.put( "", classRealmManager.getMavenApiRealm() ); 414 } 415 416 if ( parent != null && imports != null ) 417 { 418 for ( String parentImport : imports ) 419 { 420 foreignImports.put( parentImport, parent ); 421 } 422 } 423 424 return foreignImports; 425 } 426 427 public <T> T getConfiguredMojo( Class<T> mojoInterface, MavenSession session, MojoExecution mojoExecution ) 428 throws PluginConfigurationException, PluginContainerException 429 { 430 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); 431 432 PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor(); 433 434 ClassRealm pluginRealm = pluginDescriptor.getClassRealm(); 435 436 if ( logger.isDebugEnabled() ) 437 { 438 logger.debug( "Configuring mojo " + mojoDescriptor.getId() + " from plugin realm " + pluginRealm ); 439 } 440 441 // We are forcing the use of the plugin realm for all lookups that might occur during 442 // the lifecycle that is part of the lookup. Here we are specifically trying to keep 443 // lookups that occur in contextualize calls in line with the right realm. 444 ClassRealm oldLookupRealm = container.setLookupRealm( pluginRealm ); 445 446 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 447 Thread.currentThread().setContextClassLoader( pluginRealm ); 448 449 try 450 { 451 T mojo; 452 453 try 454 { 455 mojo = container.lookup( mojoInterface, mojoDescriptor.getRoleHint() ); 456 } 457 catch ( ComponentLookupException e ) 458 { 459 Throwable cause = e.getCause(); 460 while ( cause != null && !( cause instanceof LinkageError ) 461 && !( cause instanceof ClassNotFoundException ) ) 462 { 463 cause = cause.getCause(); 464 } 465 466 if ( ( cause instanceof NoClassDefFoundError ) || ( cause instanceof ClassNotFoundException ) ) 467 { 468 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 469 PrintStream ps = new PrintStream( os ); 470 ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '" 471 + pluginDescriptor.getId() + "'. A required class is missing: " + cause.getMessage() ); 472 pluginRealm.display( ps ); 473 474 throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause ); 475 } 476 else if ( cause instanceof LinkageError ) 477 { 478 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 479 PrintStream ps = new PrintStream( os ); 480 ps.println( "Unable to load the mojo '" + mojoDescriptor.getGoal() + "' in the plugin '" 481 + pluginDescriptor.getId() + "' due to an API incompatibility: " + e.getClass().getName() 482 + ": " + cause.getMessage() ); 483 pluginRealm.display( ps ); 484 485 throw new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), cause ); 486 } 487 488 throw new PluginContainerException( mojoDescriptor, pluginRealm, "Unable to load the mojo '" 489 + mojoDescriptor.getGoal() + "' (or one of its required components) from the plugin '" 490 + pluginDescriptor.getId() + "'", e ); 491 } 492 493 if ( mojo instanceof ContextEnabled ) 494 { 495 MavenProject project = session.getCurrentProject(); 496 497 Map<String, Object> pluginContext = session.getPluginContext( pluginDescriptor, project ); 498 499 if ( pluginContext != null ) 500 { 501 pluginContext.put( "project", project ); 502 503 pluginContext.put( "pluginDescriptor", pluginDescriptor ); 504 505 ( (ContextEnabled) mojo ).setPluginContext( pluginContext ); 506 } 507 } 508 509 if ( mojo instanceof Mojo ) 510 { 511 ( (Mojo) mojo ).setLog( new DefaultLog( logger ) ); 512 } 513 514 Xpp3Dom dom = mojoExecution.getConfiguration(); 515 516 PlexusConfiguration pomConfiguration; 517 518 if ( dom == null ) 519 { 520 pomConfiguration = new XmlPlexusConfiguration( "configuration" ); 521 } 522 else 523 { 524 pomConfiguration = new XmlPlexusConfiguration( dom ); 525 } 526 527 ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); 528 529 populatePluginFields( mojo, mojoDescriptor, pluginRealm, pomConfiguration, expressionEvaluator ); 530 531 return mojo; 532 } 533 finally 534 { 535 Thread.currentThread().setContextClassLoader( oldClassLoader ); 536 container.setLookupRealm( oldLookupRealm ); 537 } 538 } 539 540 private void populatePluginFields( Object mojo, MojoDescriptor mojoDescriptor, ClassRealm pluginRealm, 541 PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator ) 542 throws PluginConfigurationException 543 { 544 ComponentConfigurator configurator = null; 545 546 String configuratorId = mojoDescriptor.getComponentConfigurator(); 547 548 if ( StringUtils.isEmpty( configuratorId ) ) 549 { 550 configuratorId = "basic"; 551 } 552 553 try 554 { 555 // TODO: could the configuration be passed to lookup and the configurator known to plexus via the descriptor 556 // so that this method could entirely be handled by a plexus lookup? 557 configurator = container.lookup( ComponentConfigurator.class, configuratorId ); 558 559 ConfigurationListener listener = new DebugConfigurationListener( logger ); 560 561 ValidatingConfigurationListener validator = 562 new ValidatingConfigurationListener( mojo, mojoDescriptor, listener ); 563 564 logger.debug( "Configuring mojo '" + mojoDescriptor.getId() + "' with " + configuratorId 565 + " configurator -->" ); 566 567 configurator.configureComponent( mojo, configuration, expressionEvaluator, pluginRealm, validator ); 568 569 logger.debug( "-- end configuration --" ); 570 571 Collection<Parameter> missingParameters = validator.getMissingParameters(); 572 if ( !missingParameters.isEmpty() ) 573 { 574 if ( "basic".equals( configuratorId ) ) 575 { 576 throw new PluginParameterException( mojoDescriptor, new ArrayList<Parameter>( missingParameters ) ); 577 } 578 else 579 { 580 /* 581 * NOTE: Other configurators like the map-oriented one don't call into the listener, so do it the 582 * hard way. 583 */ 584 validateParameters( mojoDescriptor, configuration, expressionEvaluator ); 585 } 586 } 587 } 588 catch ( ComponentConfigurationException e ) 589 { 590 String message = "Unable to parse configuration of mojo " + mojoDescriptor.getId(); 591 if ( e.getFailedConfiguration() != null ) 592 { 593 message += " for parameter " + e.getFailedConfiguration().getName(); 594 } 595 message += ": " + e.getMessage(); 596 597 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), message, e ); 598 } 599 catch ( ComponentLookupException e ) 600 { 601 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), 602 "Unable to retrieve component configurator " + configuratorId 603 + " for configuration of mojo " + mojoDescriptor.getId(), e ); 604 } 605 catch ( NoClassDefFoundError e ) 606 { 607 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 608 PrintStream ps = new PrintStream( os ); 609 ps.println( "A required class was missing during configuration of mojo " + mojoDescriptor.getId() + ": " 610 + e.getMessage() ); 611 pluginRealm.display( ps ); 612 613 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e ); 614 } 615 catch ( LinkageError e ) 616 { 617 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 618 PrintStream ps = new PrintStream( os ); 619 ps.println( "An API incompatibility was encountered during configuration of mojo " + mojoDescriptor.getId() 620 + ": " + e.getClass().getName() + ": " + e.getMessage() ); 621 pluginRealm.display( ps ); 622 623 throw new PluginConfigurationException( mojoDescriptor.getPluginDescriptor(), os.toString(), e ); 624 } 625 finally 626 { 627 if ( configurator != null ) 628 { 629 try 630 { 631 container.release( configurator ); 632 } 633 catch ( ComponentLifecycleException e ) 634 { 635 logger.debug( "Failed to release mojo configurator - ignoring." ); 636 } 637 } 638 } 639 } 640 641 private void validateParameters( MojoDescriptor mojoDescriptor, PlexusConfiguration configuration, 642 ExpressionEvaluator expressionEvaluator ) 643 throws ComponentConfigurationException, PluginParameterException 644 { 645 if ( mojoDescriptor.getParameters() == null ) 646 { 647 return; 648 } 649 650 List<Parameter> invalidParameters = new ArrayList<Parameter>(); 651 652 for ( Parameter parameter : mojoDescriptor.getParameters() ) 653 { 654 if ( !parameter.isRequired() ) 655 { 656 continue; 657 } 658 659 Object value = null; 660 661 PlexusConfiguration config = configuration.getChild( parameter.getName(), false ); 662 if ( config != null ) 663 { 664 String expression = config.getValue( null ); 665 666 try 667 { 668 value = expressionEvaluator.evaluate( expression ); 669 670 if ( value == null ) 671 { 672 value = config.getAttribute( "default-value", null ); 673 } 674 } 675 catch ( ExpressionEvaluationException e ) 676 { 677 String msg = 678 "Error evaluating the expression '" + expression + "' for configuration value '" 679 + configuration.getName() + "'"; 680 throw new ComponentConfigurationException( configuration, msg, e ); 681 } 682 } 683 684 if ( value == null && ( config == null || config.getChildCount() <= 0 ) ) 685 { 686 invalidParameters.add( parameter ); 687 } 688 } 689 690 if ( !invalidParameters.isEmpty() ) 691 { 692 throw new PluginParameterException( mojoDescriptor, invalidParameters ); 693 } 694 } 695 696 public void releaseMojo( Object mojo, MojoExecution mojoExecution ) 697 { 698 if ( mojo != null ) 699 { 700 try 701 { 702 container.release( mojo ); 703 } 704 catch ( ComponentLifecycleException e ) 705 { 706 String goalExecId = mojoExecution.getGoal(); 707 708 if ( mojoExecution.getExecutionId() != null ) 709 { 710 goalExecId += " {execution: " + mojoExecution.getExecutionId() + "}"; 711 } 712 713 logger.debug( "Error releasing mojo for " + goalExecId, e ); 714 } 715 } 716 } 717 718 }