1
2
3
4 package net.sourceforge.pmd.lang.java.symboltable;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Set;
12
13 import net.sourceforge.pmd.lang.java.typeresolution.PMDASMClassLoader;
14 import net.sourceforge.pmd.util.ClasspathClassLoader;
15
16
17
18
19 public class TypeSet {
20
21 private final PMDASMClassLoader pmdClassLoader;
22 private boolean hasAuxclasspath;
23
24
25
26
27 public TypeSet() {
28 this(TypeSet.class.getClassLoader());
29 }
30
31
32
33
34
35 public TypeSet(ClassLoader classLoader) {
36 ClassLoader cl = classLoader;
37 if (cl == null) {
38 cl = TypeSet.class.getClassLoader();
39 }
40 hasAuxclasspath = cl instanceof ClasspathClassLoader;
41 pmdClassLoader = PMDASMClassLoader.getInstance(cl);
42 }
43
44
45
46
47
48 public boolean hasAuxclasspath() {
49 return hasAuxclasspath;
50 }
51
52
53
54
55
56
57
58 public interface Resolver {
59
60
61
62
63
64
65
66 Class<?> resolve(String name) throws ClassNotFoundException;
67 }
68
69
70
71
72
73 public static abstract class AbstractResolver implements Resolver {
74
75 protected final PMDASMClassLoader pmdClassLoader;
76
77
78
79
80 public AbstractResolver(PMDASMClassLoader pmdClassLoader) {
81 this.pmdClassLoader = pmdClassLoader;
82 }
83 }
84
85
86
87
88
89 public static class ExplicitImportResolver extends AbstractResolver {
90 private Set<String> importStmts;
91
92
93
94
95
96 public ExplicitImportResolver(PMDASMClassLoader pmdClassLoader, Set<String> importStmts) {
97 super(pmdClassLoader);
98 this.importStmts = importStmts;
99 }
100 @Override
101 public Class<?> resolve(String name) throws ClassNotFoundException {
102 if (name == null) {
103 throw new ClassNotFoundException();
104 }
105 for (String importStmt : importStmts) {
106 if (importStmt.endsWith(name)) {
107 return pmdClassLoader.loadClass(importStmt);
108 }
109 }
110 throw new ClassNotFoundException("Type " + name + " not found");
111 }
112 }
113
114
115
116
117 public static class CurrentPackageResolver extends AbstractResolver {
118 private String pkg;
119
120
121
122
123
124 public CurrentPackageResolver(PMDASMClassLoader pmdClassLoader, String pkg) {
125 super(pmdClassLoader);
126 this.pkg = pkg;
127 }
128 @Override
129 public Class<?> resolve(String name) throws ClassNotFoundException {
130 return pmdClassLoader.loadClass(pkg + '.' + name);
131 }
132 }
133
134
135
136
137
138 public static class ImplicitImportResolver extends AbstractResolver {
139
140
141
142
143 public ImplicitImportResolver(PMDASMClassLoader pmdClassLoader) {
144 super(pmdClassLoader);
145 }
146 @Override
147 public Class<?> resolve(String name) throws ClassNotFoundException {
148 return pmdClassLoader.loadClass("java.lang." + name);
149 }
150 }
151
152
153
154
155 public static class ImportOnDemandResolver extends AbstractResolver {
156 private Set<String> importStmts;
157
158
159
160
161
162 public ImportOnDemandResolver(PMDASMClassLoader pmdClassLoader, Set<String> importStmts) {
163 super(pmdClassLoader);
164 this.importStmts = importStmts;
165 }
166 @Override
167 public Class<?> resolve(String name) throws ClassNotFoundException {
168 for (String importStmt : importStmts) {
169 if (importStmt.endsWith("*")) {
170 try {
171 String importPkg = importStmt.substring(0, importStmt.indexOf('*') - 1);
172 return pmdClassLoader.loadClass(importPkg + '.' + name);
173 } catch (ClassNotFoundException cnfe) {
174
175 }
176 }
177 }
178 throw new ClassNotFoundException("Type " + name + " not found");
179 }
180 }
181
182
183
184
185 public static class PrimitiveTypeResolver implements Resolver {
186 private Map<String, Class<?>> primitiveTypes = new HashMap<String, Class<?>>();
187
188
189
190 @SuppressWarnings("PMD.AvoidUsingShortType")
191 public PrimitiveTypeResolver() {
192 primitiveTypes.put("int", int.class);
193 primitiveTypes.put("float", float.class);
194 primitiveTypes.put("double", double.class);
195 primitiveTypes.put("long", long.class);
196 primitiveTypes.put("boolean", boolean.class);
197 primitiveTypes.put("byte", byte.class);
198 primitiveTypes.put("short", short.class);
199 primitiveTypes.put("char", char.class);
200 }
201 @Override
202 public Class<?> resolve(String name) throws ClassNotFoundException {
203 if (!primitiveTypes.containsKey(name)) {
204 throw new ClassNotFoundException(name);
205 }
206 return primitiveTypes.get(name);
207 }
208 }
209
210
211
212
213 public static class VoidResolver implements Resolver {
214 @Override
215 public Class<?> resolve(String name) throws ClassNotFoundException {
216 if ("void".equals(name)) {
217 return void.class;
218 }
219 throw new ClassNotFoundException(name);
220 }
221 }
222
223
224
225
226
227 public static class FullyQualifiedNameResolver extends AbstractResolver {
228
229
230
231
232 public FullyQualifiedNameResolver(PMDASMClassLoader pmdClassLoader) {
233 super(pmdClassLoader);
234 }
235 @Override
236 public Class<?> resolve(String name) throws ClassNotFoundException {
237 if (name == null) {
238 throw new ClassNotFoundException();
239 }
240 return pmdClassLoader.loadClass(name);
241 }
242 }
243
244 private String pkg;
245 private Set<String> imports = new HashSet<String>();
246 private List<Resolver> resolvers = new ArrayList<Resolver>();
247
248 public void setASTCompilationUnitPackage(String pkg) {
249 this.pkg = pkg;
250 }
251
252 public String getASTCompilationUnitPackage() {
253 return pkg;
254 }
255
256
257
258
259
260 public void addImport(String importString) {
261 imports.add(importString);
262 }
263
264 public int getImportsCount() {
265 return imports.size();
266 }
267
268 public Set<String> getExplicitImports() {
269 return imports;
270 }
271
272
273
274
275
276
277
278 public Class<?> findClass(String name) throws ClassNotFoundException {
279
280
281 if (resolvers.isEmpty()) {
282 buildResolvers();
283 }
284
285 for (Resolver resolver : resolvers) {
286 try {
287 return resolver.resolve(name);
288 } catch (ClassNotFoundException cnfe) {
289
290 }
291 }
292
293 throw new ClassNotFoundException("Type " + name + " not found");
294 }
295
296 private void buildResolvers() {
297 resolvers.add(new PrimitiveTypeResolver());
298 resolvers.add(new VoidResolver());
299 resolvers.add(new ExplicitImportResolver(pmdClassLoader, imports));
300 resolvers.add(new CurrentPackageResolver(pmdClassLoader, pkg));
301 resolvers.add(new ImplicitImportResolver(pmdClassLoader));
302 resolvers.add(new ImportOnDemandResolver(pmdClassLoader, imports));
303 resolvers.add(new FullyQualifiedNameResolver(pmdClassLoader));
304 }
305 }