001package org.apache.maven.plugin; 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 022import java.io.ByteArrayOutputStream; 023import java.io.PrintStream; 024import java.util.List; 025 026import org.apache.maven.execution.MavenSession; 027import org.apache.maven.execution.MojoExecutionEvent; 028import org.apache.maven.execution.MojoExecutionListener; 029import org.apache.maven.execution.scope.internal.MojoExecutionScope; 030import org.apache.maven.model.Plugin; 031import org.apache.maven.plugin.descriptor.MojoDescriptor; 032import org.apache.maven.plugin.descriptor.PluginDescriptor; 033import org.apache.maven.project.MavenProject; 034import org.codehaus.plexus.classworlds.realm.ClassRealm; 035import org.codehaus.plexus.component.annotations.Component; 036import org.codehaus.plexus.component.annotations.Requirement; 037import org.eclipse.aether.RepositorySystemSession; 038import org.eclipse.aether.repository.RemoteRepository; 039 040// TODO: the antrun plugin has its own configurator, the only plugin that does. might need to think about how that works 041// TODO: remove the coreArtifactFilterManager 042 043@Component( role = BuildPluginManager.class ) 044public class DefaultBuildPluginManager 045 implements BuildPluginManager 046{ 047 048 @Requirement 049 private MavenPluginManager mavenPluginManager; 050 051 @Requirement 052 private LegacySupport legacySupport; 053 054 @Requirement 055 private MojoExecutionScope scope; 056 057 private MojoExecutionListener mojoExecutionListener; 058 059 // this tricks plexus-component-metadata generate required metadata 060 @Requirement( role = MojoExecutionListener.class ) 061 private List<MojoExecutionListener> mojoExecutionListeners; 062 063 public void setMojoExecutionListeners( final List<MojoExecutionListener> listeners ) 064 { 065 this.mojoExecutionListeners = listeners; 066 this.mojoExecutionListener = new CompoundMojoExecutionListener( listeners ); 067 } 068 069 /** 070 * @param plugin 071 * @param repositories 072 * @param session 073 * @return PluginDescriptor The component descriptor for the Maven plugin. 074 * @throws PluginNotFoundException The plugin could not be found in any repositories. 075 * @throws PluginResolutionException The plugin could be found but could not be resolved. 076 * @throws InvalidPluginDescriptorException 077 */ 078 public PluginDescriptor loadPlugin( Plugin plugin, List<RemoteRepository> repositories, 079 RepositorySystemSession session ) 080 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, 081 InvalidPluginDescriptorException 082 { 083 return mavenPluginManager.getPluginDescriptor( plugin, repositories, session ); 084 } 085 086 // ---------------------------------------------------------------------- 087 // Mojo execution 088 // ---------------------------------------------------------------------- 089 090 public void executeMojo( MavenSession session, MojoExecution mojoExecution ) 091 throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException 092 { 093 MavenProject project = session.getCurrentProject(); 094 095 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); 096 097 Mojo mojo = null; 098 099 ClassRealm pluginRealm; 100 try 101 { 102 pluginRealm = getPluginRealm( session, mojoDescriptor.getPluginDescriptor() ); 103 } 104 catch ( PluginResolutionException e ) 105 { 106 throw new PluginExecutionException( mojoExecution, project, e ); 107 } 108 109 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 110 Thread.currentThread().setContextClassLoader( pluginRealm ); 111 112 MavenSession oldSession = legacySupport.getSession(); 113 114 scope.enter(); 115 116 try 117 { 118 scope.seed( MavenProject.class, project ); 119 scope.seed( MojoExecution.class, mojoExecution ); 120 121 mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); 122 123 legacySupport.setSession( session ); 124 125 // NOTE: DuplicateArtifactAttachmentException is currently unchecked, so be careful removing this try/catch! 126 // This is necessary to avoid creating compatibility problems for existing plugins that use 127 // MavenProjectHelper.attachArtifact(..). 128 try 129 { 130 MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent( session, project, mojoExecution, mojo ); 131 132 mojoExecutionListener.beforeMojoExecution( mojoExecutionEvent ); 133 134 mojo.execute(); 135 136 mojoExecutionListener.afterMojoExecutionSuccess( mojoExecutionEvent ); 137 } 138 catch ( ClassCastException e ) 139 { 140 // to be processed in the outer catch block 141 throw e; 142 } 143 catch ( RuntimeException e ) 144 { 145 throw new PluginExecutionException( mojoExecution, project, e ); 146 } 147 } 148 catch ( PluginContainerException e ) 149 { 150 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 151 e ) ); 152 153 throw new PluginExecutionException( mojoExecution, project, e ); 154 } 155 catch ( NoClassDefFoundError e ) 156 { 157 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 158 e ) ); 159 160 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 161 PrintStream ps = new PrintStream( os ); 162 ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " 163 + e.getMessage() ); 164 pluginRealm.display( ps ); 165 166 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 167 168 throw new PluginExecutionException( mojoExecution, project, wrapper ); 169 } 170 catch ( LinkageError e ) 171 { 172 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 173 e ) ); 174 175 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 176 PrintStream ps = new PrintStream( os ); 177 ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " 178 + e.getClass().getName() + ": " + e.getMessage() ); 179 pluginRealm.display( ps ); 180 181 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 182 183 throw new PluginExecutionException( mojoExecution, project, wrapper ); 184 } 185 catch ( ClassCastException e ) 186 { 187 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 188 e ) ); 189 190 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 191 PrintStream ps = new PrintStream( os ); 192 ps.println( "A type incompatibility occured while executing " + mojoDescriptor.getId() + ": " 193 + e.getMessage() ); 194 pluginRealm.display( ps ); 195 196 throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); 197 } 198 catch ( RuntimeException e ) 199 { 200 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 201 e ) ); 202 203 throw e; 204 } 205 finally 206 { 207 mavenPluginManager.releaseMojo( mojo, mojoExecution ); 208 209 scope.exit(); 210 211 Thread.currentThread().setContextClassLoader( oldClassLoader ); 212 213 legacySupport.setSession( oldSession ); 214 } 215 } 216 217 /** 218 * TODO pluginDescriptor classRealm and artifacts are set as a side effect of this 219 * call, which is not nice. 220 * @throws PluginResolutionException 221 */ 222 public ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor ) 223 throws PluginResolutionException, PluginManagerException 224 { 225 ClassRealm pluginRealm = pluginDescriptor.getClassRealm(); 226 if ( pluginRealm != null ) 227 { 228 return pluginRealm; 229 } 230 231 mavenPluginManager.setupPluginRealm( pluginDescriptor, session, null, null, null ); 232 233 return pluginDescriptor.getClassRealm(); 234 } 235 236 public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List<RemoteRepository> repositories, 237 RepositorySystemSession session ) 238 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, 239 MojoNotFoundException, InvalidPluginDescriptorException 240 { 241 return mavenPluginManager.getMojoDescriptor( plugin, goal, repositories, session ); 242 } 243 244}