1 package org.apache.maven.plugins.linkcheck;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Properties;
30
31 import org.apache.maven.artifact.repository.ArtifactRepository;
32 import org.apache.maven.doxia.linkcheck.HttpBean;
33 import org.apache.maven.doxia.linkcheck.LinkCheck;
34 import org.apache.maven.doxia.linkcheck.LinkCheckException;
35 import org.apache.maven.doxia.linkcheck.model.LinkcheckModel;
36 import org.apache.maven.doxia.siterenderer.Renderer;
37 import org.apache.maven.plugin.MojoExecutionException;
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.Proxy;
42 import org.apache.maven.settings.Settings;
43 import org.codehaus.plexus.i18n.I18N;
44 import org.codehaus.plexus.util.FileUtils;
45 import org.codehaus.plexus.util.ReaderFactory;
46 import org.codehaus.plexus.util.StringUtils;
47
48
49
50
51
52
53
54
55
56 public class LinkcheckReport
57 extends AbstractMavenReport
58 {
59
60
61
62
63
64
65
66
67
68 private I18N i18n;
69
70
71
72
73
74
75 private Renderer siteRenderer;
76
77
78
79
80
81
82 private LinkCheck linkCheck;
83
84
85
86
87
88
89
90
91
92
93
94
95 private MavenProject project;
96
97
98
99
100
101
102
103
104 private ArtifactRepository localRepository;
105
106
107
108
109
110
111
112 private File outputDirectory;
113
114
115
116
117
118
119
120
121 private Settings settings;
122
123
124
125
126
127
128
129
130
131
132
133 private boolean offline;
134
135
136
137
138
139
140
141 private boolean httpFollowRedirect;
142
143
144
145
146
147
148
149 protected File linkcheckCache;
150
151
152
153
154
155
156
157 protected File linkcheckOutput;
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 private String httpMethod;
182
183
184
185
186
187
188
189 private Integer[] excludedHttpStatusErrors;
190
191
192
193
194
195
196
197 private Integer[] excludedHttpStatusWarnings;
198
199
200
201
202
203
204
205
206
207
208
209
210
211 private String[] excludedPages;
212
213
214
215
216
217
218
219
220 private String[] excludedLinks;
221
222
223
224
225
226
227
228 private String encoding;
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 private Properties httpClientParameters;
245
246
247
248
249
250
251 private int timeout;
252
253
254
255
256
257
258
259 private boolean skip;
260
261
262
263
264
265
266
267 private boolean forceSite;
268
269
270
271
272
273
274 private String baseURL;
275
276
277
278
279
280
281 private LinkcheckModel result;
282
283 protected static final String ICON_SUCCESS = "images/icon_success_sml.gif";
284 protected static final String ICON_WARNING = "images/icon_warning_sml.gif";
285 protected static final String ICON_INFO = "images/icon_info_sml.gif";
286 protected static final String ICON_ERROR = "images/icon_error_sml.gif";
287 private static final String pluginResourcesBase = "org/apache/maven/plugin/linkcheck";
288 private static final String resourceNames[] = { ICON_SUCCESS, ICON_WARNING, ICON_INFO, ICON_ERROR };
289
290
291
292
293
294
295 public String getDescription( Locale locale )
296 {
297 return i18n.getString( "linkcheck-report", locale, "report.linkcheck.description" );
298 }
299
300
301 public String getName( Locale locale )
302 {
303 return i18n.getString( "linkcheck-report", locale, "report.linkcheck.name" );
304 }
305
306
307 public String getOutputName()
308 {
309 return "linkcheck";
310 }
311
312
313 public boolean canGenerateReport()
314 {
315 if ( skip )
316 {
317 return false;
318 }
319
320 return true;
321 }
322
323
324 public void execute()
325 throws MojoExecutionException
326 {
327 if ( !canGenerateReport() )
328 {
329 return;
330 }
331
332 checkEncoding();
333
334 try
335 {
336 result = executeLinkCheck( getBasedir() );
337 }
338 catch ( LinkCheckException e )
339 {
340 throw new MojoExecutionException( "LinkCheckException: " + e.getMessage(), e );
341 }
342 }
343
344
345
346
347
348
349 protected String getOutputDirectory()
350 {
351 return outputDirectory.getAbsolutePath();
352 }
353
354
355 protected MavenProject getProject()
356 {
357 return project;
358 }
359
360
361 protected Renderer getSiteRenderer()
362 {
363 return siteRenderer;
364 }
365
366
367 protected void executeReport( Locale locale )
368 throws MavenReportException
369 {
370 if ( result == null )
371 {
372 getLog().debug( "Calling execute()" );
373
374 try
375 {
376 this.execute();
377 }
378 catch ( MojoExecutionException e )
379 {
380 throw new MavenReportException( "MojoExecutionException: " + e.getMessage(), e );
381 }
382 }
383
384 if ( result != null )
385 {
386 generateReport( locale, result );
387
388 result = null;
389 }
390 }
391
392
393
394
395
396 private void checkEncoding()
397 {
398 if ( StringUtils.isEmpty( encoding ) )
399 {
400 if ( getLog().isWarnEnabled() )
401 {
402 getLog().warn( "File encoding has not been set, using platform encoding "
403 + ReaderFactory.FILE_ENCODING + ", i.e. build is platform dependent!" );
404 }
405
406 encoding = ReaderFactory.FILE_ENCODING;
407 }
408 }
409
410 private File getBasedir()
411 throws MojoExecutionException
412 {
413 File basedir;
414
415 if ( forceSite )
416 {
417 basedir = new File( linkcheckOutput.getParentFile(), "tmpsite" );
418 basedir.mkdirs();
419
420 List documents = null;
421 try
422 {
423 documents = FileUtils.getFiles( basedir, "**/*.html", null );
424 }
425 catch ( IOException e )
426 {
427 getLog().error( "IOException: " + e.getMessage() );
428 getLog().debug( e );
429 }
430
431
432 if ( documents == null || ( documents != null && documents.size() == 0 ) )
433 {
434 getLog().info( "Invoking the maven-site-plugin to ensure that all files are generated..." );
435
436 try
437 {
438 SiteInvoker invoker = new SiteInvoker( localRepository, getLog() );
439 invoker.invokeSite( project, basedir );
440 }
441 catch ( IOException e )
442 {
443 throw new MojoExecutionException( "IOException: " + e.getMessage(), e );
444 }
445 }
446 }
447 else
448 {
449 getLog().warn( "The number of documents analyzed by Linkcheck could differ from the actual "
450 + "number of documents!" );
451
452 basedir = outputDirectory;
453 basedir.mkdirs();
454 }
455
456 return basedir;
457 }
458
459
460
461
462
463
464
465 private LinkcheckModel executeLinkCheck( File basedir )
466 throws LinkCheckException
467 {
468
469 linkCheck.setOnline( !offline );
470 linkCheck.setBasedir( basedir );
471 linkCheck.setBaseURL( baseURL );
472 linkCheck.setReportOutput( linkcheckOutput );
473 linkCheck.setLinkCheckCache( linkcheckCache );
474 linkCheck.setExcludedLinks( excludedLinks );
475 linkCheck.setExcludedPages( getExcludedPages() );
476 linkCheck.setExcludedHttpStatusErrors( asIntArray( excludedHttpStatusErrors ) );
477 linkCheck.setExcludedHttpStatusWarnings( asIntArray( excludedHttpStatusWarnings ) );
478 linkCheck.setEncoding( ( StringUtils.isNotEmpty( encoding ) ? encoding : ReaderFactory.UTF_8 ) );
479
480 HttpBean bean = new HttpBean();
481 bean.setMethod( httpMethod );
482 bean.setFollowRedirects( httpFollowRedirect );
483 bean.setTimeout( timeout );
484 if ( httpClientParameters != null )
485 {
486 bean.setHttpClientParameters( httpClientParameters );
487 }
488
489 Proxy proxy = settings.getActiveProxy();
490 if ( proxy != null )
491 {
492 bean.setProxyHost( proxy.getHost() );
493 bean.setProxyPort( proxy.getPort() );
494 bean.setProxyUser( proxy.getUsername() );
495 bean.setProxyPassword( proxy.getPassword() );
496 }
497 linkCheck.setHttp( bean );
498
499 return linkCheck.execute();
500 }
501
502
503
504
505 private String[] getExcludedPages()
506 {
507 List pagesToExclude =
508 ( excludedPages != null ? new ArrayList( Arrays.asList( excludedPages ) ) : new ArrayList() );
509
510
511 pagesToExclude.add( getOutputName() + ".html" );
512
513 return (String[]) pagesToExclude.toArray( new String[0] );
514 }
515
516
517
518
519
520 private void generateReport( Locale locale, LinkcheckModel linkcheckModel )
521 {
522 LinkcheckReportGenerator reportGenerator = new LinkcheckReportGenerator( i18n );
523
524 reportGenerator.setExcludedHttpStatusErrors( excludedHttpStatusErrors );
525 reportGenerator.setExcludedHttpStatusWarnings( excludedHttpStatusWarnings );
526 reportGenerator.setExcludedLinks( excludedLinks );
527 reportGenerator.setExcludedPages( excludedPages );
528 reportGenerator.setHttpFollowRedirect( httpFollowRedirect );
529 reportGenerator.setHttpMethod( httpMethod );
530 reportGenerator.setOffline( offline );
531
532 reportGenerator.generateReport( locale, linkcheckModel, getSink() );
533 closeReport();
534
535
536 copyStaticResources();
537 }
538
539 private void copyStaticResources()
540 {
541 try
542 {
543 getLog().debug( "Copying static linkcheck resources." );
544 for ( int i = 0; i < resourceNames.length; i++ )
545 {
546 URL url = this.getClass().getClassLoader().getResource( pluginResourcesBase + "/" + resourceNames[i] );
547 FileUtils.copyURLToFile( url, new File( getReportOutputDirectory(), resourceNames[i] ) );
548 }
549 }
550 catch ( IOException e )
551 {
552 getLog().error( "Unable to copy icons for linkcheck report." );
553 getLog().debug( e );
554 }
555 }
556
557 private static int[] asIntArray( Integer[] array )
558 {
559 if ( array == null )
560 {
561 return null;
562 }
563
564 int[] newArray = new int[array.length];
565
566 for ( int i = 0; i < array.length; i++ )
567 {
568 newArray[i] = array[i].intValue();
569 }
570
571 return newArray;
572 }
573 }