class PluginClassLoader extends URLClassLoader {

    private static final Logger Log = LoggerFactory.getLogger(PluginClassLoader.class);
    private List<JarURLConnection> cachedJarFiles = new ArrayList<JarURLConnection>();
    public PluginClassLoader() {
        super(new URL[] {}, findParentClassLoader());
    }

    /**
     * Adds a directory to the class loader.
     *
     * @param directory the directory.
     */
    public void addDirectory(File directory) {<FILL_FUNCTION_BODY>}

    /**
     * Add the given URL to the classpath for this class loader, 
     * caching the JAR file connection so it can be unloaded later
     * 
     * @param file URL for the JAR file or directory to append to classpath
     */
    public void addURLFile(URL file) {
        try {
            // open and cache JAR file connection 
            URLConnection uc = file.openConnection();
            if (uc instanceof JarURLConnection) {
                uc.setUseCaches(true);
                ((JarURLConnection) uc).getManifest();
                cachedJarFiles.add((JarURLConnection)uc);
            }
        } catch (Exception e) {
            Log.warn("Failed to cache plugin JAR file: " + file.toExternalForm());
        }
        addURL(file);
    }
    
    /**
     * Unload any JAR files that have been cached by this plugin
     */
    public void unloadJarFiles() {
        for (JarURLConnection url : cachedJarFiles) {
            try {
                Log.info("Unloading plugin JAR file " + url.getJarFile().getName());
                url.getJarFile().close();
            } catch (Exception e) {
                Log.error("Failed to unload JAR file", e);
            }
        }
    }

    /**
     * Locates the best parent class loader based on context.
     *
     * @return the best parent classloader to use.
     */
    private static ClassLoader findParentClassLoader() {
        ClassLoader parent = XMPPServer.class.getClassLoader();
        if (parent == null) {
            parent = PluginClassLoader.class.getClassLoader();
        }
        if (parent == null) {
            parent = ClassLoader.getSystemClassLoader();
        }
        return parent;
    }
}

        try {
            // Add classes directory to classpath.
            File classesDir = new File(directory, "classes");
            if (classesDir.exists()) {
                addURL(classesDir.toURI().toURL());
            }

            // Add i18n directory to classpath.
            File databaseDir = new File(directory, "database");
            if(databaseDir.exists()){
                addURL(databaseDir.toURI().toURL());
            }

            // Add i18n directory to classpath.
            File i18nDir = new File(directory, "i18n");
            if(i18nDir.exists()){
                addURL(i18nDir.toURI().toURL());
            }

            // Add web directory to classpath.
            File webDir = new File(directory, "web");
            if(webDir.exists()){
                addURL(webDir.toURI().toURL());
            }

            // Add lib directory to classpath.
            File libDir = new File(directory, "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()) {
                        String jarFileUri = jars[i].toURI().toString()  + "!/";
                        addURLFile(new URL("jar", "", -1, jarFileUri));
                    }
                }
            }
        }
        catch (MalformedURLException mue) {
            Log.error(mue.getMessage(), mue);
        }
    
<methods>public void <init>(java.net.URL[]) ,public void <init>(java.net.URL[], java.lang.ClassLoader) ,public void <init>(java.net.URL[], java.lang.ClassLoader, java.net.URLStreamHandlerFactory) ,public void <init>(java.lang.String, java.net.URL[], java.lang.ClassLoader) ,public void <init>(java.lang.String, java.net.URL[], java.lang.ClassLoader, java.net.URLStreamHandlerFactory) ,public void close() throws java.io.IOException,public java.net.URL findResource(java.lang.String) ,public Enumeration<java.net.URL> findResources(java.lang.String) throws java.io.IOException,public java.io.InputStream getResourceAsStream(java.lang.String) ,public java.net.URL[] getURLs() ,public static java.net.URLClassLoader newInstance(java.net.URL[]) ,public static java.net.URLClassLoader newInstance(java.net.URL[], java.lang.ClassLoader) <variables>private final java.security.AccessControlContext acc,private WeakHashMap<java.io.Closeable,java.lang.Void> closeables,private final jdk.internal.loader.URLClassPath ucp