1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.analysis.matchers;
20
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Map;
24 import java.util.Objects;
25 import java.util.Set;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.rat.ConfigurationException;
31 import org.apache.rat.analysis.IHeaders;
32 import org.apache.rat.config.parameters.ComponentType;
33 import org.apache.rat.config.parameters.ConfigComponent;
34
35
36
37
38
39
40
41
42
43
44
45
46 public class SPDXMatcherFactory {
47
48
49
50
51 private static final Map<String, SPDXMatcherFactory.Match> matchers = new HashMap<>();
52
53
54
55
56 public static final SPDXMatcherFactory INSTANCE = new SPDXMatcherFactory();
57
58 static final String LICENSE_IDENTIFIER = "SPDX-License-Identifier:";
59
60
61
62
63
64 private static Pattern groupSelector = Pattern.compile(".*"+LICENSE_IDENTIFIER+"\\s([A-Za-z0-9\\.\\-]+)");
65
66
67
68
69 private Set<String> lastMatch;
70
71 private boolean checked;
72
73 private SPDXMatcherFactory() {
74 lastMatch = new HashSet<>();
75 }
76
77 private void reset() {
78 lastMatch.clear();
79 checked = false;
80 }
81
82
83
84
85
86
87
88 public Match create(String spdxId) {
89 if (StringUtils.isBlank(spdxId)) {
90 throw new ConfigurationException("'SPDX' type matcher requires a name");
91 }
92 Match matcher = matchers.get(spdxId);
93 if (matcher == null) {
94 matcher = new Match(spdxId);
95 matchers.put(spdxId, matcher);
96 }
97 return matcher;
98 }
99
100
101
102
103
104
105
106
107 private boolean check(String line, Match caller) {
108
109
110
111
112 if (!checked) {
113 checked = true;
114 if (line.contains(LICENSE_IDENTIFIER)) {
115 Matcher matcher = groupSelector.matcher(line);
116 while (matcher.find()) {
117 lastMatch.add(matcher.group(1));
118 }
119 }
120 }
121
122 return lastMatch.contains(caller.spdxId);
123 }
124
125 @ConfigComponent(type = ComponentType.MATCHER, name = "spdx", desc = "Matches SPDX enclosed license identifier.")
126 public class Match extends AbstractHeaderMatcher {
127 @ConfigComponent(type = ComponentType.PARAMETER, name = "name", desc = "The SPDX identifier string")
128 String spdxId;
129
130 public String getName() {
131 return spdxId;
132 }
133
134
135
136
137
138
139
140 Match(final String spdxId) {
141 super("SPDX:" + spdxId);
142 Objects.requireNonNull(spdxId, "SpdxId is required");
143 this.spdxId = spdxId;
144 }
145
146 @Override
147 public boolean matches(IHeaders headers) {
148 return SPDXMatcherFactory.this.check(headers.raw(), this);
149 }
150
151 @Override
152 public void reset() {
153 super.reset();
154 SPDXMatcherFactory.this.reset();
155 }
156 }
157 }