KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > checks > ClassResolver


1 ////////////////////////////////////////////////////////////////////////////////
2
// checkstyle: Checks Java source code for adherence to a set of rules.
3
// Copyright (C) 2001-2005 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 JavaDoc;
22 import java.util.Iterator JavaDoc;
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 JavaDoc mPkg;
36     /** set of imports to check against **/
37     private final Set JavaDoc mImports;
38     /** use to load classes **/
39     private final ClassLoader JavaDoc 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 JavaDoc aLoader, String JavaDoc aPkg, Set JavaDoc aImports)
49     {
50         mLoader = aLoader;
51         mPkg = aPkg;
52         mImports = aImports;
53         mImports.add("java.lang.*");
54     }
55
56     /**
57      * Attempts to resolve the Class for a specified name. The algorithm is
58      * to check:
59      * - fully qualified name
60      * - explicit imports
61      * - enclosing package
62      * - star imports
63      * @param aName name of the class to resolve
64      * @param aCurrentClass name of current class (for inner classes).
65      * @return the resolved class
66      * @throws ClassNotFoundException if unable to resolve the class
67      */

68     public Class JavaDoc resolve(String JavaDoc aName, String JavaDoc aCurrentClass)
69         throws ClassNotFoundException JavaDoc
70     {
71         // See if the class is full qualified
72
Class JavaDoc clazz = resolveQualifiedName(aName);
73         if (clazz != null) {
74             return clazz;
75         }
76
77         // try matching explicit imports
78
Iterator JavaDoc it = mImports.iterator();
79         while (it.hasNext()) {
80             final String JavaDoc imp = (String JavaDoc) it.next();
81             // Very important to add the "." in the check below. Otherwise you
82
// when checking for "DataException", it will match on
83
// "SecurityDataException". This has been the cause of a very
84
// difficult bug to resolve!
85
if (imp.endsWith("." + aName)) {
86                 clazz = resolveQualifiedName(imp);
87                 if (clazz != null) {
88                     return clazz;
89                 }
90
91             }
92         }
93
94         // See if in the package
95
if (!"".equals(mPkg)) {
96             clazz = resolveQualifiedName(mPkg + "." + aName);
97             if (clazz != null) {
98                 return clazz;
99             }
100         }
101
102         //inner class of this class???
103
if (!"".equals(aCurrentClass)) {
104             final String JavaDoc innerClass = (!"".equals(mPkg) ? (mPkg + ".") : "")
105                 + aCurrentClass + "$" + aName;
106             if (isLoadable(innerClass)) {
107                 return safeLoad(innerClass);
108             }
109         }
110
111         // try star imports
112
it = mImports.iterator();
113         while (it.hasNext()) {
114             final String JavaDoc imp = (String JavaDoc) it.next();
115             if (imp.endsWith(".*")) {
116                 final String JavaDoc fqn = imp.substring(0, imp.lastIndexOf('.') + 1)
117                     + aName;
118                 clazz = resolveQualifiedName(fqn);
119                 if (clazz != null) {
120                     return clazz;
121                 }
122             }
123         }
124
125         // Giving up, the type is unknown, so load the class to generate an
126
// exception
127
return safeLoad(aName);
128     }
129
130     /**
131      * @return whether a specified class is loadable with safeLoad().
132      * @param aName name of the class to check
133      */

134     public boolean isLoadable(String JavaDoc aName)
135     {
136         try {
137             safeLoad(aName);
138             return true;
139         }
140         catch (final ClassNotFoundException JavaDoc e) {
141             return false;
142         }
143     }
144
145     /**
146      * Will load a specified class is such a way that it will NOT be
147      * initialised.
148      * @param aName name of the class to load
149      * @return the <code>Class</code> for the specified class
150      * @throws ClassNotFoundException if an error occurs
151      */

152     public Class JavaDoc safeLoad(String JavaDoc aName)
153         throws ClassNotFoundException JavaDoc
154     {
155         // The next line will load the class using the specified class
156
// loader. The magic is having the "false" parameter. This means the
157
// class will not be initialised. Very, very important.
158
return Class.forName(aName, false, mLoader);
159     }
160
161     /**
162      * Tries to resolve a class for fully-specified name.
163      * @param aName a given name of class.
164      * @return Class object for the given name or null.
165      */

166     private Class JavaDoc resolveQualifiedName(final String JavaDoc aName)
167     {
168         try {
169             if (isLoadable(aName)) {
170                 return safeLoad(aName);
171             }
172             //Perhaps it's fully-qualified inner class
173
final int dot = aName.lastIndexOf(".");
174             if (dot != -1) {
175                 final String JavaDoc innerName =
176                     aName.substring(0, dot) + "$" + aName.substring(dot + 1);
177                 if (isLoadable(innerName)) {
178                     return safeLoad(innerName);
179                 }
180             }
181         }
182         catch (final ClassNotFoundException JavaDoc ex) {
183             // we shouldn't get this exception here,
184
// so this is unexpected runtime exception
185
throw new RuntimeException JavaDoc(ex);
186         }
187
188         return null;
189     }
190 }
191
Popular Tags