/** * This will create a {@link PluginEnvironment} for the plugin at the given URL. The plugin's * descriptor is parsed. Once this method returns, the plugin's components are ready to be created * and used. * * @param pluginUrl the new plugin's jar location * @param classLoader the new plugin's classloader * @param pluginDescriptor the already parsed plugin descriptor for this plugin * @throws PluginContainerException if the plugin fails to load */ private void loadPlugin(URL pluginUrl, ClassLoader classLoader, PluginDescriptor pluginDescriptor) throws PluginContainerException { if (log.isDebugEnabled()) { log.debug("Loading plugin from [" + pluginUrl + "] in classloader [" + classLoader + "]..."); } PluginDescriptorLoader pluginDescriptorLoader = new PluginDescriptorLoader(pluginUrl, classLoader); PluginEnvironment pluginEnvironment = new PluginEnvironment(pluginDescriptor.getName(), pluginDescriptorLoader); String pluginName = pluginEnvironment.getPluginName(); // tell the plugin we have loaded it PluginLifecycleListener overseer = getPluginLifecycleListener(pluginName, pluginEnvironment, pluginDescriptor); if (overseer != null) { PluginContext context = createPluginContext(pluginName); ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(classLoader); overseer.initialize(context); } catch (Throwable t) { throw new PluginContainerException( "Plugin Lifecycle Listener failed to initialize plugin", t); } finally { Thread.currentThread().setContextClassLoader(originalContextClassLoader); } } // everything is loaded and initialized this.loadedPluginEnvironments.put(pluginName, pluginEnvironment); this.metadataManager.loadPlugin(pluginDescriptor); pluginLifecycleListenerMgr.setListener(pluginDescriptor.getName(), overseer); updateLoadedPlugins.execute(pluginDescriptor, pluginUrl); }
/** * Finds all plugins using the plugin finder defined in the <code>pluginContainerConfiguration * </code> and {@link #loadPlugin(java.net.URL, ClassLoader, * org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor) loads} each plugin found. */ public PluginManager( PluginContainerConfiguration pluginContainerConfiguration, PluginLifecycleListenerManager pluginLifecycleListenerManager) { if (pluginContainerConfiguration == null) { throw new NullPointerException("pluginContainerConfiguration is null"); } if (pluginLifecycleListenerManager == null) { throw new NullPointerException("pluginLifecycleListenerManager is null"); } this.pluginContainerConfiguration = pluginContainerConfiguration; this.pluginLifecycleListenerMgr = pluginLifecycleListenerManager; loadedPluginEnvironments = new HashMap<String, PluginEnvironment>(); loadedPlugins = new ArrayList<Plugin>(); metadataManager = new PluginMetadataManager(); metadataManager.setDisabledResourceTypes( pluginContainerConfiguration.getDisabledResourceTypes()); updateLoadedPlugins = new UpdateLoadedPlugins() { PluginTransformer transformer = new PluginTransformer(); public void execute(PluginDescriptor pluginDescriptor, URL pluginURL) { Plugin plugin = transformer.toPlugin(pluginDescriptor, pluginURL); loadedPlugins.add(plugin); } }; PluginFinder finder = pluginContainerConfiguration.getPluginFinder(); File tmpDir = pluginContainerConfiguration.getTemporaryDirectory(); List<String> disabledPlugins = pluginContainerConfiguration.getDisabledPlugins(); // The root classloader for all plugins will have all classes hidden except for those configured // in the regex. // Notice this root classloader has no jar URLs - it will provide no classes except for what it // will allow // the parent to expose as dictated by the regex. ClassLoader thisClassLoader = this.getClass().getClassLoader(); String rootPluginClassLoaderRegex = pluginContainerConfiguration.getRootPluginClassLoaderRegex(); ClassLoader rootCL = new RootPluginClassLoader(new URL[] {}, thisClassLoader, rootPluginClassLoaderRegex); // build our empty class loader manager - we use it to create and manage our plugin's // classloaders Map<String, URL> pluginNamesUrls = new HashMap<String, URL>(); // Save descriptors for later use, so we don't need to parse them twice. Map<URL, PluginDescriptor> descriptors = new HashMap<URL, PluginDescriptor>(); PluginDependencyGraph graph = new PluginDependencyGraph(); boolean createResourceCL = pluginContainerConfiguration.isCreateResourceClassloaders(); this.classLoaderManager = new ClassLoaderManager(pluginNamesUrls, graph, rootCL, tmpDir, createResourceCL); if (finder == null) { log.warn( "No plugin finder was specified in the plugin container configuration - this should only occur within test environments."); return; } try { Collection<URL> pluginUrls = finder.findPlugins(); // first, we need to parse all descriptors so we can build the dependency graph for (URL url : pluginUrls) { log.debug("Plugin found at: " + url); try { PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(url); if (!disabledPlugins.contains(descriptor.getName())) { AgentPluginDescriptorUtil.addPluginToDependencyGraph(graph, descriptor); pluginNamesUrls.put(descriptor.getName(), url); descriptors.put(url, descriptor); } else { log.info("Not loading disabled plugin: " + url); } } catch (Throwable t) { // probably due to invalid XML syntax in the deployment descriptor - the plugin will be // ignored log.error( "Plugin at [" + url + "] could not be loaded and will therefore not be deployed.", t); continue; } } // our graph is complete, get the order that we have to deploy the plugins List<String> deploymentOrder = graph.getDeploymentOrder(); // now deploy the plugins in the proper order, making sure we build the proper classloaders for (String nextPlugin : deploymentOrder) { URL pluginUrl = pluginNamesUrls.get(nextPlugin); try { ClassLoader pluginClassLoader = this.classLoaderManager.obtainPluginClassLoader(nextPlugin); PluginDescriptor descriptor = descriptors.get(pluginUrl); loadPlugin(pluginUrl, pluginClassLoader, descriptor); } catch (Throwable t) { // for some reason, the plugin failed to load - it will be ignored, and its depending // plugins will also fail later log.error( "Plugin [" + nextPlugin + "] at [" + pluginUrl + "] could not be loaded and will therefore not be deployed.", t); continue; } } log.info("Deployed plugins: " + this.loadedPlugins); metadataManager.cleanupDescriptors(); } catch (Exception e) { shutdown(); // have to clean up the environments (e.g. unpacked jars) we might have already // created log.error("Error initializing plugin container", e); throw new RuntimeException("Cannot initialize the plugin container", e); } }