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.indexOf(',') == -1) {
255 references.add(new RuleSetReferenceId(referenceString));
256 } else {
257 for (String name : referenceString.split(",")) {
258 references.add(new RuleSetReferenceId(name));
259 }
260 }
261 return references;
262 }
263
264
265
266
267
268 public boolean isExternal() {
269 return external;
270 }
271
272
273
274
275
276 public boolean isAllRules() {
277 return allRules;
278 }
279
280
281
282
283
284 public String getRuleSetFileName() {
285 return ruleSetFileName;
286 }
287
288
289
290
291
292
293 public String getRuleName() {
294 return ruleName;
295 }
296
297
298
299
300
301
302
303
304
305
306
307 public InputStream getInputStream(ClassLoader classLoader) throws RuleSetNotFoundException {
308 if (externalRuleSetReferenceId == null) {
309 InputStream in = StringUtil.isEmpty(ruleSetFileName) ? null : ResourceLoader.loadResourceAsStream(
310 ruleSetFileName, classLoader);
311 if (in == null) {
312 throw new RuleSetNotFoundException(
313 "Can't find resource " + ruleSetFileName
314 + ". Make sure the resource is a valid file or URL and is on the CLASSPATH. "
315 + "Here's the current classpath: "
316 + System.getProperty("java.class.path"));
317 }
318 return in;
319 } else {
320 return externalRuleSetReferenceId.getInputStream(classLoader);
321 }
322 }
323
324
325
326
327
328
329
330 public String toString() {
331 if (ruleSetFileName != null) {
332 if (allRules) {
333 return ruleSetFileName;
334 } else {
335 return ruleSetFileName + "/" + ruleName;
336 }
337
338 } else {
339 if (allRules) {
340 return "anonymous all Rule";
341 } else {
342 return ruleName;
343 }
344 }
345 }
346 }