View Javadoc
1   package org.apache.maven.script.ant;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.DependencyResolutionRequiredException;
24  import org.apache.maven.execution.MavenSession;
25  import org.apache.maven.plugin.AbstractMojo;
26  import org.apache.maven.plugin.ContextEnabled;
27  import org.apache.maven.plugin.MojoExecution;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
30  import org.apache.maven.plugin.descriptor.PluginDescriptor;
31  import org.apache.maven.project.MavenProject;
32  import org.apache.maven.project.path.PathTranslator;
33  import org.apache.tools.ant.Project;
34  import org.apache.tools.ant.PropertyHelper;
35  import org.apache.tools.ant.types.Path;
36  import org.codehaus.plexus.archiver.ArchiverException;
37  import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
38  import org.codehaus.plexus.component.MapOrientedComponent;
39  import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
40  import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
41  import org.codehaus.plexus.component.factory.ant.AntComponentExecutionException;
42  import org.codehaus.plexus.component.factory.ant.AntScriptInvoker;
43  import org.codehaus.plexus.component.repository.ComponentRequirement;
44  import org.codehaus.plexus.logging.LogEnabled;
45  import org.codehaus.plexus.logging.Logger;
46  import org.codehaus.plexus.util.StringUtils;
47  
48  import java.io.File;
49  import java.util.ArrayList;
50  import java.util.Collection;
51  import java.util.HashMap;
52  import java.util.List;
53  import java.util.Map;
54  
55  /**
56   * 
57   */
58  public class AntMojoWrapper
59      extends AbstractMojo
60      implements ContextEnabled, MapOrientedComponent, LogEnabled
61  {
62  
63      private Map<String, Object> pluginContext;
64      
65      private final AntScriptInvoker scriptInvoker;
66  
67      private Project antProject;
68  
69      private MavenProject mavenProject;
70  
71      private MojoExecution mojoExecution;
72  
73      private MavenSession session;
74      
75      private PathTranslator pathTranslator;
76  
77      private Logger logger;
78      
79      private transient List<String> unconstructedParts = new ArrayList<>();
80  
81      public AntMojoWrapper( AntScriptInvoker scriptInvoker )
82      {
83          this.scriptInvoker = scriptInvoker;
84      }
85  
86      public void execute()
87          throws MojoExecutionException
88      {
89          if ( antProject == null )
90          {
91              antProject = scriptInvoker.getProject();
92          }
93          
94          Map<String, Object> allConfig = new HashMap<>();
95          if ( pluginContext != null && !pluginContext.isEmpty() )
96          {
97              allConfig.putAll( pluginContext );
98          }
99          
100         @SuppressWarnings( "unchecked" )
101         Map<String, PathTranslator> refs = scriptInvoker.getReferences();
102         if ( refs != null )
103         {
104             allConfig.putAll( refs );
105             
106             for ( Map.Entry<String, PathTranslator> entry : refs.entrySet() )
107             {
108                 if ( entry.getKey().startsWith( PathTranslator.class.getName() ) )
109                 {
110                     pathTranslator = entry.getValue();
111                 }
112             }
113         }
114 
115         mavenProject = (MavenProject) allConfig.get( "project" );
116         
117         mojoExecution = (MojoExecution) allConfig.get( "mojoExecution" );
118         
119         session = (MavenSession) allConfig.get( "session" );
120         
121         unpackFileBasedResources();
122 
123         addClasspathReferences();
124         
125         if ( logger.isDebugEnabled() && !unconstructedParts.isEmpty() )
126         {
127             StringBuilder buffer = new StringBuilder();
128             
129             buffer.append( "The following standard Maven Ant-mojo support objects could not be created:\n\n" );
130             
131             for ( String part : unconstructedParts )
132             {
133                 buffer.append( "\n-  " ).append( part );
134             }
135             
136             buffer.append( "\n\nMaven project, session, mojo-execution, or path-translation parameter "
137                 + "information is " );
138             buffer.append( "\nmissing from this mojo's plugin descriptor." );
139             buffer.append( "\n\nPerhaps this Ant-based mojo depends on maven-script-ant < 2.1.0, " );
140             buffer.append( "or used maven-plugin-tools-ant < 2.2 during release?\n\n" );
141             
142             logger.debug( buffer.toString() );
143         }
144 
145         try
146         {
147             scriptInvoker.invoke();
148         }
149         catch ( AntComponentExecutionException e )
150         {
151             throw new MojoExecutionException( "Failed to execute: " + e.getMessage(), e );
152         }
153         
154         unconstructedParts.clear();
155     }
156 
157     public void setPluginContext( Map pluginContext )
158     {
159         this.pluginContext = pluginContext;
160     }
161 
162     public Map getPluginContext()
163     {
164         return pluginContext;
165     }
166 
167     public void addComponentRequirement( ComponentRequirement requirementDescriptor, Object requirementValue )
168         throws ComponentConfigurationException
169     {
170         scriptInvoker.addComponentRequirement( requirementDescriptor, requirementValue );
171     }
172 
173     public void setComponentConfiguration( Map componentConfiguration )
174         throws ComponentConfigurationException
175     {
176         scriptInvoker.setComponentConfiguration( componentConfiguration );
177         antProject = scriptInvoker.getProject();
178     }
179 
180     private void unpackFileBasedResources()
181         throws MojoExecutionException
182     {
183         if ( mojoExecution == null || mavenProject == null )
184         {
185             unconstructedParts.add( "Unpacked Ant build scripts (in Maven build directory)." );
186             
187             return;
188         }
189         
190         // What we need to write out any resources in the plugin to the target directory of the
191         // mavenProject using the Ant-based plugin:
192         //
193         // 1. Need a reference to the plugin JAR itself
194         // 2. Need a reference to the ${basedir} of the mavenProject
195 
196         PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor();
197         
198         File pluginJar = pluginDescriptor.getPluginArtifact().getFile();
199 
200         String resourcesPath = pluginDescriptor.getArtifactId();
201 
202         File outputDirectory = new File( mavenProject.getBuild().getDirectory() );
203 
204         try
205         {
206             ZipUnArchiver ua = new ZipUnArchiver( pluginJar );
207             ua.enableLogging( logger );
208 
209             ua.extract( resourcesPath, outputDirectory );
210         }
211         catch ( ArchiverException e )
212         {
213             throw new MojoExecutionException( "Error extracting resources from your Ant-based plugin.", e );
214         }
215     }
216 
217     private void addClasspathReferences()
218         throws MojoExecutionException
219     {
220         try
221         {
222             if ( mavenProject != null && session != null && pathTranslator != null )
223             {
224                 ExpressionEvaluator exprEvaluator =
225                     new PluginParameterExpressionEvaluator( session, mojoExecution, pathTranslator, logger,
226                                                             mavenProject, mavenProject.getProperties() );
227                 
228                 PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper( antProject );
229                 propertyHelper.setNext( new AntPropertyHelper( exprEvaluator, mavenProject.getArtifacts(), getLog() ) );
230             }
231             else
232             {
233                 unconstructedParts.add( "Maven parameter expression evaluator for Ant properties." );
234             }
235 
236             @SuppressWarnings( "unchecked" )
237             Map<String, Object> references = scriptInvoker.getReferences();
238 
239             if ( mavenProject != null )
240             {
241 
242                 // Compile classpath
243                 Path p = new Path( antProject );
244 
245                 p.setPath( StringUtils.join( mavenProject.getCompileClasspathElements().iterator(),
246                                              File.pathSeparator ) );
247 
248                 /* maven.dependency.classpath it's deprecated as it's equal to maven.compile.classpath */
249                 references.put( "maven.dependency.classpath", p );
250                 antProject.addReference( "maven.dependency.classpath", p );
251                 
252                 references.put( "maven.compile.classpath", p );
253                 antProject.addReference( "maven.compile.classpath", p );
254 
255                 // Runtime classpath
256                 p = new Path( antProject );
257 
258                 p.setPath( StringUtils.join( mavenProject.getRuntimeClasspathElements().iterator(),
259                                              File.pathSeparator ) );
260 
261                 references.put( "maven.runtime.classpath", p );
262                 antProject.addReference( "maven.runtime.classpath", p );
263 
264                 // Test classpath
265                 p = new Path( antProject );
266 
267                 p.setPath( StringUtils.join( mavenProject.getTestClasspathElements().iterator(),
268                                              File.pathSeparator ) );
269 
270                 references.put( "maven.test.classpath", p );
271                 antProject.addReference( "maven.test.classpath", p );
272 
273             }
274             else
275             {
276                 unconstructedParts.add( "Maven standard project-based classpath references." );
277             }
278             
279             if ( mojoExecution != null )
280             {
281                 // Plugin dependency classpath
282                 Path p =
283                     getPathFromArtifacts( mojoExecution.getMojoDescriptor().getPluginDescriptor().getArtifacts(),
284                                           antProject );
285                 
286                 references.put( "maven.plugin.classpath", p );
287                 antProject.addReference( "maven.plugin.classpath", p );
288             }
289             else
290             {
291                 unconstructedParts.add( "Maven standard plugin-based classpath references." );
292             }
293         }
294         catch ( DependencyResolutionRequiredException e )
295         {
296             throw new MojoExecutionException( "Error creating classpath references for Ant-based plugin scripts.", e );
297         }
298     }
299 
300     public Path getPathFromArtifacts( Collection<Artifact> artifacts, Project antProject )
301         throws DependencyResolutionRequiredException
302     {
303         List<String> list = new ArrayList<>( artifacts.size() );
304 
305         for ( Artifact a : artifacts )
306         {
307             File file = a.getFile();
308 
309             if ( file == null )
310             {
311                 throw new DependencyResolutionRequiredException( a );
312             }
313 
314             list.add( file.getPath() );
315         }
316 
317         Path p = new Path( antProject );
318 
319         p.setPath( StringUtils.join( list.iterator(), File.pathSeparator ) );
320 
321         return p;
322     }
323 
324     public Project getAntProject()
325     {
326         return antProject;
327     }
328 
329     public void setAntProject( Project antProject )
330     {
331         this.antProject = antProject;
332     }
333 
334     public MavenProject getMavenProject()
335     {
336         return mavenProject;
337     }
338 
339     public void setMavenProject( MavenProject mavenProject )
340     {
341         this.mavenProject = mavenProject;
342     }
343 
344     public MojoExecution getMojoExecution()
345     {
346         return mojoExecution;
347     }
348 
349     public void setMojoExecution( MojoExecution mojoExecution )
350     {
351         this.mojoExecution = mojoExecution;
352     }
353 
354     public MavenSession getSession()
355     {
356         return session;
357     }
358 
359     public void setSession( MavenSession session )
360     {
361         this.session = session;
362     }
363 
364     public PathTranslator getPathTranslator()
365     {
366         return pathTranslator;
367     }
368 
369     public void setPathTranslator( PathTranslator pathTranslator )
370     {
371         this.pathTranslator = pathTranslator;
372     }
373 
374     public AntScriptInvoker getScriptInvoker()
375     {
376         return scriptInvoker;
377     }
378 
379     public void enableLogging( Logger logger )
380     {
381         this.logger = logger;
382     }
383 }