1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.FilenameFilter;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.io.OutputStreamWriter;
28 import java.io.PrintWriter;
29 import java.net.MalformedURLException;
30 import java.net.URI;
31 import java.net.URL;
32 import java.nio.charset.StandardCharsets;
33 import java.nio.file.Files;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Objects;
37 import java.util.SortedSet;
38 import java.util.TreeSet;
39 import java.util.function.Consumer;
40
41 import org.apache.commons.io.filefilter.FalseFileFilter;
42 import org.apache.commons.io.filefilter.IOFileFilter;
43 import org.apache.commons.io.function.IOSupplier;
44 import org.apache.rat.config.AddLicenseHeaders;
45 import org.apache.rat.license.ILicense;
46 import org.apache.rat.license.ILicenseFamily;
47 import org.apache.rat.license.LicenseFamilySetFactory;
48 import org.apache.rat.license.LicenseSetFactory;
49 import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
50 import org.apache.rat.report.IReportable;
51 import org.apache.rat.utils.Log;
52 import org.apache.rat.utils.ReportingSet;
53
54
55
56
57
58
59 public class ReportConfiguration {
60
61 public enum Processing {
62
63 NOTIFICATION("List file as present"),
64
65 PRESENCE("List any licenses found"),
66
67 ABSENCE("List licenses found and any unknown licences");
68
69 private final String description;
70 Processing(String description) {
71 this.description = description;
72 }
73 public String desc() { return description; }
74 }
75
76
77 private final ReportingSet<ILicenseFamily> families;
78 private final ReportingSet<ILicense> licenses;
79 private final SortedSet<String> approvedLicenseCategories;
80 private final SortedSet<String> removedLicenseCategories;
81 private boolean addingLicenses;
82 private boolean addingLicensesForced;
83 private String copyrightMessage;
84 private IOSupplier<OutputStream> out;
85 private boolean styleReport;
86 private IOSupplier<InputStream> styleSheet;
87 private IReportable reportable;
88 private FilenameFilter filesToIgnore;
89 private IOFileFilter directoriesToIgnore;
90 private final Log log;
91 private LicenseFilter listFamilies;
92 private LicenseFilter listLicenses;
93 private boolean dryRun;
94 private Processing archiveProcessing;
95 private Processing standardProcessing;
96
97
98
99
100 public ReportConfiguration(Log log) {
101 this.log = log;
102 families = new ReportingSet<>(LicenseFamilySetFactory.emptyLicenseFamilySet()).setLog(log)
103 .setMsgFormat( s -> String.format("Duplicate LicenseFamily category: %s", s.getFamilyCategory()));
104 licenses = new ReportingSet<>(LicenseSetFactory.emptyLicenseSet()).setLog(log)
105 .setMsgFormat( s -> String.format( "Duplicate License %s (%s) of type %s", s.getName(), s.getId(), s.getLicenseFamily().getFamilyCategory()));
106 approvedLicenseCategories = new TreeSet<>();
107 removedLicenseCategories = new TreeSet<>();
108 styleReport = true;
109 listFamilies = Defaults.LIST_FAMILIES;
110 listLicenses = Defaults.LIST_LICENSES;
111 dryRun = false;
112 }
113
114
115
116
117
118 public Processing getArchiveProcessing() {
119 return archiveProcessing == null ? Defaults.ARCHIVE_PROCESSING : archiveProcessing;
120 }
121
122
123
124
125
126 public void setArchiveProcessing(Processing archiveProcessing) {
127 this.archiveProcessing = archiveProcessing;
128 }
129
130
131
132
133
134 public Processing getStandardProcessing() {
135 return standardProcessing == null ? Defaults.STANDARD_PROCESSING : standardProcessing;
136 }
137
138
139
140
141
142 public void setStandardProcessing(Processing standardProcessing) {
143 this.standardProcessing = standardProcessing;
144 }
145
146
147
148
149
150 public Log getLog() {
151 return log;
152 }
153
154
155
156
157
158 public void logFamilyCollisions(Log.Level level) {
159 families.setLogLevel(level);
160 }
161
162
163
164
165
166 public void familyDuplicateOption(ReportingSet.Options state) {
167 families.setDuplicateOption(state);
168 }
169
170
171
172
173
174 public void logLicenseCollisions(Log.Level level) {
175 licenses.setLogLevel(level);
176 }
177
178
179
180
181
182 public void licenseDuplicateOption(ReportingSet.Options state) {
183 licenses.setDuplicateOption(state);
184 }
185
186
187
188
189
190 public void listFamilies(LicenseFilter filter) {
191 listFamilies = filter;
192 }
193
194 public LicenseFilter listFamilies() {
195 return listFamilies;
196 }
197
198
199
200
201
202 public void listLicenses(LicenseFilter filter) {
203 listLicenses = filter;
204 }
205
206 public LicenseFilter listLicenses() {
207 return listLicenses;
208 }
209
210
211
212
213
214 public void setDryRun(boolean state) {
215 dryRun = state;
216 }
217
218
219
220
221
222 public boolean isDryRun() {
223 return dryRun;
224 }
225
226
227
228
229
230 public FilenameFilter getFilesToIgnore() {
231 return filesToIgnore == null ? Defaults.FILES_TO_IGNORE : filesToIgnore;
232 }
233
234
235
236
237
238
239
240 public void setFilesToIgnore(FilenameFilter filesToIgnore) {
241 this.filesToIgnore = filesToIgnore;
242 }
243
244
245
246
247
248 public IOFileFilter getDirectoriesToIgnore() {
249 return directoriesToIgnore == null ? Defaults.DIRECTORIES_TO_IGNORE : directoriesToIgnore;
250 }
251
252
253
254
255
256
257
258
259 public void setDirectoriesToIgnore(IOFileFilter directoriesToIgnore) {
260 this.directoriesToIgnore = directoriesToIgnore == null ? FalseFileFilter.FALSE : directoriesToIgnore;
261 }
262
263
264
265
266
267 public void addDirectoryToIgnore(IOFileFilter directoryToIgnore) {
268 this.directoriesToIgnore = this.directoriesToIgnore.or(directoryToIgnore);
269 }
270
271
272
273
274 public IReportable getReportable() {
275 return reportable;
276 }
277
278
279
280
281 public void setReportable(IReportable reportable) {
282 this.reportable = reportable;
283 }
284
285
286
287
288
289 public IOSupplier<InputStream> getStyleSheet() {
290 return styleSheet;
291 }
292
293
294
295
296
297
298
299
300 public void setStyleSheet(IOSupplier<InputStream> styleSheet) {
301 this.styleSheet = styleSheet;
302 }
303
304
305
306
307
308
309
310
311 public void setFrom(Defaults defaults) {
312 addLicensesIfNotPresent(defaults.getLicenses(LicenseFilter.ALL));
313 addApprovedLicenseCategories(defaults.getLicenseIds(LicenseFilter.APPROVED));
314 if (isStyleReport() && getStyleSheet() == null) {
315 setStyleSheet(Defaults.getPlainStyleSheet());
316 }
317 }
318
319
320
321
322
323 public void setStyleSheet(File styleSheet) {
324 Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
325 setStyleSheet(styleSheet.toURI());
326 }
327
328
329
330
331
332
333
334 public void setStyleSheet(URI styleSheet) {
335 Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
336 try {
337 setStyleSheet(styleSheet.toURL());
338 } catch (MalformedURLException e) {
339 throw new ConfigurationException("Unable to process stylesheet", e);
340 }
341 }
342
343
344
345
346
347
348
349 public void setStyleSheet(URL styleSheet) {
350 Objects.requireNonNull(styleSheet, "styleSheet file should not be null");
351 setStyleSheet(styleSheet::openStream);
352 }
353
354
355
356
357 public boolean isStyleReport() {
358 return styleReport;
359 }
360
361
362
363
364 public void setStyleReport(boolean styleReport) {
365 this.styleReport = styleReport;
366 }
367
368
369
370
371
372
373
374
375
376
377
378 public void setOut(IOSupplier<OutputStream> out) {
379 this.out = out;
380 }
381
382
383
384
385
386
387
388
389
390 public void setOut(File file) {
391 Objects.requireNonNull(file, "output file should not be null");
392 if (file.exists()) {
393 try {
394 Files.delete(file.toPath());
395 } catch (IOException e) {
396 log.warn("Unable to delete file:"+file);
397 }
398 }
399 setOut(() -> new FileOutputStream(file, true));
400 }
401
402
403
404
405
406
407
408 public IOSupplier<OutputStream> getOutput() {
409 return out == null ? () -> new NoCloseOutputStream(System.out) : out;
410 }
411
412
413
414
415
416 public IOSupplier<PrintWriter> getWriter() {
417 return () -> new PrintWriter(new OutputStreamWriter(getOutput().get(), StandardCharsets.UTF_8));
418 }
419
420
421
422
423
424
425
426 public void addLicense(ILicense license) {
427 if (license != null) {
428 this.licenses.add(license);
429 this.families.addIfNotPresent(license.getLicenseFamily());
430 }
431 }
432
433
434
435
436
437
438
439
440 public ILicense addLicense(ILicense.Builder builder) {
441 if (builder != null) {
442 ILicense license = builder.setLicenseFamilies(families).build();
443 this.licenses.add(license);
444 return license;
445 }
446 return null;
447 }
448
449
450
451
452
453
454
455 public void addLicenses(Collection<ILicense> licenses) {
456 this.licenses.addAll(licenses);
457 licenses.stream().map(ILicense::getLicenseFamily).forEach(families::add);
458 }
459
460
461
462
463
464
465
466 public void addLicensesIfNotPresent(Collection<ILicense> licenses) {
467 this.licenses.addAllIfNotPresent(licenses);
468 licenses.stream().map(ILicense::getLicenseFamily).forEach(families::addIfNotPresent);
469 }
470
471
472
473
474
475
476
477 public void addFamily(ILicenseFamily family) {
478 if (family != null) {
479 this.families.add(family);
480 }
481 }
482
483
484
485
486
487
488
489
490 public void addFamily(ILicenseFamily.Builder builder) {
491 if (builder != null) {
492 this.families.add(builder.build());
493 }
494 }
495
496
497
498
499
500
501
502 public void addFamilies(Collection<ILicenseFamily> families) {
503 this.families.addAll(families);
504 }
505
506
507
508
509
510
511 public void addApprovedLicenseCategory(ILicenseFamily approvedILicenseFamily) {
512 approvedLicenseCategories.add(approvedILicenseFamily.getFamilyCategory());
513 }
514
515
516
517
518
519
520 public void addApprovedLicenseCategory(String familyCategory) {
521 approvedLicenseCategories.add(ILicenseFamily.makeCategory(familyCategory));
522 }
523
524
525
526
527
528
529
530 public void addApprovedLicenseCategories(Collection<String> approvedLicenseCategories) {
531 approvedLicenseCategories.forEach(this::addApprovedLicenseCategory);
532 }
533
534
535
536
537
538
539
540 public void removeApprovedLicenseCategory(String familyCategory) {
541 removedLicenseCategories.add(ILicenseFamily.makeCategory(familyCategory));
542 }
543
544
545
546
547
548
549
550
551 public void removeApprovedLicenseCategories(Collection<String> familyCategory) {
552 familyCategory.forEach(this::removeApprovedLicenseCategory);
553 }
554
555
556
557
558
559
560
561 public SortedSet<String> getApprovedLicenseCategories() {
562 SortedSet<String> result = new TreeSet<>(approvedLicenseCategories);
563 result.removeAll(removedLicenseCategories);
564 return result;
565 }
566
567
568
569
570
571
572
573
574 public String getCopyrightMessage() {
575 return copyrightMessage;
576 }
577
578
579
580
581
582
583
584
585 public void setCopyrightMessage(String copyrightMessage) {
586 this.copyrightMessage = copyrightMessage;
587 }
588
589
590
591
592
593
594
595 public boolean isAddingLicensesForced() {
596 return addingLicensesForced;
597 }
598
599
600
601
602
603
604 public boolean isAddingLicenses() {
605 return addingLicenses;
606 }
607
608
609
610
611
612
613
614
615
616
617 public void setAddLicenseHeaders(AddLicenseHeaders addLicenseHeaders) {
618 addingLicenses = false;
619 addingLicensesForced = false;
620 switch (addLicenseHeaders) {
621 case FALSE:
622
623 break;
624 case FORCED:
625 addingLicensesForced = true;
626
627 case TRUE:
628 addingLicenses = true;
629 break;
630 }
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644 public SortedSet<ILicense> getLicenses(LicenseFilter filter) {
645 switch (filter) {
646 case ALL:
647 return Collections.unmodifiableSortedSet(licenses);
648 case APPROVED:
649 return new LicenseSetFactory(licenses, getApprovedLicenseCategories()).getLicenses(filter);
650 case NONE:
651 default:
652 return LicenseSetFactory.emptyLicenseSet();
653 }
654 }
655
656
657
658
659
660
661
662
663
664
665
666
667
668 public SortedSet<ILicenseFamily> getLicenseFamilies(LicenseFilter filter) {
669 return new LicenseFamilySetFactory(families, getApprovedLicenseCategories()).getFamilies(filter);
670 }
671
672
673
674
675
676
677 public void validate(Consumer<String> logger) {
678 if (reportable == null) {
679 throw new ConfigurationException("Reportable may not be null");
680 }
681 if (licenses.isEmpty()) {
682 throw new ConfigurationException("You must specify at least one license");
683 }
684 if (styleSheet != null && !isStyleReport()) {
685 logger.accept("Ignoring stylesheet because styling is not selected");
686 }
687 if (styleSheet == null && isStyleReport()) {
688 throw new ConfigurationException("Stylesheet must be specified if report styling is selected");
689 }
690 }
691
692
693
694
695 public static class NoCloseOutputStream extends OutputStream {
696 private final OutputStream delegate;
697
698 public NoCloseOutputStream(OutputStream delegate) {
699 this.delegate = delegate;
700 }
701
702 @Override
703 public void write(int arg0) throws IOException {
704 delegate.write(arg0);
705 }
706
707 @Override
708 public void close() throws IOException {
709 this.delegate.flush();
710 }
711
712 @Override
713 public boolean equals(Object obj) {
714 return delegate.equals(obj);
715 }
716
717 @Override
718 public void flush() throws IOException {
719 delegate.flush();
720 }
721
722 @Override
723 public int hashCode() {
724 return delegate.hashCode();
725 }
726
727 @Override
728 public String toString() {
729 return delegate.toString();
730 }
731
732 @Override
733 public void write(byte[] arg0, int arg1, int arg2) throws IOException {
734 delegate.write(arg0, arg1, arg2);
735 }
736
737 @Override
738 public void write(byte[] b) throws IOException {
739 delegate.write(b);
740 }
741 }
742 }