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.plugin.plugin.report;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.Locale;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.maven.doxia.markup.Markup;
27  import org.apache.maven.doxia.sink.Sink;
28  import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
29  import org.apache.maven.plugin.descriptor.MojoDescriptor;
30  import org.apache.maven.plugin.descriptor.PluginDescriptor;
31  import org.apache.maven.project.MavenProject;
32  import org.apache.maven.tools.plugin.util.PluginUtils;
33  import org.codehaus.plexus.i18n.I18N;
34  
35  /**
36   * Generates an overview page with the list of goals
37   * and a link to the goal's page.
38   */
39  class PluginOverviewRenderer extends AbstractPluginReportRenderer {
40  
41      private final List<RequirementsHistory> requirementsHistories;
42  
43      private final PluginDescriptor pluginDescriptor;
44  
45      private final boolean hasExtensionsToLoad;
46  
47      /**
48       * @param sink                  not null
49       * @param i18n                  not null
50       * @param locale                not null
51       * @param project               not null
52       * @param requirementsHistories not null
53       * @param pluginDescriptor      not null
54       */
55      PluginOverviewRenderer(
56              Sink sink,
57              I18N i18n,
58              Locale locale,
59              MavenProject project,
60              List<RequirementsHistory> requirementsHistories,
61              PluginDescriptor pluginDescriptor,
62              boolean hasExtensionsToLoad) {
63          super(sink, locale, i18n, project);
64  
65          this.requirementsHistories = requirementsHistories;
66  
67          this.pluginDescriptor = pluginDescriptor;
68  
69          this.hasExtensionsToLoad = hasExtensionsToLoad;
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      @Override
76      protected void renderBody() {
77          startSection(getTitle());
78  
79          if (!(pluginDescriptor.getMojos() != null && pluginDescriptor.getMojos().size() > 0)) {
80              paragraph(getI18nString("goals.nogoal"));
81              endSection();
82              return;
83          }
84  
85          boolean hasMavenReport = false;
86          for (MojoDescriptor mojo : pluginDescriptor.getMojos()) {
87              if (PluginUtils.isMavenReport(mojo.getImplementation(), project)) {
88                  hasMavenReport = true;
89                  break;
90              }
91          }
92  
93          paragraph(getI18nString("description"));
94  
95          renderGoalsSection(hasMavenReport);
96  
97          renderSystemRequirementsSection();
98  
99          renderRequirementsHistoriesSection();
100 
101         renderUsageSection(hasMavenReport);
102 
103         endSection();
104     }
105 
106     private void renderGoalsSection(boolean hasMavenReport) {
107         startSection(getI18nString("goals"));
108 
109         paragraph(getI18nString("goals.intro"));
110 
111         startTable();
112 
113         String goalColumnName = getI18nString("goals.column.goal");
114         String isMavenReport = getI18nString("goals.column.isMavenReport");
115         String descriptionColumnName = getI18nString("goals.column.description");
116         if (hasMavenReport) {
117             tableHeader(new String[] {goalColumnName, isMavenReport, descriptionColumnName});
118         } else {
119             tableHeader(new String[] {goalColumnName, descriptionColumnName});
120         }
121 
122         List<MojoDescriptor> mojos = new ArrayList<>();
123         mojos.addAll(pluginDescriptor.getMojos());
124         PluginUtils.sortMojos(mojos);
125         for (MojoDescriptor mojo : mojos) {
126             sink.tableRow();
127 
128             String goalName = mojo.getFullGoalName();
129             /*
130              * Added ./ to define a relative path
131              * @see AbstractMavenReportRenderer#getValidHref(java.lang.String)
132              */
133             String goalDocumentationLink = "./" + mojo.getGoal() + "-mojo.html";
134             sink.tableCell();
135             link(goalDocumentationLink, goalName);
136             sink.tableCell_();
137 
138             if (hasMavenReport) {
139                 if (PluginUtils.isMavenReport(mojo.getImplementation(), project)) {
140                     tableCell(getI18nString("isReport"));
141                 } else {
142                     tableCell(getI18nString("isNotReport"));
143                 }
144             }
145 
146             sink.tableCell();
147             if (StringUtils.isNotEmpty(mojo.getDeprecated())) {
148                 sink.division();
149                 sink.inline(SinkEventAttributeSet.Semantics.STRONG);
150                 sink.text(getI18nString("goal.deprecated"));
151                 sink.text(".");
152                 sink.inline_();
153                 sink.text(" ");
154                 sink.rawText(mojo.getDeprecated());
155                 sink.division_();
156                 sink.lineBreak();
157             }
158 
159             String description;
160             if (StringUtils.isNotEmpty(mojo.getDescription())) {
161                 description = mojo.getDescription();
162             } else {
163                 description = getI18nString("goal.nodescription");
164             }
165             sink.rawText(description);
166             sink.tableCell_();
167             sink.tableRow_();
168         }
169 
170         endTable();
171 
172         endSection();
173     }
174 
175     private void renderSystemRequirementsSection() {
176         startSection(getI18nString("systemrequirements"));
177 
178         paragraph(getI18nString("systemrequirements.intro"));
179 
180         startTable();
181 
182         String maven = RequirementsHistory.discoverMavenRequirement(project, pluginDescriptor);
183         sink.tableRow();
184         tableCell(getI18nString("systemrequirements.maven"));
185         tableCell((maven != null ? maven : getI18nString("systemrequirements.nominimum")));
186         sink.tableRow_();
187 
188         String jdk = RequirementsHistory.discoverJdkRequirement(project, pluginDescriptor);
189         sink.tableRow();
190         tableCell(getI18nString("systemrequirements.jdk"));
191         tableCell((jdk != null ? jdk : getI18nString("systemrequirements.nominimum")));
192         sink.tableRow_();
193 
194         endTable();
195 
196         endSection();
197     }
198 
199     private void renderRequirementsHistoriesSection() {
200         if (requirementsHistories.isEmpty()) {
201             return;
202         }
203 
204         startSection(getI18nString("systemrequirements.history"));
205         paragraph(getI18nString("systemrequirements.history.intro"));
206 
207         startTable();
208         tableHeader(new String[] {
209             getI18nString("systemrequirements.history.version"),
210             getI18nString("systemrequirements.history.maven"),
211             getI18nString("systemrequirements.history.jdk")
212         });
213 
214         // group by same requirements
215         final List<List<RequirementsHistory>> requirementsVersions = new ArrayList<>();
216         requirementsHistories.forEach(requirementsHistory -> {
217             List<RequirementsHistory> current =
218                     requirementsVersions.isEmpty() ? null : requirementsVersions.get(requirementsVersions.size() - 1);
219             if (current != null && current.get(0).hasSameRequirements(requirementsHistory)) {
220                 current.add(requirementsHistory);
221             } else {
222                 current = new ArrayList<>();
223                 current.add(requirementsHistory);
224                 requirementsVersions.add(current);
225             }
226         });
227 
228         // render by common requirements
229         requirementsVersions.forEach(requirementsHistories -> {
230             sink.tableRow();
231             RequirementsHistory current = requirementsHistories.get(0);
232             if (requirementsHistories.size() == 1) {
233                 tableCell(current.getVersion());
234             } else {
235                 RequirementsHistory from = requirementsHistories.get(requirementsHistories.size() - 1);
236                 tableCell("from " + from.getVersion() + " to " + current.getVersion());
237             }
238             tableCell(current.getMaven());
239             tableCell(current.getJdk());
240             sink.tableRow_();
241         });
242         endTable();
243 
244         endSection();
245     }
246 
247     /**
248      * Render the section about the usage of the plugin.
249      *
250      * @param hasMavenReport If the plugin has a report or not
251      */
252     private void renderUsageSection(boolean hasMavenReport) {
253         startSection(getI18nString("usage"));
254 
255         // Configuration
256         paragraph(getI18nString("usage.intro"));
257 
258         StringBuilder sb = new StringBuilder();
259         sb.append("<project>").append(Markup.EOL);
260         sb.append("  ...").append(Markup.EOL);
261         sb.append("  <build>").append(Markup.EOL);
262         sb.append("    <!-- " + getI18nString("usage.pluginManagement") + " -->")
263                 .append(Markup.EOL);
264         sb.append("    <pluginManagement>").append(Markup.EOL);
265         sb.append("      <plugins>").append(Markup.EOL);
266         sb.append("        <plugin>").append(Markup.EOL);
267         sb.append("          <groupId>")
268                 .append(pluginDescriptor.getGroupId())
269                 .append("</groupId>")
270                 .append(Markup.EOL);
271         sb.append("          <artifactId>")
272                 .append(pluginDescriptor.getArtifactId())
273                 .append("</artifactId>")
274                 .append(Markup.EOL);
275         sb.append("          <version>")
276                 .append(pluginDescriptor.getVersion())
277                 .append("</version>")
278                 .append(Markup.EOL);
279         if (hasExtensionsToLoad) {
280             sb.append("          <extensions>true</extensions>").append(Markup.EOL);
281         }
282         sb.append("        </plugin>").append(Markup.EOL);
283         sb.append("        ...").append(Markup.EOL);
284         sb.append("      </plugins>").append(Markup.EOL);
285         sb.append("    </pluginManagement>").append(Markup.EOL);
286         sb.append("    <!-- " + getI18nString("usage.plugins") + " -->").append(Markup.EOL);
287         sb.append("    <plugins>").append(Markup.EOL);
288         sb.append("      <plugin>").append(Markup.EOL);
289         sb.append("        <groupId>")
290                 .append(pluginDescriptor.getGroupId())
291                 .append("</groupId>")
292                 .append(Markup.EOL);
293         sb.append("        <artifactId>")
294                 .append(pluginDescriptor.getArtifactId())
295                 .append("</artifactId>")
296                 .append(Markup.EOL);
297         sb.append("      </plugin>").append(Markup.EOL);
298         sb.append("      ...").append(Markup.EOL);
299         sb.append("    </plugins>").append(Markup.EOL);
300         sb.append("  </build>").append(Markup.EOL);
301 
302         if (hasMavenReport) {
303             sb.append("  ...").append(Markup.EOL);
304             sb.append("  <!-- " + getI18nString("usage.reporting") + " -->").append(Markup.EOL);
305             sb.append("  <reporting>").append(Markup.EOL);
306             sb.append("    <plugins>").append(Markup.EOL);
307             sb.append("      <plugin>").append(Markup.EOL);
308             sb.append("        <groupId>")
309                     .append(pluginDescriptor.getGroupId())
310                     .append("</groupId>")
311                     .append(Markup.EOL);
312             sb.append("        <artifactId>")
313                     .append(pluginDescriptor.getArtifactId())
314                     .append("</artifactId>")
315                     .append(Markup.EOL);
316             sb.append("        <version>")
317                     .append(pluginDescriptor.getVersion())
318                     .append("</version>")
319                     .append(Markup.EOL);
320             sb.append("      </plugin>").append(Markup.EOL);
321             sb.append("      ...").append(Markup.EOL);
322             sb.append("    </plugins>").append(Markup.EOL);
323             sb.append("  </reporting>").append(Markup.EOL);
324         }
325 
326         sb.append("  ...").append(Markup.EOL);
327         sb.append("</project>");
328 
329         verbatimText(sb.toString());
330 
331         sink.paragraph();
332         linkPatternedText(getI18nString("configuration.end"));
333         sink.paragraph_();
334 
335         endSection();
336     }
337 
338     @Override
339     protected String getI18nSection() {
340         return "plugin";
341     }
342 }