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    }