PluginClassLoader.java 3.83 KB
Newer Older
Matt Tucker's avatar
Matt Tucker committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/**
 * $RCSfile$
 * $Revision$
 * $Date$
 *
 * Copyright (C) 2004 Jive Software. All rights reserved.
 *
 * This software is published under the terms of the GNU Public License (GPL),
 * a copy of which is included in this distribution.
 */

package org.jivesoftware.messenger.container;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * ClassLoader for plugins. It searches the plugin directory for classes
 * and JAR files, then constructs a class loader for the resources found.
 * Resources are loaded as follows:<ul>
27 28 29
 * <p/>
 * <li>Any JAR files in the <tt>lib</tt> will be added to the classpath.
 * <li>Any files in the classes directory will be added to the classpath.
Matt Tucker's avatar
Matt Tucker committed
30 31 32 33 34 35 36
 * </ul>
 *
 * @author Derek DeMoro
 */
class PluginClassLoader {

    private URLClassLoader classLoader;
37 38
    private final List list = new ArrayList();

Matt Tucker's avatar
Matt Tucker committed
39 40 41 42 43

    /**
     * Constructs a plugin loader for the given plugin directory.
     *
     * @param pluginDir the plugin directory.
44 45
     * @throws java.lang.SecurityException    if the created class loader violates
     *                                        existing security constraints.
Matt Tucker's avatar
Matt Tucker committed
46
     * @throws java.net.MalformedURLException if a located resource name cannot be
47
     *                                        properly converted to a URL.
Matt Tucker's avatar
Matt Tucker committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
     */
    public PluginClassLoader(File pluginDir) throws MalformedURLException, SecurityException {
        File classesDir = new File(pluginDir, "classes");
        if (classesDir.exists()) {
            list.add(classesDir.toURL());
        }
        File libDir = new File(pluginDir, "lib");
        File[] jars = libDir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".jar") || name.endsWith(".zip");
            }
        });
        if (jars != null) {
            for (int i = 0; i < jars.length; i++) {
                if (jars[i] != null && jars[i].isFile()) {
                    list.add(jars[i].toURL());
                }
            }
        }
67 68 69 70 71 72 73
    }

    public void addURL(URL url) {
        list.add(url);
    }

    public void initialize(){
Matt Tucker's avatar
Matt Tucker committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
        Iterator urls = list.iterator();
        URL[] urlArray = new URL[list.size()];
        for (int i = 0; urls.hasNext(); i++) {
            urlArray[i] = (URL)urls.next();
        }
        classLoader = new URLClassLoader(urlArray, findParentClassLoader());
    }

    /**
     * Load a class using this plugin class loader.
     *
     * @param name the fully qualified name of the class to load.
     * @return The module object loaded
     * @throws ClassNotFoundException if the class could not be loaded by this class loader.
     * @throws IllegalAccessException if the class constructor was private or protected.
     * @throws InstantiationException if the class could not be instantiated (initialization error).
90
     * @throws SecurityException      if the custom class loader not allowed.
Matt Tucker's avatar
Matt Tucker committed
91 92
     */
    public Class loadClass(String name) throws ClassNotFoundException, IllegalAccessException,
93
            InstantiationException, SecurityException {
Matt Tucker's avatar
Matt Tucker committed
94 95 96
        return classLoader.loadClass(name);
    }

97 98 99 100 101 102 103
    /**
     * Destroys this class loader.
     */
    public void destroy() {
        classLoader = null;
    }

Matt Tucker's avatar
Matt Tucker committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
    /**
     * Locates the best parent class loader based on context.
     *
     * @return the best parent classloader to use.
     */
    private ClassLoader findParentClassLoader() {
        ClassLoader parent = Thread.currentThread().getContextClassLoader();
        if (parent == null) {
            parent = this.getClass().getClassLoader();
        }
        if (parent == null) {
            parent = ClassLoader.getSystemClassLoader();
        }
        return parent;
    }
}