Source code: com/puppycrawl/tools/checkstyle/checks/ClassResolver.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 Oliver Burn
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ////////////////////////////////////////////////////////////////////////////////
19 package com.puppycrawl.tools.checkstyle.checks;
20
21 import java.util.Set;
22 import java.util.Iterator;
23
24 /**
25 * Utility class to resolve a class name to an actual class. Note that loaded
26 * classes are not initialized.
27 * <p>Limitations: this does not handle inner classes very well.</p>
28 *
29 * @author Oliver Burn
30 * @version 1.0
31 */
32 public class ClassResolver
33 {
34 /** name of the package to check if the class belongs to **/
35 private final String mPkg;
36 /** set of imports to check against **/
37 private final Set mImports;
38 /** use to load classes **/
39 private final ClassLoader mLoader;
40
41 /**
42 * Creates a new <code>ClassResolver</code> instance.
43 *
44 * @param aLoader the ClassLoader to load classes with.
45 * @param aPkg the name of the package the class may belong to
46 * @param aImports set of imports to check if the class belongs to
47 */
48 public ClassResolver(ClassLoader aLoader, String aPkg, Set aImports)
49 {
50 mLoader = aLoader;
51 mPkg = aPkg;
52 mImports = aImports;
53 }
54
55 /**
56 * Attempts to resolve the Class for a specified name. The algorithm is
57 * to check:
58 * - fully qualified name
59 * - explicit imports
60 * - enclosing package
61 * - star imports
62 * @param aName name of the class to resolve
63 * @return the resolved class
64 * @throws ClassNotFoundException if unable to resolve the class
65 */
66 public Class resolve(String aName) throws ClassNotFoundException
67 {
68 // See if the class is full qualified
69 if (isLoadable(aName)) {
70 return safeLoad(aName);
71 }
72
73 // try matching explicit imports
74 Iterator it = mImports.iterator();
75 while (it.hasNext()) {
76 final String imp = (String) it.next();
77 if (imp.endsWith(aName) && isLoadable(imp)) {
78 return safeLoad(imp);
79 }
80 }
81
82 // See if in the package
83 if (mPkg != null) {
84 final String fqn = mPkg + "." + aName;
85 if (isLoadable(fqn)) {
86 return safeLoad(fqn);
87 }
88 }
89
90 // try "java.lang."
91 final String langClass = "java.lang." + aName;
92 if (isLoadable(langClass)) {
93 return safeLoad(langClass);
94 }
95
96 // try star imports
97 it = mImports.iterator();
98 while (it.hasNext()) {
99 final String imp = (String) it.next();
100 if (imp.endsWith(".*")) {
101 final String fqn = imp.substring(0, imp.lastIndexOf('.') + 1)
102 + aName;
103 if (isLoadable(fqn)) {
104 return safeLoad(fqn);
105 }
106 }
107 }
108
109 // Giving up, the type is unknown, so load the class to generate an
110 // exception
111 return safeLoad(aName);
112 }
113
114 /**
115 * @return whether a specified class is loadable with safeLoad().
116 * @param aName name of the class to check
117 */
118 public boolean isLoadable(String aName)
119 {
120 try {
121 safeLoad(aName);
122 return true;
123 }
124 catch (ClassNotFoundException e) {
125 return false;
126 }
127 }
128
129 /**
130 * Will load a specified class is such a way that it will NOT be
131 * initialised.
132 * @param aName name of the class to load
133 * @return the <code>Class</code> for the specified class
134 * @throws ClassNotFoundException if an error occurs
135 */
136 public Class safeLoad(String aName)
137 throws ClassNotFoundException
138 {
139 // The next line will load the class using the specified class
140 // loader. The magic is having the "false" parameter. This means the
141 // class will not be initialised. Very, very important.
142 return Class.forName(aName, false, mLoader);
143 }
144 }