19
19
package org .apache .maven .plugins .surefire .report ;
20
20
21
21
import java .io .File ;
22
+ import java .io .IOException ;
23
+ import java .net .MalformedURLException ;
24
+ import java .net .URL ;
25
+ import java .net .URLClassLoader ;
26
+ import java .text .MessageFormat ;
22
27
import java .util .ArrayList ;
23
28
import java .util .Iterator ;
24
29
import java .util .List ;
25
30
import java .util .Locale ;
31
+ import java .util .MissingResourceException ;
32
+ import java .util .ResourceBundle ;
26
33
27
34
import org .apache .maven .model .ReportPlugin ;
28
35
import org .apache .maven .plugin .surefire .log .api .ConsoleLogger ;
36
+ import org .apache .maven .plugins .annotations .Component ;
29
37
import org .apache .maven .plugins .annotations .Parameter ;
30
38
import org .apache .maven .project .MavenProject ;
31
39
import org .apache .maven .reporting .AbstractMavenReport ;
32
40
import org .apache .maven .reporting .MavenReportException ;
41
+ import org .apache .maven .settings .Settings ;
33
42
import org .apache .maven .shared .utils .PathTool ;
43
+ import org .codehaus .plexus .i18n .I18N ;
44
+ import org .codehaus .plexus .interpolation .EnvarBasedValueSource ;
45
+ import org .codehaus .plexus .interpolation .InterpolationException ;
46
+ import org .codehaus .plexus .interpolation .PrefixedObjectValueSource ;
47
+ import org .codehaus .plexus .interpolation .PropertiesBasedValueSource ;
48
+ import org .codehaus .plexus .interpolation .RegexBasedInterpolator ;
34
49
35
50
import static java .util .Collections .addAll ;
36
51
import static org .apache .maven .plugins .surefire .report .SurefireReportParser .hasReportFiles ;
@@ -87,6 +102,27 @@ public abstract class AbstractSurefireReportMojo extends AbstractMavenReport {
87
102
@ Parameter (defaultValue = "false" , property = "aggregate" )
88
103
private boolean aggregate ;
89
104
105
+ /**
106
+ * The current user system settings for use in Maven.
107
+ */
108
+ @ Parameter (defaultValue = "${settings}" , readonly = true , required = true )
109
+ private Settings settings ;
110
+
111
+ /**
112
+ * Path for a custom bundle instead of using the default one. <br>
113
+ * Using this field, you could change the texts in the generated reports.
114
+ *
115
+ * @since 3.1.0
116
+ */
117
+ @ Parameter (defaultValue = "src/site/custom/surefire-report.properties" )
118
+ private String customBundle ;
119
+
120
+ /**
121
+ * Internationalization component
122
+ */
123
+ @ Component
124
+ private I18N i18n ;
125
+
90
126
private List <File > resolvedReportsDirectories ;
91
127
92
128
/**
@@ -109,14 +145,6 @@ protected boolean isGeneratedWhenNoResults() {
109
145
return false ;
110
146
}
111
147
112
- public abstract void setTitle (String title );
113
-
114
- public abstract String getTitle ();
115
-
116
- public abstract void setDescription (String description );
117
-
118
- public abstract String getDescription ();
119
-
120
148
/**
121
149
* {@inheritDoc}
122
150
*/
@@ -128,8 +156,9 @@ public void executeReport(Locale locale) throws MavenReportException {
128
156
129
157
SurefireReportRenderer r = new SurefireReportRenderer (
130
158
getSink (),
159
+ getI18N (locale ),
160
+ getI18Nsection (),
131
161
locale ,
132
- getBundle (locale ),
133
162
getConsoleLogger (),
134
163
showSuccess ,
135
164
getReportsDirectories (),
@@ -270,19 +299,44 @@ private String determineXrefLocation() {
270
299
}
271
300
272
301
/**
273
- * {@inheritDoc}
302
+ * @param locale The locale
303
+ * @param key The key to search for
304
+ * @return The text appropriate for the locale.
274
305
*/
275
- @ Override
276
- public String getName (Locale locale ) {
277
- return getBundle (locale ).getReportName ();
306
+ protected String getI18nString (Locale locale , String key ) {
307
+ return getI18N (locale ).getString ("surefire-report" , locale , "report." + getI18Nsection () + '.' + key );
278
308
}
309
+ /**
310
+ * @param locale The local.
311
+ * @return I18N for the locale
312
+ */
313
+ protected I18N getI18N (Locale locale ) {
314
+ if (customBundle != null ) {
315
+ File customBundleFile = new File (customBundle );
316
+ if (customBundleFile .isFile () && customBundleFile .getName ().endsWith (".properties" )) {
317
+ if (!i18n .getClass ().isAssignableFrom (CustomI18N .class )
318
+ || !i18n .getDefaultLanguage ().equals (locale .getLanguage ())) {
319
+ // first load
320
+ i18n = new CustomI18N (project , settings , customBundleFile , locale , i18n );
321
+ }
322
+ }
323
+ }
279
324
325
+ return i18n ;
326
+ }
280
327
/**
281
- * {@inheritDoc}
328
+ * @return The according string for the section.
282
329
*/
283
- @ Override
330
+ protected abstract String getI18Nsection ();
331
+
332
+ /** {@inheritDoc} */
333
+ public String getName (Locale locale ) {
334
+ return getI18nString (locale , "name" );
335
+ }
336
+
337
+ /** {@inheritDoc} */
284
338
public String getDescription (Locale locale ) {
285
- return getBundle (locale ). getReportDescription ( );
339
+ return getI18nString (locale , "description" );
286
340
}
287
341
288
342
/**
@@ -291,18 +345,199 @@ public String getDescription(Locale locale) {
291
345
@ Override
292
346
public abstract String getOutputName ();
293
347
294
- protected abstract LocalizedProperties getBundle (Locale locale , ClassLoader resourceBundleClassLoader );
295
-
296
348
protected final ConsoleLogger getConsoleLogger () {
297
349
return new PluginConsoleLogger (getLog ());
298
350
}
299
351
300
- final LocalizedProperties getBundle (Locale locale ) {
301
- return getBundle (locale , getClass ().getClassLoader ());
302
- }
303
-
304
352
@ Override
305
353
protected MavenProject getProject () {
306
354
return project ;
307
355
}
356
+
357
+ // TODO Review, especially Locale.getDefault()
358
+ private static class CustomI18N implements I18N {
359
+ private final MavenProject project ;
360
+
361
+ private final Settings settings ;
362
+
363
+ private final String bundleName ;
364
+
365
+ private final Locale locale ;
366
+
367
+ private final I18N i18nOriginal ;
368
+
369
+ private ResourceBundle bundle ;
370
+
371
+ private static final Object [] NO_ARGS = new Object [0 ];
372
+
373
+ CustomI18N (MavenProject project , Settings settings , File customBundleFile , Locale locale , I18N i18nOriginal ) {
374
+ super ();
375
+ this .project = project ;
376
+ this .settings = settings ;
377
+ this .locale = locale ;
378
+ this .i18nOriginal = i18nOriginal ;
379
+ this .bundleName = customBundleFile
380
+ .getName ()
381
+ .substring (0 , customBundleFile .getName ().indexOf (".properties" ));
382
+
383
+ URLClassLoader classLoader = null ;
384
+ try {
385
+ classLoader = new URLClassLoader (
386
+ new URL [] {customBundleFile .getParentFile ().toURI ().toURL ()}, null );
387
+ } catch (MalformedURLException e ) {
388
+ // could not happen.
389
+ }
390
+
391
+ this .bundle = ResourceBundle .getBundle (this .bundleName , locale , classLoader );
392
+ if (!this .bundle .getLocale ().getLanguage ().equals (locale .getLanguage ())) {
393
+ this .bundle = ResourceBundle .getBundle (this .bundleName , Locale .getDefault (), classLoader );
394
+ }
395
+ }
396
+
397
+ /** {@inheritDoc} */
398
+ public String getDefaultLanguage () {
399
+ return locale .getLanguage ();
400
+ }
401
+
402
+ /** {@inheritDoc} */
403
+ public String getDefaultCountry () {
404
+ return locale .getCountry ();
405
+ }
406
+
407
+ /** {@inheritDoc} */
408
+ public String getDefaultBundleName () {
409
+ return bundleName ;
410
+ }
411
+
412
+ /** {@inheritDoc} */
413
+ public String [] getBundleNames () {
414
+ return new String [] {bundleName };
415
+ }
416
+
417
+ /** {@inheritDoc} */
418
+ public ResourceBundle getBundle () {
419
+ return bundle ;
420
+ }
421
+
422
+ /** {@inheritDoc} */
423
+ public ResourceBundle getBundle (String bundleName ) {
424
+ return bundle ;
425
+ }
426
+
427
+ /** {@inheritDoc} */
428
+ public ResourceBundle getBundle (String bundleName , String languageHeader ) {
429
+ return bundle ;
430
+ }
431
+
432
+ /** {@inheritDoc} */
433
+ public ResourceBundle getBundle (String bundleName , Locale locale ) {
434
+ return bundle ;
435
+ }
436
+
437
+ /** {@inheritDoc} */
438
+ public Locale getLocale (String languageHeader ) {
439
+ return new Locale (languageHeader );
440
+ }
441
+
442
+ /** {@inheritDoc} */
443
+ public String getString (String key ) {
444
+ return getString (bundleName , locale , key );
445
+ }
446
+
447
+ /** {@inheritDoc} */
448
+ public String getString (String key , Locale locale ) {
449
+ return getString (bundleName , locale , key );
450
+ }
451
+
452
+ /** {@inheritDoc} */
453
+ public String getString (String bundleName , Locale locale , String key ) {
454
+ String value ;
455
+
456
+ if (locale == null ) {
457
+ locale = getLocale (null );
458
+ }
459
+
460
+ ResourceBundle rb = getBundle (bundleName , locale );
461
+ value = getStringOrNull (rb , key );
462
+
463
+ if (value == null ) {
464
+ // try to load default
465
+ value = i18nOriginal .getString (bundleName , locale , key );
466
+ }
467
+
468
+ if (!value .contains ("${" )) {
469
+ return value ;
470
+ }
471
+
472
+ final RegexBasedInterpolator interpolator = new RegexBasedInterpolator ();
473
+ try {
474
+ interpolator .addValueSource (new EnvarBasedValueSource ());
475
+ } catch (final IOException e ) {
476
+ // In which cases could this happen? And what should we do?
477
+ }
478
+
479
+ interpolator .addValueSource (new PropertiesBasedValueSource (System .getProperties ()));
480
+ interpolator .addValueSource (new PropertiesBasedValueSource (project .getProperties ()));
481
+ interpolator .addValueSource (new PrefixedObjectValueSource ("project" , project ));
482
+ interpolator .addValueSource (new PrefixedObjectValueSource ("pom" , project ));
483
+ interpolator .addValueSource (new PrefixedObjectValueSource ("settings" , settings ));
484
+
485
+ try {
486
+ value = interpolator .interpolate (value );
487
+ } catch (final InterpolationException e ) {
488
+ // What does this exception mean?
489
+ }
490
+
491
+ return value ;
492
+ }
493
+
494
+ /** {@inheritDoc} */
495
+ public String format (String key , Object arg1 ) {
496
+ return format (bundleName , locale , key , new Object [] {arg1 });
497
+ }
498
+
499
+ /** {@inheritDoc} */
500
+ public String format (String key , Object arg1 , Object arg2 ) {
501
+ return format (bundleName , locale , key , new Object [] {arg1 , arg2 });
502
+ }
503
+
504
+ /** {@inheritDoc} */
505
+ public String format (String bundleName , Locale locale , String key , Object arg1 ) {
506
+ return format (bundleName , locale , key , new Object [] {arg1 });
507
+ }
508
+
509
+ /** {@inheritDoc} */
510
+ public String format (String bundleName , Locale locale , String key , Object arg1 , Object arg2 ) {
511
+ return format (bundleName , locale , key , new Object [] {arg1 , arg2 });
512
+ }
513
+
514
+ /** {@inheritDoc} */
515
+ public String format (String bundleName , Locale locale , String key , Object [] args ) {
516
+ if (locale == null ) {
517
+ locale = getLocale (null );
518
+ }
519
+
520
+ String value = getString (bundleName , locale , key );
521
+ if (args == null ) {
522
+ args = NO_ARGS ;
523
+ }
524
+
525
+ MessageFormat messageFormat = new MessageFormat ("" );
526
+ messageFormat .setLocale (locale );
527
+ messageFormat .applyPattern (value );
528
+
529
+ return messageFormat .format (args );
530
+ }
531
+
532
+ private String getStringOrNull (ResourceBundle rb , String key ) {
533
+ if (rb != null ) {
534
+ try {
535
+ return rb .getString (key );
536
+ } catch (MissingResourceException ignored ) {
537
+ // intentional
538
+ }
539
+ }
540
+ return null ;
541
+ }
542
+ }
308
543
}
0 commit comments