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    }