1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.configuration;
20
21 import java.io.IOException;
22 import java.io.Writer;
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.Optional;
28 import java.util.Set;
29 import java.util.SortedSet;
30 import java.util.UUID;
31 import java.util.function.Predicate;
32
33 import org.apache.commons.lang3.StringUtils;
34 import org.apache.rat.ImplementationException;
35 import org.apache.rat.ReportConfiguration;
36 import org.apache.rat.analysis.IHeaderMatcher;
37 import org.apache.rat.api.RatException;
38 import org.apache.rat.config.parameters.ComponentType;
39 import org.apache.rat.config.parameters.Description;
40 import org.apache.rat.configuration.builders.MatcherRefBuilder;
41 import org.apache.rat.license.ILicense;
42 import org.apache.rat.license.ILicenseFamily;
43 import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
44 import org.apache.rat.report.xml.writer.IXmlWriter;
45 import org.apache.rat.report.xml.writer.impl.base.XmlWriter;
46
47
48
49
50 public class XMLConfigurationWriter {
51 private ReportConfiguration configuration;
52 private Set<String> matchers;
53 private Set<String> licenseChildren;
54
55
56
57
58
59 public XMLConfigurationWriter(ReportConfiguration configuration) {
60 this.configuration = configuration;
61 this.matchers = new HashSet<>();
62 licenseChildren = new HashSet<>(Arrays.asList(XMLConfig.LICENSE_CHILDREN));
63 }
64
65 private Predicate<Description> attributeFilter(Description parent) {
66 return d -> {
67 if (d.getType() == ComponentType.PARAMETER) {
68 switch (parent.getType()) {
69 case MATCHER:
70 return !XMLConfig.isInlineNode(parent.getCommonName(), d.getCommonName());
71 case LICENSE:
72 return !licenseChildren.contains(d.getCommonName());
73 default:
74 return true;
75 }
76 }
77 return false;
78 };
79 }
80
81
82
83
84
85
86 public void write(Writer plainWriter) throws RatException {
87 write(new XmlWriter(plainWriter));
88 }
89
90
91
92
93
94
95 public void write(IXmlWriter writer) throws RatException {
96 if (configuration.listFamilies() != LicenseFilter.NONE || configuration.listLicenses() != LicenseFilter.NONE) {
97 try {
98 writer.openElement(XMLConfig.ROOT);
99
100
101 SortedSet<ILicenseFamily> families = configuration.getLicenseFamilies(configuration.listFamilies());
102 if (!families.isEmpty()) {
103 writer.openElement(XMLConfig.FAMILIES);
104 for (ILicenseFamily family : families) {
105 writeFamily(writer, family);
106 }
107 writer.closeElement();
108 }
109
110
111 SortedSet<ILicense> licenses = configuration.getLicenses(configuration.listLicenses());
112 if (!licenses.isEmpty()) {
113 writer.openElement(XMLConfig.LICENSES);
114 for (ILicense license : licenses) {
115 writeDescription(writer, license.getDescription(), license);
116 }
117 writer.closeElement();
118 }
119
120
121 writer.openElement(XMLConfig.APPROVED);
122 for (String family : configuration.getApprovedLicenseCategories()) {
123 writer.openElement(XMLConfig.APPROVED).attribute(XMLConfig.ATT_LICENSE_REF, family.trim())
124 .closeElement();
125 }
126 writer.closeElement();
127
128
129 MatcherBuilderTracker tracker = MatcherBuilderTracker.INSTANCE;
130 writer.openElement(XMLConfig.MATCHERS);
131 for (Class<?> clazz : tracker.getClasses()) {
132 writer.openElement(XMLConfig.MATCHER).attribute(XMLConfig.ATT_CLASS_NAME, clazz.getCanonicalName())
133 .closeElement();
134 }
135 writer.closeElement();
136
137 writer.closeElement();
138 } catch (IOException e) {
139 throw new RatException(e);
140 }
141 }
142 }
143
144 private void writeFamily(IXmlWriter writer, ILicenseFamily family) throws RatException {
145 try {
146 writer.openElement(XMLConfig.FAMILY).attribute(XMLConfig.ATT_ID, family.getFamilyCategory().trim())
147 .attribute(XMLConfig.ATT_NAME, family.getFamilyName());
148 writer.closeElement();
149 } catch (IOException e) {
150 throw new RatException(e);
151 }
152 }
153
154 private void writeDescriptions(IXmlWriter writer, Collection<Description> descriptions, IHeaderMatcher component)
155 throws RatException {
156 for (Description description : descriptions) {
157 writeDescription(writer, description, component);
158 }
159 }
160
161 private void writeChildren(IXmlWriter writer, Description description, IHeaderMatcher component)
162 throws RatException {
163 writeAttributes(writer, description.filterChildren(attributeFilter(component.getDescription())), component);
164 writeDescriptions(writer, description.filterChildren(attributeFilter(component.getDescription()).negate()),
165 component);
166 }
167
168 private void writeAttributes(IXmlWriter writer, Collection<Description> descriptions, IHeaderMatcher component)
169 throws RatException {
170 for (Description d : descriptions) {
171 try {
172 writeAttribute(writer, d, component);
173 } catch (IOException e) {
174 throw new RatException(e);
175 }
176 }
177 }
178
179 private void writeComment(IXmlWriter writer, Description description) throws IOException {
180 if (StringUtils.isNotBlank(description.getDescription())) {
181 writer.comment(description.getDescription());
182 }
183 }
184
185 private void writeAttribute(IXmlWriter writer, Description description, IHeaderMatcher component)
186 throws IOException {
187 String paramValue = description.getParamValue(configuration.getLog(), component);
188 if (paramValue != null) {
189 writer.attribute(description.getCommonName(), paramValue);
190 }
191 }
192
193
194 @SuppressWarnings("unchecked")
195 void writeDescription(IXmlWriter writer, Description description, IHeaderMatcher component) throws RatException {
196 try {
197 switch (description.getType()) {
198 case MATCHER:
199
200 Optional<Description> id = description.childrenOfType(ComponentType.PARAMETER).stream()
201 .filter(i -> XMLConfig.ATT_ID.equals(i.getCommonName())).findFirst();
202
203
204 if (id.isPresent()) {
205 String matcherId = id.get().getParamValue(configuration.getLog(), component);
206
207 if (matchers.contains(matcherId.toString())) {
208 component = new MatcherRefBuilder.IHeaderMatcherProxy(matcherId.toString(), null);
209 description = component.getDescription();
210 } else {
211 matchers.add(matcherId.toString());
212 }
213
214 try {
215 UUID.fromString(matcherId);
216 description.getChildren().remove(XMLConfig.ATT_ID);
217 } catch (IllegalArgumentException expected) {
218 if (description.getCommonName().equals("spdx")) {
219 description.getChildren().remove(XMLConfig.ATT_ID);
220 }
221 }
222 }
223
224
225 Optional<Description> resource = description.childrenOfType(ComponentType.PARAMETER).stream()
226 .filter(i -> XMLConfig.ATT_RESOURCE.equals(i.getCommonName())).findFirst();
227 if (resource.isPresent()) {
228 String resourceStr = resource.get().getParamValue(configuration.getLog(), component);
229 if (StringUtils.isNotBlank(resourceStr)) {
230 description.getChildren().remove("enclosed");
231 }
232 }
233 writeComment(writer, description);
234 writer.openElement(description.getCommonName());
235 writeChildren(writer, description, component);
236 writer.closeElement();
237 break;
238 case LICENSE:
239 writer.openElement(XMLConfig.LICENSE);
240 writeChildren(writer, description, component);
241 writer.closeElement();
242 break;
243 case PARAMETER:
244 if ("id".equals(description.getCommonName())) {
245 try {
246 String paramId = description.getParamValue(configuration.getLog(), component);
247
248 if (paramId != null) {
249 UUID.fromString(paramId.toString());
250 return;
251 }
252 } catch (IllegalArgumentException expected) {
253
254 }
255 }
256 if (description.getChildType() == String.class) {
257
258 boolean inline = XMLConfig.isInlineNode(component.getDescription().getCommonName(),
259 description.getCommonName());
260 String s = description.getParamValue(configuration.getLog(), component);
261 if (StringUtils.isNotBlank(s)) {
262 if (!inline) {
263 writer.openElement(description.getCommonName());
264 }
265 writer.content(description.getParamValue(configuration.getLog(), component));
266 if (!inline) {
267 writer.closeElement();
268 }
269 }
270 } else {
271 try {
272 if (description.isCollection()) {
273 for (IHeaderMatcher matcher : (Collection<IHeaderMatcher>) description
274 .getter(component.getClass()).invoke(component)) {
275 writeDescription(writer, matcher.getDescription(), matcher);
276 }
277 } else {
278 IHeaderMatcher matcher = (IHeaderMatcher) description.getter(component.getClass())
279 .invoke(component);
280 writeDescription(writer, matcher.getDescription(), matcher);
281 }
282 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
283 | NoSuchMethodException | SecurityException | RatException e) {
284 throw new ImplementationException(e);
285 }
286 }
287 break;
288 case BUILD_PARAMETER:
289
290 break;
291 }
292 } catch (IOException e) {
293 throw new RatException(e);
294 }
295 }
296 }