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 }