tvbrowser.core.PluginLoader.java Source code

Java tutorial

Introduction

Here is the source code for tvbrowser.core.PluginLoader.java

Source

/*
 * TV-Browser
 * Copyright (C) 04-2003 Martin Oberhauser (martin@tvbrowser.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * CVS information:
 *  $RCSfile$
 *   $Source$
 *     $Date: 2010-08-24 00:22:31 +0200 (Tue, 24 Aug 2010) $
 *   $Author: ds10 $
 * $Revision: 6712 $
 */
package tvbrowser.core;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.apache.commons.lang.StringUtils;

import tvbrowser.core.plugin.AbstractPluginProxy;
import tvbrowser.core.plugin.BeanShellPluginProxy;
import tvbrowser.core.plugin.JavaPluginProxy;
import tvbrowser.core.plugin.PluginBaseInfo;
import tvbrowser.core.plugin.PluginProxy;
import tvbrowser.core.plugin.PluginProxyManager;
import tvbrowser.core.tvdataservice.DefaultTvDataServiceProxy;
import tvbrowser.core.tvdataservice.TvDataServiceProxy;
import tvbrowser.core.tvdataservice.TvDataServiceProxyManager;
import util.exc.ErrorHandler;
import util.exc.TvBrowserException;
import util.io.IOUtilities;
import devplugin.Plugin;
import devplugin.PluginInfo;
import devplugin.Version;

/**
 * The PluginLoader loads all plugins and assigns each plugin to
 * the appropriate manager (TvDataServiceProxyManager or PluginProxyManager)
 */
public class PluginLoader {

    private static final String[] IGNORED_PLUGINS = new String[] { "FavoritesPlugin.jar", "ReminderPlugin.jar",
            "ProgramInfo.jar", "SearchPlugin.jar", "ShowviewPlugin.jar" };

    private static final String PLUGIN_PROXY_EXTENSION = ".jar.proxy";

    private static final String PLUGIN_INSTALL_EXTENSION = ".inst";

    /** The logger for this class */
    private static final Logger mLog = Logger.getLogger(PluginLoader.class.getName());

    private static PluginLoader mInstance;

    /** The name of the directory where the plugins are located in TV-Browser 2.1 and later */
    private static String PLUGIN_DIRECTORY = "plugins";

    private HashSet<String> mSuccessfullyLoadedPluginFiles;

    private HashMap<Object, File> mDeleteablePlugin;

    private ArrayList<PluginProxy> loadedProxies;

    private ArrayList<String> mNewInstalledPlugins = new ArrayList<String>();

    private PluginLoader() {
        mSuccessfullyLoadedPluginFiles = new HashSet<String>();
        mDeleteablePlugin = new HashMap<Object, File>();
    }

    public static PluginLoader getInstance() {
        if (mInstance == null) {
            mInstance = new PluginLoader();
        }
        return mInstance;
    }

    /**
     * Installs all plugins that could not be installed the last time, because an
     * old version was in use.
     */
    public void installPendingPlugins() {
        File[] installableFiles = new File(Settings.propPluginsDirectory.getString())
                .listFiles(new FilenameFilter() {
                    @Override
                    public boolean accept(File dir, String fileName) {
                        return fileName.endsWith(PLUGIN_INSTALL_EXTENSION);
                    }
                });
        if (installableFiles == null || installableFiles.length == 0) {
            // Nothing to do
            return;
        }

        // Install all pending plugins
        for (File file : installableFiles) {
            // This plugin wants to be installed
            String fileName = file.getAbsolutePath();
            String oldFileName = fileName.substring(0, fileName.length() - PLUGIN_INSTALL_EXTENSION.length());
            File oldFile = new File(oldFileName);

            // delete the old proxy, this will force loading of the new plugin (even if it's not active)
            String oldProxyName = getProxyFileName(oldFile);
            File oldProxy = new File(oldProxyName);
            if (oldProxy.exists()) {
                deletePluginProxy(oldProxy);
            }
            String oldIconName = getProxyIconFileName(oldFile);
            File oldIcon = new File(oldIconName);
            if (oldIcon.exists()) {
                deletePluginProxy(oldIcon);
            }

            // Delete the old file
            deletePluginProxy(oldFile);

            // Rename the file, so the PluginLoader will install it later
            if (!file.renameTo(oldFile)) {
                mLog.warning("Installing pending plugin failed: " + fileName);
            }

            mNewInstalledPlugins.add(oldFileName);
        }
    }

