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