001    package org.apache.maven.script.ant;
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 org.apache.maven.artifact.Artifact;
023    import org.apache.maven.artifact.DependencyResolutionRequiredException;
024    import org.apache.maven.execution.MavenSession;
025    import org.apache.maven.plugin.AbstractMojo;
026    import org.apache.maven.plugin.ContextEnabled;
027    import org.apache.maven.plugin.MojoExecution;
028    import org.apache.maven.plugin.MojoExecutionException;
029    import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
030    import org.apache.maven.plugin.descriptor.PluginDescriptor;
031    import org.apache.maven.project.MavenProject;
032    import org.apache.maven.project.path.PathTranslator;
033    import org.apache.tools.ant.Project;
034    import org.apache.tools.ant.PropertyHelper;
035    import org.apache.tools.ant.types.Path;
036    import org.codehaus.plexus.archiver.ArchiverException;
037    import org.codehaus.plexus.archiver.UnArchiver;
038    import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
039    import org.codehaus.plexus.component.MapOrientedComponent;
040    import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
041    import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
042    import org.codehaus.plexus.component.factory.ant.AntComponentExecutionException;
043    import org.codehaus.plexus.component.factory.ant.AntScriptInvoker;
044    import org.codehaus.plexus.component.repository.ComponentRequirement;
045    import org.codehaus.plexus.logging.LogEnabled;
046    import org.codehaus.plexus.logging.Logger;
047    import org.codehaus.plexus.util.StringUtils;
048    
049    import java.io.File;
050    import java.util.ArrayList;
051    import java.util.Collection;
052    import java.util.HashMap;
053    import java.util.List;
054    import java.util.Map;
055    
056    public class AntMojoWrapper
057        extends AbstractMojo
058        implements ContextEnabled, MapOrientedComponent, LogEnabled
059    {
060    
061        private Map<String, Object> pluginContext;
062        
063        private final AntScriptInvoker scriptInvoker;
064    
065        private Project antProject;
066    
067        private MavenProject mavenProject;
068    
069        private MojoExecution mojoExecution;
070    
071        private MavenSession session;
072        
073        private PathTranslator pathTranslator;
074    
075        private Logger logger;
076        
077        private transient List<String> unconstructedParts = new ArrayList<String>();
078    
079        public AntMojoWrapper( AntScriptInvoker scriptInvoker )
080        {
081            this.scriptInvoker = scriptInvoker;
082        }
083    
084        public void execute()
085            throws MojoExecutionException
086        {
087            if ( antProject == null )
088            {
089                antProject = scriptInvoker.getProject();
090            }
091            
092            Map<String, Object> allConfig = new HashMap<String, Object>();
093            if ( pluginContext != null && !pluginContext.isEmpty() )
094            {
095                allConfig.putAll( pluginContext );
096            }
097            
098            @SuppressWarnings( "unchecked" )
099            Map<String, PathTranslator> refs = scriptInvoker.getReferences();
100            if ( refs != null )
101            {
102                allConfig.putAll( refs );
103                
104                for ( Map.Entry<String, PathTranslator> entry : refs.entrySet() )
105                {
106                    if ( entry.getKey().startsWith( PathTranslator.class.getName() ) )
107                    {
108                        pathTranslator = entry.getValue();
109                    }
110                }
111            }
112    
113            mavenProject = (MavenProject) allConfig.get( "project" );
114            
115            mojoExecution = (MojoExecution) allConfig.get( "mojoExecution" );
116            
117            session = (MavenSession) allConfig.get( "session" );
118            
119            unpackFileBasedResources();
120    
121            addClasspathReferences();
122            
123            if ( logger.isDebugEnabled() && !unconstructedParts.isEmpty() )
124            {
125                StringBuffer buffer = new StringBuffer();
126                
127                buffer.append( "The following standard Maven Ant-mojo support objects could not be created:\n\n" );
128                
129                for ( String part : unconstructedParts )
130                {
131                    buffer.append( "\n-  " ).append( part );
132                }
133                
134                buffer.append( "\n\nMaven project, session, mojo-execution, or path-translation parameter information is " );
135                buffer.append( "\nmissing from this mojo's plugin descriptor." );
136                buffer.append( "\n\nPerhaps this Ant-based mojo depends on maven-script-ant < 2.1.0, " );
137                buffer.append( "or used maven-plugin-tools-ant < 2.2 during release?\n\n" );
138                
139                logger.debug( buffer.toString() );
140            }
141    
142            try
143            {
144                scriptInvoker.invoke();
145            }
146            catch ( AntComponentExecutionException e )
147            {
148                throw new MojoExecutionException( "Failed to execute: " + e.getMessage(), e );
149            }
150            
151            unconstructedParts.clear();
152        }
153    
154        public void setPluginContext( Map pluginContext )
155        {
156            this.pluginContext = pluginContext;
157        }
158    
159        public Map getPluginContext()
160        {
161            return pluginContext;
162        }
163    
164        public void addComponentRequirement( ComponentRequirement requirementDescriptor, Object requirementValue )
165            throws ComponentConfigurationException
166        {
167            scriptInvoker.addComponentRequirement( requirementDescriptor, requirementValue );
168        }
169    
170        public void setComponentConfiguration( Map componentConfiguration )
171            throws ComponentConfigurationException
172        {
173            scriptInvoker.setComponentConfiguration( componentConfiguration );
174            antProject = scriptInvoker.getProject();
175        }
176    
177        private void unpackFileBasedResources()
178            throws MojoExecutionException
179        {
180            if ( mojoExecution == null || mavenProject == null )
181            {
182                unconstructedParts.add( "Unpacked Ant build scripts (in Maven build directory)." );
183                
184                return;
185            }
186            
187            // What we need to write out any resources in the plugin to the target directory of the
188            // mavenProject using the Ant-based plugin:
189            //
190            // 1. Need a reference to the plugin JAR itself
191            // 2. Need a reference to the ${basedir} of the mavenProject
192    
193            PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor();
194            
195            File pluginJar = pluginDescriptor.getPluginArtifact().getFile();
196    
197            String resourcesPath = pluginDescriptor.getArtifactId();
198    
199            File outputDirectory = new File( mavenProject.getBuild().getDirectory() );
200    
201            try
202            {
203                UnArchiver ua = new ZipUnArchiver( pluginJar );
204    
205                ua.extract( resourcesPath, outputDirectory );
206            }
207            catch ( ArchiverException e )
208            {
209                throw new MojoExecutionException( "Error extracting resources from your Ant-based plugin.", e );
210            }
211        }
212    
213        private void addClasspathReferences()
214            throws MojoExecutionException
215        {
216            try
217            {
218                if ( mavenProject != null && session != null && pathTranslator != null )
219                {
220                    ExpressionEvaluator exprEvaluator =
221                        new PluginParameterExpressionEvaluator( session, mojoExecution, pathTranslator, logger, mavenProject,
222                                                                mavenProject.getProperties() );
223                    
224                    PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper( antProject );
225                    propertyHelper.setNext( new AntPropertyHelper( exprEvaluator, mavenProject.getArtifacts(), getLog() ) );
226                }
227                else
228                {
229                    unconstructedParts.add( "Maven parameter expression evaluator for Ant properties." );
230                }
231    
232                @SuppressWarnings( "unchecked" )
233                Map<String, Object> references = scriptInvoker.getReferences();
234    
235                if ( mavenProject != null )
236                {
237    
238                    // Compile classpath
239                    Path p = new Path( antProject );
240    
241                    p.setPath( StringUtils.join( mavenProject.getCompileClasspathElements().iterator(), File.pathSeparator ) );
242    
243                    /* maven.dependency.classpath it's deprecated as it's equal to maven.compile.classpath */
244                    references.put( "maven.dependency.classpath", p );
245                    antProject.addReference( "maven.dependency.classpath", p );
246                    
247                    references.put( "maven.compile.classpath", p );
248                    antProject.addReference( "maven.compile.classpath", p );
249    
250                    // Runtime classpath
251                    p = new Path( antProject );
252    
253                    p.setPath( StringUtils.join( mavenProject.getRuntimeClasspathElements().iterator(), File.pathSeparator ) );
254    
255                    references.put( "maven.runtime.classpath", p );
256                    antProject.addReference( "maven.runtime.classpath", p );
257    
258                    // Test classpath
259                    p = new Path( antProject );
260    
261                    p.setPath( StringUtils.join( mavenProject.getTestClasspathElements().iterator(), File.pathSeparator ) );
262    
263                    references.put( "maven.test.classpath", p );
264                    antProject.addReference( "maven.test.classpath", p );
265    
266                }
267                else
268                {
269                    unconstructedParts.add( "Maven standard project-based classpath references." );
270                }
271                
272                if ( mojoExecution != null )
273                {
274                    // Plugin dependency classpath
275    
276                    Path p = getPathFromArtifacts( mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifacts(), antProject );
277                    
278                    references.put( "maven.plugin.classpath", p );
279                    antProject.addReference( "maven.plugin.classpath", p );
280                }
281                else
282                {
283                    unconstructedParts.add( "Maven standard plugin-based classpath references." );
284                }
285            }
286            catch ( DependencyResolutionRequiredException e )
287            {
288                throw new MojoExecutionException( "Error creating classpath references for Ant-based plugin scripts.", e  );
289            }
290        }
291    
292        public Path getPathFromArtifacts( Collection<Artifact> artifacts, Project antProject )
293            throws DependencyResolutionRequiredException
294        {
295            List<String> list = new ArrayList<String>( artifacts.size() );
296    
297            for ( Artifact a : artifacts )
298            {
299                File file = a.getFile();
300    
301                if ( file == null )
302                {
303                    throw new DependencyResolutionRequiredException( a );
304                }
305    
306                list.add( file.getPath() );
307            }
308    
309            Path p = new Path( antProject );
310    
311            p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) );
312    
313            return p;
314        }
315    
316        public Project getAntProject()
317        {
318            return antProject;
319        }
320    
321        public void setAntProject( Project antProject )
322        {
323            this.antProject = antProject;
324        }
325    
326        public MavenProject getMavenProject()
327        {
328            return mavenProject;
329        }
330    
331        public void setMavenProject( MavenProject mavenProject )
332        {
333            this.mavenProject = mavenProject;
334        }
335    
336        public MojoExecution getMojoExecution()
337        {
338            return mojoExecution;
339        }
340    
341        public void setMojoExecution( MojoExecution mojoExecution )
342        {
343            this.mojoExecution = mojoExecution;
344        }
345    
346        public MavenSession getSession()
347        {
348            return session;
349        }
350    
351        public void setSession( MavenSession session )
352        {
353            this.session = session;
354        }
355    
356        public PathTranslator getPathTranslator()
357        {
358            return pathTranslator;
359        }
360    
361        public void setPathTranslator( PathTranslator pathTranslator )
362        {
363            this.pathTranslator = pathTranslator;
364        }
365    
366        public AntScriptInvoker getScriptInvoker()
367        {
368            return scriptInvoker;
369        }
370    
371        public void enableLogging( Logger logger )
372        {
373            this.logger = logger;
374        }
375    }