1
2
3
4 package net.sourceforge.pmd;
5
6 import java.io.File;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import org.apache.commons.io.IOUtils;
12
13 import net.sourceforge.pmd.util.ResourceLoader;
14 import net.sourceforge.pmd.util.StringUtil;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public class RuleSetReferenceId {
79 private final boolean external;
80 private final String ruleSetFileName;
81 private final boolean allRules;
82 private final String ruleName;
83 private final RuleSetReferenceId externalRuleSetReferenceId;
84
85
86
87
88
89
90 public RuleSetReferenceId(final String id) {
91 this(id, null);
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public RuleSetReferenceId(final String id, final RuleSetReferenceId externalRuleSetReferenceId) {
107 if (externalRuleSetReferenceId != null && !externalRuleSetReferenceId.isExternal()) {
108 throw new IllegalArgumentException("Cannot pair with non-external <" + externalRuleSetReferenceId + ">.");
109 }
110 if (id != null && id.indexOf(',') >= 0) {
111 throw new IllegalArgumentException("A single RuleSetReferenceId cannot contain ',' (comma) characters: "
112 + id);
113 }
114
115
116
117
118 if (isFullRuleSetName(id)) {
119
120 external = true;
121 ruleSetFileName = id;
122 allRules = true;
123 ruleName = null;
124 } else {
125 String tempRuleName = getRuleName(id);
126 String tempRuleSetFileName = tempRuleName != null && id != null ?
127 id.substring(0, id.length() - tempRuleName.length() - 1) : id;
128
129 if (isFullRuleSetName(tempRuleSetFileName)) {
130
131 external = true;
132 ruleSetFileName = tempRuleSetFileName;
133 ruleName = tempRuleName;
134 allRules = tempRuleName == null;
135 } else {
136
137 String builtinRuleSet = resolveBuiltInRuleset(tempRuleSetFileName);
138 if (checkRulesetExists(builtinRuleSet)) {
139 external = true;
140 ruleSetFileName = builtinRuleSet;
141 ruleName = tempRuleName;
142 allRules = tempRuleName == null;
143 } else {
144
145
146
147
148
149
150
151 if (tempRuleSetFileName == null || tempRuleSetFileName.contains(File.separator)) {
152 external = true;
153 ruleSetFileName = id;
154 ruleName = null;
155 allRules = true;
156 } else {
157 external = externalRuleSetReferenceId != null ? externalRuleSetReferenceId.isExternal() : false;
158 ruleSetFileName = externalRuleSetReferenceId != null ? externalRuleSetReferenceId.getRuleSetFileName() : null;
159 ruleName = id;
160 allRules = false;
161 }
162 }
163 }
164 }
165
166 if (this.external && this.ruleName != null && !this.ruleName.equals(id) && externalRuleSetReferenceId != null) {
167 throw new IllegalArgumentException("Cannot pair external <" + this + "> with external <"
168 + externalRuleSetReferenceId + ">.");
169 }
170 this.externalRuleSetReferenceId = externalRuleSetReferenceId;
171 }
172
173
174
175
176
177
178 private boolean checkRulesetExists(String name) {
179 boolean resourceFound = false;
180 if (name != null) {
181 try {
182 InputStream resource = ResourceLoader.loadResourceAsStream(name, RuleSetReferenceId.class.getClassLoader());
183 if (resource != null) {
184 resourceFound = true;
185 IOUtils.closeQuietly(resource);
186 }
187 } catch (RuleSetNotFoundException e) {
188 resourceFound = false;
189 }
190 }
191 return resourceFound;
192 }
193
194
195
196
197
198
199
200
201
202 private String resolveBuiltInRuleset(final String name) {
203 String result = null;
204 if (name != null) {
205
206 int index = name.indexOf('-');
207 if (index >= 0) {
208
209 result = "rulesets/" + name.substring(0, index) + "/" + name.substring(index + 1)
210 + ".xml";
211 } else {
212
213 if (name.matches("[0-9]+.*")) {
214 result = "rulesets/releases/" + name + ".xml";
215 } else {
216
217 result = name;
218 }
219 }
220 }
221 return result;
222 }
223
224
225
226
227
228
229
230 private String getRuleName(final String rulesetName) {
231 String result = null;
232 if (rulesetName != null) {
233
234 final int separatorIndex = Math.max(rulesetName.lastIndexOf('/'), rulesetName.lastIndexOf('\\'));
235 if (separatorIndex >= 0 && separatorIndex != rulesetName.length() - 1) {
236 result = rulesetName.substring(separatorIndex + 1);
237 }
238 }
239 return result;
240 }
241
242 private static boolean isFullRuleSetName(String name) {
243 return name != null && name.endsWith(".xml");
244 }
245
246
247
248
249
250
251
252 public static List<RuleSetReferenceId> parse(String referenceString) {
253 List<RuleSetReferenceId> references = new ArrayList<RuleSetReferenceId>();
254 if (referenceString != null && referenceString.trim().length() > 0) {
255
256 if (referenceString.indexOf(',') == -1) {
257 references.add(new RuleSetReferenceId(referenceString));
258 } else {
259 for (String name : referenceString.split(",")) {
260 references.add(new RuleSetReferenceId(name.trim()));
261 }
262 }
263 }
264 return references;
265 }
266
267
268
269
270
271 public boolean isExternal() {
272 return external;
273 }
274
275
276
277
278
279 public boolean isAllRules() {
280 return allRules;
281 }
282
283
284
285
286
287 public String getRuleSetFileName() {
288 return ruleSetFileName;
289 }
290
291
292
293
294
295
296 public String getRuleName() {
297 return ruleName;
298 }
299
300
301
302
303
304
305
306
307
308
309
310 public InputStream getInputStream(ClassLoader classLoader) throws RuleSetNotFoundException {
311 if (externalRuleSetReferenceId == null) {
312 InputStream in = StringUtil.isEmpty(ruleSetFileName) ? null : ResourceLoader.loadResourceAsStream(
313 ruleSetFileName, classLoader);
314 if (in == null) {
315 throw new RuleSetNotFoundException(
316 "Can't find resource '" + ruleSetFileName + "' for rule '" + ruleName + "'"
317 + ". Make sure the resource is a valid file or URL and is on the CLASSPATH. "
318 + "Here's the current classpath: "
319 + System.getProperty("java.class.path"));
320 }
321 return in;
322 } else {
323 return externalRuleSetReferenceId.getInputStream(classLoader);
324 }
325 }
326
327
328
329
330
331
332
333 public String toString() {
334 if (ruleSetFileName != null) {
335 if (allRules) {
336 return ruleSetFileName;
337 } else {
338 return ruleSetFileName + "/" + ruleName;
339 }
340
341 } else {
342 if (allRules) {
343 return "anonymous all Rule";
344 } else {
345 return ruleName;
346 }
347 }
348 }
349 }