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 }