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.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import org.apache.commons.lang3.StringUtils;
25 import org.apache.rat.ConfigurationException;
26 import org.apache.rat.analysis.IHeaders;
27 import org.apache.rat.config.parameters.ComponentType;
28 import org.apache.rat.config.parameters.ConfigComponent;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @ConfigComponent(type = ComponentType.MATCHER, name = "copyright", desc = "Matches copyright statements.")
56 public class CopyrightMatcher extends AbstractHeaderMatcher {
57
58 private static final String COPYRIGHT_SYMBOL_DEFN = "\\([Cc]\\)|©|\\&[Cc][Oo][Pp][Yy]\\;";
59
60 private static final String COPYRIGHT_PATTERN_DEFN = "(\\b)?" + COPYRIGHT_SYMBOL_DEFN + "|Copyright\\b";
61
62 private static final Pattern COPYRIGHT_PATTERN = Pattern.compile(COPYRIGHT_PATTERN_DEFN);
63
64 private static final String ONE_PART = "\\s+((" + COPYRIGHT_SYMBOL_DEFN + ")\\s+)?%s";
65
66 private static final String TWO_PART = "\\s+((" + COPYRIGHT_SYMBOL_DEFN + ")\\s+)?%s,?\\s+%s";
67
68 private static final String DOUBLE_DATE_FMT = "%s\\s*-\\s*%s";
69
70 private static final String ARBITRARY_DATE = "[0-9]{4}";
71
72 private final Pattern dateOwnerPattern;
73
74 private final Pattern ownerDatePattern;
75
76 @ConfigComponent(type = ComponentType.PARAMETER, desc = "The initial date of the copyright")
77 private final String start;
78
79 @ConfigComponent(type = ComponentType.PARAMETER, desc = "The last date the copyright was modifed")
80 private final String end;
81
82 @ConfigComponent(type = ComponentType.PARAMETER, desc = "The owner of the copyright")
83 private final String owner;
84
85
86
87
88
89
90
91
92
93
94 public CopyrightMatcher(final String start, final String end, final String owner) {
95 this(null, start, end, owner);
96 }
97
98 private static void assertNumber(final String label, final String value) {
99 try {
100 if (StringUtils.isNotEmpty(value)) {
101 Integer.parseInt(value);
102 }
103 } catch (NumberFormatException e) {
104 throw new ConfigurationException(String.format("'%s' must be numeric (value provided: '%s')", label, value));
105 }
106 }
107
108
109
110
111
112
113
114
115
116
117 public CopyrightMatcher(final String id, final String start, final String end, final String owner) {
118 super(id);
119 if (StringUtils.isBlank(start) && !StringUtils.isBlank(end)) {
120 throw new ConfigurationException("'end' may not be set if 'start' is not set.");
121 }
122 assertNumber("start", start);
123 assertNumber("end", end);
124 this.start = start;
125 this.end = end;
126 this.owner = owner;
127 String dateDefn = "";
128 if (StringUtils.isNotEmpty(start)) {
129 if (StringUtils.isNotEmpty(end)) {
130 dateDefn = String.format(DOUBLE_DATE_FMT, this.start, this.end);
131 } else {
132 dateDefn = this.start;
133 }
134 }
135 if (StringUtils.isEmpty(owner)) {
136
137 if (StringUtils.isEmpty(dateDefn)) {
138 dateDefn = ARBITRARY_DATE;
139 }
140 dateOwnerPattern = Pattern.compile(String.format(ONE_PART, dateDefn));
141 ownerDatePattern = null;
142 } else {
143 if (StringUtils.isEmpty(dateDefn)) {
144 dateDefn = String.format(DOUBLE_DATE_FMT, "(((" + ARBITRARY_DATE, ")?" + ARBITRARY_DATE + "))?");
145 dateOwnerPattern = Pattern.compile(String.format(TWO_PART, dateDefn, owner));
146 ownerDatePattern = Pattern.compile(String.format(ONE_PART, owner));
147 } else {
148 dateOwnerPattern = Pattern.compile(String.format(TWO_PART, dateDefn, owner));
149 ownerDatePattern = Pattern.compile(String.format(TWO_PART, owner, dateDefn));
150 }
151 }
152 }
153
154
155
156
157
158 public String getStart() {
159 return start;
160 }
161
162
163
164
165
166 public String getEnd() {
167 return end;
168 }
169
170
171
172
173
174 public String getOwner() {
175 return owner;
176 }
177
178 @Override
179 public boolean matches(final IHeaders headers) {
180 String lowerLine = headers.raw().toLowerCase();
181 if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || lowerLine.contains("©") ||
182 lowerLine.contains("©")) {
183 Matcher matcher = COPYRIGHT_PATTERN.matcher(headers.raw());
184 if (matcher.find()) {
185 String buffer = headers.raw().substring(matcher.end());
186 matcher = dateOwnerPattern.matcher(buffer);
187 if (matcher.find() && matcher.start() == 0) {
188 return true;
189 }
190 if (ownerDatePattern != null) {
191 matcher = ownerDatePattern.matcher(buffer);
192 return matcher.find() && matcher.start() == 0;
193 }
194 }
195 }
196 return false;
197 }
198 }