001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.maven.tools.plugin.scanner;
020
021import javax.inject.Inject;
022import javax.inject.Named;
023
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.HashMap;
027import java.util.HashSet;
028import java.util.List;
029import java.util.Map;
030import java.util.Set;
031
032import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
033import org.apache.maven.plugin.descriptor.MojoDescriptor;
034import org.apache.maven.tools.plugin.PluginToolsRequest;
035import org.apache.maven.tools.plugin.extractor.ExtractionException;
036import org.apache.maven.tools.plugin.extractor.GroupKey;
037import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
038import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractorComparator;
039import org.slf4j.Logger;
040import org.slf4j.LoggerFactory;
041
042/**
043 * @author jdcasey
044 */
045@Named
046public class DefaultMojoScanner implements MojoScanner {
047    private static final Logger LOGGER = LoggerFactory.getLogger("standalone-scanner-logger");
048
049    private Map<String, MojoDescriptorExtractor> mojoDescriptorExtractors;
050
051    /**
052     * The names of the active extractors
053     */
054    private Set<String> activeExtractors;
055
056    /**
057     * Default constructor
058     *
059     * @param extractors not null
060     */
061    @Inject
062    public DefaultMojoScanner(Map<String, MojoDescriptorExtractor> extractors) {
063        this.mojoDescriptorExtractors = extractors;
064    }
065
066    /**
067     * Empty constructor
068     */
069    public DefaultMojoScanner() {
070        // nop
071    }
072
073    /**
074     * {@inheritDoc}
075     */
076    @Override
077    public void populatePluginDescriptor(PluginToolsRequest request)
078            throws ExtractionException, InvalidPluginDescriptorException {
079
080        int numMojoDescriptors = 0;
081
082        List<MojoDescriptorExtractor> orderedExtractors = getOrderedExtractors();
083
084        LOGGER.debug("Using " + orderedExtractors.size() + " mojo extractors.");
085
086        HashMap<String, Integer> groupStats = new HashMap<>();
087
088        for (MojoDescriptorExtractor extractor : orderedExtractors) {
089            GroupKey groupKey = extractor.getGroupKey();
090            String extractorId = extractor.getName();
091
092            LOGGER.debug("Applying " + extractorId + " mojo extractor");
093
094            List<MojoDescriptor> extractorDescriptors = extractor.execute(request);
095
096            int extractorDescriptorsCount = extractorDescriptors.size();
097
098            LOGGER.info(extractorId + " mojo extractor found " + extractorDescriptorsCount + " mojo descriptor"
099                    + (extractorDescriptorsCount > 1 ? "s" : "") + ".");
100            numMojoDescriptors += extractorDescriptorsCount;
101
102            if (extractor.isDeprecated() && extractorDescriptorsCount > 0) {
103                LOGGER.warn("");
104                LOGGER.warn("Deprecated extractor " + extractorId
105                        + " extracted " + extractorDescriptorsCount
106                        + " descriptor" + (extractorDescriptorsCount > 1 ? "s" : "")
107                        + ". Upgrade your Mojo definitions.");
108                if (GroupKey.JAVA_GROUP.equals(groupKey.getGroup())) {
109                    LOGGER.warn("You should use Mojo Annotations instead of Javadoc tags.");
110                }
111                LOGGER.warn("");
112            }
113
114            if (groupStats.containsKey(groupKey.getGroup())) {
115                groupStats.put(groupKey.getGroup(), groupStats.get(groupKey.getGroup()) + extractorDescriptorsCount);
116            } else {
117                groupStats.put(groupKey.getGroup(), extractorDescriptorsCount);
118            }
119
120            for (MojoDescriptor descriptor : extractorDescriptors) {
121                LOGGER.debug("Adding mojo: " + descriptor + " to plugin descriptor.");
122
123                descriptor.setPluginDescriptor(request.getPluginDescriptor());
124
125                request.getPluginDescriptor().addMojo(descriptor);
126            }
127        }
128
129        LOGGER.debug("Discovered descriptors by groups: " + groupStats);
130
131        if (numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound()) {
132            throw new InvalidPluginDescriptorException("No mojo definitions were found for plugin: "
133                    + request.getPluginDescriptor().getPluginLookupKey() + ".");
134        }
135    }
136
137    /**
138     * Returns a list of extractors sorted by {@link MojoDescriptorExtractor#getGroupKey()}s, never {@code null}.
139     */
140    private List<MojoDescriptorExtractor> getOrderedExtractors() throws ExtractionException {
141        Set<String> extractors = activeExtractors;
142
143        if (extractors == null) {
144            extractors = new HashSet<>(mojoDescriptorExtractors.keySet());
145        }
146
147        ArrayList<MojoDescriptorExtractor> orderedExtractors = new ArrayList<>();
148        for (String extractorId : extractors) {
149            MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get(extractorId);
150
151            if (extractor == null) {
152                throw new ExtractionException("No mojo extractor with '" + extractorId + "' id.");
153            }
154
155            orderedExtractors.add(extractor);
156        }
157
158        Collections.sort(orderedExtractors, MojoDescriptorExtractorComparator.INSTANCE);
159
160        return orderedExtractors;
161    }
162
163    @Override
164    public void setActiveExtractors(Set<String> extractors) {
165        if (extractors == null) {
166            this.activeExtractors = null;
167        } else {
168            this.activeExtractors = new HashSet<>();
169
170            for (String extractor : extractors) {
171                if (extractor != null && !extractor.isEmpty()) {
172                    this.activeExtractors.add(extractor);
173                }
174            }
175        }
176    }
177}