/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.deployment.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Properties;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
import org.jboss.mx.util.ObjectNameFactory;
import org.jboss.services.deployment.MBeanData;
import org.jboss.test.JBossTestCase;
/**
* DeploymentService tests
*
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis </a>
* @author <a href="mailto:peter.johnson2@unisys.com">Peter Johnson </a>
* @version $Revision: 81036 $
*/
public class DeploymentServiceUnitTestCase extends JBossTestCase
{
private ObjectName deploymentService = ObjectNameFactory
.create("jboss:service=DeploymentService");
private ObjectName mainDeployer = ObjectNameFactory
.create("jboss.system:service=MainDeployer");
public DeploymentServiceUnitTestCase(String name)
{
super(name);
}
/**
* Check if I can get the available templates
*/
public void testListModuleTemplates() throws Exception
{
log.info("+++ testListModuleTemplates");
MBeanServerConnection server = getServer();
try
{
boolean isRegistered = server.isRegistered(deploymentService);
assertTrue(deploymentService + " is registered", isRegistered);
log.info("Loaded templates: "
+ server.invoke(deploymentService, "listModuleTemplates",
new Object[] {}, new String[] {}));
}
finally
{
// empty
}
}
/**
* Try to create, remove and re-create a jms topic (don't deploy)
*/
public void testCreateAndRemoveAndCreateTopic() throws Exception
{
log.info("+++ testCreateAndRemoveAndCreateTopic");
try
{
String module = "testTopic1-service.xml";
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("TopicName", "testTopic1"); // the topic name (mandatory)
props.put("InMemory", new Boolean(true)); // set this to true to
// persist the topic in
// memory
props.put("MaxDepth", new Integer(5)); // set the MaxDepth property
// to 5
String template = "jms-topic";
// Create a topic destination module, in case of any problem an
// exception will be thrown
module = createModule(module, template, props);
// remove the module
removeModule(module);
// Re-create the topic destination module with the same module name.
// In case of any problem an exception will be thrown
module = createModule(module, template, props);
}
catch (Exception e)
{
super.fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to create a no-tx-datasource (don't deploy)
*/
public void testCreateNoTxDataSource() throws Exception
{
log.info("+++ testCreateNoTxDataSource");
try
{
String module = "test-no-tx-hsqldb-ds.xml";
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", "TestNoTxDataSource");
props.put("connection-url", "jdbc:hsqldb:hsql://localhost:1701");
props.put("driver-class", "org.hsqldb.jdbcDriver");
// Add some fake connection properties
Hashtable ht = new Hashtable();
ht.put("property1", "someString");
ht.put("property2", new Boolean(true));
ht.put("property3", new Integer(666));
props.put("connection-properties", ht);
props.put("user-name", "sa");
props.put("password", "");
props.put("min-pool-size", new Integer(5));
props.put("max-pool-size", new Integer(20));
props.put("track-statements", "NOWARN");
props.put("security-config", "APPLICATION-MANAGED-SECURITY");
props.put("type-mapping", "Hypersonic SQL");
props.put("dependencies", new ObjectName[] { new ObjectName(
"jboss:service=Hypersonic") });
String template = "no-tx-datasource";
// In case of any problem an exception will be thrown
module = createModule(module, template, props);
}
catch (Exception e)
{
super.fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to create an xa-datasource (don't deploy)
*/
public void testCreateXaDataSource() throws Exception
{
log.info("+++ testCreateXaDataSource");
try
{
String module = "test-xa-oracle-ds.xml";
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", "TestOracleXaDataSource");
props.put("track-connection-by-tx", new Boolean(true));
props.put("is-same-RM-override-value", new Boolean(false));
props.put("xa-datasource-class",
"oracle.jdbc.xa.client.OracleXADataSource");
// Add some xa-datasource-properties
Hashtable ht = new Hashtable();
ht.put("URL", "jdbc:oracle:oci8:@tc");
ht.put("User", "scott");
ht.put("Password", "tiger");
props.put("xa-datasource-properties", ht);
props.put("exception-sorter-class-name",
"org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter");
props.put("no-tx-separate-pools", new Boolean(true));
props.put("type-mapping", "Oracle9i");
String template = "xa-datasource";
// In case of any problem an exception will be thrown
module = createModule(module, template, props);
}
catch (Exception e)
{
super.fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to create and deploy a local-tx-datasource
*/
public void testCreateAndDeployLocalTxDataSource() throws Exception
{
log.info("+++ testCreateAndDeployLocalTxDataSource");
try
{
String module = "test-local-tx-hsqldb-ds.xml";
String jndiName = "TestLocalTxHsqlDataSource";
// undeploye module in case it's deployed
undeployModule(module);
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", jndiName); // use a name other than default
props.put("use-java-context", new Boolean(false)); // set this to
// false to allow
// remote lookup
props.put("connection-url", "jdbc:hsqldb:hsql://localhost:1701"); // using
// hsqldb
props.put("driver-class", "org.hsqldb.jdbcDriver");
props.put("user-name", "sa");
props.put("password", "");
props.put("min-pool-size", new Integer(5));
props.put("max-pool-size", new Integer(20));
props.put("idle-timeout-minutes", new Integer(0));
props.put("track-statements", "TRUE");
props.put("security-config", "APPLICATION-MANAGED-SECURITY");
props.put("type-mapping", "Hypersonic SQL");
props.put("dependencies", new ObjectName[] { new ObjectName(
"jboss:service=Hypersonic") });
String template = "local-tx-datasource";
// In case of any problem an exception will be thrown
module = createModule(module, template, props);
boolean isDeployed = deployModule(module);
// was deployment succesful?
assertTrue("deployed successful : " + isDeployed, isDeployed);
// see if we can get a connection
InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup(jndiName);
Connection connection = ds.getConnection();
connection.close();
// undeploy module
undeployModule(module);
// remove module
removeModule(module);
// regenerate with wrong usename
props.put("user-name", "rogue-admin");
module = createModule(module, template, props);
// deploy again
isDeployed = deployModule(module);
// was deployment succesful?
assertTrue("deployed successful : " + isDeployed, isDeployed);
// lookup the datasource again and see if we can get a connection
// it should fail this time
try
{
ds = (DataSource) ic.lookup(jndiName);
connection = ds.getConnection();
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// ok
}
// undeploy module
undeployModule(module);
}
finally
{
// empty
}
}
/**
* Try to update an mbean with a standard set of properties. In this case,
* the mbean name is bad and an error should be returned from the deployment
* service.
*/
public void testUpdateMBeanBadName() throws Exception
{
log.info("+++ testUpdateMBeanBadName");
// Establish the property values
Properties attrs = new Properties();
attrs.put("Attr1", "aaaaa");
attrs.put("Attr2", "bbbbb");
;
// Set up the MBean configuration bean:
MBeanData data = new MBeanData();
data.setTemplateName("mbean-update");
data.setAttributes(attrs);
// Try with a null mbean name:
try
{
data.setName(null);
updateMBean(data);
String msg = "Unexpectedly found mbean with invalid name: " + data;
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
// Try with an empty mbean name:
try
{
data.setName("");
updateMBean(data);
String msg = "Unexpectedly found mbean with invalid name: " + data;
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
// Try with an unknown mbean name:
try
{
data.setName("jboss.xxx:service=NoneSuch");
updateMBean(data);
String msg = "Unexpectedly found mbean with name: " + data;
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
// Try with an unknown mbean name with multiple attributes::
try
{
data.setName("jboss.xxx:service=NoneSuch,type=Unknown,Alias=whatever");
updateMBean(data);
String msg = "Unexpectedly found mbean with name: " + data;
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
}
/**
* Try to update an mbean with a standard set of properties. In this case, no
* template is given for doing the update. The update should fail.
*/
public void testUpdateMBeanBadTemplate() throws Exception
{
log.info("+++ testUpdateMBeanBadTemplate");
// Establish the property values
Properties attrs = new Properties();
attrs.put("Attr1", "aaaaa");
attrs.put("Attr2", "bbbbb");
;
// Set up the MBean configuration bean:
MBeanData data = new MBeanData();
data.setName("jboss.mq:service=MessageCache");
data.setAttributes(attrs);
// Try with a null template name:
try
{
data.setTemplateName(null);
log.info("Template=" + data.getTemplateName());
updateMBean(data);
String msg = "Update was successful with null template name: "
+ data.getTemplateName();
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
// Try again, but with an empty template name:
try
{
data.setTemplateName("");
log.info("Template=" + data.getTemplateName());
updateMBean(data);
String msg = "Update was successful with empty template name "
+ data.getTemplateName();
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
// Try again, but with an unknown template name:
try
{
data.setTemplateName("nonesuch");
log.info("Template=" + data.getTemplateName());
updateMBean(data);
String msg = "Update was successful with null template "
+ data.getTemplateName();
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
}
/**
* Try to update an mbean with a standard set of properties. In this case,
* the mbean attributes are bad. The update should succeed.
*/
public void testUpdateMBeanBadAttributes() throws Exception
{
log.info("+++ testUpdateMBeanBadAttributes");
// Set up the MBean configuration bean:
MBeanData data = new MBeanData();
data.setName("jboss.mq:service=MessageCache");
data.setTemplateName("mbean-update");
data.setAttributes(null);
// Update the mbean
boolean result = updateMBean(data);
// Yes, I could have used assertTrue, but I want to log all errors:
if (result)
{
log.info("passed");
}
else
{
String msg = "Failed to update mbean when attributes were null: "
+ data;
log.error(msg);
fail(msg);
}
}
/**
* Try to update an mbean with a standard set of properties. In this case,
* the mbean data is bad. The update should fail.
*/
public void testUpdateMBeanBadData() throws Exception
{
log.info("+++ testUpdateMBeanBadData");
// Attempt to update the mbean with no data
try
{
updateMBean(null);
String msg = "Update was successful with null data";
log.error(msg);
fail(msg);
}
catch (MBeanException e)
{
// expected
log.info("passed");
}
}
/**
* Try to update an mbean with a standard set of properties. The mbean we use
* is the MessageCache mbean for the messaging service. The mbean properties
* are changed to innocuous values that should cause no problems. This test
* might have to be updated when the new messing service is rolled out.
*/
public void testUpdateMBeanStandard() throws Exception
{
log.info("+++ testUpdateMBeanStandard");
// Establish the property values
String value = "999";
Properties attrs = new Properties();
attrs.put("MaxMemoryMark", value);
attrs.put("HighMemoryMark", value);
attrs.put("CacheStore", "jboss.mq:service=PersistenceManager");
attrs.put("MaximumHard", value);
attrs.put("MinimumHard", value);
attrs.put("SoftenAtLeastEveryMillis", value);
attrs.put("SoftenNoMoreOftenThanMillis", value);
attrs.put("MakeSoftReferences", "true");
// For some reason, the following value is rounded up to 1000 if set to
// 999, so we will use 1000 as the value:
attrs.put("SoftenWaitMillis", "1000");
// Set up the MBean configuration bean:
MBeanData data = new MBeanData();
String name = "jboss.mq:service=MessageCache";
data.setName(name);
data.setTemplateName("mbean-update");
data.setAttributes(attrs);
// Update and verify the mbean:
boolean result = updateMBean(data);
// Yes, I could have used assertTrue, but I want to log all errors:
if (!result)
{
String msg = "Failed to update mbean " + data;
log.error(msg);
fail(msg);
}
verifyMBean(data, null);
}
/**
* Try to update an mbean where one of the properties has a value expressed
* as a nested XML property rather than as simple text. The mbean we use is
* the SecurityManager mbean for the messaging service. The mbean property
* that is of interest is the DefaultSecurityConfig. This test might have to
* be updated when the new messing service is rolled out.
*/
public void testUpdateMBeanNested() throws Exception
{
log.info("+++ testUpdateMBeanNested");
// Establish the property values
Properties attrs = new Properties();
String nestedAttr = "DefaultSecurityConfig";
attrs
.put(
nestedAttr,
"<security><role name=\"guest\" read=\"true\" write=\"false\" create=\"false\"/></security>");
attrs.put("SecurityDomain", "java:/jaas/jbossmq");
// Establish the dependency values
Properties depends = new Properties();
depends.put("NextInterceptor", "jboss.mq:service=DestinationManager");
// Set up the MBean configuration bean:
MBeanData data = new MBeanData();
String name = "jboss.mq:service=SecurityManager";
data.setName(name);
data.setTemplateName("mbean-update");
data.setAttributes(attrs);
data.setDepends(depends);
// Update and verify the mbean:
boolean result = updateMBean(data);
// Yes, I could have used assertTrue, but I want to log all errors:
if (!result)
{
String msg = "Failed to update mbean " + data;
log.error(msg);
fail(msg);
}
verifyMBean(data, nestedAttr);
}
/**
* Try to update an mbean that has a name with multiple attributes. We will
* update the mbean twice, each time presenting the name attributes in a
* different order. We will use one of the InvocationLayer mbeans from the
* uil2-service.xml file.
*/
public void testUpdateMBeanXpath() throws Exception
{
log.info("+++ testUpdateMBeanXpath");
// Establish the property values
Properties attrs = new Properties();
attrs.put("FromName", "XXXXXXXXX");
attrs.put("ToName", "AAAAAAAAAA");
// Establish the dependency values
Properties depends = new Properties();
depends.put("", "jboss:service=Naming");
// Set up the MBean configuration bean, this time with the attributes
// in the order in which they appear when asking the mbean for the name
MBeanData data = new MBeanData();
data
.setName("jboss.mq:alias=UIL2XAConnectionFactory,service=InvocationLayer,type=UIL2XA");
data.setTemplateName("mbean-update");
data.setAttributes(attrs);
data.setDepends(depends);
// Update and verify the mbean:
if (!updateMBean(data))
{
String msg = "Failed to update mbean: " + data;
log.error(msg);
fail(msg);
}
verifyMBean(data, null);
// Try again, but with the name attributes in a different order. This
// time in the order in which they appear in the xml file:
attrs = new Properties();
attrs.put("FromName", "RRRRRRRRRRR");
attrs.put("ToName", "QQQQQQQQQQQQQ");
data
.setName("jboss.mq:service=InvocationLayer,type=UIL2XA,alias=UIL2XAConnectionFactory");
data.setAttributes(attrs);
// Update and verify the mbean:
if (!updateMBean(data))
{
String msg = "Failed to update mbean: " + data;
log.error(msg);
fail(msg);
}
verifyMBean(data, null);
// Try again, but with the name attributes in another order. This
// time in the order is different that the mbean name or xml file:
attrs = new Properties();
attrs.put("FromName", "LLLLLLLLLLLL");
attrs.put("ToName", "KKKKKKKKKKKK");
data
.setName("jboss.mq:type=UIL2XA,alias=UIL2XAConnectionFactory,service=InvocationLayer");
data.setAttributes(attrs);
// Update and verify the mbean:
if (!updateMBean(data))
{
String msg = "Failed to update mbean: " + data;
log.error(msg);
fail(msg);
}
verifyMBean(data, null);
}
/**
* Try to update a local transaction data source. This test case uses the
* DefaultDS data source.
*/
public void testUpdateDataSourceLocal() throws Exception
{
log.info("+++ testUpdateDataSourceLocal");
try
{
String jndiName = "DefaultDS";
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", jndiName);
props.put("use-java-context", new Boolean(false)); // set this to
// false to allow
// remote lookup
props.put("connection-url", "jdbc:hsqldb:hsql://localhost:1701"); // using
// hsqldb
props.put("driver-class", "org.hsqldb.jdbcDriver");
props.put("user-name", "sa");
props.put("password", "");
props.put("min-pool-size", new Integer(9));
props.put("max-pool-size", new Integer(99));
props.put("idle-timeout-minutes", new Integer(99));
props.put("track-statements", "TRUE");
props.put("security-config", "APPLICATION-MANAGED-SECURITY");
props.put("type-mapping", "Hypersonic SQL");
props.put("dependencies", new ObjectName[] { new ObjectName(
"jboss:service=Hypersonic") });
String template = "local-tx-datasource";
// In case of any problem an exception will be thrown
boolean isDeployed = updateDataSource("hsqldb-ds.xml", template, props);
assertTrue("deployed successful : " + isDeployed, isDeployed);
// see if we can get a connection
boolean connected = connectToDataSource(jndiName);
assertTrue("Data source " + jndiName + " connected successful : "
+ connected, connected);
// Try with the other module name
isDeployed = updateDataSource("hsqldb", template, props);
assertTrue("deployed successful : " + isDeployed, isDeployed);
// see if we can get a connection
connected = connectToDataSource(jndiName);
assertTrue("Data source " + jndiName + " connected successful : "
+ connected, connected);
log.info("passed");
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to update a no transaction data source. This test case uses the data
* source created by testCreateNoTxDataSource. This test is hidden for now,
* the test-no-tx-hsqldb data source is never deployed and is thus not
* visible.
*/
public void hide_testUpdateDataSourceNo() throws Exception
{
log.info("+++ testUpdateDataSourceNo");
try
{
String module = "test-no-tx-hsqldb-ds.xml";
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", "TestNoTxDataSource");
props.put("connection-url", "jdbc:hsqldb:hsql://localhost:1701");
props.put("driver-class", "org.hsqldb.jdbcDriver");
// Add some fake connection properties
Hashtable ht = new Hashtable();
ht.put("property1", "someString");
ht.put("property2", new Boolean(true));
ht.put("property3", new Integer(666));
props.put("connection-properties", ht);
props.put("user-name", "sa");
props.put("password", "");
props.put("min-pool-size", new Integer(5));
props.put("max-pool-size", new Integer(20));
props.put("track-statements", "NOWARN");
props.put("security-config", "APPLICATION-MANAGED-SECURITY");
props.put("type-mapping", "Hypersonic SQL");
props.put("dependencies", new ObjectName[] { new ObjectName(
"jboss:service=Hypersonic,") });
String template = "no-tx-datasource";
// In case of any problem an exception will be thrown
boolean isDeployed = updateDataSource(module, template, props);
assertTrue("deployed successful : " + isDeployed, isDeployed);
// We don't try to get a connection because the original
// data source was never deployed.
log.info("passed");
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to update an XA transaction data source. This test case uses the data
* source created by testCreateXaDataSource. This test is hidden for now, the
* test-xa-oracle data source is never deployed and is thus not visible.
*/
public void hide_testUpdateDataSourceXa() throws Exception
{
log.info("+++ testUpdateDataSourceNo");
try
{
String module = "test-xa-oracle-ds.xml";
// remove module in case it exists
removeModule(module);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", "TestOracleXaDataSource");
props.put("track-connection-by-tx", new Boolean(true));
props.put("is-same-RM-override-value", new Boolean(false));
props.put("xa-datasource-class",
"oracle.jdbc.xa.client.OracleXADataSource");
// Add some xa-datasource-properties
Hashtable ht = new Hashtable();
ht.put("URL", "jdbc:oracle:oci8:@tc");
ht.put("User", "scott");
ht.put("Password", "tiger");
props.put("xa-datasource-properties", ht);
props.put("exception-sorter-class-name",
"org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter");
props.put("no-tx-separate-pools", new Boolean(true));
props.put("type-mapping", "Oracle9i");
String template = "xa-datasource";
// In case of any problem an exception will be thrown
boolean isDeployed = updateDataSource(module, template, props);
assertTrue("deployed successful : " + isDeployed, isDeployed);
// We don't try to get a connection because the original
// data source was never deployed.
log.info("passed");
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
finally
{
// empty
}
}
/**
* Try to remove a data source using the removeDataSource() method. This test
* case uses the "TestLocalTxHsqlDataSource" created by
* testCreateAndDeployLocalTxDataSource().
*
* Note that the "TestLocalTxHsqlDataSource" will be removed from the
* test-local-tx-hsqldb-ds.xml file, thus further reference to this data
* source may be in-appropriate.
*/
public void testRemoveDataSource() throws Exception
{
log.info("+++ testRemoveDataSource");
try
{
String module = "test-local-tx-hsqldb-ds.xml";
String jndiName = "TestLocalTxHsqlDataSource";
// Deploy the module
boolean isDeployed = deployModule(module);
// Was deployment succesful?
assertTrue("deployed successful : " + isDeployed, isDeployed);
// Prepare the template properties
HashMap props = new HashMap();
props.put("jndi-name", jndiName);
String template = "datasource-remove";
// In case of any problem an exception will be thrown
isDeployed = removeDataSource(module, template, props);
// The module should be deployed
assertTrue("removed successful : " + isDeployed, isDeployed);
// But we should NOT be able to get a connection
try
{
InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup(jndiName);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// Ok, undeploy the module
undeployModule(module);
}
log.info("passed");
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
}
/**
* Try to remove a data source using the removeDataSource() method from a
* module with multiple data sources configured. This test case uses the
* testMultipleDataSources-ds.xml module located under the
* "testsuite/src/etc/deployment-test" directory.
*/
public void testRemoveDataSourceFromMultiNodesModule() throws Exception
{
log.info("+++ testRemoveDataSourceFromMultiNodesModule");
try
{
String module = "testMultipleDataSources-ds.xml";
String jndiName1 = "TestDataSource1";
String jndiName2 = "TestDataSource2";
String delim = File.separator;
// Find the server directory
MBeanServerConnection server = getServer();
ObjectName serverConfig = new ObjectName(
"jboss.system:type=ServerConfig");
String serverHome = ((File) server.getAttribute(serverConfig,
"ServerHomeDir")).getCanonicalPath();
log.info("serverHome = " + serverHome);
// Find the directory where the test module resides
String myPath = new File("").getAbsolutePath();
log.info("myPath = " + myPath);
int inx = myPath.lastIndexOf(delim);
if (inx >= 0)
myPath = myPath.substring(0, myPath.lastIndexOf(delim));
// Copy the module to the deploy directory
String source = myPath + delim + "src" + delim + "etc" + delim
+ "deployment-test" + delim + module;
String target = serverHome + delim + "deploy" + delim + module;
log.info("source = " + source);
log.info("target = " + target);
FileChannel srcChannel = new FileInputStream(source).getChannel();
FileChannel destChannel = new FileOutputStream(target).getChannel();
srcChannel.transferTo(0, srcChannel.size(), destChannel);
srcChannel.close();
destChannel.close();
// See if we can get connection to the data sources:
boolean connected = connectToDataSource(jndiName1);
assertTrue("Data source " + jndiName1 + " connected successful : "
+ connected, connected);
connected = connectToDataSource(jndiName2);
assertTrue("Data source " + jndiName2 + " connected successful : "
+ connected, connected);
// Prepare the template properties for removing "TestDataSource1"
HashMap props = new HashMap();
props.put("jndi-name", jndiName1);
String template = "datasource-remove";
// In case of any problem an exception will be thrown
boolean isDeployed = removeDataSource(module, template, props);
// The module should be deployed
assertTrue("removed successful : " + isDeployed, isDeployed);
// We should be able to connect to TestDataSource2
connected = connectToDataSource(jndiName2);
assertTrue("Data source " + jndiName2 + " connected successful : "
+ connected, connected);
// But we should NOT be able connect to TestDataSource1
try
{
InitialContext ic = new InitialContext();
DataSource ds1 = (DataSource) ic.lookup(jndiName1);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// Ok, remove the file
File targetFile = new File(target);
targetFile.delete();
}
log.info("passed");
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
}
/**
* Try to remove a data source using the removeDataSource() method. In this
* case, the module name is bad and an error should be returned from the
* deployment service.
*/
public void testRemoveDataSourceBadModule() throws Exception
{
log.info("+++ testRemoveDataSourceBadModule");
// Setup the data
String module = null;
String template = "datasource-remove";
HashMap props = new HashMap();
// Try with a null module name:
try
{
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
// Try with an empty module name:
try
{
module = "";
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
// Try with an unknown module name:
try
{
module = "unknoenModule";
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
}
/**
* Try to remove a data source using the removeDataSource() method. In this
* case, the template name is bad and an error should be returned from the
* deployment service.
*/
public void testRemoveDataSourceBadTemplate() throws Exception
{
log.info("+++ testRemoveDataSourceBadTemplate");
try
{
String module = "test-local-tx-hsqldb-ds.xml";
String template = null;
HashMap props = new HashMap();
// Deploy the module
boolean isDeployed = deployModule(module);
// Was deployment succesful?
assertTrue("deployed successful : " + isDeployed, isDeployed);
// Try with a null template name:
try
{
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
// Try with an empty template name:
try
{
template = "";
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
// Try with an unknown template name:
try
{
template = "unknownTemplate";
removeDataSource(module, template, props);
fail("Shouldn't reach this point");
}
catch (Exception e)
{
// expected
log.info("passed");
}
// Undeploy the module:
undeployModule(module);
}
catch (Exception e)
{
log.error("failed", e);
fail("Caught exception, message: " + e.getMessage());
}
}
private String createModule(String module, String template, HashMap props)
throws Exception
{
MBeanServerConnection server = getServer();
// create the module
module = (String) server
.invoke(deploymentService, "createModule", new Object[] { module,
template, props }, new String[] { "java.lang.String",
"java.lang.String", "java.util.HashMap" });
log.info("Module '" + module + "' created: " + module);
return module;
}
private boolean removeModule(String module) throws Exception
{
MBeanServerConnection server = getServer();
// remove the module, in case it exists
Boolean removed = (Boolean) server.invoke(deploymentService,
"removeModule", new Object[] { module },
new String[] { "java.lang.String" });
log.info("Module '" + module + "' removed: " + removed);
return removed.booleanValue();
}
private boolean deployModule(String module) throws Exception
{
MBeanServerConnection server = getServer();
// Deploy the module (move to ./deploy)
server.invoke(deploymentService, "deployModuleAsynch",
new Object[] { module }, new String[] { "java.lang.String" });
return verifyDeploy(server, module);
}
private boolean undeployModule(String module) throws Exception
{
MBeanServerConnection server = getServer();
try
{
// Get the deployed URL
URL deployedURL = (URL) server.invoke(deploymentService,
"getDeployedURL", new Object[] { module },
new String[] { "java.lang.String" });
// Undeploy the module (move to ./undeploy)
server.invoke(deploymentService, "undeployModuleAsynch",
new Object[] { module }, new String[] { "java.lang.String" });
// Ask the MainDeployer every 3 secs, 5 times (15secs max wait) if
// the module was undeployed
Boolean isDeployed = new Boolean(false);
for (int tries = 0; tries < 5; tries++)
{
// sleep for 3 secs
Thread.sleep(3000);
isDeployed = (Boolean) server
.invoke(mainDeployer, "isDeployed",
new Object[] { deployedURL },
new String[] { "java.net.URL" });
if (!isDeployed.booleanValue())
{
break;
}
}
log.info("Module '" + module + "' deployed: " + isDeployed);
return isDeployed.booleanValue();
}
catch (Exception e)
{
// the module does not exist
log.info("Ignoring caught exception, message: " + e.getMessage());
return false;
}
}
/**
* Proxy method that makes the deployment service call to update an mbean.
*
* @param data
* The data used to update the mbean
* @return True if the mbean was updated, false otherwise.
* @throws Exception
* Bad things happened.
*/
private boolean updateMBean(MBeanData data) throws Exception
{
MBeanServerConnection server = getServer();
log.info("Updating MBean '" + data + "'");
// create the module
boolean result = false;
result = ((Boolean) server.invoke(deploymentService, "updateMBean",
new Object[] { data },
new String[] { "org.jboss.services.deployment.MBeanData" }))
.booleanValue();
log.info("MBean '" + data + "' update result: " + result);
return result;
}
/**
* Verifies that the mbean was updated successfully by comparing the values
* of all of the attributes.
*
* @param data
* The mbean data that was set.
* @param nestedAttr
* If any of the mbean attribuets were nested xml data, set this to
* the name of said attribute. If not, set to null.
*/
private void verifyMBean(MBeanData data, String nestedAttr)
{
try
{
// Wait for the changes to be deployed (assume 5 second scan delay):
log.info("Wait 10 seconds for changes to deploy");
Thread.sleep(10000);
// Compare all of the changed attribute values to the actual values.
// They must all match for the test to pass.
InitialContext ic = new InitialContext();
RMIAdaptor server = (RMIAdaptor) ic.lookup("jmx/invoker/RMIAdaptor");
ObjectName objectName = new ObjectName(data.getName());
Properties attrs = data.getAttributes();
Enumeration keys = attrs.keys();
log.info("Verifying MBean attribute values:");
while (keys.hasMoreElements())
{
String attr = (String) keys.nextElement();
String expected = (String) attrs.get(attr);
Object obj = server.getAttribute(objectName, attr);
String actual = obj.toString();
log.info("-- attribute = " + attr);
log.info(" expect value = " + expected);
log.info(" actual value = " + actual);
log.info(" actual type = " + obj.getClass().getName());
// Note that the value for the nested attribute is not returned
// as expected, so we will not verify that it is correct:
if (!actual.equals(expected) && nestedAttr != null
&& !attr.equals(nestedAttr))
{
String msg = "Attribute '" + attr + "' has actual value '"
+ actual + "', expected value " + expected + "'";
log.error(msg);
fail(msg);
}
}
log.info("passed");
}
catch (Exception e)
{
log.error(e);
fail("Unexpected error: " + e.getMessage());
}
}
/**
* Calls the deployment service to update the data source.
*/
private boolean updateDataSource(String module, String template,
HashMap props) throws Exception
{
log.info("updateDataSource('" + module + "', '" + template + "', "
+ props);
MBeanServerConnection server = getServer();
// update the data source
module = (String) server
.invoke(deploymentService, "updateDataSource", new Object[] {
module, template, props }, new String[] { "java.lang.String",
"java.lang.String", "java.util.HashMap" });
// sleep for 3 secs to allow the old datasource to be undeployed first
// before we verify deployment
Thread.sleep(3000);
return verifyDeploy(server, module);
}
/**
* Calls the deployment service to remove the data source.
*/
private boolean removeDataSource(String module, String template,
HashMap props) throws Exception
{
log.info("removeDataSource('" + module + "', '" + template + "', "
+ props);
MBeanServerConnection server = getServer();
// remove the data source
module = (String) server
.invoke(deploymentService, "removeDataSource", new Object[] {
module, template, props }, new String[] { "java.lang.String",
"java.lang.String", "java.util.HashMap" });
// sleep for 3 secs to allow the datasource to be undeployed first
// before we verify deployment
Thread.sleep(3000);
return verifyDeploy(server, module);
}
/**
* Try to connect to the specified data source. Try the connection every 3
* seconds, maximum 5 times.
*/
private boolean connectToDataSource(String jndiName) throws Exception
{
boolean connected = false;
InitialContext ic = new InitialContext();
DataSource ds = null;
Connection connection = null;
// See if we can get a connection
for (int tries = 0; tries < 5; tries++)
{
try
{
ds = (DataSource) ic.lookup(jndiName);
connection = ds.getConnection();
connection.close();
connected = true;
log.info("Connected to data source: " + jndiName);
break;
}
catch (Exception e)
{
log.info("Unable to connect to data source: " + jndiName
+ ". Try again");
// Sleep for 3 secs then try again
Thread.sleep(3000);
}
}
return connected;
}
/**
* Verifies that a given module is acutally deployed. Waits for a while,
* checking every few seconds, to see if the module has deployed yet.
*
* @param server
* User to invoke methods on the dpeloyment service.
* @param module
* The name of the module (must include the suffix).
* @return
*/
private boolean verifyDeploy(MBeanServerConnection server, String module)
throws Exception
{
// Get the deployed URL
URL deployedURL = (URL) server.invoke(deploymentService,
"getDeployedURL", new Object[] { module },
new String[] { "java.lang.String" });
// Ask the MainDeployer every 3 secs, 5 times (15secs max wait) if the
// module was deployed
Boolean isDeployed = new Boolean(false);
for (int tries = 0; tries < 5; tries++)
{
// sleep for 3 secs
Thread.sleep(3000);
isDeployed = (Boolean) server.invoke(mainDeployer, "isDeployed",
new Object[] { deployedURL }, new String[] { "java.net.URL" });
if (isDeployed.booleanValue())
{
break;
}
}
log.info("Module '" + module + "' deployed: " + isDeployed);
return isDeployed.booleanValue();
}
}