/*
* RHQ Management Platform
* Copyright (C) 2005-2014 Red Hat, Inc.
* All rights reserved.
*
* 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 version 2 of the License.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.core.pc.plugin;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
import org.rhq.core.pc.PluginContainerConfiguration;
import org.rhq.core.pluginapi.plugin.PluginContext;
import org.rhq.core.pluginapi.plugin.PluginLifecycleListener;
public class PluginManagerTest {
static final String PLUGIN_A = "plugin-A.jar";
static final String PLUGIN_B = "plugin-B-depends-on-A.jar";
static final String PLUGIN_C = "plugin-C-depends-on-B.jar";
PluginDescriptor descriptorA;
PluginDescriptor descriptorB;
PluginDescriptor descriptorC;
@BeforeClass
public void initClass() throws Exception {
verifyPluginsExist();
initPluginDescriptors();
}
void verifyPluginsExist() {
assertPluginJarFileExists(PLUGIN_A);
assertPluginJarFileExists(PLUGIN_B);
assertPluginJarFileExists(PLUGIN_C);
}
void initPluginDescriptors() throws Exception {
descriptorA = loadPluginDescriptor(getClass().getResource(PLUGIN_A));
descriptorB = loadPluginDescriptor(getClass().getResource(PLUGIN_B));
descriptorC = loadPluginDescriptor(getClass().getResource(PLUGIN_C));
}
void assertPluginJarFileExists(String pluginPath) {
URL pluginURL = getClass().getResource(pluginPath);
File pluginJarFile = FileUtils.toFile(pluginURL);
assertTrue(pluginJarFile.exists(), pluginJarFile.getAbsolutePath() + " does not exist and is needed for " +
"tests in " + PluginManagerTest.class.getName());
}
@Test
public void initializeShouldLoadDiscoveredPlugins() throws Exception {
PluginContainerConfiguration configuration = createConfiguration();
FakePluginLifecycleListenerManager mgr = new FakePluginLifecycleListenerManager();
PluginManager pluginMgr = new PluginManager(configuration, mgr);
verifyThatPluginsAreLoaded(pluginMgr);
}
@Test
public void pluginsShouldBeLoadedInCorrectOrder() throws Exception {
PluginContainerConfiguration configuration = createConfiguration();
FakePluginLifecycleListenerManager pluginLifecycleListenerMgr = new FakePluginLifecycleListenerManager();
PluginManager pluginMgr = new PluginManager(configuration, pluginLifecycleListenerMgr);
verifyPluginsLoadedInCorrectOrder(pluginLifecycleListenerMgr);
}
@Test
public void pluginsShouldBeShutdownInCorrectOrder() throws Exception {
PluginContainerConfiguration configuration = createConfiguration();
FakePluginLifecycleListenerManager pluginLifecycleListenerMgr = new FakePluginLifecycleListenerManager();
PluginManager pluginMgr = new PluginManager(configuration, pluginLifecycleListenerMgr);
pluginMgr.shutdown();
verifyPluginsShutdownInCorrectOrder(pluginLifecycleListenerMgr);
}
private PluginContainerConfiguration createConfiguration() {
PluginContainerConfiguration configuration = new PluginContainerConfiguration();
configuration.setPluginFinder(new PluginFinder() {
public Collection<URL> findPlugins() {
List<URL> pluginURLs = new ArrayList<URL>();
pluginURLs.add(getClass().getResource(PLUGIN_A));
pluginURLs.add(getClass().getResource(PLUGIN_B));
pluginURLs.add(getClass().getResource(PLUGIN_C));
return pluginURLs;
}
});
return configuration;
}
void verifyThatPluginsAreLoaded(PluginManager pluginMgr) throws Exception {
assertPluginLoaded(descriptorA, pluginMgr);
assertPluginLoaded(descriptorB, pluginMgr);
assertPluginLoaded(descriptorC, pluginMgr);
}
void assertPluginLoaded(PluginDescriptor pluginDescriptor, PluginManager pluginMgr) throws Exception {
PluginEnvironment pluginEnvironment = pluginMgr.getPlugin(pluginDescriptor.getName());
assertNotNull(pluginEnvironment, "Expected the '" + pluginDescriptor.getName() + "' plugin to be loaded.");
}
void verifyPluginsLoadedInCorrectOrder(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
assertPluginALoadedFirst(pluginLifecycleListenerMgr);
assertPluginBLoadedSecond(pluginLifecycleListenerMgr);
assertPluginCLoadedThird(pluginLifecycleListenerMgr);
}
void assertPluginALoadedFirst(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int initOrder = pluginLifecycleListenerMgr.lifecycleTracker.getInitializationOrder(descriptorA.getName());
assertEquals(initOrder, 0, "Expected " + descriptorA.getName() + " to be initialized first.");
}
void assertPluginBLoadedSecond(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int initOrder = pluginLifecycleListenerMgr.lifecycleTracker.getInitializationOrder(descriptorB.getName());
assertEquals(initOrder, 1, "Expected " + descriptorB.getName() + " to be initialized second.");
}
void assertPluginCLoadedThird(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int initOrder = pluginLifecycleListenerMgr.lifecycleTracker.getInitializationOrder(descriptorC.getName());
assertEquals(initOrder, 2, "Expected " + descriptorC.getName() + " to be initialized third.");
}
void verifyPluginsShutdownInCorrectOrder(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
assertPluginCShutdownFirst(pluginLifecycleListenerMgr);
assertPluginBShutdownSecond(pluginLifecycleListenerMgr);
assertPluginAShutdownThird(pluginLifecycleListenerMgr);
}
void assertPluginCShutdownFirst(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int shutdownOrder = pluginLifecycleListenerMgr.lifecycleTracker.getShutdownOrder(descriptorC.getName());
assertEquals(shutdownOrder, 0, "Expected " + descriptorC.getName() + " to be shutdown first.");
}
void assertPluginBShutdownSecond(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int shutdownOrder = pluginLifecycleListenerMgr.lifecycleTracker.getShutdownOrder(descriptorB.getName());
assertEquals(shutdownOrder, 1, "Expected " + descriptorB.getName() + " to be shutdown second.");
}
void assertPluginAShutdownThird(FakePluginLifecycleListenerManager pluginLifecycleListenerMgr) throws Exception {
int shutdownOrder = pluginLifecycleListenerMgr.lifecycleTracker.getShutdownOrder(descriptorA.getName());
assertEquals(shutdownOrder, 2, "Expected " + descriptorA.getName() + " to be shutdown third.");
}
PluginDescriptor loadPluginDescriptor(URL pluginURL) throws PluginContainerException {
return AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginURL);
}
static class FakePluginLifecycleListenerManager implements PluginLifecycleListenerManager {
Map<String, PluginLifecycleListener> listeners = new HashMap<String, PluginLifecycleListener>();
PluginLifecycleTracker lifecycleTracker = new PluginLifecycleTracker();
public PluginLifecycleListener loadListener(PluginDescriptor pluginDescriptor, PluginEnvironment pluginEnvironment)
throws PluginContainerException {
FakePluginLifecycleListener listener = new FakePluginLifecycleListener(pluginDescriptor.getName(),
lifecycleTracker);
listeners.put(pluginDescriptor.getName(), listener);
return listener;
}
public PluginLifecycleListener getListener(String pluginName) {
return listeners.get(pluginName);
}
public void setListener(String pluginName, PluginLifecycleListener listener) {
listeners.put(pluginName, listener);
}
public void shutdown() {
}
}
/**
* This is helper class that is used to track the order of start up and shutdown for the plugins used by these
* tests.
*/
static class PluginLifecycleTracker {
private final List<String> initializedPlugins = new LinkedList<String>();
private final List<String> shutdownPlugins = new LinkedList<String>();
public void initialize(String plugin) {
initializedPlugins.add(plugin);
}
public void shutdown(String plugin) {
shutdownPlugins.add(plugin);
}
public int getInitializationOrder(String plugin) {
return initializedPlugins.indexOf(plugin);
}
public int getShutdownOrder(String plugin) {
return shutdownPlugins.indexOf(plugin);
}
}
static class FakePluginLifecycleListener implements PluginLifecycleListener {
String pluginName;
PluginLifecycleTracker lifecycleTracker;
public FakePluginLifecycleListener(String pluginName, PluginLifecycleTracker lifecycleTracker) {
this.pluginName = pluginName;
this.lifecycleTracker = lifecycleTracker;
}
public void initialize(PluginContext context) throws Exception {
lifecycleTracker.initialize(pluginName);
}
public void shutdown() {
lifecycleTracker.shutdown(pluginName);
}
}
}