001package org.apache.maven.tools.plugin.scanner;
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 javax.inject.Inject;
023import javax.inject.Named;
024
025import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
026import org.apache.maven.plugin.descriptor.MojoDescriptor;
027import org.apache.maven.tools.plugin.PluginToolsRequest;
028import org.apache.maven.tools.plugin.extractor.ExtractionException;
029import org.apache.maven.tools.plugin.extractor.GroupKey;
030import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
031import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractorComparator;
032import org.codehaus.plexus.logging.AbstractLogEnabled;
033import org.codehaus.plexus.logging.Logger;
034import org.codehaus.plexus.logging.console.ConsoleLogger;
035import org.codehaus.plexus.util.StringUtils;
036
037import java.util.ArrayList;
038import java.util.Collections;
039import java.util.HashMap;
040import java.util.HashSet;
041import java.util.List;
042import java.util.Map;
043import java.util.Set;
044
045/**
046 * @author jdcasey
047 */
048@Named
049public class DefaultMojoScanner
050    extends AbstractLogEnabled
051    implements MojoScanner
052{
053
054    private Map<String, MojoDescriptorExtractor> mojoDescriptorExtractors;
055
056    /**
057     * The names of the active extractors
058     */
059    private Set<String> activeExtractors;
060
061    /**
062     * Default constructor
063     *
064     * @param extractors not null
065     */
066    @Inject
067    public DefaultMojoScanner( Map<String, MojoDescriptorExtractor> extractors )
068    {
069        this.mojoDescriptorExtractors = extractors;
070
071        this.enableLogging( new ConsoleLogger( Logger.LEVEL_INFO, "standalone-scanner-logger" ) );
072    }
073
074    /**
075     * Empty constructor
076     */
077    public DefaultMojoScanner()
078    {
079        // nop
080    }
081
082    /**
083     * {@inheritDoc}
084     */
085    @Override
086    public void populatePluginDescriptor( PluginToolsRequest request )
087        throws ExtractionException, InvalidPluginDescriptorException
088    {
089        Logger logger = getLogger();
090
091        int numMojoDescriptors = 0;
092
093        List<MojoDescriptorExtractor> orderedExtractors = getOrderedExtractors();
094
095        logger.debug( "Using " + orderedExtractors.size() + " mojo extractors." );
096
097        HashMap<String, Integer> groupStats = new HashMap<>();
098
099        for ( MojoDescriptorExtractor extractor : orderedExtractors )
100        {
101            GroupKey groupKey = extractor.getGroupKey();
102            String extractorId = extractor.getName();
103
104            logger.debug( "Applying " + extractorId + " mojo extractor" );
105
106            List<MojoDescriptor> extractorDescriptors = extractor.execute( request );
107
108            int extractorDescriptorsCount = extractorDescriptors.size();
109
110            logger.info( extractorId + " mojo extractor found " + extractorDescriptorsCount
111                             + " mojo descriptor" + ( extractorDescriptorsCount > 1 ? "s" : "" ) + "." );
112            numMojoDescriptors += extractorDescriptorsCount;
113
114            if ( extractor.isDeprecated() &&  extractorDescriptorsCount > 0 )
115            {
116                logger.warn( "" );
117                logger.warn( "Deprecated extractor " + extractorId
118                             + " extracted " + extractorDescriptorsCount
119                             + " descriptor" + ( extractorDescriptorsCount > 1 ? "s" : "" )
120                             + ". Upgrade your Mojo definitions." );
121                if ( GroupKey.JAVA_GROUP.equals( groupKey.getGroup() ) )
122                {
123                    logger.warn( "You should use Mojo Annotations instead of Javadoc tags." );
124                }
125                logger.warn( "" );
126            }
127
128            if ( groupStats.containsKey( groupKey.getGroup() ) )
129            {
130                groupStats.put( groupKey.getGroup(),
131                    groupStats.get( groupKey.getGroup() ) + extractorDescriptorsCount );
132            }
133            else
134            {
135                groupStats.put( groupKey.getGroup(), extractorDescriptorsCount );
136            }
137
138            for ( MojoDescriptor descriptor : extractorDescriptors )
139            {
140                logger.debug( "Adding mojo: " + descriptor + " to plugin descriptor." );
141
142                descriptor.setPluginDescriptor( request.getPluginDescriptor() );
143
144                request.getPluginDescriptor().addMojo( descriptor );
145            }
146        }
147
148        logger.debug( "Discovered descriptors by groups: " + groupStats );
149
150        if ( numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound() )
151        {
152            throw new InvalidPluginDescriptorException(
153                "No mojo definitions were found for plugin: " + request.getPluginDescriptor().getPluginLookupKey()
154                    + "." );
155        }
156    }
157
158    /**
159     * Returns a list of extractors sorted by {@link MojoDescriptorExtractor#getGroupKey()}s, never {@code null}.
160     */
161    private List<MojoDescriptorExtractor> getOrderedExtractors() throws ExtractionException
162    {
163        Set<String> extractors = activeExtractors;
164
165        if ( extractors == null )
166        {
167            extractors = new HashSet<>( mojoDescriptorExtractors.keySet() );
168        }
169
170        ArrayList<MojoDescriptorExtractor> orderedExtractors = new ArrayList<>();
171        for ( String extractorId : extractors )
172        {
173            MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get( extractorId );
174
175            if ( extractor == null )
176            {
177                throw new ExtractionException( "No mojo extractor with '" + extractorId + "' id." );
178            }
179
180            orderedExtractors.add( extractor );
181        }
182
183        Collections.sort( orderedExtractors, MojoDescriptorExtractorComparator.INSTANCE );
184
185        return orderedExtractors;
186    }
187
188    @Override
189    public void setActiveExtractors( Set<String> extractors )
190    {
191        if ( extractors == null )
192        {
193            this.activeExtractors = null;
194        }
195        else
196        {
197            this.activeExtractors = new HashSet<>();
198
199            for ( String extractor : extractors )
200            {
201                if ( StringUtils.isNotEmpty( extractor ) )
202                {
203                    this.activeExtractors.add( extractor );
204                }
205            }
206        }
207    }
208
209}