View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.tools.plugin.scanner;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Set;
31  
32  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
33  import org.apache.maven.plugin.descriptor.MojoDescriptor;
34  import org.apache.maven.tools.plugin.PluginToolsRequest;
35  import org.apache.maven.tools.plugin.extractor.ExtractionException;
36  import org.apache.maven.tools.plugin.extractor.GroupKey;
37  import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
38  import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractorComparator;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  /**
43   * @author jdcasey
44   */
45  @Named
46  public class DefaultMojoScanner implements MojoScanner {
47      private static final Logger LOGGER = LoggerFactory.getLogger("standalone-scanner-logger");
48  
49      private Map<String, MojoDescriptorExtractor> mojoDescriptorExtractors;
50  
51      /**
52       * The names of the active extractors
53       */
54      private Set<String> activeExtractors;
55  
56      /**
57       * Default constructor
58       *
59       * @param extractors not null
60       */
61      @Inject
62      public DefaultMojoScanner(Map<String, MojoDescriptorExtractor> extractors) {
63          this.mojoDescriptorExtractors = extractors;
64      }
65  
66      /**
67       * Empty constructor
68       */
69      public DefaultMojoScanner() {
70          // nop
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      public void populatePluginDescriptor(PluginToolsRequest request)
78              throws ExtractionException, InvalidPluginDescriptorException {
79  
80          int numMojoDescriptors = 0;
81  
82          List<MojoDescriptorExtractor> orderedExtractors = getOrderedExtractors();
83  
84          LOGGER.debug("Using " + orderedExtractors.size() + " mojo extractors.");
85  
86          HashMap<String, Integer> groupStats = new HashMap<>();
87  
88          for (MojoDescriptorExtractor extractor : orderedExtractors) {
89              GroupKey groupKey = extractor.getGroupKey();
90              String extractorId = extractor.getName();
91  
92              LOGGER.debug("Applying " + extractorId + " mojo extractor");
93  
94              List<MojoDescriptor> extractorDescriptors = extractor.execute(request);
95  
96              int extractorDescriptorsCount = extractorDescriptors.size();
97  
98              LOGGER.info(extractorId + " mojo extractor found " + extractorDescriptorsCount + " mojo descriptor"
99                      + (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 }