/* * RHQ Management Platform * Copyright (C) 2005-2009 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.enterprise.server.plugin; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.persistence.Query; import org.hibernate.LazyInitializationException; import org.testng.annotations.Test; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.plugin.PluginConfigurationRequiredException; import org.rhq.core.domain.plugin.PluginDeploymentType; import org.rhq.core.domain.plugin.PluginKey; import org.rhq.core.domain.plugin.PluginStatusType; import org.rhq.core.domain.plugin.ServerPlugin; import org.rhq.enterprise.server.plugin.pc.ServerPluginType; import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService; import org.rhq.enterprise.server.test.AbstractEJB3Test; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType; /** * @author John Mazzitelli */ @Test public class ServerPluginsBeanTest extends AbstractEJB3Test { private static final String TEST_PLUGIN_NAME_PREFIX = "serverplugintest"; private static final String TEST_PLUGIN_JAR_NAME = "test-plugin.jar"; private ServerPluginManagerLocal serverPluginsBean; @Override protected void beforeMethod() { TestGenericServerPluginService pluginService; pluginService = new TestGenericServerPluginService(getTempDir()); prepareCustomServerPluginService(pluginService); serverPluginsBean = LookupUtil.getServerPluginManager(); pluginService.masterConfig.getPluginDirectory().mkdirs(); JavaArchive archive = ShrinkWrap.create(JavaArchive.class); URL res = this.getClass().getClassLoader().getResource("serverplugins/simple-generic-serverplugin.xml"); archive.addAsResource(res, "META-INF/rhq-serverplugin.xml"); File pluginFile = new File(pluginService.masterConfig.getPluginDirectory(), TEST_PLUGIN_JAR_NAME); archive.as(ZipExporter.class).exportTo(pluginFile, true); } @Override protected void afterMethod() { try { unprepareServerPluginService(); } catch (Exception e) { } try { getTransactionManager().begin(); em = getEntityManager(); Query q = em .createQuery("SELECT p FROM ServerPlugin p LEFT JOIN FETCH p.pluginConfiguration ppc LEFT JOIN FETCH p.scheduledJobsConfiguration psjc WHERE p.name LIKE 'serverplugintest%'"); List<ServerPlugin> doomed = q.getResultList(); for (ServerPlugin plugin : doomed) { em.remove(em.getReference(ServerPlugin.class, plugin.getId())); } getTransactionManager().commit(); } catch (Exception e) { try { System.out.println("CANNOT CLEAN UP TEST: Cause: " + e); getTransactionManager().rollback(); } catch (Exception ignore) { } } } public void testGetPlugins() throws Exception { ServerPlugin p1 = registerPlugin(1); ServerPlugin p2 = registerPlugin(2); PluginKey p1key = new PluginKey(p1); PluginKey p2key = new PluginKey(p2); List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert pluginKeys.contains(p1key) : pluginKeys; assert pluginKeys.contains(p2key) : pluginKeys; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert !pluginKeys.contains(p1key) : pluginKeys; assert !pluginKeys.contains(p2key) : pluginKeys; ServerPlugin plugin = this.serverPluginsBean.getServerPlugin(p1key); assert plugin.getId() == p1.getId() : plugin; assert plugin.getName().equals(p1.getName()) : plugin; assetLazyInitializationException(plugin); plugin = this.serverPluginsBean.getServerPluginRelationships(plugin); assert plugin.getPluginConfiguration() != null; assert plugin.getScheduledJobsConfiguration() != null; assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration()); assert plugin.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()); List<ServerPlugin> plugins = this.serverPluginsBean.getServerPlugins(); assert plugins.contains(p1) : plugins; assert plugins.contains(p2) : plugins; assetLazyInitializationException(plugins.get(plugins.indexOf(p1))); assetLazyInitializationException(plugins.get(plugins.indexOf(p2))); plugins = this.serverPluginsBean.getAllServerPlugins(); assert plugins.contains(p1) : plugins; assert plugins.contains(p2) : plugins; assetLazyInitializationException(plugins.get(plugins.indexOf(p1))); assetLazyInitializationException(plugins.get(plugins.indexOf(p2))); List<Integer> ids = new ArrayList<Integer>(2); ids.add(p1.getId()); ids.add(p2.getId()); plugins = this.serverPluginsBean.getServerPluginsById(ids); assert plugins.size() == 2 : plugins; assert plugins.contains(p1) : plugins; assert plugins.contains(p2) : plugins; assetLazyInitializationException(plugins.get(plugins.indexOf(p1))); assetLazyInitializationException(plugins.get(plugins.indexOf(p2))); long lastTimestamp; lastTimestamp = this.serverPluginsBean.getLastConfigurationChangeTimestamp(p1.getId()); assert lastTimestamp == getConfigurationLastModifiedTimestamp(p1); lastTimestamp = this.serverPluginsBean.getLastConfigurationChangeTimestamp(p2.getId()); assert lastTimestamp == getConfigurationLastModifiedTimestamp(p2); } public void testUpdatePlugins() throws Exception { ServerPlugin p1 = registerPlugin(1); PluginKey p1key = new PluginKey(p1); p1 = this.serverPluginsBean.getServerPlugin(p1key); p1 = this.serverPluginsBean.getServerPluginRelationships(p1); ServerPlugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1); p1update = this.serverPluginsBean.getServerPluginRelationships(p1update); assert p1update.getId() == p1.getId() : p1update; assert p1update.getId() == p1.getId() : p1update; assert p1update.getName().equals(p1.getName()) : p1update; assert p1update.getName().equals(p1.getName()) : p1update; assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update; assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update; p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()); p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()); } public void testTryEnableServerPluginsWithMissingRequiredConfiguration() throws Exception { ServerPlugin p1 = registerPlugin(1, Configuration.builder().addSimple("foo", "bar").build()); ServerPlugin p2 = registerPlugin(2); PluginKey p1key = new PluginKey(p1); PluginKey p2key = new PluginKey(p2); List<Integer> ids = new ArrayList<Integer>(2); ids.add(p1.getId()); ids.add(p2.getId()); // first disable both plugins List<PluginKey> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids); assert disabled.size() == 2 : disabled; assert disabled.contains(p1key) : disabled; assert disabled.contains(p2key) : disabled; // try to enable, but expect failure boolean caught = false; try { this.serverPluginsBean.enableServerPlugins(getOverlord(), ids); } catch (PluginConfigurationRequiredException pcre) { caught = true; } assert caught == true : "Exception must be thrown when attempting to enable plugin without required configuration set"; } public void testDisableEnablePlugins() throws Exception { ServerPlugin p1 = registerPlugin(1); ServerPlugin p2 = registerPlugin(2); PluginKey p1key = new PluginKey(p1); PluginKey p2key = new PluginKey(p2); List<Integer> ids = new ArrayList<Integer>(2); ids.add(p1.getId()); ids.add(p2.getId()); List<PluginKey> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids); assert disabled.size() == 2 : disabled; assert disabled.contains(p1key) : disabled; assert disabled.contains(p2key) : disabled; ; assert this.serverPluginsBean.getServerPlugin(p1key).getStatus() == PluginStatusType.INSTALLED; // still installed assert this.serverPluginsBean.getServerPlugin(p2key).getStatus() == PluginStatusType.INSTALLED; // still installed List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert pluginKeys.contains(p1key) : pluginKeys; assert pluginKeys.contains(p2key) : pluginKeys; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert !pluginKeys.contains(p1key) : pluginKeys; assert !pluginKeys.contains(p2key) : pluginKeys; // re-enable them this.serverPluginsBean.enableServerPlugins(getOverlord(), ids); pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert pluginKeys.contains(p1key) : pluginKeys; assert pluginKeys.contains(p2key) : pluginKeys; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert !pluginKeys.contains(p1key) : pluginKeys; assert !pluginKeys.contains(p2key) : pluginKeys; // make sure none of these enable/disable settings lost our config ServerPlugin plugin = this.serverPluginsBean.getServerPlugin(p1key); plugin = this.serverPluginsBean.getServerPluginRelationships(plugin); assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown! assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration()); plugin = this.serverPluginsBean.getServerPlugin(p2key); plugin = this.serverPluginsBean.getServerPluginRelationships(plugin); assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown! assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration()); } public void testUndeployPlugins() throws Exception { int originalSize = this.serverPluginsBean.getAllServerPlugins().size(); PluginStatusType status; PluginKey missingKey; missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class).stringify(), TEST_PLUGIN_NAME_PREFIX + "1"); status = this.serverPluginsBean.getServerPluginStatus(missingKey); assert status == null; missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class).stringify(), TEST_PLUGIN_NAME_PREFIX + "2"); status = this.serverPluginsBean.getServerPluginStatus(missingKey); assert status == null; ServerPlugin p1 = registerPlugin(1); ServerPlugin p2 = registerPlugin(2); PluginKey p1key = new PluginKey(p1); PluginKey p2key = new PluginKey(p2); status = this.serverPluginsBean.getServerPluginStatus(p1key); assert status == PluginStatusType.INSTALLED; status = this.serverPluginsBean.getServerPluginStatus(p2key); assert status == PluginStatusType.INSTALLED; assert this.serverPluginsBean.getServerPlugins().size() == originalSize + 2; assert this.serverPluginsBean.getAllServerPlugins().size() == originalSize + 2; List<Integer> ids = new ArrayList<Integer>(2); ids.add(p1.getId()); ids.add(p2.getId()); List<PluginKey> undeployed = this.serverPluginsBean.deleteServerPlugins(getOverlord(), ids); assert undeployed.size() == 2 : undeployed; assert undeployed.contains(p1key) : undeployed; assert undeployed.contains(p2key) : undeployed; ServerPlugin p1deleted = getDeletedPluginInTx(p1.getName()); ServerPlugin p2deleted = getDeletedPluginInTx(p2.getName()); assert p1deleted.getStatus() == PluginStatusType.DELETED; assert p2deleted.getStatus() == PluginStatusType.DELETED; List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert !pluginKeys.contains(p1key) : "deleted plugins should not be returned even here" + pluginKeys; assert !pluginKeys.contains(p2key) : "deleted plugins should not be returned even here" + pluginKeys; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert !pluginKeys.contains(p1.getName()) : pluginKeys; assert !pluginKeys.contains(p2.getName()) : pluginKeys; assert this.serverPluginsBean.getServerPlugins().size() == originalSize; assert this.serverPluginsBean.getAllServerPlugins().size() == originalSize + 2; } public void testReRegisterPlugins() throws Exception { PluginStatusType status; PluginKey missingKey; missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class).stringify(), TEST_PLUGIN_NAME_PREFIX + "1"); status = this.serverPluginsBean.getServerPluginStatus(missingKey); assert status == null; missingKey = new PluginKey(PluginDeploymentType.SERVER, new ServerPluginType(GenericPluginDescriptorType.class).stringify(), TEST_PLUGIN_NAME_PREFIX + "2"); status = this.serverPluginsBean.getServerPluginStatus(missingKey); assert status == null; ServerPlugin p1 = registerPlugin(1); ServerPlugin p2 = registerPlugin(2); PluginKey p1key = new PluginKey(p1); PluginKey p2key = new PluginKey(p2); status = this.serverPluginsBean.getServerPluginStatus(p1key); assert status == PluginStatusType.INSTALLED; status = this.serverPluginsBean.getServerPluginStatus(p2key); assert status == PluginStatusType.INSTALLED; List<Integer> ids = new ArrayList<Integer>(2); ids.add(p1.getId()); ids.add(p2.getId()); List<PluginKey> undeployed = this.serverPluginsBean.deleteServerPlugins(getOverlord(), ids); assert undeployed.size() == 2 : undeployed; assert undeployed.contains(p1key) : undeployed; assert undeployed.contains(p2key) : undeployed; ServerPlugin p1deleted = getDeletedPluginInTx(p1.getName()); assert p1deleted.getStatus() == PluginStatusType.DELETED; assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this ServerPlugin p2deleted = getDeletedPluginInTx(p1.getName()); assert p2deleted.getStatus() == PluginStatusType.DELETED; assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this List<PluginKey> pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert !pluginKeys.contains(p1key) : "deleted plugins should not be returned even here" + pluginKeys; assert !pluginKeys.contains(p2key) : "deleted plugins should not be returned even here" + pluginKeys; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert !pluginKeys.contains(p1key) : pluginKeys; assert !pluginKeys.contains(p2key) : pluginKeys; // purge them completely from the DB to prepare to re-register them this.serverPluginsBean.purgeServerPlugin(p1.getId()); this.serverPluginsBean.purgeServerPlugin(p2.getId()); // we just purged the database, make sure our entity ID's are all zero, since the original IDs are gone p1.setId(0); p2.setId(0); p1.setPluginConfiguration(p1.getPluginConfiguration().deepCopy(false)); p2.setPluginConfiguration(p2.getPluginConfiguration().deepCopy(false)); p1.setScheduledJobsConfiguration(p1.getScheduledJobsConfiguration().deepCopy(false)); p2.setScheduledJobsConfiguration(p2.getScheduledJobsConfiguration().deepCopy(false)); // re-register them now ServerPlugin p1again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p1, null); ServerPlugin p2again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p2, null); pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(true); assert pluginKeys.contains(p1key) : pluginKeys; assert pluginKeys.contains(p2key) : pluginKeys; assert p1again.getStatus() == PluginStatusType.INSTALLED; assert p2again.getStatus() == PluginStatusType.INSTALLED; pluginKeys = this.serverPluginsBean.getServerPluginKeysByEnabled(false); assert !pluginKeys.contains(p1key) : pluginKeys; assert !pluginKeys.contains(p2key) : pluginKeys; } private ServerPlugin registerPlugin(int index, Configuration pluginConfiguration) throws Exception { ServerPlugin plugin = new ServerPlugin(0, TEST_PLUGIN_NAME_PREFIX + index, TEST_PLUGIN_JAR_NAME, "displayName", true, PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion", pluginConfiguration, createScheduledJobsConfiguration(), new ServerPluginType( GenericPluginDescriptorType.class).stringify(), System.currentTimeMillis(), System.currentTimeMillis()); plugin = this.serverPluginsBean.registerServerPlugin(getOverlord(), plugin, null); assert plugin.getId() > 0; assert plugin.isEnabled() == true; assert plugin.getDeployment() == PluginDeploymentType.SERVER; assert plugin.getStatus() == PluginStatusType.INSTALLED; assert plugin.getPluginConfiguration() != null; assert plugin.getScheduledJobsConfiguration() != null; assert plugin.getType().equals(new ServerPluginType(GenericPluginDescriptorType.class).stringify()); return plugin; } private ServerPlugin registerPlugin(int index) throws Exception { return registerPlugin(index, createPluginConfiguration()); } private void assetLazyInitializationException(ServerPlugin plugin) { try { plugin.getPluginConfiguration().toString(); assert false : "Should have thrown a lazy-initialization exception - we didn't load config"; } catch (LazyInitializationException ok) { } try { plugin.getScheduledJobsConfiguration().toString(); assert false : "Should have thrown a lazy-initialization exception - we didn't load config"; } catch (LazyInitializationException ok) { } } private Configuration createPluginConfiguration() { Configuration config = new Configuration(); config.put(new PropertySimple("simpleprop1", "simpleprop1value")); // set this property to something as this is defined as required in simple-generic-serverplugin.xml config.put(new PropertySimple("plugin-simple-prop-1", "foo")); return config; } private Configuration createScheduledJobsConfiguration() { Configuration config = new Configuration(); PropertyMap map = new PropertyMap("jobname"); config.put(map); map.put(new PropertySimple("methodName", "methodNameValue")); return config; } private Subject getOverlord() { return LookupUtil.getSubjectManager().getOverlord(); } private ServerPlugin getDeletedPluginInTx(String pluginName) throws Exception { getTransactionManager().begin(); try { Query q = em.createNamedQuery(ServerPlugin.QUERY_FIND_ANY_BY_NAME); q.setParameter("name", pluginName); return (ServerPlugin) q.getSingleResult(); } finally { getTransactionManager().rollback(); } } private long getConfigurationLastModifiedTimestamp(ServerPlugin plugin) { // determine the last time the plugin config or schedule jobs changed // return 0 value if plugin doesn't have any config whatsoever long timestamp = 0; Configuration config = plugin.getPluginConfiguration(); if (config != null) { timestamp = config.getModifiedTime(); } config = plugin.getScheduledJobsConfiguration(); if (config != null && config.getModifiedTime() > timestamp) { timestamp = config.getModifiedTime(); } return timestamp; } }