    private PluginProxy loadProxy(File proxyFile) {
        String lcFileName = proxyFile.getName().toLowerCase();
        if (!lcFileName.endsWith(".proxy")) {
            mLog.warning("not a valid proxy file " + proxyFile.getAbsolutePath());
            return null;
        }
        if (proxyFile.canRead()) {
            JavaPluginProxy proxy = readPluginProxy(proxyFile);
            if (proxy != null) {
                PluginProxyManager.getInstance().registerPlugin(proxy);
                if (new File(proxy.getPluginFileName()).getParentFile()
                        .equals(new File(Settings.propPluginsDirectory.getString()))) {
                    File pluginFile = new File(proxy.getPluginFileName());
                    mDeleteablePlugin.put(proxy, pluginFile);
                }
                return proxy;
            }
        }
        return null;
    }

    /**
     * Loads the plugin from the file system
     * @param pluginFile File to load
     * @param deleteable is the Plugin deleteable
     */
    public Object loadPlugin(File pluginFile, boolean deleteable) {
        Object plugin = null;
        String lcFileName = pluginFile.getName().toLowerCase();
        if (mSuccessfullyLoadedPluginFiles.contains(lcFileName)) {
            mLog.warning("cannot load plugin " + pluginFile.getAbsolutePath() + " - already loaded");
            return null;
        }

        try {
            if (lcFileName.endsWith(".jar")) {
                plugin = loadJavaPlugin(pluginFile);
            } else if (lcFileName.endsWith(".bsh")) {
                plugin = loadBeanShellPlugin(pluginFile);
            } else {
                mLog.warning("Unknown plugin type: " + pluginFile.getAbsolutePath());
            }

            if (plugin instanceof Plugin) {
                // check if the proxy is already loaded, but the plugin was not loaded yet
                JavaPluginProxy javaplugin = (JavaPluginProxy) PluginProxyManager.getInstance()
                        .getPluginForId(JavaPluginProxy.getJavaPluginId((Plugin) plugin));
                if (javaplugin != null) {
                    javaplugin.setPlugin((Plugin) plugin, pluginFile.getPath());
                }
                // it was not yet loaded, so create new proxy
                else {
                    javaplugin = new JavaPluginProxy((Plugin) plugin, pluginFile.getPath());
                    PluginProxyManager.getInstance().registerPlugin(javaplugin);
                }
                if (mNewInstalledPlugins.contains(pluginFile.getAbsolutePath())) {
                    // add this plugin to the icon settings for program panels
                    String iconText = ((Plugin) plugin).getProgramTableIconText();
                    if (iconText != null && !iconText.isEmpty()) {
                        if (!Settings.propProgramTableIconPlugins.containsItem(((Plugin) plugin).getId())) {
                            Settings.propProgramTableIconPlugins.addItem(((Plugin) plugin).getId());
                        }
                    }
                }
                if (deleteable) {
                    mDeleteablePlugin.put(javaplugin, pluginFile);
                }

                saveProxyInfo(pluginFile, javaplugin);
            } else if (plugin instanceof AbstractPluginProxy) {
                PluginProxyManager.getInstance().registerPlugin((AbstractPluginProxy) plugin);
                if (deleteable) {
                    mDeleteablePlugin.put(plugin, pluginFile);
                }
            } else if (plugin instanceof devplugin.AbstractTvDataService) {
                TvDataServiceProxy proxy = new DefaultTvDataServiceProxy((devplugin.AbstractTvDataService) plugin);
                TvDataServiceProxyManager.getInstance().registerTvDataService(proxy);
                if (deleteable) {
                    mDeleteablePlugin.put(proxy, pluginFile);
                }
            }

            if (plugin != null) {
                mSuccessfullyLoadedPluginFiles.add(lcFileName);
                mLog.info("Loaded plugin " + pluginFile.getAbsolutePath());
            }
        } catch (Throwable thr) {
            mLog.log(Level.WARNING, "Loading plugin file failed: " + pluginFile.getAbsolutePath(), thr);
            thr.printStackTrace();
        }
        return plugin;
    }

