Skip to content

Commit 6718f14

Browse files
committed
[SUREFIRE-2160] Replace LocalizedProperties with (Custom)I18N approach from MPIR
1 parent 33d30c6 commit 6718f14

File tree

21 files changed

+530
-321
lines changed

21 files changed

+530
-321
lines changed

maven-surefire-report-plugin/src/main/java/org/apache/maven/plugins/surefire/report/AbstractSurefireReportMojo.java

Lines changed: 257 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,33 @@
1919
package org.apache.maven.plugins.surefire.report;
2020

2121
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;
2227
import java.util.ArrayList;
2328
import java.util.Iterator;
2429
import java.util.List;
2530
import java.util.Locale;
31+
import java.util.MissingResourceException;
32+
import java.util.ResourceBundle;
2633

2734
import org.apache.maven.model.ReportPlugin;
2835
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
36+
import org.apache.maven.plugins.annotations.Component;
2937
import org.apache.maven.plugins.annotations.Parameter;
3038
import org.apache.maven.project.MavenProject;
3139
import org.apache.maven.reporting.AbstractMavenReport;
3240
import org.apache.maven.reporting.MavenReportException;
41+
import org.apache.maven.settings.Settings;
3342
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;
3449

3550
import static java.util.Collections.addAll;
3651
import static org.apache.maven.plugins.surefire.report.SurefireReportParser.hasReportFiles;
@@ -87,6 +102,27 @@ public abstract class AbstractSurefireReportMojo extends AbstractMavenReport {
87102
@Parameter(defaultValue = "false", property = "aggregate")
88103
private boolean aggregate;
89104

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+
90126
private List<File> resolvedReportsDirectories;
91127

92128
/**
@@ -109,14 +145,6 @@ protected boolean isGeneratedWhenNoResults() {
109145
return false;
110146
}
111147

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-
120148
/**
121149
* {@inheritDoc}
122150
*/
@@ -128,8 +156,9 @@ public void executeReport(Locale locale) throws MavenReportException {
128156

129157
SurefireReportRenderer r = new SurefireReportRenderer(
130158
getSink(),
159+
getI18N(locale),
160+
getI18Nsection(),
131161
locale,
132-
getBundle(locale),
133162
getConsoleLogger(),
134163
showSuccess,
135164
getReportsDirectories(),
@@ -270,19 +299,44 @@ private String determineXrefLocation() {
270299
}
271300

272301
/**
273-
* {@inheritDoc}
302+
* @param locale The locale
303+
* @param key The key to search for
304+
* @return The text appropriate for the locale.
274305
*/
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);
278308
}
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+
}
279324

325+
return i18n;
326+
}
280327
/**
281-
* {@inheritDoc}
328+
* @return The according string for the section.
282329
*/
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} */
284338
public String getDescription(Locale locale) {
285-
return getBundle(locale).getReportDescription();
339+
return getI18nString(locale, "description");
286340
}
287341

288342
/**
@@ -291,18 +345,199 @@ public String getDescription(Locale locale) {
291345
@Override
292346
public abstract String getOutputName();
293347

294-
protected abstract LocalizedProperties getBundle(Locale locale, ClassLoader resourceBundleClassLoader);
295-
296348
protected final ConsoleLogger getConsoleLogger() {
297349
return new PluginConsoleLogger(getLog());
298350
}
299351

300-
final LocalizedProperties getBundle(Locale locale) {
301-
return getBundle(locale, getClass().getClassLoader());
302-
}
303-
304352
@Override
305353
protected MavenProject getProject() {
306354
return project;
307355
}
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+
}
308543
}

0 commit comments

Comments
 (0)