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