KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > puppycrawl > tools > checkstyle > bcel > ClassFileSetCheck


1 //Tested with BCEL-5.1
2
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
3

4 package com.puppycrawl.tools.checkstyle.bcel;
5
6 import java.io.File JavaDoc;
7 import java.io.IOException JavaDoc;
8 import java.io.InputStream JavaDoc;
9 import java.util.Enumeration JavaDoc;
10 import java.util.HashMap JavaDoc;
11 import java.util.HashSet JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Set JavaDoc;
14 import java.util.zip.ZipEntry JavaDoc;
15 import java.util.zip.ZipFile JavaDoc;
16
17 import org.apache.bcel.Repository;
18 import org.apache.bcel.classfile.ClassParser;
19 import org.apache.bcel.classfile.JavaClass;
20 import org.apache.bcel.classfile.Visitor;
21 import org.apache.bcel.util.ClassLoaderRepository;
22 import com.puppycrawl.tools.checkstyle.DefaultContext;
23 import com.puppycrawl.tools.checkstyle.ModuleFactory;
24 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
25 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
26 import com.puppycrawl.tools.checkstyle.api.Configuration;
27 import com.puppycrawl.tools.checkstyle.api.Context;
28 import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
29 import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
30
31 /**
32  * Checks a set of class files using BCEL
33  * @author Rick Giles
34  */

