1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.help;
20
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.io.Writer;
24 import java.lang.reflect.InvocationTargetException;
25 import java.util.Collection;
26 import java.util.Comparator;
27 import java.util.Map;
28 import java.util.SortedSet;
29 import java.util.TreeSet;
30 import java.util.UUID;
31
32 import org.apache.commons.cli.HelpFormatter;
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.rat.ConfigurationException;
35 import org.apache.rat.ReportConfiguration;
36 import org.apache.rat.analysis.IHeaderMatcher;
37 import org.apache.rat.config.parameters.ComponentType;
38 import org.apache.rat.config.parameters.Description;
39 import org.apache.rat.config.parameters.DescriptionBuilder;
40 import org.apache.rat.configuration.MatcherBuilderTracker;
41 import org.apache.rat.configuration.builders.AbstractBuilder;
42 import org.apache.rat.license.ILicense;
43 import org.apache.rat.license.ILicenseFamily;
44 import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
45
46 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
47
48 import static java.lang.String.format;
49
50
51
52
53
54 public final class Licenses extends AbstractHelp {
55
56 private final ReportConfiguration config;
57
58 private final SortedSet<ILicense> licenses;
59
60 private final HelpFormatter formatter;
61
62 private final PrintWriter printWriter;
63
64
65
66
67
68
69 @SuppressFBWarnings("EI_EXPOSE_REP2")
70 public Licenses(final ReportConfiguration config, final Writer writer) {
71 this.config = config;
72 this.licenses = config.getLicenses(LicenseFilter.ALL);
73 printWriter = new PrintWriter(writer);
74 formatter = HelpFormatter.builder().setShowDeprecated(false).setPrintWriter(printWriter).get();
75 }
76
77
78
79
80
81
82 void print(final int indent, final String text) {
83 int leftMargin = indent * HELP_PADDING;
84 int tabStop = leftMargin + (HELP_PADDING / 2);
85 formatter.printWrapped(printWriter, HELP_WIDTH, tabStop, createPadding(leftMargin) + text);
86 }
87
88
89
90
91
92 public void printHelp() throws IOException {
93 print(0, format("Listing of licenses for %s", versionInfo));
94 output();
95 }
96
97
98
99
100
101 public void output() throws IOException {
102
103 print(0, header("LICENSES"));
104
105 if (licenses.isEmpty()) {
106 print(0, "No licenses defined");
107 } else {
108 Description licenseDescription = DescriptionBuilder.build(licenses.first());
109 Collection<Description> licenseParams = licenseDescription.filterChildren(d -> d.getType() == ComponentType.PARAMETER);
110
111 print(0, format("Licenses have the following properties:%n"));
112
113 for (Description param : licenseParams) {
114 print(1, format("%s: %s%n", param.getCommonName(), param.getDescription()));
115 }
116
117 print(0, format("%nThe defined licenses are:%n"));
118 for (ILicense l : licenses) {
119 print(0, System.lineSeparator());
120 printObject(0, l);
121 }
122 }
123 print(0, header("DEFINED MATCHERS"));
124 SortedSet<Description> matchers = new TreeSet<>(Comparator.comparing(Description::getCommonName));
125 for (Class<? extends AbstractBuilder> mClazz : MatcherBuilderTracker.instance().getClasses()) {
126 try {
127 AbstractBuilder builder = mClazz.getConstructor().newInstance();
128 matchers.add(builder.getDescription());
129 } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
130 | IllegalArgumentException | InvocationTargetException e) {
131 throw new ConfigurationException(
132 format("Can not instantiate matcher builder %s ", mClazz.getName()), e);
133 }
134 }
135 for (Description description : matchers) {
136 print(0, format("%n%s: %s%n", description.getCommonName(), description.getDescription()));
137 for (Description child : description.getChildren().values()) {
138 if (IHeaderMatcher.class.isAssignableFrom(child.getChildType())) {
139 if (child.isCollection()) {
140 print(2, "Encloses multiple matchers");
141 } else {
142 print(2, "Wraps a single matcher");
143 }
144 } else {
145 print(1, format("%s: %s%s", child.getCommonName(), child.isRequired() ? "(required) " : "", child.getDescription()));
146 }
147 }
148 }
149
150 print(0, header("DEFINED FAMILIES"));
151 for (ILicenseFamily family : config.getLicenseFamilies(LicenseFilter.ALL)) {
152 print(1, format("%s - %s%n", family.getFamilyCategory(), family.getFamilyName()));
153 }
154 printWriter.flush();
155 }
156
157
158
159
160
161
162
163 private void printObject(final int indent, final Object object) throws IOException {
164 if (object == null) {
165 return;
166 }
167 Description description = DescriptionBuilder.build(object);
168 if (description == null) {
169 print(indent, format("Unknown Object of class: %s%n", object.getClass().getName()));
170 } else {
171 print(indent, format("%s (%s)%n", description.getCommonName(), description.getDescription()));
172 printChildren(indent + 1, object, description.getChildren());
173 }
174 }
175
176
177
178
179
180
181 private boolean isUUID(final String s) {
182 try {
183 UUID.fromString(s);
184 return true;
185 } catch (IllegalArgumentException expected) {
186 return false;
187 }
188 }
189
190
191
192
193
194
195
196
197 private void printChildren(final int indent, final Object parent, final Map<String, Description> children) throws IOException {
198 for (Description d : children.values()) {
199 switch (d.getType()) {
200 case PARAMETER:
201 if (d.isCollection()) {
202 print(indent, format("%s: %n", d.getCommonName()));
203 try {
204 Collection<?> result = (Collection<?>) d.getter(parent.getClass()).invoke(parent);
205 for (Object o : result) {
206 printObject(indent + 1, o);
207 }
208 return;
209 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
210 throw new RuntimeException(e);
211 }
212 }
213 if (IHeaderMatcher.class.isAssignableFrom(d.getChildType())) {
214 print(indent, format("%s: %n", d.getCommonName()));
215
216 try {
217 Object matcher = d.getter(parent.getClass()).invoke(parent);
218 printObject(indent + 1, matcher);
219 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
220 throw new RuntimeException(e);
221 }
222 } else {
223 String txt = StringUtils.defaultIfBlank(d.getParamValue(parent), "").replaceAll("\\s{2,}", " ");
224 if (!txt.isEmpty() && !(d.getCommonName().equals("id") && isUUID(txt))) {
225 print(indent, format("%s: %s%n", d.getCommonName(), txt.replaceAll("\\s{2,}", " ")));
226 }
227 }
228 break;
229 case BUILD_PARAMETER:
230 case LICENSE:
231
232 break;
233 case MATCHER:
234 printChildren(indent + 1, parent, d.getChildren());
235 break;
236 }
237 }
238 }
239 }