1 package org.apache.maven.report.projectinfo;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.factory.ArtifactFactory;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.resolver.ArtifactResolver;
26 import org.apache.maven.doxia.sink.render.RenderingContext;
27 import org.apache.maven.doxia.site.decoration.Body;
28 import org.apache.maven.doxia.site.decoration.DecorationModel;
29 import org.apache.maven.doxia.siterenderer.Renderer;
30 import org.apache.maven.doxia.siterenderer.RendererException;
31 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
32 import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
33 import org.apache.maven.doxia.tools.SiteTool;
34 import org.apache.maven.doxia.tools.SiteToolException;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.plugins.annotations.Component;
37 import org.apache.maven.plugins.annotations.Parameter;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.reporting.AbstractMavenReport;
40 import org.apache.maven.reporting.MavenReportException;
41 import org.apache.maven.settings.Settings;
42 import org.codehaus.plexus.i18n.I18N;
43 import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
44 import org.codehaus.plexus.interpolation.InterpolationException;
45 import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
46 import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
47 import org.codehaus.plexus.interpolation.RegexBasedInterpolator;
48 import org.codehaus.plexus.util.IOUtil;
49
50
51 import java.io.File;
52 import java.io.FileOutputStream;
53 import java.io.IOException;
54 import java.io.OutputStreamWriter;
55 import java.io.Writer;
56 import java.net.MalformedURLException;
57 import java.net.URL;
58 import java.net.URLClassLoader;
59 import java.text.MessageFormat;
60 import java.util.HashMap;
61 import java.util.List;
62 import java.util.Locale;
63 import java.util.Map;
64 import java.util.MissingResourceException;
65 import java.util.ResourceBundle;
66
67
68
69
70
71
72
73
74 public abstract class AbstractProjectInfoReport
75 extends AbstractMavenReport
76 {
77
78
79
80
81
82
83
84
85
86 @Component
87 protected SiteTool siteTool;
88
89
90
91
92 @Component
93 protected Renderer siteRenderer;
94
95
96
97
98 @Component
99 protected ArtifactResolver resolver;
100
101
102
103
104 @Component
105 protected ArtifactFactory factory;
106
107
108
109
110 @Component
111 private I18N i18n;
112
113
114
115
116
117
118
119
120
121
122 @Parameter( property = "project.reporting.outputDirectory", required = true )
123 protected File outputDirectory;
124
125
126
127
128 @Component
129 protected MavenProject project;
130
131
132
133
134 @Parameter( property = "localRepository", required = true, readonly = true )
135 protected ArtifactRepository localRepository;
136
137
138
139
140
141
142 @Parameter( property = "project.remoteArtifactRepositories" )
143 protected List<ArtifactRepository> remoteRepositories;
144
145
146
147
148
149
150 @Component
151 protected Settings settings;
152
153
154
155
156
157
158
159 @Parameter( defaultValue = "${project.basedir}/src/site/custom/project-info-report.properties" )
160 protected String customBundle;
161
162
163
164
165
166 @Override
167 public void execute()
168 throws MojoExecutionException
169 {
170 if ( !canGenerateReport() )
171 {
172 return;
173 }
174
175
176 Writer writer = null;
177 try
178 {
179 String filename = getOutputName() + ".html";
180
181 DecorationModel model = new DecorationModel();
182 model.setBody( new Body() );
183
184 Map<String, Object> attributes = new HashMap<String, Object>();
185 attributes.put( "outputEncoding", "UTF-8" );
186 attributes.put( "project", project );
187
188 Locale locale = Locale.getDefault();
189 Artifact defaultSkin =
190 siteTool.getDefaultSkinArtifact( localRepository, project.getRemoteArtifactRepositories() );
191
192 SiteRenderingContext siteContext =
193 siteRenderer.createContextForSkin( defaultSkin.getFile(), attributes, model, getName( locale ), locale );
194
195 RenderingContext context = new RenderingContext( outputDirectory, filename );
196
197 SiteRendererSink sink = new SiteRendererSink( context );
198
199 generate( sink, null, locale );
200
201 outputDirectory.mkdirs();
202
203 writer = new OutputStreamWriter( new FileOutputStream( new File( outputDirectory, filename ) ), "UTF-8" );
204
205 siteRenderer.generateDocument( writer, sink, siteContext );
206
207 siteRenderer.copyResources( siteContext, new File( project.getBasedir(), "src/site/resources" ),
208 outputDirectory );
209 }
210 catch ( RendererException e )
211 {
212 throw new MojoExecutionException( "An error has occurred in " + getName( Locale.ENGLISH )
213 + " report generation.", e );
214 }
215 catch ( IOException e )
216 {
217 throw new MojoExecutionException( "An error has occurred in " + getName( Locale.ENGLISH )
218 + " report generation.", e );
219 }
220 catch ( SiteToolException e )
221 {
222 throw new MojoExecutionException( "An error has occurred in " + getName( Locale.ENGLISH )
223 + " report generation.", e );
224 }
225 catch ( MavenReportException e )
226 {
227 throw new MojoExecutionException( "An error has occurred in " + getName( Locale.ENGLISH )
228 + " report generation.", e );
229 }
230 finally
231 {
232 IOUtil.close( writer );
233 }
234 }
235
236 @Override
237 public String getCategoryName()
238 {
239 return CATEGORY_PROJECT_INFORMATION;
240 }
241
242
243
244
245
246 @Override
247 protected String getOutputDirectory()
248 {
249 return outputDirectory.getAbsolutePath();
250 }
251
252 @Override
253 public File getReportOutputDirectory()
254 {
255 return outputDirectory;
256 }
257
258 @Override
259 public void setReportOutputDirectory( File reportOutputDirectory )
260 {
261 this.outputDirectory = reportOutputDirectory;
262 }
263
264 @Override
265 protected MavenProject getProject()
266 {
267 return project;
268 }
269
270 @Override
271 protected Renderer getSiteRenderer()
272 {
273 return siteRenderer;
274 }
275
276 protected String getI18nString( Locale locale, String key )
277 {
278 return getI18N( locale ).getString( "project-info-report", locale, "report." + getI18Nsection() + '.' + key );
279 }
280
281 protected I18N getI18N( Locale locale )
282 {
283 if ( customBundle != null )
284 {
285 File customBundleFile = new File( customBundle );
286 if ( customBundleFile.isFile() && customBundleFile.getName().endsWith( ".properties" ) )
287 {
288 if ( !i18n.getClass().isAssignableFrom( CustomI18N.class ) )
289 {
290
291 i18n = new CustomI18N( project, settings, customBundleFile, locale, i18n );
292 }
293 else if ( !i18n.getDefaultLanguage().equals( locale.getLanguage() ) )
294 {
295 i18n = new CustomI18N( project, settings, customBundleFile, locale, i18n );
296 }
297 }
298 }
299
300 return i18n;
301 }
302
303 protected abstract String getI18Nsection();
304
305
306 public String getName( Locale locale )
307 {
308 return getI18nString( locale, "name" );
309 }
310
311
312 public String getDescription( Locale locale )
313 {
314 return getI18nString( locale, "description" );
315 }
316
317 private static class CustomI18N
318 implements I18N
319 {
320 private final MavenProject project;
321
322 private final Settings settings;
323
324 private final String bundleName;
325
326 private final Locale locale;
327
328 private final I18N i18nOriginal;
329
330 private ResourceBundle bundle;
331
332 private final static Object[] NO_ARGS = new Object[0];
333
334 public CustomI18N( MavenProject project, Settings settings, File customBundleFile, Locale locale,
335 I18N i18nOriginal )
336 {
337 super();
338 this.project = project;
339 this.settings = settings;
340 this.locale = locale;
341 this.i18nOriginal = i18nOriginal;
342 this.bundleName =
343 customBundleFile.getName().substring( 0, customBundleFile.getName().indexOf( ".properties" ) );
344
345 URLClassLoader classLoader = null;
346 try
347 {
348 classLoader = new URLClassLoader( new URL[] { customBundleFile.getParentFile().toURI().toURL() } );
349 }
350 catch ( MalformedURLException e )
351 {
352 }
353
354 this.bundle = ResourceBundle.getBundle( this.bundleName, locale, classLoader );
355 if ( !this.bundle.getLocale().getLanguage().equals( locale.getLanguage() ) )
356 {
357 this.bundle = ResourceBundle.getBundle( this.bundleName, Locale.getDefault(), classLoader );
358 }
359 }
360
361
362 public String getDefaultLanguage()
363 {
364 return locale.getLanguage();
365 }
366
367
368 public String getDefaultCountry()
369 {
370 return locale.getCountry();
371 }
372
373
374 public String getDefaultBundleName()
375 {
376 return bundleName;
377 }
378
379
380 public String[] getBundleNames()
381 {
382 return new String[] { bundleName };
383 }
384
385
386 public ResourceBundle getBundle()
387 {
388 return bundle;
389 }
390
391
392 public ResourceBundle getBundle( String bundleName )
393 {
394 return bundle;
395 }
396
397
398 public ResourceBundle getBundle( String bundleName, String languageHeader )
399 {
400 return bundle;
401 }
402
403
404 public ResourceBundle getBundle( String bundleName, Locale locale )
405 {
406 return bundle;
407 }
408
409
410 public Locale getLocale( String languageHeader )
411 {
412 return new Locale( languageHeader );
413 }
414
415
416 public String getString( String key )
417 {
418 return getString( bundleName, locale, key );
419 }
420
421
422 public String getString( String key, Locale locale )
423 {
424 return getString( bundleName, locale, key );
425 }
426
427
428 public String getString( String bundleName, Locale locale, String key )
429 {
430 String value;
431
432 if ( locale == null )
433 {
434 locale = getLocale( null );
435 }
436
437 ResourceBundle rb = getBundle( bundleName, locale );
438 value = getStringOrNull( rb, key );
439
440 if ( value == null )
441 {
442
443 value = i18nOriginal.getString( bundleName, locale, key );
444 }
445
446 if ( value.indexOf( "${" ) < 0 )
447 {
448 return value;
449 }
450
451 final RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
452 try
453 {
454 interpolator.addValueSource( new EnvarBasedValueSource() );
455 }
456 catch ( final IOException e )
457 {
458 }
459
460 interpolator.addValueSource( new PropertiesBasedValueSource( System.getProperties() ) );
461 interpolator.addValueSource( new PropertiesBasedValueSource( project.getProperties() ) );
462 interpolator.addValueSource( new PrefixedObjectValueSource( "project", project ) );
463 interpolator.addValueSource( new PrefixedObjectValueSource( "pom", project ) );
464 interpolator.addValueSource( new PrefixedObjectValueSource( "settings", settings ) );
465
466 try
467 {
468 value = interpolator.interpolate( value );
469 }
470 catch ( final InterpolationException e )
471 {
472 }
473
474 return value;
475 }
476
477
478 public String format( String key, Object arg1 )
479 {
480 return format( bundleName, locale, key, new Object[] { arg1 } );
481 }
482
483
484 public String format( String key, Object arg1, Object arg2 )
485 {
486 return format( bundleName, locale, key, new Object[] { arg1, arg2 } );
487 }
488
489
490 public String format( String bundleName, Locale locale, String key, Object arg1 )
491 {
492 return format( bundleName, locale, key, new Object[] { arg1 } );
493 }
494
495
496 public String format( String bundleName, Locale locale, String key, Object arg1, Object arg2 )
497 {
498 return format( bundleName, locale, key, new Object[] { arg1, arg2 } );
499 }
500
501
502 public String format( String bundleName, Locale locale, String key, Object[] args )
503 {
504 if ( locale == null )
505 {
506 locale = getLocale( null );
507 }
508
509 String value = getString( bundleName, locale, key );
510 if ( args == null )
511 {
512 args = NO_ARGS;
513 }
514
515 MessageFormat messageFormat = new MessageFormat( "" );
516 messageFormat.setLocale( locale );
517 messageFormat.applyPattern( value );
518
519 return messageFormat.format( args );
520 }
521
522 private String getStringOrNull( ResourceBundle rb, String key )
523 {
524 if ( rb != null )
525 {
526 try
527 {
528 return rb.getString( key );
529 }
530 catch ( MissingResourceException ignored )
531 {
532
533 }
534 }
535 return null;
536 }
537 }
538 }