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, RepositorySystemSession session ) 079 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, InvalidPluginDescriptorException 080 { 081 return mavenPluginManager.getPluginDescriptor( plugin, repositories, session ); 082 } 083 084 // ---------------------------------------------------------------------- 085 // Mojo execution 086 // ---------------------------------------------------------------------- 087 088 public void executeMojo( MavenSession session, MojoExecution mojoExecution ) 089 throws MojoFailureException, MojoExecutionException, PluginConfigurationException, PluginManagerException 090 { 091 MavenProject project = session.getCurrentProject(); 092 093 MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); 094 095 Mojo mojo = null; 096 097 ClassRealm pluginRealm; 098 try 099 { 100 pluginRealm = getPluginRealm( session, mojoDescriptor.getPluginDescriptor() ); 101 } 102 catch ( PluginResolutionException e ) 103 { 104 throw new PluginExecutionException( mojoExecution, project, e ); 105 } 106 107 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 108 Thread.currentThread().setContextClassLoader( pluginRealm ); 109 110 MavenSession oldSession = legacySupport.getSession(); 111 112 scope.enter(); 113 114 try 115 { 116 scope.seed( MavenProject.class, project ); 117 scope.seed( MojoExecution.class, mojoExecution ); 118 119 mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); 120 121 legacySupport.setSession( session ); 122 123 // NOTE: DuplicateArtifactAttachmentException is currently unchecked, so be careful removing this try/catch! 124 // This is necessary to avoid creating compatibility problems for existing plugins that use 125 // MavenProjectHelper.attachArtifact(..). 126 try 127 { 128 MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent( session, project, mojoExecution, mojo ); 129 130 mojoExecutionListener.beforeMojoExecution( mojoExecutionEvent ); 131 132 mojo.execute(); 133 134 mojoExecutionListener.afterMojoExecutionSuccess( mojoExecutionEvent ); 135 } 136 catch ( ClassCastException e ) 137 { 138 // to be processed in the outer catch block 139 throw e; 140 } 141 catch ( RuntimeException e ) 142 { 143 throw new PluginExecutionException( mojoExecution, project, e ); 144 } 145 } 146 catch ( PluginContainerException e ) 147 { 148 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 149 e ) ); 150 151 throw new PluginExecutionException( mojoExecution, project, e ); 152 } 153 catch ( NoClassDefFoundError e ) 154 { 155 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 156 e ) ); 157 158 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 159 PrintStream ps = new PrintStream( os ); 160 ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " 161 + e.getMessage() ); 162 pluginRealm.display( ps ); 163 164 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 165 166 throw new PluginExecutionException( mojoExecution, project, wrapper ); 167 } 168 catch ( LinkageError e ) 169 { 170 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 171 e ) ); 172 173 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 174 PrintStream ps = new PrintStream( os ); 175 ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " 176 + e.getClass().getName() + ": " + e.getMessage() ); 177 pluginRealm.display( ps ); 178 179 Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); 180 181 throw new PluginExecutionException( mojoExecution, project, wrapper ); 182 } 183 catch ( ClassCastException e ) 184 { 185 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 186 e ) ); 187 188 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 189 PrintStream ps = new PrintStream( os ); 190 ps.println( "A type incompatibility occured while executing " + mojoDescriptor.getId() + ": " 191 + e.getMessage() ); 192 pluginRealm.display( ps ); 193 194 throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); 195 } 196 catch ( RuntimeException e ) 197 { 198 mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, 199 e ) ); 200 201 throw e; 202 } 203 finally 204 { 205 mavenPluginManager.releaseMojo( mojo, mojoExecution ); 206 207 scope.exit(); 208 209 Thread.currentThread().setContextClassLoader( oldClassLoader ); 210 211 legacySupport.setSession( oldSession ); 212 } 213 } 214 215 /** 216 * TODO pluginDescriptor classRealm and artifacts are set as a side effect of this 217 * call, which is not nice. 218 * @throws PluginResolutionException 219 */ 220 public ClassRealm getPluginRealm( MavenSession session, PluginDescriptor pluginDescriptor ) 221 throws PluginResolutionException, PluginManagerException 222 { 223 ClassRealm pluginRealm = pluginDescriptor.getClassRealm(); 224 if ( pluginRealm != null ) 225 { 226 return pluginRealm; 227 } 228 229 mavenPluginManager.setupPluginRealm( pluginDescriptor, session, null, null, null ); 230 231 return pluginDescriptor.getClassRealm(); 232 } 233 234 public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List<RemoteRepository> repositories, 235 RepositorySystemSession session ) 236 throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException, 237 MojoNotFoundException, InvalidPluginDescriptorException 238 { 239 return mavenPluginManager.getMojoDescriptor( plugin, goal, repositories, session ); 240 } 241 242}