Changeset 743


Ignore:
Timestamp:
01/23/14 12:22:39 (10 years ago)
Author:
bln4
Message:

Added a special case to 'getClassesNew' for handling the protocol bundleresource.
This is the protocol that eclipse uses for their packaging of plugins.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/reflection/PackageLoader.java

    r570 r743  
    66import java.net.URI;
    77import java.net.URL;
    8 import java.net.URLDecoder;
     8import java.net.URLConnection;
    99import java.util.ArrayList;
    10 import java.util.Arrays;
    1110import java.util.Enumeration;
    1211import java.util.LinkedList;
     
    1615import java.util.zip.ZipEntry;
    1716
     17
    1818public class PackageLoader {
    1919
    20         // The following is adapted from:
    21         // http://stackoverflow.com/questions/1456930/how-do-i-read-all-classes-from-a-java-package-in-the-classpath
    22 
    23         public static List<Class<?>> getClassesNew(String packageName) throws ClassNotFoundException {
    24 
    25                 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    26 
    27                 ArrayList<String> names = new ArrayList<String>();
    28                 ;
    29                 final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
    30 
    31                 String realPackageName = packageName;
    32                 packageName = packageName.replace(".", "/");
    33                 URL packageURL = classLoader.getResource(packageName);
    34 
    35                 if (packageURL.getProtocol().equals("jar")) {
    36 
    37                         // build jar file name, then loop through zipped entries
    38 
    39                         String jarFileNameUndecoded = packageURL.getFile();
    40 
     20    // The following is adapted from:
     21    // http://stackoverflow.com/questions/1456930/how-do-i-read-all-classes-from-a-java-package-in-the-classpath
     22
     23    public static List<Class<?>> getClassesNew(String packageName)
     24            throws ClassNotFoundException {
     25
     26        ClassLoader classLoader = Thread.currentThread()
     27                .getContextClassLoader();
     28
     29        ArrayList<String> names = new ArrayList<String>();
     30        ;
     31        final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
     32
     33        String realPackageName = packageName;
     34        packageName = packageName.replace(".", "/");
     35        URL packageURL = classLoader.getResource(packageName);
     36
     37        if (packageURL.getProtocol().equals("jar")) {
     38
     39            // build jar file name, then loop through zipped entries
     40
     41            String jarFileNameUndecoded = packageURL.getFile();
     42
     43            try {
     44                JarURLConnection ju_connection = (JarURLConnection) packageURL
     45                        .openConnection();
     46                JarFile jf = ju_connection.getJarFile();
     47
     48                Enumeration<JarEntry> jarEntries = jf.entries();
     49                while (jarEntries.hasMoreElements()) {
     50                    String entryName = jarEntries.nextElement().getName();
     51
     52                    if (entryName.startsWith(packageName)) {
     53
     54                        if (entryName.endsWith(".class")
     55                                && !entryName.contains("$")) {
     56
     57                            // Deal with situation where the class found might
     58                            // be a further sub-package
     59                            // e.g. for "org.expeditee.action"
     60                            // there is:
     61                            // org/expeditee/action/widgets/Chart.class
     62                            // which would produce a value of 'entryName' as
     63                            // widgets/Chart.class
     64
     65                            entryName = entryName.substring(0,
     66                                    entryName.length() - 6); // 6 = '.class'
     67                            entryName = entryName.replace('/', '.');
     68
     69                            names.add(entryName);
     70                            classes.add(Class.forName(entryName));
     71                        }
     72                    }
     73                }
     74            } catch (Exception e) {
     75                System.err.println("Failed to decode jar file: "
     76                        + jarFileNameUndecoded);
     77                e.printStackTrace();
     78            }
     79        } else if (packageURL.getProtocol().equals("bundleresource")) {
     80            try {
     81                final URLConnection urlConnection = packageURL.openConnection();
     82                final Class<?> c = urlConnection.getClass();
     83                final java.lang.reflect.Method toInvoke = c.getMethod("getFileURL");
     84                final URL fileURL = (URL)toInvoke.invoke(urlConnection);
     85                final File folder = new File(fileURL.getFile());
     86                final List<String> files = findFiles(folder);
     87                for (final String s : files) {
     88                    String entryName = realPackageName + s;
     89                    if (entryName.endsWith(".class") && !entryName.contains("$")) {
     90                        entryName = entryName.substring(0, entryName.lastIndexOf('.'));
     91                        entryName = entryName.replace('/', '.');
     92                        names.add(entryName);
    4193                        try {
    42                                 String jarFileName = URLDecoder.decode(jarFileNameUndecoded, "UTF-8");
    43 
    44                                 JarURLConnection ju_connection = (JarURLConnection) packageURL.openConnection();
    45                                 JarFile jf = ju_connection.getJarFile();
    46 
    47                                 Enumeration<JarEntry> jarEntries = jf.entries();
    48                                 while (jarEntries.hasMoreElements()) {
    49                                         String entryName = jarEntries.nextElement().getName();
    50 
    51                                         if (entryName.startsWith(packageName)) {
    52 
    53                                                 if (entryName.endsWith(".class") && !entryName.contains("$")) {
    54 
    55                                                         // Deal with situation where the class found might be a further sub-package
    56                                                         // e.g. for "org.expeditee.action"
    57                                                         // there is: org/expeditee/action/widgets/Chart.class
    58                                                         // which would produce a value of 'entryName' as widgets/Chart.class
    59 
    60                                                         entryName = entryName.substring(0, entryName.length() - 6); // 6 = '.class'
    61                                                         entryName = entryName.replace('/', '.');
    62 
    63                                                         names.add(entryName);
    64                                                         classes.add(Class.forName(entryName));
    65                                                 }
    66                                         }
    67                                 }
    68                         } catch (Exception e) {
    69                                 System.err.println("Failed to decode jar file: " + jarFileNameUndecoded);
    70                                 e.printStackTrace();
     94                            final Class<?> tmpc = Class.forName(entryName);
     95                            classes.add(tmpc);
     96                        } catch (NoClassDefFoundError e) {
     97                            System.err.println("Unable to instantiate class " + entryName);
     98                            System.err.println(e.getMessage());
    7199                        }
    72                 } else {
    73                         // loop through files in classpath
    74 
    75                         String packageURLString = packageURL.toString();
    76                         try {
    77                                 URI uri = new URI(packageURLString);
    78                                 File folder = new File(uri.getPath());
    79 
    80                                 List<String> files = findFiles(folder);
    81                                 for(String s : files) {
    82                                         String entryName = realPackageName + s;
    83 
    84                                         if (entryName.endsWith(".class") && !entryName.contains("$")) {
    85                                                 entryName = entryName.substring(0, entryName.lastIndexOf('.'));
    86                                                 entryName = entryName.replace('/', '.');
    87 
    88                                                 names.add(entryName);
    89                                                 classes.add(Class.forName(entryName));
    90                                         }
    91                                 }
    92                         } catch (Exception e) {
    93                                 System.err.println("Failed to process file: " + packageURLString);
    94                                 e.printStackTrace();
     100                    }
     101                }
     102            } catch (final Exception e) {
     103                System.err.println("Failed to process file: " + packageName);
     104                e.printStackTrace();
     105            }
     106        } else {
     107            // loop through files in classpath
     108
     109            String packageURLString = packageURL.toString();
     110            try {
     111                URI uri = new URI(packageURLString);
     112                File folder = new File(uri.getPath());
     113
     114                List<String> files = findFiles(folder);
     115                for (String s : files) {
     116                    String entryName = realPackageName + s;
     117
     118                    if (entryName.endsWith(".class")
     119                            && !entryName.contains("$")) {
     120                        entryName = entryName.substring(0,
     121                                entryName.lastIndexOf('.'));
     122                        entryName = entryName.replace('/', '.');
     123
     124                        names.add(entryName);
     125                        classes.add(Class.forName(entryName));
     126                    }
     127                }
     128            } catch (Exception e) {
     129                System.err.println("Failed to process file: "
     130                        + packageURLString);
     131                e.printStackTrace();
     132            }
     133        }
     134
     135        return classes;
     136    }
     137
     138    /**
     139     * Finds all files in a directory and it's subdirectories
     140     *
     141     * @param directory
     142     *            The folder to start in
     143     *
     144     * @return A list of Strings containing file paths relative to the starting
     145     *         directory
     146     */
     147    private static List<String> findFiles(File directory) {
     148        List<String> files = new LinkedList<String>();
     149        for (File f : directory.listFiles()) {
     150            if (f.isDirectory()) {
     151                for (String s : findFiles(f)) {
     152                    files.add(f.getName() + "/" + s);
     153                }
     154            } else {
     155                files.add(f.getName());
     156            }
     157        }
     158        return files;
     159    }
     160
     161    public static List<Class<?>> getClasses(final String pckgname)
     162            throws ClassNotFoundException {
     163
     164        final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
     165
     166        // Must be a forward slash for loading resources
     167        final String packagePath = pckgname.replace('.', '/');
     168
     169        if (System.getProperty("eclipse.expeditee.home") == null) {
     170            final ClassLoader cld = Thread.currentThread()
     171                    .getContextClassLoader();
     172            if (cld == null) {
     173                throw new ClassNotFoundException("Can't get class loader.");
     174            }
     175            URL resource = null;
     176            try {
     177                final Enumeration<URL> resources = cld
     178                        .getResources(packagePath);
     179                while (resources.hasMoreElements()) {
     180                    URL url = resources.nextElement();
     181                    resource = url;
     182                }
     183            } catch (IOException e) {
     184                System.err
     185                        .println("A IO Error has occured when trying to use the ContextClassLoader"
     186                                + System.getProperty("line.separator")
     187                                + "Are you running from within Eclipse? (or just not with Jar)  Then make sure your"
     188                                + " 'eclipse.expeditee.home' property is set correctly.  It is currently: '"
     189                                + System.getProperty("eclipse.expeditee.home")
     190                                + "'"
     191                                + System.getProperty("line.separator")
     192                                + "You can set it by adding a VM argument.  "
     193                                + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
     194                e.printStackTrace();
     195            }
     196            if (resource == null) {
     197                throw new ClassNotFoundException("No resource for "
     198                        + packagePath);
     199            }
     200            final File directory = new File(resource.getFile());
     201
     202            final int splitPoint = directory.getPath().indexOf('!');
     203            if (splitPoint > 0) {
     204                String jarName = directory.getPath().substring(
     205                        "file:".length(), splitPoint);
     206                // Windows HACK
     207                if (jarName.indexOf(":") >= 0)
     208                    jarName = jarName.substring(1);
     209
     210                if (jarName.indexOf("%20") > 0) {
     211                    jarName = jarName.replace("%20", " ");
     212                }
     213                // System.out.println("JarName:" + jarName);
     214                try {
     215                    final JarFile jarFile = new JarFile(jarName);
     216                    final Enumeration<?> entries = jarFile.entries();
     217                    while (entries.hasMoreElements()) {
     218                        final ZipEntry entry = (ZipEntry) entries.nextElement();
     219                        final String className = entry.getName();
     220                        if (className.startsWith(packagePath)) {
     221                            if (className.endsWith(".class")
     222                                    && !className.contains("$")) {
     223                                // The forward slash below is a forwards slash
     224                                // for
     225                                // both windows and linux
     226
     227                                String class_forname = className.substring(0,
     228                                        className.length() - 6);
     229                                class_forname = class_forname.replace('/', '.');
     230
     231                                classes.add(Class.forName(class_forname));
     232                            }
    95233                        }
    96                 }
    97 
    98                 return classes;
     234                    }
     235                    try {
     236                        jarFile.close();
     237                    } catch (IOException e) {
     238                        System.err
     239                                .println("Error attempting to close Jar file");
     240                        e.printStackTrace();
     241                    }
     242                } catch (IOException e) {
     243                    System.err.println("Error Instantiating Jar File Object");
     244                    e.printStackTrace();
     245                }
     246            } else {
     247
     248                System.err
     249                        .println("A Error has occured when trying to use a Jar file to find actions or agents."
     250                                + System.getProperty("line.separator")
     251                                + "Are you running from within Eclipse? (or just not with Jar)  Then make sure your"
     252                                + " 'eclipse.expeditee.home' property is set correctly.  It is currently: '"
     253                                + System.getProperty("eclipse.expeditee.home")
     254                                + "'"
     255                                + System.getProperty("line.separator")
     256                                + "You can set it by adding a VM argument.  "
     257                                + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
     258            }
     259        } else {
     260            String eclipse_expeditee_home = System.getProperty(
     261                    "eclipse.expeditee.home", "");
     262            String full_package_path = eclipse_expeditee_home + File.separator
     263                    + "bin" + File.separator + packagePath;
     264
     265            final File directory = new File(full_package_path);
     266
     267            if (directory.exists()) {
     268                // Get the list of the files contained in the package
     269                String[] files = directory.list();
     270                for (int i = 0; i < files.length; i++) {
     271                    // we are only interested in .class files
     272                    if (files[i].endsWith(".class") && !files[i].contains("$")
     273                            && !files[i].equals("Actions.class")) {
     274                        // removes the .class extension
     275                        classes.add(Class.forName(pckgname
     276                                + files[i].substring(0, files[i].length() - 6)));
     277                    }
     278                }
     279            } else {
     280                throw new ClassNotFoundException("The package '" + pckgname
     281                        + "' in the directory '" + directory
     282                        + "' does not appear to be a valid package");
     283            }
    99284        }
    100        
    101         /**
    102          * Finds all files in a directory and it's subdirectories
    103          *
    104          * @param directory The folder to start in
    105          *
    106          * @return A list of Strings containing file paths relative to the starting directory
    107          */
    108         private static List<String> findFiles(File directory) {
    109                 List<String> files = new LinkedList<String>();
    110                 for(File f : directory.listFiles()) {
    111                         if(f.isDirectory()) {
    112                                 for(String s : findFiles(f)) {
    113                                         files.add(f.getName() + "/" + s);
    114                                 }
    115                         } else {
    116                                 files.add(f.getName());
    117                         }
    118                 }
    119                 return files;
    120         }
    121 
    122         public static List<Class<?>> getClasses(final String pckgname) throws ClassNotFoundException {
    123 
    124                 final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
    125 
    126                 // Must be a forward slash for loading resources
    127                 final String packagePath = pckgname.replace('.', '/');
    128 
    129                 if (System.getProperty("eclipse.expeditee.home") == null) {
    130                         final ClassLoader cld = Thread.currentThread().getContextClassLoader();
    131                         if (cld == null) {
    132                                 throw new ClassNotFoundException("Can't get class loader.");
    133                         }
    134                         URL resource = null;
    135                         try {
    136                                 final Enumeration<URL> resources = cld.getResources(packagePath);
    137                                 while (resources.hasMoreElements()) {
    138                                         URL url = resources.nextElement();
    139                                         resource = url;
    140                                 }
    141                         } catch (IOException e) {
    142                                 System.err.println("A IO Error has occured when trying to use the ContextClassLoader"
    143                                         + System.getProperty("line.separator")
    144                                         + "Are you running from within Eclipse? (or just not with Jar)  Then make sure your"
    145                                         + " 'eclipse.expeditee.home' property is set correctly.  It is currently: '"
    146                                         + System.getProperty("eclipse.expeditee.home") + "'" + System.getProperty("line.separator")
    147                                         + "You can set it by adding a VM argument.  "
    148                                         + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
    149                                 e.printStackTrace();
    150                         }
    151                         if (resource == null) {
    152                                 throw new ClassNotFoundException("No resource for " + packagePath);
    153                         }
    154                         final File directory = new File(resource.getFile());
    155 
    156                         final int splitPoint = directory.getPath().indexOf('!');
    157                         if (splitPoint > 0) {
    158                                 String jarName = directory.getPath().substring("file:".length(), splitPoint);
    159                                 // Windows HACK
    160                                 if (jarName.indexOf(":") >= 0)
    161                                         jarName = jarName.substring(1);
    162 
    163                                 if (jarName.indexOf("%20") > 0) {
    164                                         jarName = jarName.replace("%20", " ");
    165                                 }
    166                                 // System.out.println("JarName:" + jarName);
    167                                 try {
    168                                         final JarFile jarFile = new JarFile(jarName);
    169                                         final Enumeration<?> entries = jarFile.entries();
    170                                         while (entries.hasMoreElements()) {
    171                                                 final ZipEntry entry = (ZipEntry) entries.nextElement();
    172                                                 final String className = entry.getName();
    173                                                 if (className.startsWith(packagePath)) {
    174                                                         if (className.endsWith(".class") && !className.contains("$")) {
    175                                                                 // The forward slash below is a forwards slash for
    176                                                                 // both windows and linux
    177 
    178                                                                 String class_forname = className.substring(0, className.length() - 6);
    179                                                                 class_forname = class_forname.replace('/', '.');
    180 
    181                                                                 classes.add(Class.forName(class_forname));
    182                                                         }
    183                                                 }
    184                                         }
    185                                         try {
    186                                                 jarFile.close();
    187                                         } catch (IOException e) {
    188                                                 System.err.println("Error attempting to close Jar file");
    189                                                 e.printStackTrace();
    190                                         }
    191                                 } catch (IOException e) {
    192                                         System.err.println("Error Instantiating Jar File Object");
    193                                         e.printStackTrace();
    194                                 }
    195                         } else {
    196 
    197                                 System.err.println("A Error has occured when trying to use a Jar file to find actions or agents."
    198                                         + System.getProperty("line.separator")
    199                                         + "Are you running from within Eclipse? (or just not with Jar)  Then make sure your"
    200                                         + " 'eclipse.expeditee.home' property is set correctly.  It is currently: '"
    201                                         + System.getProperty("eclipse.expeditee.home") + "'" + System.getProperty("line.separator")
    202                                         + "You can set it by adding a VM argument.  "
    203                                         + "Example: -Declipse.expeditee.home=D:\\Desktop\\Research\\expeditee-svn");
    204                         }
    205                 } else {
    206                         String eclipse_expeditee_home = System.getProperty("eclipse.expeditee.home", "");
    207                         String full_package_path = eclipse_expeditee_home + File.separator + "bin" + File.separator + "src"
    208                                 + File.separator + packagePath;
    209 
    210                         final File directory = new File(full_package_path);
    211 
    212                         if (directory.exists()) {
    213                                 // Get the list of the files contained in the package
    214                                 String[] files = directory.list();
    215                                 for (int i = 0; i < files.length; i++) {
    216                                         // we are only interested in .class files
    217                                         if (files[i].endsWith(".class") && !files[i].contains("$") && !files[i].equals("Actions.class")) {
    218                                                 // removes the .class extension
    219                                                 classes.add(Class.forName(pckgname + files[i].substring(0, files[i].length() - 6)));
    220                                         }
    221                                 }
    222                         } else {
    223                                 throw new ClassNotFoundException("The package '" + pckgname + "' in the directory '" + directory
    224                                         + "' does not appear to be a valid package");
    225                         }
    226                 }
    227                 return classes;
    228         }
     285        return classes;
     286    }
    229287
    230288}
Note: See TracChangeset for help on using the changeset viewer.