35 //TODO: Refactor with AbstractFileSetCheck and TreeWalker
36
public class ClassFileSetCheck
37     extends AbstractFileSetCheck
38     implements IObjectSetVisitor
39 {
40     /** visitors for BCEL parse tree walk */
41     private final Set JavaDoc mTreeVisitors = new HashSet JavaDoc();
42
43     /** all the registered checks */
44     private final Set JavaDoc mAllChecks = new HashSet JavaDoc();
45
46     /** all visitors for IObjectSetVisitor visits */
47     private final Set JavaDoc mObjectSetVisitors = new HashSet JavaDoc();
48
49     /** class loader to resolve classes with. **/
50     private ClassLoader JavaDoc mClassLoader;
51
52     /** context of child components */
53     private Context mChildContext;
54
55     /** a factory for creating submodules (i.e. the Checks) */
56     private ModuleFactory mModuleFactory;
57
58     /** Error messages */
59     HashMap JavaDoc mMessageMap = new HashMap JavaDoc();
60
61     /**
62      * Creates a new <code>ClassFileSetCheck</code> instance.
63      * Initializes the acceptable file extensions.
64      */

65     public ClassFileSetCheck()
66     {
67         setFileExtensions(new String JavaDoc[]{"class", "jar", "zip"});
68     }
69
70     /**
71      * Stores the class loader and makes it the Repository's class loader.
72      * @param aClassLoader class loader to resolve classes with.
73      */

74     public void setClassLoader(ClassLoader JavaDoc aClassLoader)
75     {
76         Repository.setRepository(new ClassLoaderRepository(aClassLoader));
77         mClassLoader = aClassLoader;
78     }
79
80     /**
81      * Sets the module factory for creating child modules (Checks).
82      * @param aModuleFactory the factory
83      */

84     public void setModuleFactory(ModuleFactory aModuleFactory)
85     {
86         mModuleFactory = aModuleFactory;
87     }
88
89     /**
90      * Instantiates, configures and registers a Check that is specified
91      * in the provided configuration.
92      * @see com.puppycrawl.tools.checkstyle.api.AutomaticBean
93      */

94     public void setupChild(Configuration aChildConf)
95         throws CheckstyleException
96     {
97         // TODO: improve the error handing
98
final String JavaDoc name = aChildConf.getName();
99         final Object JavaDoc module = mModuleFactory.createModule(name);
100         if (!(module instanceof AbstractCheckVisitor)) {
101             throw new CheckstyleException(
102                 "ClassFileSet is not allowed as a parent of " + name);
103         }
104         final AbstractCheckVisitor c = (AbstractCheckVisitor) module;
105         c.contextualize(mChildContext);
106         c.configure(aChildConf);
107         c.init();
108
109         registerCheck(c);
110     }
111
112     /** @see com.puppycrawl.tools.checkstyle.api.Configurable */
113     public void finishLocalSetup()
114     {
115         DefaultContext checkContext = new DefaultContext();
116         checkContext.add("classLoader", mClassLoader);
117         checkContext.add("messageMap", mMessageMap);
118         checkContext.add("severity", getSeverity());
119
120         mChildContext = checkContext;
121     }
122
123     /**
124      * Register a check.
125      * @param aCheck the check to register
126      */

127     private void registerCheck(AbstractCheckVisitor aCheck)
128     {
129         mAllChecks.add(aCheck);
130     }
131
132     /**
133      * @see com.puppycrawl.tools.checkstyle.api.FileSetCheck
134      */

135     public void process(File JavaDoc[] aFiles)
136     {
137         registerVisitors();
138
139         // get all the JavaClasses in the files
140
final Set JavaDoc javaClasses = extractJavaClasses(aFiles);
141
142         visitSet(javaClasses);
143
144         // walk each Java class parse tree
145
final JavaClassWalker walker = new JavaClassWalker();
146         walker.setVisitor(getTreeVisitor());
147         final Iterator JavaDoc it = javaClasses.iterator();
148         while (it.hasNext()) {
149             final JavaClass clazz = (JavaClass) it.next();
150             visitObject(clazz);
151             walker.walk(clazz);
152             leaveObject(clazz);
153         }
154
155         leaveSet(javaClasses);
156         fireErrors();
157     }
158
159     /**
160      * Gets the visitor for a parse tree walk.
161      * @return the visitor for a parse tree walk.
162      */

163     private Visitor getTreeVisitor()
164     {
165         return new VisitorSet(mTreeVisitors);
166     }
167
168     /**
169      * Registers all the visitors for IObjectSetVisitor visits, and for
170      * tree walk visits.
171      */

172     private void registerVisitors()
173     {
174         mObjectSetVisitors.addAll(mAllChecks);
175         final Iterator JavaDoc it = mAllChecks.iterator();
176         while (it.hasNext()) {
177             final AbstractCheckVisitor check = (AbstractCheckVisitor) it.next();
178             final IDeepVisitor visitor = check.getVisitor();
179             mObjectSetVisitors.add(visitor);
180             mTreeVisitors.add(visitor);
181         }
182     }
183
184     /**
185      * Gets the set of all visitors for all the checks.
186      * @return the set of all visitors for all the checks.
187      */

188     private Set JavaDoc getObjectSetVisitors()
189     {
190         return mObjectSetVisitors;
191     }
192
193     /**
194      * Gets the set of all JavaClasses within a set of Files.
195      * @param aFiles the set of files to extract from.
196      * @return the set of all JavaClasses within aFiles.
197      */

198     private Set JavaDoc extractJavaClasses(File JavaDoc[] aFiles)
199     {
200         final Set JavaDoc result = new HashSet JavaDoc();
201         final File JavaDoc[] classFiles = filter(aFiles);
202         // get Java classes from each filtered file
203
for (int i = 0; i < classFiles.length; i++) {
204             try {
205                 final Set JavaDoc extracted = extractJavaClasses(classFiles[i]);
206                 result.addAll(extracted);
207             }
208             catch (IOException JavaDoc e) {
209                 // TODO Auto-generated catch block
210
e.printStackTrace();
211             }
212         }
213         return result;
214     }
215
216     /** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
217     public void visitSet(Set JavaDoc aSet)
218     {
219         // register the JavaClasses in the Repository
220
Repository.clearCache();
221         Iterator JavaDoc it = aSet.iterator();
222         while (it.hasNext()) {
223             final JavaClass javaClass = (JavaClass) it.next();
224             Repository.addClass(javaClass);
225         }
226
227         // visit the visitors
228
it = getObjectSetVisitors().iterator();
229         while (it.hasNext()) {
230             final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
231             visitor.visitSet(aSet);
232         }
233     }
234
235     /** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
236     public void visitObject(Object JavaDoc aObject)
237     {
238         final Iterator JavaDoc it = getObjectSetVisitors().iterator();
239         while (it.hasNext()) {
240             final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
241             visitor.visitObject(aObject);
242         }
243     }
244
245     /** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
246     public void leaveObject(Object JavaDoc aObject)
247     {
248         final Iterator JavaDoc it = getObjectSetVisitors().iterator();
249         while (it.hasNext()) {
250             final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
251             visitor.leaveObject(aObject);
252         }
253     }
254
255     /** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
256     public void leaveSet(Set JavaDoc aSet)
257     {
258         final Iterator JavaDoc it = getObjectSetVisitors().iterator();
259         while (it.hasNext()) {
260             final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
261             visitor.leaveSet(aSet);
262         }
263     }
264
265     /**
266      * Extracts the JavaClasses from .class, .zip, and .jar files.
267      * @param aFile the file to extract from.
268      * @return the set of JavaClasses from aFile.
269      * @throws IOException if there is an error.
270      */

271     private Set JavaDoc extractJavaClasses(File JavaDoc aFile)
272         throws IOException JavaDoc
273     {
274         final Set JavaDoc result = new HashSet JavaDoc();
275         final String JavaDoc fileName = aFile.getPath();
276         if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
277             final ZipFile JavaDoc zipFile = new ZipFile JavaDoc(fileName);
278             final Enumeration JavaDoc entries = zipFile.entries();
279             while (entries.hasMoreElements()) {
280                 final ZipEntry JavaDoc entry = (ZipEntry JavaDoc) entries.nextElement();
281                 final String JavaDoc entryName = entry.getName();
282                 if (entryName.endsWith(".class")) {
283                     final InputStream JavaDoc in = zipFile.getInputStream(entry);
284                     final JavaClass javaClass =
285                         new ClassParser(in, entryName).parse();
286                     result.add(javaClass);
287                 }
288             }
289         }
290         else {
291             final JavaClass javaClass = new ClassParser(fileName).parse();
292             result.add(javaClass);
293         }
294         return result;
295     }
296
297     /**
298      * Notify all listeners about the errors in a file.
299      * Calls <code>MessageDispatcher.fireErrors()</code> with
300      * all logged errors and than clears errors' list.
301      */

302     private void fireErrors()
303     {
304         Set JavaDoc keys = mMessageMap.keySet();
305         Iterator JavaDoc iter = keys.iterator();
306         while (iter.hasNext()) {
307             String JavaDoc key = (String JavaDoc) iter.next();
308             getMessageDispatcher().fireFileStarted(key);
309             LocalizedMessages localizedMessages = (LocalizedMessages) mMessageMap.get(key);
310             final LocalizedMessage[] errors = localizedMessages.getMessages();
311             localizedMessages.reset();
312             getMessageDispatcher().fireErrors(key, errors);
313             getMessageDispatcher().fireFileFinished(key);
314         }
315     }
316
317 }
318
Popular Tags