View Javadoc

1   /*
2   Copyright (C) 2000 - 2007 Grid Systems, S.A.
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2, as
6   published by the Free Software Foundation.
7   
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17  package com.gridsystems.utils;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.Enumeration;
23  import java.util.List;
24  import java.util.jar.JarEntry;
25  import java.util.jar.JarFile;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * Utility class to discover classes inside directories or jar files.
32   *
33   * @author dsanchez
34   */
35  public final class ClassDiscovery {
36  
37    /**
38     * Class logger.
39     */
40    private static final Log LOG = LogFactory.getLog(ClassDiscovery.class);
41  
42    /**
43     * Private constructor.
44     */
45    private ClassDiscovery() {
46    }
47  
48    /**
49     * Finds a list of classes in the jars located in a given directory.
50     *
51     * @param baseDir the base directory
52     * @param packageName the base package name
53     * @param suffix a suffix for the jars to search
54     * @param parentClassOrInterface the parent class or interface
55     * @return the list of classes
56     */
57    public static List<Class<?>> findInJars(String baseDir,
58                                  String packageName,
59                                  String suffix,
60                                  Class<?> parentClassOrInterface) {
61      String name = new String(packageName);
62      name = name.replace('.', '/');
63  
64      List<Class<?>> results = new ArrayList<Class<?>>();
65      File directory = new File(baseDir);
66      File[] allFiles = directory.listFiles();
67  
68      String jarSuffix = (suffix == null) ? ".jar" : suffix + ".jar";
69      for (int i = 0; i < allFiles.length; i++) {
70        LOG.debug("Processing file number " + i + ": " + allFiles[i].getName());
71        if (!allFiles[i].getName().endsWith(jarSuffix)) {
72          continue;
73        }
74  
75        JarFile jFile = null;
76        try {
77          jFile = new JarFile(allFiles[i]);
78          Enumeration<JarEntry> en = jFile.entries();
79          while (en.hasMoreElements()) {
80            JarEntry entry = en.nextElement();
81            String entryName = entry.getName();
82            if (entryName.startsWith(name) && entryName.endsWith(".class")) {
83              String className =
84                entryName.substring(0, entryName.length() - ".class".length());
85              if (className.startsWith("/")) {
86                className = className.substring(1);
87              }
88              className = className.replace('/', '.');
89              try {
90                // Try to load the class
91                Class<?> clazz = Class.forName(className);
92                if (parentClassOrInterface.isAssignableFrom(clazz)) {
93                  LOG.debug("Adding class " + className);
94                  results.add(clazz);
95                }
96              } catch (Exception e) {
97                LOG.debug("Error instantiating class " + className, e);
98              }
99            }
100         }
101       } catch (IOException ioe) {
102         LOG.debug("Error accessing jar " + allFiles[i].getAbsolutePath(), ioe);
103       } finally {
104         FileUtils.close(jFile);
105       }
106     }
107     return results;
108   }
109 }