001 package org.apache.maven.plugin; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license 005 * agreements. See the NOTICE file distributed with this work for additional information regarding 006 * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance with the License. You may obtain a 008 * copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed under the License 013 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 014 * or implied. See the License for the specific language governing permissions and limitations under 015 * the License. 016 */ 017 018 import java.io.ByteArrayOutputStream; 019 import java.io.PrintStream; 020 import java.util.List; 021 022 import org.apache.maven.execution.MavenSession; 023 import org.apache.maven.model.Plugin; 024 import org.apache.maven.plugin.descriptor.MojoDescriptor; 025 import org.apache.maven.plugin.descriptor.PluginDescriptor; 026 import org.apache.maven.project.MavenProject; 027 import org.codehaus.plexus.classworlds.realm.ClassRealm; 028 import org.codehaus.plexus.component.annotations.Component; 029 import org.codehaus.plexus.component.annotations.Requirement; 030 import org.sonatype.aether.RepositorySystemSession; 031 import org.sonatype.aether.repository.RemoteRepository; 032 033 // TODO: the antrun plugin has its own configurator, the only plugin that does. might need to think about how that works 034 // TODO: remove the coreArtifactFilterManager 035 036 @Component(role = BuildPluginManager.class) 037 public class DefaultBuildPluginManager 038 implements BuildPluginManager 039 { 040 041 @Requirement 042 private MavenPluginManager mavenPluginManager; 043 044 @Requirement 045 private LegacySupport legacySupport; 046 047 /** 048 * 049 * @param plugin 050 * @param repositoryRequest 051 * @return PluginDescriptor The component descriptor for the Maven plugin. 052 * @throws PluginNotFoundException The plugin could not be found in any repositories. 053 * @throws PluginResolutionException The plugin could be found but could not be resolved. 054 * @throws InvalidPluginDescriptorException 055 */ 056 public PluginDescriptor loadPlugin( Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session ) 057 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, InvalidPluginDescriptorException 058 { 059 return mavenPluginManager.getPluginDescriptor( plugin, repositories, session ); 060 } 061 062 // ---------------------------------------------------------------------- 063 // Mojo execution 064 // ---------------------------------------------------------------------- 065 066 public void executeMojo( MavenSession session, MojoExecution mojoExecution ) 067 throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException 068 { 069 MavenProject project = session.getCurrentProject(); 070 071 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); 072 073 Mojo mojo = null; 074 075 ClassRealm pluginRealm; 076 try 077 { 078 pluginRealm = getPluginRealm( session, mojoDescriptor.getPluginDescriptor() ); 079 } 080 catch ( PluginResolutionException e ) 081 { 082 throw new PluginExecutionException( mojoExecution, project, e ); 083 } 084 085 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 086 Thread.currentThread().setContextClassLoader( pluginRealm ); 087 088 MavenSession oldSession = legacySupport.getSession(); 089 090 try 091 { 092 mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); 093 094 legacySupport.setSession( session ); 095 096 // NOTE: DuplicateArtifactAttachmentException is currently unchecked, so be careful removing this try/catch! 097 // This is necessary to avoid creating compatibility problems for existing plugins that use 098 // MavenProjectHelper.attachArtifact(..). 099 try 100 { 101 mojo.execute(); 102 } 103 catch ( ClassCastException e ) 104 { 105 // to be processed in the outer catch block 106 throw e; 107 } 108 catch ( RuntimeException e ) 109 { 110 throw new PluginExecutionException( mojoExecution, project, e ); 111 } 112 } 113 catch ( PluginContainerException e ) 114 { 115 throw new PluginExecutionException( mojoExecution, project, e ); 116 } 117 catch ( NoClassDefFoundError e ) 118 { 119 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 120 PrintStream ps = new PrintStream( os ); 121 ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " 122 + e.getMessage() ); 123 pluginRealm.display( ps ); 124 125 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 126 127 throw new PluginExecutionException( mojoExecution, project, wrapper ); 128 } 129 catch ( LinkageError e ) 130 { 131 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 132 PrintStream ps = new PrintStream( os ); 133 ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " 134 + e.getClass().getName() + ": " + e.getMessage() ); 135 pluginRealm.display( ps ); 136 137 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 138 139 throw new PluginExecutionException( mojoExecution, project, wrapper ); 140 } 141 catch ( ClassCastException e ) 142 { 143 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 144 PrintStream ps = new PrintStream( os ); 145 ps.println( "A type incompatibility occured while executing " + mojoDescriptor.getId() + ": " 146 + e.getMessage() ); 147 pluginRealm.display( ps ); 148 149 throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); 150 } 151 finally 152 { 153 mavenPluginManager.releaseMojo( mojo, mojoExecution ); 154 155 Thread.currentThread().setContextClassLoader( oldClassLoader ); 156 157 legacySupport.setSession( oldSession ); 158 } 159 } 160 161 /** 162 * TODO pluginDescriptor classRealm and artifacts are set as a side effect of this 163 * call, which is not nice. 164 * @throws PluginResolutionException 165 */ 166 public ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor ) 167 throws PluginResolutionException, PluginManagerException 168 { 169 ClassRealm pluginRealm = pluginDescriptor.getClassRealm(); 170 if ( pluginRealm != null ) 171 { 172 return pluginRealm; 173 } 174 175 mavenPluginManager.setupPluginRealm( pluginDescriptor, session, null, null, null ); 176 177 return pluginDescriptor.getClassRealm(); 178 } 179 180 public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List<RemoteRepository> repositories, 181 RepositorySystemSession session ) 182 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, 183 MojoNotFoundException, InvalidPluginDescriptorException 184 { 185 return mavenPluginManager.getMojoDescriptor( plugin, goal, repositories, session ); 186 } 187 188 }