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.plugin.tools.model.PluginMetadataParseException;
033import org.apache.maven.plugin.tools.model.PluginMetadataParser;
034import org.apache.maven.project.MavenProject;
035import org.apache.maven.project.path.PathTranslator;
036import org.apache.maven.tools.plugin.PluginToolsRequest;
037import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
038import org.apache.maven.tools.plugin.extractor.ExtractionException;
039import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
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 907040 2014-04-27 09:50:12Z 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( Map<String, Set<File>> metadataFilesKeyedByBasedir,
062                                                                       PluginToolsRequest request )
063        throws ExtractionException, InvalidPluginDescriptorException
064    {
065        List<MojoDescriptor> descriptors = new ArrayList<MojoDescriptor>();
066
067        PluginMetadataParser parser = new PluginMetadataParser();
068
069        for ( Map.Entry<String, Set<File>> entry : metadataFilesKeyedByBasedir.entrySet() )
070        {
071            String basedir = entry.getKey();
072            Set<File> metadataFiles = entry.getValue();
073
074            for ( File metadataFile : metadataFiles )
075            {
076                String basename = metadataFile.getName();
077                basename = basename.substring( 0, basename.length() - METADATA_FILE_EXTENSION.length() );
078
079                File scriptFile = new File( metadataFile.getParentFile(), basename + SCRIPT_FILE_EXTENSION );
080
081                if ( !scriptFile.exists() )
082                {
083                    throw new InvalidPluginDescriptorException(
084                        "Found orphaned plugin metadata file: " + metadataFile );
085                }
086
087                String relativePath = scriptFile.getPath().substring( basedir.length() ).replace( '\\', '/' );
088                
089                if ( relativePath.startsWith( "/" ) )
090                {
091                    relativePath = relativePath.substring( 1 );
092                }
093
094                try
095                {
096                    Set<MojoDescriptor> mojoDescriptors = parser.parseMojoDescriptors( metadataFile );
097
098                    for ( MojoDescriptor descriptor : mojoDescriptors )
099                    {
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 elements." );
140                            param.setEditable( false );
141                            param.setRequired( true );
142
143                            descriptor.addParameter( param );
144                        }
145
146                        if ( !paramMap.containsKey( "session" ) )
147                        {
148                            Parameter param = new Parameter();
149                            param.setName( "session" );
150                            param.setDefaultValue( "${session}" );
151                            param.setType( "org.apache.maven.execution.MavenSession" );
152                            param.setDescription( "The current MavenSession instance, which is used for plugin-style expression resolution." );
153                            param.setEditable( false );
154                            param.setRequired( true );
155
156                            descriptor.addParameter( param );
157                        }
158
159                        if ( !paramMap.containsKey( "mojoExecution" ) )
160                        {
161                            Parameter param = new Parameter();
162                            param.setName( "mojoExecution" );
163                            param.setDefaultValue( "${mojoExecution}" );
164                            param.setType( "org.apache.maven.plugin.MojoExecution" );
165                            param.setDescription( "The current Maven MojoExecution instance, which contains information about the mojo currently executing." );
166                            param.setEditable( false );
167                            param.setRequired( true );
168
169                            descriptor.addParameter( param );
170                        }
171                        
172                        @SuppressWarnings( "unchecked" )
173                        List<ComponentRequirement> requirements = descriptor.getRequirements();
174                        Map<String, ComponentRequirement> reqMap = new HashMap<String, ComponentRequirement>();
175
176                        if ( requirements != null )
177                        {
178                            for ( ComponentRequirement req : requirements )
179                            {
180                                reqMap.put( req.getRole(), req );
181                            }
182                        }
183                        
184                        if ( !reqMap.containsKey( PathTranslator.class.getName() ) )
185                        {
186                            ComponentRequirement req = new ComponentRequirement();
187                            req.setRole( PathTranslator.class.getName() );
188                            
189                            descriptor.addRequirement( req );
190                        }
191
192                        String implementation = relativePath;
193
194                        String dImpl = descriptor.getImplementation();
195                        if ( StringUtils.isNotEmpty( dImpl ) )
196                        {
197                            if ( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.equals( dImpl ) )
198                            {
199                                implementation = relativePath;
200                            }
201                            else
202                            {
203                                implementation =
204                                    relativePath + dImpl.substring( PluginMetadataParser.IMPL_BASE_PLACEHOLDER.length() );
205                            }
206                        }
207
208                        descriptor.setImplementation( implementation );
209
210                        descriptor.setLanguage( "ant-mojo" );
211                        descriptor.setComponentComposer( "map-oriented" );
212                        descriptor.setComponentConfigurator( "map-oriented" );
213
214                        descriptor.setPluginDescriptor( request.getPluginDescriptor() );
215
216                        descriptors.add( descriptor );
217                    }
218                }
219                catch ( PluginMetadataParseException e )
220                {
221                    throw new ExtractionException( "Error extracting mojo descriptor from script: " + metadataFile, e );
222                }
223            }
224        }
225
226        return descriptors;
227    }
228
229    /** {@inheritDoc} */
230    protected String getScriptFileExtension( PluginToolsRequest request )
231    {
232        return SCRIPT_FILE_EXTENSION;
233    }
234
235    /** {@inheritDoc} */
236    protected String getMetadataFileExtension( PluginToolsRequest request )
237    {
238        return METADATA_FILE_EXTENSION;
239    }
240}