View Javadoc
1   package org.apache.maven.tools.plugin.extractor.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 java.io.File;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
30  import org.apache.maven.plugin.descriptor.MojoDescriptor;
31  import org.apache.maven.plugin.descriptor.Parameter;
32  import org.apache.maven.project.MavenProject;
33  import org.apache.maven.project.path.PathTranslator;
34  import org.apache.maven.tools.plugin.PluginToolsRequest;
35  import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
36  import org.apache.maven.tools.plugin.extractor.ExtractionException;
37  import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
38  import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException;
39  import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser;
40  import org.codehaus.plexus.component.annotations.Component;
41  import org.codehaus.plexus.component.repository.ComponentRequirement;
42  import org.codehaus.plexus.util.StringUtils;
43  
44  /**
45   * Extracts Mojo descriptors from <a href="http://ant.apache.org">Ant</a> sources.
46   *
47   */
48  @Component( role = MojoDescriptorExtractor.class, hint = "ant" )
49  public class AntMojoDescriptorExtractor
50      extends AbstractScriptedMojoDescriptorExtractor
51      implements MojoDescriptorExtractor
52  {
53      /** Default metadata file extension */
54      private static final String METADATA_FILE_EXTENSION = ".mojos.xml";
55  
56      /** Default Ant build file extension */
57      private static final String SCRIPT_FILE_EXTENSION = ".build.xml";
58      
59      /** {@inheritDoc} */
60      protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata(
61                                                                    Map<String, Set<File>> metadataFilesKeyedByBasedir,
62                                                                    PluginToolsRequest request )
63          throws ExtractionException, InvalidPluginDescriptorException
64      {
65          List<MojoDescriptor> descriptors = new ArrayList<>();
66  
67          PluginMetadataParser parser = new PluginMetadataParser();
68  
69          for ( Map.Entry<String, Set<File>> entry : metadataFilesKeyedByBasedir.entrySet() )
70          {
71              String basedir = entry.getKey();
72              Set<File> metadataFiles = entry.getValue();
73  
74              for ( File metadataFile : metadataFiles )
75              {
76                  String basename = metadataFile.getName();
77                  basename = basename.substring( 0, basename.length() - METADATA_FILE_EXTENSION.length() );
78  
79                  File scriptFile = new File( metadataFile.getParentFile(), basename + SCRIPT_FILE_EXTENSION );
80  
81                  if ( !scriptFile.exists() )
82                  {
83                      throw new InvalidPluginDescriptorException(
84                          "Found orphaned plugin metadata file: " + metadataFile );
85                  }
86  
87                  String relativePath = scriptFile.getPath().substring( basedir.length() ).replace( '\\', '/' );
88                  
89                  if ( relativePath.startsWith( "/" ) )
90                  {
91                      relativePath = relativePath.substring( 1 );
92                  }
93  
94                  try
95                  {
96                      Set<MojoDescriptor> mojoDescriptors = parser.parseMojoDescriptors( metadataFile );
97  
98                      for ( MojoDescriptor descriptor : mojoDescriptors )
99                      {
100                         @SuppressWarnings( "unchecked" )
101                         Map<String, ?> paramMap = descriptor.getParameterMap();
102 
103                         if ( !paramMap.containsKey( "basedir" ) )
104                         {
105                             Parameter param = new Parameter();
106                             param.setName( "basedir" );
107                             param.setAlias( "ant.basedir" );
108                             param.setExpression( "${antBasedir}" );
109                             param.setDefaultValue( "${basedir}" );
110                             param.setType( "java.io.File" );
111                             param.setDescription( "The base directory from which to execute the Ant script." );
112                             param.setEditable( true );
113                             param.setRequired( true );
114 
115                             descriptor.addParameter( param );
116                         }
117 
118                         if ( !paramMap.containsKey( "antMessageLevel" ) )
119                         {
120                             Parameter param = new Parameter();
121                             param.setName( "messageLevel" );
122                             param.setAlias( "ant.messageLevel" );
123                             param.setExpression( "${antMessageLevel}" );
124                             param.setDefaultValue( "info" );
125                             param.setType( "java.lang.String" );
126                             param.setDescription( "The message-level used to tune the verbosity of Ant logging." );
127                             param.setEditable( true );
128                             param.setRequired( false );
129 
130                             descriptor.addParameter( param );
131                         }
132                         
133                         if ( !paramMap.containsKey( "project" ) )
134                         {
135                             Parameter param = new Parameter();
136                             param.setName( "project" );
137                             param.setDefaultValue( "${project}" );
138                             param.setType( MavenProject.class.getName() );
139                             param.setDescription( "The current MavenProject instance, which contains classpath "
140                                 + "elements." );
141                             param.setEditable( false );
142                             param.setRequired( true );
143 
144                             descriptor.addParameter( param );
145                         }
146 
147                         if ( !paramMap.containsKey( "session" ) )
148                         {
149                             Parameter param = new Parameter();
150                             param.setName( "session" );
151                             param.setDefaultValue( "${session}" );
152                             param.setType( "org.apache.maven.execution.MavenSession" );
153                             param.setDescription( "The current MavenSession instance, which is used for "
154                                 + "plugin-style expression resolution." );
155                             param.setEditable( false );
156                             param.setRequired( true );
157 
158                             descriptor.addParameter( param );
159                         }
160 
161                         if ( !paramMap.containsKey( "mojoExecution" ) )
162                         {
163                             Parameter param = new Parameter();
164                             param.setName( "mojoExecution" );
165                             param.setDefaultValue( "${mojoExecution}" );
166                             param.setType( "org.apache.maven.plugin.MojoExecution" );
167                             param.setDescription( "The current Maven MojoExecution instance, which contains "
168                                 + "information about the mojo currently executing." );
169                             param.setEditable( false );
170                             param.setRequired( true );
171 
172                             descriptor.addParameter( param );
173                         }
174                         
175                         @SuppressWarnings( "unchecked" )
176                         List<ComponentRequirement> requirements = descriptor.getRequirements();
177                         Map<String, ComponentRequirement> reqMap = new HashMap<>();
178 
179                         if ( requirements != null )
180                         {
181                             for ( ComponentRequirement req : requirements )
182                             {
183                                 reqMap.put( req.getRole(), req );
184                             }
185                         }
186                         
187                         if ( !reqMap.containsKey( PathTranslator.class.getName() ) )
188                         {
189                             ComponentRequirement req = new ComponentRequirement();
190                             req.setRole( PathTranslator.class.getName() );
191                             
192                             descriptor.addRequirement( req );
193                         }
194 
195                         String implementation = relativePath;
196 
197                         String dImpl = descriptor.getImplementation();
198                         if ( StringUtils.isNotEmpty( dImpl ) )
199                         {
200                             if ( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.equals( dImpl ) )
201                             {
202                                 implementation = relativePath;
203                             }
204                             else
205                             {
206                                 implementation =
207                                     relativePath
208                                         + dImpl.substring( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.length() );
209                             }
210                         }
211 
212                         descriptor.setImplementation( implementation );
213 
214                         descriptor.setLanguage( "ant-mojo" );
215                         descriptor.setComponentComposer( "map-oriented" );
216                         descriptor.setComponentConfigurator( "map-oriented" );
217 
218                         descriptor.setPluginDescriptor( request.getPluginDescriptor() );
219 
220                         descriptors.add( descriptor );
221                     }
222                 }
223                 catch ( PluginMetadataParseException e )
224                 {
225                     throw new ExtractionException( "Error extracting mojo descriptor from script: " + metadataFile, e );
226                 }
227             }
228         }
229 
230         return descriptors;
231     }
232 
233     /** {@inheritDoc} */
234     protected String getScriptFileExtension( PluginToolsRequest request )
235     {
236         return SCRIPT_FILE_EXTENSION;
237     }
238 
239     /** {@inheritDoc} */
240     protected String getMetadataFileExtension( PluginToolsRequest request )
241     {
242         return METADATA_FILE_EXTENSION;
243     }
244 }