    /**
     * read the contents of a proxy file to get the necessary
     * information about the plugin managed by this proxy to recreate
     * the proxy without the plugin actually being loaded
     *
     * @param proxyFile
     * @return pluginProxy
     */
    private JavaPluginProxy readPluginProxy(File proxyFile) {
        DataInputStream in = null;

        try {
            in = new DataInputStream(new BufferedInputStream(new FileInputStream(proxyFile)));

            String name = in.readUTF();
            String author = in.readUTF();
            String description = in.readUTF();
            String license = in.readUTF();

            DummyPlugin.setCurrentVersion(new Version(in));

            String pluginId = in.readUTF();
            in.readLong(); // file size is unused
            String lcFileName = in.readUTF();
            in.close();
            // check existence of plugin file
            File pluginFile = new File(lcFileName);
            if (!pluginFile.canRead()) {
                deletePluginProxy(proxyFile);
                return null;
            }

            // everything seems fine, create plugin proxy and plugin info
            PluginInfo info = new PluginInfo(DummyPlugin.class, name, description, author, license);
            // now get icon
            String iconFileName = getProxyIconFileName(proxyFile);
            return new JavaPluginProxy(info, lcFileName, pluginId, iconFileName);
        } catch (Exception e) {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                    // ignore
                }
            }
            // delete proxy on read error, maybe the format has changed
            deletePluginProxy(proxyFile);
            return null;
        }
    }

    private void deletePluginProxy(File proxyFile) {
        String iconName = getProxyIconFileName(proxyFile);
        proxyFile.delete();
        File iconFile = new File(iconName);
        iconFile.delete();
    }

    /**
     * Saves the information of a plugin to disk, so it does not need to be loaded next time
     * @param pluginFile full plugin file name
     * @param proxy proxy of the plugin
     */
    private void saveProxyInfo(File pluginFile, JavaPluginProxy proxy) {
        try {
            String proxyFileName = getProxyFileName(pluginFile);
            DataOutputStream out = new DataOutputStream(
                    new BufferedOutputStream(new FileOutputStream(proxyFileName)));

            PluginInfo info = proxy.getInfo();
            out.writeUTF(info.getName());
            out.writeUTF(info.getAuthor());
            out.writeUTF(info.getDescription());
            String license = info.getLicense();
            if (license == null) {
                license = "";
            }
            out.writeUTF(license);

            info.getVersion().writeData(out); //write version

            out.writeUTF(proxy.getId());
            out.writeLong(pluginFile.length());
            out.writeUTF(proxy.getPluginFileName());
            out.close();
            // also store the plugin icon, if it is not yet available
            String iconFileName = getProxyIconFileName(pluginFile);
            File iconFile = new File(iconFileName);
            if (!iconFile.exists()) {
                Icon pluginIcon = proxy.getPluginIcon();
                if (pluginIcon != null && pluginIcon instanceof ImageIcon) {
                    IOUtilities.writeImageIconToFile((ImageIcon) pluginIcon, "png", iconFile);
                }
            }
        } catch (Exception e) {
        }
    }

    /**
     * get the file name of the proxied icon for a plugin
     * @param pluginFile
     * @return icon file name
     */
    private String getProxyIconFileName(File pluginFile) {
        String name = pluginFile.getName();
        name = StringUtils.substringBefore(name, ".");
        return Settings.getUserSettingsDirName() + File.separatorChar + name + ".icon.png";
    }

    /**
     * file name of the proxy file for a plugin
     *
     * @param pluginFile
     * @return proxy file name
     */
    private String getProxyFileName(File pluginFile) {
        return Settings.getUserSettingsDirName() + File.separatorChar + pluginFile.getName() + ".proxy";
    }

    /**
     * Loads all plugins within the specified folder
     * @param folder specific Folder
     * @param deleteable True if the Plugins in this Folder are deleteable
     */
    private void loadPlugins(File folder, boolean deleteable) {
        // check for plugin proxies only one time per run
        if (loadedProxies == null) {
            loadedProxies = new ArrayList<PluginProxy>();
            final String[] deactivatedPluginArr = Settings.propDeactivatedPlugins.getStringArray();

            // only check proxies if at least one plugin is not active
            if (deactivatedPluginArr != null && deactivatedPluginArr.length > 0) {
                File settingsDir = new File(Settings.getUserSettingsDirName());
                File[] proxyFiles = settingsDir.listFiles(new FilenameFilter() {
                    public boolean accept(File dir, String name) {
                        if (!name.endsWith(PLUGIN_PROXY_EXTENSION)) {
                            return false;
                        }
                        String mainName = name.substring(0, name.length() - PLUGIN_PROXY_EXTENSION.length())
                                .toLowerCase();
                        for (String deactivatedId : deactivatedPluginArr) {
                            if (deactivatedId.contains(mainName)) {
                                return true;
                            }
                        }
                        return false;
                    }
                });
                if (proxyFiles != null) {
                    for (File proxyFile : proxyFiles) {
                        PluginProxy proxy = loadProxy(proxyFile);
                        if (proxy != null) {
                            loadedProxies.add(proxy);
                            mLog.info("Loaded plugin proxy " + proxyFile);
                        } else {
                            mLog.warning("Failed loading plugin proxy " + proxyFile);
                        }
                    }
                }
            }
        }

        File[] fileArr = folder.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String fileName) {
                for (String ignored : IGNORED_PLUGINS) {
                    if (fileName.equalsIgnoreCase(ignored)) {
                        return false;
                    }
                }
                return true;
            }
        });
        if (fileArr == null) {
            return;
        }

        // remove old cleverepg service, if new one is found
        File oldService = null;
        ArrayList<File> files = new ArrayList<File>(Arrays.asList(fileArr));
        for (File file : fileArr) {
            if (file.getName().equalsIgnoreCase("CleverEPGDataService3.jar")) {
                for (File file2 : files) {
                    if (file2.getName().equalsIgnoreCase("CleverEPGDataService.jar")) {
                        oldService = file2;
                        break;
                    }
                }
            }
        }
        if (oldService != null) {
            files.remove(oldService);
        }

        for (File file : files) {
            boolean load = true;
            for (PluginProxy proxy : loadedProxies) {
                if (proxy.getPluginFileName().equalsIgnoreCase(file.getPath())) {
                    load = false;
                    break;
                }
            }
            if (load) {
                loadPlugin(file, deleteable);
            }
        }
    }

    public void loadAllPlugins() {

        /* 0) delete all plugins the user doesn't want anymore */

        String[] files = Settings.propDeleteFilesAtStart.getStringArray();

        if ((files != null) && (files.length > 0)) {
            for (String file : files) {
                try {
                    mLog.info("Deleting " + file);
                    new File(file).delete();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            Settings.propDeleteFilesAtStart.setStringArray(new String[0]);
        }

        /* 1) load all plugins from the plugins folder in the user's home directory */
        String pluginsFolderName = Settings.propPluginsDirectory.getString();
        File f = new File(pluginsFolderName);
        boolean success = true;
        if (!f.exists()) {
            if (!f.mkdirs()) {
                mLog.warning("Could not create plugins folder " + f.getAbsolutePath());
                success = false;
            }
        }
        if (success) {
            loadPlugins(f, true);
        }

        /* 2) load the plugins from the plugins folder */
        loadPlugins(new File(PluginProxyManager.PLUGIN_DIRECTORY), false);

        /* 3) load the plugins from the tvdataservice folder */
        loadPlugins(new File(TvDataServiceProxyManager.PLUGIN_DIRECTORY), false);

    }

    private Object loadJavaPlugin(File jarFile) throws TvBrowserException {
        Object plugin = null;

        // Create a class loader for the plugin
        ClassLoader classLoader;
        ClassLoader classLoader2 = null;

        try {
            URL[] urls = new URL[] { jarFile.toURI().toURL() };
            classLoader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());

            try {
                if (!new File(PLUGIN_DIRECTORY).equals(jarFile.getParentFile())
                        && new File(PLUGIN_DIRECTORY, jarFile.getName()).isFile()) {
                    urls = new URL[] { new File(PLUGIN_DIRECTORY, jarFile.getName()).toURI().toURL() };
                    classLoader2 = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
                }
            } catch (MalformedURLException exc) {
            }
        } catch (MalformedURLException exc) {
            throw new TvBrowserException(getClass(), "error.1", "Loading Jar file of a plugin failed: {0}.",
                    jarFile.getAbsolutePath(), exc);
        }

        // Get the plugin name
        String pluginName = jarFile.getName();
        if (pluginName.endsWith(".jar")) {
            pluginName = pluginName.substring(0, pluginName.length() - 4);
        }

        boolean isBlockedDataService = false;

        // Create a plugin instance
        try {
            Class pluginClass = classLoader.loadClass(pluginName.toLowerCase() + "." + pluginName);
            Method getVersion = pluginClass.getMethod("getVersion", new Class[0]);
            Version version1 = null;
            try {
                version1 = (Version) getVersion.invoke(pluginClass, new Object[0]);
            } catch (Exception e) {
            }
            if (version1 == null || version1.toString().equals("0.0.0.0")) {
                mLog.warning("Did not load plugin " + pluginName + ", version is too old.");
                return null;
            }

            if (pluginClass.getSuperclass().equals(devplugin.AbstractTvDataService.class) || classLoader2 != null) {
                getVersion = pluginClass.getMethod("getVersion", new Class[0]);
                version1 = (Version) getVersion.invoke(pluginClass, new Object[0]);

                if (pluginClass.getSuperclass().equals(devplugin.AbstractTvDataService.class)) {
                    isBlockedDataService = Settings.propBlockedPluginArray
                            .isBlocked(pluginName.toLowerCase() + "." + pluginName, version1);
                }
            }

            if (classLoader2 != null) {
                try {
                    Class pluginClass2 = classLoader2.loadClass(pluginName.toLowerCase() + "." + pluginName);
                    Method getVersion2 = pluginClass2.getMethod("getVersion", new Class[0]);

                    Version version2 = (Version) getVersion2.invoke(pluginClass2, new Object[0]);

                    if (version2.compareTo(version1) > 0) {
                        return null;
                    }
                } catch (Throwable t) {
                }
            }

            try {
                Method preInstancing = pluginClass.getMethod("preInstancing", new Class[0]);
                preInstancing.invoke(pluginClass, new Object[0]);
            } catch (Throwable ti) {
            }

            if (!isBlockedDataService) {
                plugin = pluginClass.newInstance();
            }
        } catch (Throwable thr) {
            throw new TvBrowserException(getClass(), "error.2", "Could not load plugin {0}.",
                    jarFile.getAbsolutePath(), thr);
        }

        return plugin;
    }

    private Object loadBeanShellPlugin(File file) {
        return new BeanShellPluginProxy(file);
    }

    /**
     * Delete a Plugin
     * @param proxy Proxy for the Plugin that should be deleted
     * @return true if successful
     */
    public boolean deletePlugin(PluginProxy proxy) {
        if (deletePluginOrService(proxy)) {
            try {
                PluginProxyManager.getInstance().removePlugin(proxy);
            } catch (TvBrowserException exc) {
                ErrorHandler.handle(exc);
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * Delete a data service
     * @param service Data service that should be deleted
     * @return true if successful
     * @since 2.7
     */
    public boolean deleteDataService(TvDataServiceProxy service) {
        return deletePluginOrService(service);
    }

    private boolean deletePluginOrService(Object plugin) {
        // mark plugin file for deletion
        File file = mDeleteablePlugin.get(plugin);
        if (file != null) {
            Settings.propDeleteFilesAtStart.addItem(file.toString());

            // mark proxy file for deletion
            String proxyFile = getProxyFileName(file);
            Settings.propDeleteFilesAtStart.addItem(proxyFile);

            mDeleteablePlugin.remove(plugin);
            return true;
        }
        return false;
    }

    /**
     * Is a Plugin deleteable ?
     * @param plugin Plugin that should be deleted
     * @return true if deleteable
     */
    public boolean isPluginDeletable(PluginProxy plugin) {
        return mDeleteablePlugin.containsKey(plugin);
    }

    /**
     * Is a data service deleteable ?
     * @param service Data service that should be deleted
     * @return true if deleteable
     * @since 2.7
     */
    public boolean isDataServiceDeletable(TvDataServiceProxy service) {
        return mDeleteablePlugin.containsKey(service);
    }

    /**
     * delete all plugin proxies to force re-reading the plugin classes on next start
     */
    public void deleteAllPluginProxies() {
        File settingsDir = new File(Settings.getUserSettingsDirName());
        File[] proxyFiles = settingsDir.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(PLUGIN_PROXY_EXTENSION);
            }
        });
        if (proxyFiles != null) {
            for (File proxyFile : proxyFiles) {
                Settings.propDeleteFilesAtStart.addItem(proxyFile.toString());
            }
        }
    }

    /**
     * Gets the base infos for all available plugins.
     * <p>
     * @return The array with the base info for all available plugins.
     */
    public PluginBaseInfo[] getInfoOfAvailablePlugins() {
        ArrayList<PluginBaseInfo> availablePlugins = new ArrayList<PluginBaseInfo>();

        /* 1) get base info for plugins in user dir */
        getBaseInfoOfPluginsInDirectory(new File(Settings.propPluginsDirectory.getString()), availablePlugins);

        /* 2) get base info for plugins in the plugins folder */
        getBaseInfoOfPluginsInDirectory(new File(PluginProxyManager.PLUGIN_DIRECTORY), availablePlugins);

        /* 3) get base info for in the tvdataservice folder */
        getBaseInfoOfPluginsInDirectory(new File(TvDataServiceProxyManager.PLUGIN_DIRECTORY), availablePlugins);

        return availablePlugins.toArray(new PluginBaseInfo[availablePlugins.size()]);
    }

    private void getBaseInfoOfPluginsInDirectory(File directory, ArrayList<PluginBaseInfo> availablePlugins) {
        if (directory.exists()) {
            File[] pluginFiles = directory.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    for (String ignored : IGNORED_PLUGINS) {
                        if (name.equalsIgnoreCase(ignored)) {
                            return false;
                        }
                    }

                    return name.toLowerCase().endsWith(".jar");
                }
            });

            getBaseInfoOfPlugins(pluginFiles, availablePlugins);
        }
    }

    private void getBaseInfoOfPlugins(File[] plugins, ArrayList<PluginBaseInfo> availablePlugins) {
        for (File plugin : plugins) {
            URL[] urls;

            // Get the plugin name
            String pluginName = plugin.getName();
            pluginName = pluginName.substring(0, pluginName.length() - 4);
            Class pluginClass = null;

            try {
                urls = new URL[] { plugin.toURI().toURL() };
                ClassLoader classLoader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());

                pluginClass = classLoader.loadClass(pluginName.toLowerCase() + "." + pluginName);
                Method getVersion = pluginClass.getMethod("getVersion", new Class[0]);

                try {
                    Version version = (Version) getVersion.invoke(pluginClass, new Object[0]);

                    PluginBaseInfo baseInfo = new PluginBaseInfo("java." + pluginClass.getName(), version);

                    if (!availablePlugins.contains(baseInfo)) {
                        availablePlugins.add(baseInfo);
                    }
                } catch (Exception e) {
                }

            } catch (Throwable t) {
                urls = null;
                pluginClass = null;
                System.gc();

                PluginBaseInfo baseInfo = new PluginBaseInfo("java." + pluginName.toLowerCase() + "." + pluginName,
                        new Version(0, 0));

                if (!availablePlugins.contains(baseInfo)) {
                    availablePlugins.add(baseInfo);
                }

                mLog.info("Could not load base info for plugin file '" + plugin.getAbsolutePath()
                        + "'. Use default version instead.");
            }
        }
    }

}