001package org.apache.maven.tools.plugin.extractor.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
022import java.io.File;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028
029import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
030import org.apache.maven.plugin.descriptor.MojoDescriptor;
031import org.apache.maven.plugin.descriptor.Parameter;
032import org.apache.maven.project.MavenProject;
033import org.apache.maven.project.path.PathTranslator;
034import org.apache.maven.tools.plugin.PluginToolsRequest;
035import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
036import org.apache.maven.tools.plugin.extractor.ExtractionException;
037import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
038import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException;
039import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser;
040import org.codehaus.plexus.component.annotations.Component;
041import org.codehaus.plexus.component.repository.ComponentRequirement;
042import org.codehaus.plexus.util.StringUtils;
043
044/**
045 * Extracts Mojo descriptors from <a href="http://ant.apache.org">Ant</a> sources.
046 *
047 * @version $Id: AntMojoDescriptorExtractor.html 1030109 2018-05-20 14:45:18Z hboutemy $
048 */
049@Component( role = MojoDescriptorExtractor.class, hint = "ant" )
050public class AntMojoDescriptorExtractor
051    extends AbstractScriptedMojoDescriptorExtractor
052    implements MojoDescriptorExtractor
053{
054    /** Default metadata file extension */
055    private static final String METADATA_FILE_EXTENSION = ".mojos.xml";
056
057    /** Default Ant build file extension */
058    private static final String SCRIPT_FILE_EXTENSION = ".build.xml";
059    
060    /** {@inheritDoc} */
061    protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata(
062                                                                  Map<String, Set<File>> metadataFilesKeyedByBasedir,
063                                                                  PluginToolsRequest request )
064        throws ExtractionException, InvalidPluginDescriptorException
065    {
066        List<MojoDescriptor> descriptors = new ArrayList<MojoDescriptor>();
067
068        PluginMetadataParser parser = new PluginMetadataParser();
069
070        for ( Map.Entry<String, Set<File>> entry : metadataFilesKeyedByBasedir.entrySet() )
071        {
072            String basedir = entry.getKey();
073            Set<File> metadataFiles = entry.getValue();
074
075            for ( File metadataFile : metadataFiles )
076            {
077                String basename = metadataFile.getName();
078                basename = basename.substring( 0, basename.length() - METADATA_FILE_EXTENSION.length() );
079
080                File scriptFile = new File( metadataFile.getParentFile(), basename + SCRIPT_FILE_EXTENSION );
081
082                if ( !scriptFile.exists() )
083                {
084                    throw new InvalidPluginDescriptorException(
085                        "Found orphaned plugin metadata file: " + metadataFile );
086                }
087
088                String relativePath = scriptFile.getPath().substring( basedir.length() ).replace( '\\', '/' );
089                
090                if ( relativePath.startsWith( "/" ) )
091                {
092                    relativePath = relativePath.substring( 1 );
093                }
094
095                try
096                {
097                    Set<MojoDescriptor> mojoDescriptors = parser.parseMojoDescriptors( metadataFile );
098
099                    for ( MojoDescriptor descriptor : mojoDescriptors )
100                    {
101                        @SuppressWarnings( "unchecked" )
102                        Map<String, ?> paramMap = descriptor.getParameterMap();
103
104                        if ( !paramMap.containsKey( "basedir" ) )
105                        {
106                            Parameter param = new Parameter();
107                            param.setName( "basedir" );
108                            param.setAlias( "ant.basedir" );
109                            param.setExpression( "${antBasedir}" );
110                            param.setDefaultValue( "${basedir}" );
111                            param.setType( "java.io.File" );
112                            param.setDescription( "The base directory from which to execute the Ant script." );
113                            param.setEditable( true );
114                            param.setRequired( true );
115
116                            descriptor.addParameter( param );
117                        }
118
119                        if ( !paramMap.containsKey( "antMessageLevel" ) )
120                        {
121                            Parameter param = new Parameter();
122                            param.setName( "messageLevel" );
123                            param.setAlias( "ant.messageLevel" );
124                            param.setExpression( "${antMessageLevel}" );
125                            param.setDefaultValue( "info" );
126                            param.setType( "java.lang.String" );
127                            param.setDescription( "The message-level used to tune the verbosity of Ant logging." );
128                            param.setEditable( true );
129                            param.setRequired( false );
130
131                            descriptor.addParameter( param );
132                        }
133                        
134                        if ( !paramMap.containsKey( "project" ) )
135                        {
136                            Parameter param = new Parameter();
137                            param.setName( "project" );
138                            param.setDefaultValue( "${project}" );
139                            param.setType( MavenProject.class.getName() );
140                            param.setDescription( "The current MavenProject instance, which contains classpath "
141                                + "elements." );
142                            param.setEditable( false );
143                            param.setRequired( true );
144
145                            descriptor.addParameter( param );
146                        }
147
148                        if ( !paramMap.containsKey( "session" ) )
149                        {
150                            Parameter param = new Parameter();
151                            param.setName( "session" );
152                            param.setDefaultValue( "${session}" );
153                            param.setType( "org.apache.maven.execution.MavenSession" );
154                            param.setDescription( "The current MavenSession instance, which is used for "
155                                + "plugin-style expression resolution." );
156                            param.setEditable( false );
157                            param.setRequired( true );
158
159                            descriptor.addParameter( param );
160                        }
161
162                        if ( !paramMap.containsKey( "mojoExecution" ) )
163                        {
164                            Parameter param = new Parameter();
165                            param.setName( "mojoExecution" );
166                            param.setDefaultValue( "${mojoExecution}" );
167                            param.setType( "org.apache.maven.plugin.MojoExecution" );
168                            param.setDescription( "The current Maven MojoExecution instance, which contains "
169                                + "information about the mojo currently executing." );
170                            param.setEditable( false );
171                            param.setRequired( true );
172
173                            descriptor.addParameter( param );
174                        }
175                        
176                        @SuppressWarnings( "unchecked" )
177                        List<ComponentRequirement> requirements = descriptor.getRequirements();
178                        Map<String, ComponentRequirement> reqMap = new HashMap<String, ComponentRequirement>();
179
180                        if ( requirements != null )
181                        {
182                            for ( ComponentRequirement req : requirements )
183                            {
184                                reqMap.put( req.getRole(), req );
185                            }
186                        }
187                        
188                        if ( !reqMap.containsKey( PathTranslator.class.getName() ) )
189                        {
190                            ComponentRequirement req = new ComponentRequirement();
191                            req.setRole( PathTranslator.class.getName() );
192                            
193                            descriptor.addRequirement( req );
194                        }
195
196                        String implementation = relativePath;
197
198                        String dImpl = descriptor.getImplementation();
199                        if ( StringUtils.isNotEmpty( dImpl ) )
200                        {
201                            if ( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.equals( dImpl ) )
202                            {
203                                implementation = relativePath;
204                            }
205                            else
206                            {
207                                implementation =
208                                    relativePath
209                                        + dImpl.substring( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.length() );
210                            }
211                        }
212
213                        descriptor.setImplementation( implementation );
214
215                        descriptor.setLanguage( "ant-mojo" );
216                        descriptor.setComponentComposer( "map-oriented" );
217                        descriptor.setComponentConfigurator( "map-oriented" );
218
219                        descriptor.setPluginDescriptor( request.getPluginDescriptor() );
220
221                        descriptors.add( descriptor );
222                    }
223                }
224                catch ( PluginMetadataParseException e )
225                {
226                    throw new ExtractionException( "Error extracting mojo descriptor from script: " + metadataFile, e );
227                }
228            }
229        }
230
231        return descriptors;
232    }
233
234    /** {@inheritDoc} */
235    protected String getScriptFileExtension( PluginToolsRequest request )
236    {
237        return SCRIPT_FILE_EXTENSION;
238    }
239
240    /** {@inheritDoc} */
241    protected String getMetadataFileExtension( PluginToolsRequest request )
242    {
243        return METADATA_FILE_EXTENSION;
244    }
245}