001    package 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    
022    import java.io.File;
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.Set;
028    
029    import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
030    import org.apache.maven.plugin.descriptor.MojoDescriptor;
031    import org.apache.maven.plugin.descriptor.Parameter;
032    import org.apache.maven.plugin.tools.model.PluginMetadataParseException;
033    import org.apache.maven.plugin.tools.model.PluginMetadataParser;
034    import org.apache.maven.project.MavenProject;
035    import org.apache.maven.project.path.PathTranslator;
036    import org.apache.maven.tools.plugin.PluginToolsRequest;
037    import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
038    import org.apache.maven.tools.plugin.extractor.ExtractionException;
039    import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
040    import org.codehaus.plexus.component.annotations.Component;
041    import org.codehaus.plexus.component.repository.ComponentRequirement;
042    import 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.java 1343107 2012-05-27 21:35:40Z hboutemy $
048     */
049    @Component( role = MojoDescriptorExtractor.class, hint = "ant" )
050    public 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    }