1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.ci.maven.mojo;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.lang.reflect.Field;
21 import java.util.List;
22 import java.util.Properties;
23
24 import org.apache.commons.io.IOUtils;
25 import org.apache.commons.lang.reflect.FieldUtils;
26 import org.apache.maven.artifact.factory.ArtifactFactory;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.execution.MavenSession;
29 import org.apache.maven.plugin.AbstractMojo;
30 import org.apache.maven.plugin.MojoExecutionException;
31 import org.apache.maven.plugin.MojoFailureException;
32 import org.apache.maven.plugin.PluginManager;
33 import org.apache.maven.plugin.logging.Log;
34 import org.apache.maven.plugins.help.DescribeMojo;
35 import org.apache.maven.project.MavenProject;
36 import org.apache.maven.project.MavenProjectBuilder;
37 import org.apache.maven.settings.Settings;
38
39
40
41
42
43
44
45
46
47
48 public final class HelpMojo extends AbstractMojo
49 {
50
51
52
53
54
55
56
57
58
59
60
61
62
63 private ArtifactFactory artifactFactory;
64
65
66
67
68
69
70 private PluginManager pluginManager;
71
72
73
74
75
76
77
78
79 private MavenProjectBuilder projectBuilder;
80
81
82
83
84
85
86
87
88
89
90 private MavenProject project;
91
92
93
94
95
96
97
98
99
100
101 private Settings settings;
102
103
104
105
106
107
108
109
110
111
112 private MavenSession session;
113
114
115
116
117
118
119
120
121
122
123 private ArtifactRepository localRepository;
124
125
126
127
128
129
130
131
132
133 private List<?> remoteRepositories;
134
135
136
137
138
139
140
141
142
143
144 private String goal;
145
146
147
148
149
150
151
152
153
154
155
156
157 private boolean detail;
158
159
160
161
162
163
164
165
166 private boolean medium;
167
168
169
170
171
172
173
174
175 private boolean minimal;
176
177
178
179
180
181
182 private String pluginId;
183
184
185
186
187
188 private String pluginShortId;
189
190
191
192
193
194
195
196
197 private final class LogCatcher implements Log
198 {
199
200
201
202
203
204
205
206
207
208 private final Log delegate;
209
210
211
212
213
214 private LogCatcher(final Log delegate)
215 {
216 this.delegate = delegate;
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 @Override
237 public boolean isDebugEnabled()
238 {
239 return delegate.isDebugEnabled();
240 }
241
242
243
244
245
246
247 @Override
248 public void debug(final CharSequence content)
249 {
250 delegate.debug(content);
251 }
252
253
254
255
256
257
258
259 @Override
260 public void debug(final CharSequence content, final Throwable error)
261 {
262 delegate.debug(content, error);
263 }
264
265
266
267
268
269
270 @Override
271 public void debug(final Throwable error)
272 {
273 delegate.debug(error);
274 }
275
276
277
278
279
280
281 @Override
282 public boolean isInfoEnabled()
283 {
284 return delegate.isInfoEnabled();
285 }
286
287
288
289
290
291
292 @Override
293 public void info(final CharSequence content)
294 {
295 final String string = content.toString();
296
297 if (string.startsWith(pluginId))
298 {
299 final String strippedContent = stripAllGoals(string);
300 delegate.info(strippedContent);
301 }
302 else if (string.startsWith("Mojo: '" + pluginShortId))
303 {
304 final String strippedContent = stripSingleGoal(string);
305 delegate.info(strippedContent);
306 }
307 else
308 {
309 delegate.info(content);
310 }
311 }
312
313 private String stripAllGoals(final String string)
314 {
315 final String tag = "Goal Prefix: " + pluginShortId;
316 final int startIndex = string.indexOf(tag) + tag.length();
317 final String fragment = string.substring(startIndex).trim();
318 final String replaced = replaceHelpIds(fragment);
319 return replaced;
320 }
321
322 private String replaceHelpIds(final String fragment)
323 {
324 final String replaced =
325 fragment.replaceAll("help:describe", pluginShortId + ":help")
326 .replace(" [...]", "");
327 return replaced;
328 }
329
330 private String stripSingleGoal(final String string)
331 {
332 final String replaced = replaceHelpIds(string);
333 return replaced;
334 }
335
336
337
338
339
340
341
342 @Override
343 public void info(final CharSequence content, final Throwable error)
344 {
345 delegate.info(content, error);
346 }
347
348
349
350
351
352
353 @Override
354 public void info(final Throwable error)
355 {
356 delegate.info(error);
357 }
358
359
360
361
362
363
364 @Override
365 public boolean isWarnEnabled()
366 {
367 return delegate.isWarnEnabled();
368 }
369
370
371
372
373
374
375 @Override
376 public void warn(final CharSequence content)
377 {
378 delegate.warn(content);
379 }
380
381
382
383
384
385
386
387 @Override
388 public void warn(final CharSequence content, final Throwable error)
389 {
390 delegate.warn(content, error);
391 }
392
393
394
395
396
397
398 @Override
399 public void warn(final Throwable error)
400 {
401 delegate.warn(error);
402 }
403
404
405
406
407
408
409 @Override
410 public boolean isErrorEnabled()
411 {
412 return delegate.isErrorEnabled();
413 }
414
415
416
417
418
419
420 @Override
421 public void error(final CharSequence content)
422 {
423 delegate.error(content);
424 }
425
426
427
428
429
430
431
432 @Override
433 public void error(final CharSequence content, final Throwable error)
434 {
435 delegate.error(content, error);
436 }
437
438
439
440
441
442
443 @Override
444 public void error(final Throwable error)
445 {
446 delegate.error(error);
447 }
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465 @Override
466 public void execute() throws MojoExecutionException,
467 MojoFailureException
468 {
469 initPluginInfo();
470
471 if (goal != null)
472 {
473 this.detail = true;
474 }
475
476 final DescribeMojo describeMojo = new DescribeMojo()
477 {
478 @Override
479 public Log getLog()
480 {
481 return new LogCatcher(super.getLog());
482 }
483 };
484
485 setValue(describeMojo, "artifactFactory", artifactFactory);
486 setValue(describeMojo, "pluginManager", pluginManager);
487 setValue(describeMojo, "projectBuilder", projectBuilder);
488
489 setValue(describeMojo, "project", project);
490 setValue(describeMojo, "settings", settings);
491 setValue(describeMojo, "session", session);
492
493 setValue(describeMojo, "localRepository", localRepository);
494 setValue(describeMojo, "remoteRepositories", remoteRepositories);
495
496 setValue(describeMojo, "plugin", pluginId);
497 setValue(describeMojo, "goal", goal);
498
499 setValue(describeMojo, "detail", detail);
500 setValue(describeMojo, "medium", medium);
501 setValue(describeMojo, "minimal", minimal);
502
503 try
504 {
505 describeMojo.execute();
506 }
507 catch (final MojoExecutionException e)
508 {
509 throw new MojoExecutionException(createErrorMessage(), e);
510 }
511 catch (final MojoFailureException e)
512 {
513 throw new MojoExecutionException(createErrorMessage(), e);
514 }
515 }
516
517 private void initPluginInfo() throws MojoExecutionException
518 {
519 final Properties properties = new Properties();
520 final InputStream inStream =
521 getClass().getResourceAsStream("/META-INF/build.properties");
522 try
523 {
524 properties.load(inStream);
525
526 final String groupId = properties.getProperty("build.groupId");
527 final String artifactId = properties.getProperty("build.artifactId");
528 final String version = properties.getProperty("build.version");
529
530 this.pluginId = groupId + ':' + artifactId + ':' + version;
531
532 final int endIndexShortId = artifactId.indexOf('-');
533 this.pluginShortId = artifactId.substring(0, endIndexShortId);
534 }
535 catch (final IOException e)
536 {
537 throw new MojoExecutionException("Cannot determine plugin properties.", e);
538 }
539 finally
540 {
541 IOUtils.closeQuietly(inStream);
542 }
543 }
544
545 private String createErrorMessage()
546 {
547 return "Cannot provide help information"
548 + (goal != null ? " on " + goal : "") + '.';
549 }
550
551 private static void setValue(final Object object, final String fieldName,
552 final Object value) throws MojoFailureException
553 {
554 final Class<?> type = object.getClass();
555
556 try
557 {
558 final Field field = FieldUtils.getField(type, fieldName, true);
559 field.setAccessible(true);
560 field.set(object, value);
561 }
562 catch (final Exception e)
563 {
564 throw new MojoFailureException("Cannot change describe mojo's field '"
565 + fieldName + "'.", e);
566 }
567 }
568
569
570
571 }