MOA 12.03
Real Time Analytics for Data Streams
AutoClassDiscovery.java
Go to the documentation of this file.
00001 /*
00002  *    AutoClassDiscovery.java
00003  *    Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
00004  *    @author Richard Kirkby ([email protected])
00005  *
00006  *    This program is free software; you can redistribute it and/or modify
00007  *    it under the terms of the GNU General Public License as published by
00008  *    the Free Software Foundation; either version 3 of the License, or
00009  *    (at your option) any later version.
00010  *
00011  *    This program is distributed in the hope that it will be useful,
00012  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *    GNU General Public License for more details.
00015  *
00016  *    You should have received a copy of the GNU General Public License
00017  *    along with this program. If not, see <http://www.gnu.org/licenses/>.
00018  *    
00019  */
00020 package moa.core;
00021 
00022 import java.io.File;
00023 import java.io.IOException;
00024 import java.net.URL;
00025 import java.net.URLClassLoader;
00026 import java.net.URISyntaxException;
00027 import java.util.ArrayList;
00028 import java.util.Arrays;
00029 import java.util.Enumeration;
00030 import java.util.HashMap;
00031 import java.util.HashSet;
00032 import java.util.Map;
00033 import java.util.jar.JarEntry;
00034 import java.util.jar.JarFile;
00035 
00042 public class AutoClassDiscovery {
00043 
00044     protected static final Map<String, String[]> cachedClassNames = new HashMap<String, String[]>();
00045 
00046     public static String[] findClassNames(String packageNameToSearch) {
00047         String[] cached = cachedClassNames.get(packageNameToSearch);
00048         if (cached == null) {
00049             HashSet<String> classNames = new HashSet<String>();
00050             /*StringTokenizer pathTokens = new StringTokenizer(System
00051             .getProperty("java.class.path"), File.pathSeparator);*/
00052             String packageDirName = packageNameToSearch.replace('.',
00053                     File.separatorChar);
00054             String packageJarName = packageNameToSearch.length() > 0 ? (packageNameToSearch.replace('.', '/') + "/")
00055                     : "";
00056             String part = "";
00057 
00058 
00059             AutoClassDiscovery adc = new AutoClassDiscovery();
00060             URLClassLoader sysLoader = (URLClassLoader) adc.getClass().getClassLoader();
00061             URL[] cl_urls = sysLoader.getURLs();
00062 
00063             for (int i = 0; i < cl_urls.length; i++) {
00064                 part = cl_urls[i].toString();
00065                 if (part.startsWith("file:")) {
00066                     part = part.replace(" ", "%20");
00067                     try {
00068                         File temp = new File(new java.net.URI(part));
00069                         part = temp.getAbsolutePath();
00070                     } catch (URISyntaxException e) {
00071                         e.printStackTrace();
00072                     }
00073                 }
00074 
00075                 // find classes
00076                 ArrayList<File> files = new ArrayList<File>();
00077                 File dir = new File(part);
00078                 if (dir.isDirectory()) {
00079                     File root = new File(dir.toString() + File.separatorChar + packageDirName);
00080                     String[] names = findClassesInDirectoryRecursive(root, "");
00081                     classNames.addAll(Arrays.asList(names));
00082                 } else {
00083                     try {
00084                         JarFile jar = new JarFile(part);
00085                         Enumeration<JarEntry> jarEntries = jar.entries();
00086                         while (jarEntries.hasMoreElements()) {
00087                             String jarEntry = jarEntries.nextElement().getName();
00088                             if (jarEntry.startsWith(packageJarName)) {
00089                                 String relativeName = jarEntry.substring(packageJarName.length());
00090                                 if (relativeName.endsWith(".class")) {
00091                                     relativeName = relativeName.replace('/',
00092                                             '.');
00093                                     classNames.add(relativeName.substring(0,
00094                                             relativeName.length()
00095                                             - ".class".length()));
00096                                 }
00097                             }
00098                         }
00099                     } catch (IOException ignored) {
00100                         // ignore unreadable files
00101                     }
00102                 }
00103             }
00104 
00105             /*while (pathTokens.hasMoreElements()) {
00106             String pathToSearch = pathTokens.nextElement().toString();
00107             if (pathToSearch.endsWith(".jar")) {
00108             try {
00109             JarFile jar = new JarFile(pathToSearch);
00110             Enumeration<JarEntry> jarEntries = jar.entries();
00111             while (jarEntries.hasMoreElements()) {
00112             String jarEntry = jarEntries.nextElement()
00113             .getName();
00114             if (jarEntry.startsWith(packageJarName)) {
00115             String relativeName = jarEntry
00116             .substring(packageJarName.length());
00117             if (relativeName.endsWith(".class")) {
00118             relativeName = relativeName.replace('/',
00119             '.');
00120             classNames.add(relativeName.substring(0,
00121             relativeName.length()
00122             - ".class".length()));
00123             }
00124             }
00125             }
00126             } catch (IOException ignored) {
00127             // ignore unreadable files
00128             }
00129             } else {
00130             File root = new File(pathToSearch + File.separatorChar
00131             + packageDirName);
00132             String[] names = findClassesInDirectoryRecursive(root, "");
00133             for (String name : names) {
00134             classNames.add(name);
00135             }
00136             }
00137             } */
00138             cached = classNames.toArray(new String[classNames.size()]);
00139             Arrays.sort(cached);
00140             cachedClassNames.put(packageNameToSearch, cached);
00141         }
00142         return cached;
00143     }
00144 
00145     protected static String[] findClassesInDirectoryRecursive(File root,
00146             String packagePath) {
00147         HashSet<String> classNames = new HashSet<String>();
00148         if (root.isDirectory()) {
00149             String[] list = root.list();
00150             for (String string : list) {
00151                 if (string.endsWith(".class")) {
00152                     classNames.add(packagePath
00153                             + string.substring(0, string.length()
00154                             - ".class".length()));
00155                 } else {
00156                     File testDir = new File(root.getPath() + File.separatorChar
00157                             + string);
00158                     if (testDir.isDirectory()) {
00159                         String[] names = findClassesInDirectoryRecursive(
00160                                 testDir, packagePath + string + ".");
00161                         classNames.addAll(Arrays.asList(names));
00162                     }
00163                 }
00164             }
00165         }
00166         return classNames.toArray(new String[classNames.size()]);
00167     }
00168 
00169     public static Class[] findClassesOfType(String packageNameToSearch,
00170             Class<?> typeDesired) {
00171         ArrayList<Class<?>> classesFound = new ArrayList<Class<?>>();
00172         String[] classNames = findClassNames(packageNameToSearch);
00173         for (String className : classNames) {
00174             String fullName = packageNameToSearch.length() > 0 ? (packageNameToSearch
00175                     + "." + className)
00176                     : className;
00177             if (isPublicConcreteClassOfType(fullName, typeDesired)) {
00178                 try {
00179                     classesFound.add(Class.forName(fullName));
00180                 } catch (Exception ignored) {
00181                     // ignore classes that we cannot instantiate
00182                 }
00183             }
00184         }
00185         return classesFound.toArray(new Class[classesFound.size()]);
00186     }
00187 
00188     public static boolean isPublicConcreteClassOfType(String className,
00189             Class<?> typeDesired) {
00190         Class<?> testClass = null;
00191         try {
00192             testClass = Class.forName(className);
00193         } catch (Exception e) {
00194             return false;
00195         }
00196         int classModifiers = testClass.getModifiers();
00197         return (java.lang.reflect.Modifier.isPublic(classModifiers)
00198                 && !java.lang.reflect.Modifier.isAbstract(classModifiers)
00199                 && typeDesired.isAssignableFrom(testClass) && hasEmptyConstructor(testClass));
00200     }
00201 
00202     public static boolean hasEmptyConstructor(Class<?> type) {
00203         try {
00204             type.getConstructor();
00205             return true;
00206         } catch (Exception ignored) {
00207             return false;
00208         }
00209     }
00210 }
 All Classes Namespaces Files Functions Variables Enumerations