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