[rhq] Branch 'rhq-on-as7' - .classpath modules/enterprise

mazz mazz at fedoraproject.org
Tue Aug 7 06:54:13 UTC 2012


 .classpath                                                                                                                  |    1 
 modules/enterprise/gui/installer/pom.xml                                                                                    |    8 
 modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClient.java        |  232 +++++++++
 modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/JBossASClient.java                  |   17 
 modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java    |    3 
 modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/client/gwt/InstallerGWTService.java         |    9 
 modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java |  165 +++---
 modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java       |  238 ++++++++++
 modules/enterprise/gui/installer/src/test/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClientTest.java    |  112 ++++
 9 files changed, 712 insertions(+), 73 deletions(-)

New commits:
commit c0241073ca53f3444a727037d376f33536252359
Author: John Mazzitelli <mazz at redhat.com>
Date:   Tue Aug 7 02:54:10 2012 -0400

    installer now completely deploys datasources and everything they need (security domain, and child connection properties)

diff --git a/.classpath b/.classpath
index 44bf71a..e67c6a5 100644
--- a/.classpath
+++ b/.classpath
@@ -50,6 +50,7 @@
 	<classpathentry kind="src" path="modules/enterprise/gui/portal-war/src/test/java"/>
 	<classpathentry kind="src" path="modules/enterprise/gui/installer-war/src/main/java"/>
 	<classpathentry kind="src" path="modules/enterprise/gui/installer/src/main/java"/>
+	<classpathentry kind="src" path="modules/enterprise/gui/installer/src/test/java"/>
 	<classpathentry kind="src" path="modules/enterprise/gui/installer/target/generated-sources/gwt"/>
 	<classpathentry kind="src" path="modules/enterprise/gui/base-perspective-jar/src/main/java"/>
 	<classpathentry kind="src" path="modules/enterprise/gui/content_http-war/src/main/java"/>
diff --git a/modules/enterprise/gui/installer/pom.xml b/modules/enterprise/gui/installer/pom.xml
index 131e893..a48d2b9 100644
--- a/modules/enterprise/gui/installer/pom.xml
+++ b/modules/enterprise/gui/installer/pom.xml
@@ -160,6 +160,14 @@
             <scope>provided</scope> <!-- provided by AS7 -->
         </dependency>
 
+        <!-- test deps -->
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>1.9.0</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClient.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClient.java
index fb3135c..5831b38 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClient.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClient.java
@@ -18,7 +18,11 @@
  */
 package org.rhq.common.jbossas.client.controller;
 
+import java.util.List;
+import java.util.Map;
+
 import org.jboss.as.controller.client.ModelControllerClient;
+import org.jboss.dmr.ModelNode;
 
 /**
  * Provides convienence methods associated with datasource management.
@@ -27,8 +31,236 @@ import org.jboss.as.controller.client.ModelControllerClient;
  */
 public class DatasourceJBossASClient extends JBossASClient {
 
+    public static final String SUBSYSTEM_DATASOURCES = "datasources";
+    public static final String DATA_SOURCE = "data-source";
+    public static final String XA_DATA_SOURCE = "xa-data-source";
+    public static final String JDBC_DRIVER = "jdbc-driver";
+    public static final String CONNECTION_PROPERTIES = "connection-properties";
+    public static final String XA_DATASOURCE_PROPERTIES = "xa-datasource-properties";
+
     public DatasourceJBossASClient(ModelControllerClient client) {
         super(client);
     }
 
+    /**
+     * Checks to see if there is already a JDBC driver with the given name.
+     *
+     * @param jdbcDriverName the name to check
+     * @return true if there is a JDBC driver with the given name already in existence
+     */
+    public boolean isJDBCDriver(String jdbcDriverName) throws Exception {
+        Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES);
+        ModelNode queryNode = createRequest(READ_RESOURCE, addr);
+        ModelNode results = execute(queryNode);
+        if (isSuccess(results)) {
+            ModelNode drivers = getResults(results).get(JDBC_DRIVER);
+            List<ModelNode> list = drivers.asList();
+            for (ModelNode driver : list) {
+                if (driver.has(jdbcDriverName)) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            throw new FailureException(results, "Failed to get JDBC drivers");
+        }
+    }
+
+    /**
+     * Returns a ModelNode that can be used to create a JDBC driver configuration for use by datasources.
+     * Callers are free to tweek the JDBC driver request that is returned,
+     * if they so choose, before asking the client to execute the request.
+     *
+     * NOTE: the JDBC module must have already been installed in the JBossAS's modules/ location.
+     *
+     * @param name the name of the JDBC driver (this is not the name of the JDBC jar or the module name, it is
+     *             just a convienence name of the JDBC driver configuration).
+     * @param moduleName the name of the JBossAS module where the JDBC driver is installed
+     * @param driverXaClassName the JDBC driver's XA datasource classname
+     *
+     * @return the request to create the JDBC driver configuration.
+     */
+    public ModelNode createNewJdbcDriverRequest(String name, String moduleName, String driverXaClassName) {
+        String dmrTemplate = "" //
+            + "{" //
+            + "\"driver-module-name\" => \"%s\" " //
+            + ", \"driver-xa-datasource-class-name\" => \"%s\" " //
+            + "}";
+
+        String dmr = String.format(dmrTemplate, moduleName, driverXaClassName);
+
+        Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES, JDBC_DRIVER, name);
+        final ModelNode request = ModelNode.fromString(dmr);
+        request.get(OPERATION).set(ADD);
+        request.get(ADDRESS).set(addr.getAddressNode());
+
+        return request;
+    }
+
+    /**
+     * Returns a ModelNode that can be used to create a datasource.
+     * Callers are free to tweek the datasource request that is returned,
+     * if they so choose, before asking the client to execute the request.
+     *
+     * @param name
+     * @param blockingTimeoutWaitMillis
+     * @param connectionUrlExpression
+     * @param driverName
+     * @param exceptionSorterClassName
+     * @param idleTimeoutMinutes
+     * @param jta true if this DS should support transactions; false if not
+     * @param minPoolSize
+     * @param maxPoolSize
+     * @param preparedStatementCacheSize
+     * @param securityDomain
+     * @param staleConnectionCheckerClassName
+     * @param transactionIsolation
+     * @param validConnectionCheckerClassName
+     * @param connectionProperties
+     *
+     * @return the request that can be used to create the datasource
+     */
+    public ModelNode createNewDatasourceRequest(String name, int blockingTimeoutWaitMillis,
+        String connectionUrlExpression, String driverName, String exceptionSorterClassName, int idleTimeoutMinutes,
+        boolean jta, int minPoolSize, int maxPoolSize, int preparedStatementCacheSize, String securityDomain,
+        String staleConnectionCheckerClassName, String transactionIsolation, String validConnectionCheckerClassName,
+        Map<String, String> connectionProperties) {
+
+        String jndiName = "java:jboss/datasources/" + name;
+
+        String dmrTemplate = "" //
+            + "{" //
+            + "\"blocking-timeout-wait-millis\" => %dL " //
+            + ", \"connection-url\" => expression \"%s\" " //
+            + ", \"driver-name\" => \"%s\" " //
+            + ", \"exception-sorter-class-name\" => \"%s\" " //
+            + ", \"idle-timeout-minutes\" => %dL " //
+            + ", \"jndi-name\" => \"%s\" " //
+            + ", \"jta\" => %s " //
+            + ", \"min-pool-size\" => %d " //
+            + ", \"max-pool-size\" => %d " //
+            + ", \"prepared-statements-cache-size\" => %dL " //
+            + ", \"security-domain\" => \"%s\" " //
+            + ", \"stale-connection-checker-class-name\" => \"%s\" " //
+            + ", \"transaction-isolation\" => \"%s\" " //
+            + ", \"use-java-context\" => true " //
+            + ", \"valid-connection-checker-class-name\" => \"%s\" " //
+            + "}";
+
+        String dmr = String.format(dmrTemplate, blockingTimeoutWaitMillis, connectionUrlExpression, driverName,
+            exceptionSorterClassName, idleTimeoutMinutes, jndiName, jta, minPoolSize, maxPoolSize,
+            preparedStatementCacheSize, securityDomain, staleConnectionCheckerClassName, transactionIsolation,
+            validConnectionCheckerClassName);
+
+        Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES, DATA_SOURCE, name);
+        final ModelNode request1 = ModelNode.fromString(dmr);
+        request1.get(OPERATION).set(ADD);
+        request1.get(ADDRESS).set(addr.getAddressNode());
+
+        // if there are no conn properties, no need to create a batch request, there is only one ADD request to make
+        if (connectionProperties == null || connectionProperties.size() == 0) {
+            return request1;
+        }
+
+        // create a batch of requests - the first is the main one, the rest create each conn property
+        ModelNode[] batch = new ModelNode[1 + connectionProperties.size()];
+        batch[0] = request1;
+        int n = 1;
+        for (Map.Entry<String, String> entry : connectionProperties.entrySet()) {
+            addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES, DATA_SOURCE, name, CONNECTION_PROPERTIES,
+                entry.getKey());
+            final ModelNode requestN = new ModelNode();
+            requestN.get(OPERATION).set(ADD);
+            requestN.get(ADDRESS).set(addr.getAddressNode());
+            if (entry.getValue().indexOf("${") > -1) {
+                requestN.get(VALUE).setExpression(entry.getValue());
+            } else {
+                requestN.get(VALUE).set(entry.getValue());
+            }
+            batch[n++] = requestN;
+        }
+
+        return createBatchRequest(batch);
+    }
+
+    /**
+     * Returns a ModelNode that can be used to create an XA datasource.
+     * Callers are free to tweek the datasource request that is returned,
+     * if they so choose, before asking the client to execute the request.
+     *
+     * @param name
+     * @param blockingTimeoutWaitMillis
+     * @param driverName
+     * @param exceptionSorterClassName
+     * @param idleTimeoutMinutes
+     * @param minPoolSize
+     * @param maxPoolSize
+     * @param preparedStatementCacheSize
+     * @param securityDomain
+     * @param staleConnectionCheckerClassName
+     * @param transactionIsolation
+     * @param validConnectionCheckerClassName
+     * @param xaDatasourceProperties
+     *
+     * @return the request that can be used to create the XA datasource
+     */
+    public ModelNode createNewXADatasourceRequest(String name, int blockingTimeoutWaitMillis, String driverName,
+        String exceptionSorterClassName, int idleTimeoutMinutes, int minPoolSize, int maxPoolSize,
+        int preparedStatementCacheSize, String securityDomain, String staleConnectionCheckerClassName,
+        String transactionIsolation, String validConnectionCheckerClassName, Map<String, String> xaDatasourceProperties) {
+
+        String jndiName = "java:jboss/datasources/" + name;
+
+        String dmrTemplate = "" //
+            + "{" //
+            + "\"blocking-timeout-wait-millis\" => %dL " //
+            + ", \"driver-name\" => \"%s\" " //
+            + ", \"exception-sorter-class-name\" => \"%s\" " //
+            + ", \"idle-timeout-minutes\" => %dL " //
+            + ", \"jndi-name\" => \"%s\" " //
+            + ", \"jta\" => true " //
+            + ", \"min-pool-size\" => %d " //
+            + ", \"max-pool-size\" => %d " //
+            + ", \"prepared-statements-cache-size\" => %dL " //
+            + ", \"security-domain\" => \"%s\" " //
+            + ", \"stale-connection-checker-class-name\" => \"%s\" " //
+            + ", \"transaction-isolation\" => \"%s\" " //
+            + ", \"use-java-context\" => true " //
+            + ", \"valid-connection-checker-class-name\" => \"%s\" " //
+            + "}";
+
+        String dmr = String.format(dmrTemplate, blockingTimeoutWaitMillis, driverName, exceptionSorterClassName,
+            idleTimeoutMinutes, jndiName, minPoolSize, maxPoolSize, preparedStatementCacheSize, securityDomain,
+            staleConnectionCheckerClassName, transactionIsolation, validConnectionCheckerClassName);
+
+        Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES, XA_DATA_SOURCE, name);
+        final ModelNode request1 = ModelNode.fromString(dmr);
+        request1.get(OPERATION).set(ADD);
+        request1.get(ADDRESS).set(addr.getAddressNode());
+
+        // if there are no xa datasource properties, no need to create a batch request, there is only one ADD request to make
+        if (xaDatasourceProperties == null || xaDatasourceProperties.size() == 0) {
+            return request1;
+        }
+
+        // create a batch of requests - the first is the main one, the rest create each conn property
+        ModelNode[] batch = new ModelNode[1 + xaDatasourceProperties.size()];
+        batch[0] = request1;
+        int n = 1;
+        for (Map.Entry<String, String> entry : xaDatasourceProperties.entrySet()) {
+            addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_DATASOURCES, XA_DATA_SOURCE, name, XA_DATASOURCE_PROPERTIES,
+                entry.getKey());
+            final ModelNode requestN = new ModelNode();
+            requestN.get(OPERATION).set(ADD);
+            requestN.get(ADDRESS).set(addr.getAddressNode());
+            if (entry.getValue().indexOf("${") > -1) {
+                requestN.get(VALUE).setExpression(entry.getValue());
+            } else {
+                requestN.get(VALUE).set(entry.getValue());
+            }
+            batch[n++] = requestN;
+        }
+
+        return createBatchRequest(batch);
+    }
 }
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/JBossASClient.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/JBossASClient.java
index c8d040c..576e2d6 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/JBossASClient.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/JBossASClient.java
@@ -54,6 +54,7 @@ public class JBossASClient {
     public static final String READ_RESOURCE = "read-resource";
     public static final String WRITE_ATTRIBUTE = "write-attribute";
     public static final String ADD = "add";
+    public static final String SYSTEM_PROPERTY = "system-property";
 
     private ModelControllerClient client;
 
@@ -301,4 +302,20 @@ public class JBossASClient {
                 + "]");
         }
     }
+
+    /**
+     * Can set a runtime system property in the JVM.
+     *
+     * @param name
+     * @param value
+     * @throws Exception
+     */
+    public void setSystemProperty(String name, String value) throws Exception {
+        ModelNode request = createRequest(ADD, Address.root().add(SYSTEM_PROPERTY, name));
+        request.get(VALUE).set(value);
+        ModelNode response = execute(request);
+        if (!isSuccess(response)) {
+            throw new FailureException(response, "Failed to set system property [" + name + "]");
+        }
+    }
 }
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
index a73ba79..6f0589f 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
@@ -95,6 +95,9 @@ public class SecurityDomainJBossASClient extends JBossASClient {
         loginModule.get(FLAG).set("required");
         ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
         moduleOptions.setEmptyList();
+        // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
+        // for username and password so rhq-server.properties can be used to set these.
+        // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
         moduleOptions.add(USERNAME, username);
         moduleOptions.add(PASSWORD, password);
         loginModulesNode.add(loginModule);
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/client/gwt/InstallerGWTService.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/client/gwt/InstallerGWTService.java
index 97e776e..b640b61 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/client/gwt/InstallerGWTService.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/client/gwt/InstallerGWTService.java
@@ -102,6 +102,15 @@ public interface InstallerGWTService extends RemoteService {
     HashMap<String, String> getServerProperties() throws Exception;
 
     /**
+     * Allows the installer to set runtime system properties in the JBossAS app server container.
+     *
+     * @param name the name of the sysprop to set
+     * @param value the value of the sysprop to set
+     * @throws Exception
+     */
+    void setSystemProperty(String name, String value) throws Exception;
+
+    /**
      * Returns the version string for the app server itself (e.g. "7.1.2.Final").
      * @return version string of app server
      * @throws Exception
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
index fcc8a51..afd5a3f 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/InstallerGWTServiceImpl.java
@@ -35,7 +35,6 @@ import org.jboss.as.controller.client.ModelControllerClient;
 
 import org.rhq.common.jbossas.client.controller.Address;
 import org.rhq.common.jbossas.client.controller.JBossASClient;
-import org.rhq.common.jbossas.client.controller.SecurityDomainJBossASClient;
 import org.rhq.core.db.DatabaseTypeFactory;
 import org.rhq.core.util.PropertiesFileUpdate;
 import org.rhq.core.util.exception.ThrowableUtil;
@@ -44,6 +43,7 @@ import org.rhq.enterprise.gui.installer.client.shared.ServerDetails;
 import org.rhq.enterprise.gui.installer.client.shared.ServerProperties;
 import org.rhq.enterprise.gui.installer.server.service.ManagementService;
 import org.rhq.enterprise.gui.installer.server.servlet.ServerInstallUtil.ExistingSchemaOption;
+import org.rhq.enterprise.gui.installer.server.servlet.ServerInstallUtil.SupportedDatabaseType;
 
 /**
  * Remote RPC API implementation for the GWT Installer.
@@ -55,21 +55,21 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
 
     private static final long serialVersionUID = 1L;
 
-    private static final String RHQ_SECURITY_DOMAIN = "RHQDSSecurityDomain";
-
     @Override
-    public void install(HashMap<String, String> serverProperties, ServerDetails serverDetails, String existingSchemaOption) throws Exception {
+    public void install(HashMap<String, String> serverProperties, ServerDetails serverDetails,
+        String existingSchemaOption) throws Exception {
+
         // make sure the data is at least in the correct format (booleans are true/false, integers are valid numbers)
-        StringBuilder dataErrors = new StringBuilder();
+        final StringBuilder dataErrors = new StringBuilder();
         for (Map.Entry<String, String> entry : serverProperties.entrySet()) {
-            String name = entry.getKey();
+            final String name = entry.getKey();
             if (ServerProperties.BOOLEAN_PROPERTIES.contains(name)) {
-                String newValue = entry.getValue();
+                final String newValue = entry.getValue();
                 if (!(newValue.equals("true") || newValue.equals("false"))) {
                     dataErrors.append("[" + name + "] must be 'true' or 'false' : [" + newValue + "]\n");
                 }
             } else if (ServerProperties.INTEGER_PROPERTIES.contains(name)) {
-                String newValue = entry.getValue();
+                final String newValue = entry.getValue();
                 try {
                     Integer.parseInt(newValue);
                 } catch (NumberFormatException e) {
@@ -87,7 +87,7 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
 
         // if we are in auto-install mode, ignore the server details passed in and build our own using the given server properties
         // if not in auto-install mode, make sure user gave us the server details that we will need
-        boolean autoInstallMode = ServerInstallUtil.isAutoinstallEnabled(serverProperties);
+        final boolean autoInstallMode = ServerInstallUtil.isAutoinstallEnabled(serverProperties);
         if (autoInstallMode) {
             serverDetails = getServerDetailsFromPropertiesOnly(serverProperties);
         } else {
@@ -107,35 +107,33 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         DatabaseTypeFactory.clearDatabaseTypeCache();
 
         // determine the type of database to connect to
-        String databaseType = serverProperties.get(ServerProperties.PROP_DATABASE_TYPE);
+        final String databaseType = serverProperties.get(ServerProperties.PROP_DATABASE_TYPE);
         if (ServerInstallUtil.isEmpty(databaseType)) {
             throw new Exception("Please indicate the type of database to connect to");
         }
 
-        boolean isPostgres = databaseType.toLowerCase().indexOf("postgres") > -1;
-        boolean isOracle = databaseType.toLowerCase().indexOf("oracle") > -1;
-
-        if (isPostgres == false && isOracle == false) {
+        SupportedDatabaseType supportedDbType = ServerInstallUtil.getSupportedDatabaseType(databaseType);
+        if (supportedDbType == null) {
             throw new IllegalArgumentException("Invalid database type: " + databaseType);
         }
 
         // parse the database connection URL to extract the servername/port/dbname; this is needed for the XA datasource
         try {
-            String url = serverProperties.get(ServerProperties.PROP_DATABASE_CONNECTION_URL);
+            final String url = serverProperties.get(ServerProperties.PROP_DATABASE_CONNECTION_URL);
             Pattern pattern = null;
-            if (isPostgres) {
+            if (supportedDbType == SupportedDatabaseType.POSTGRES) {
                 pattern = Pattern.compile(".*://(.*):([0123456789]+)/(.*)"); // jdbc:postgresql://host.name:5432/rhq
-            } else if (isOracle) {
+            } else if (supportedDbType == SupportedDatabaseType.ORACLE) {
                 // if we ever find that we'll need these props set, uncomment below and it should all work
                 //pattern = Pattern.compile(".*@(.*):([0123456789]+)[:/](.*)"); // jdbc:oracle:thin:@host.name:1521:rhq (or /rhq)
             }
 
             if (pattern != null) {
-                Matcher match = pattern.matcher(url);
+                final Matcher match = pattern.matcher(url);
                 if (match.find() && (match.groupCount() == 3)) {
-                    String serverName = match.group(1);
-                    String port = match.group(2);
-                    String dbName = match.group(3);
+                    final String serverName = match.group(1);
+                    final String port = match.group(2);
+                    final String dbName = match.group(3);
                     serverProperties.put(ServerProperties.PROP_DATABASE_SERVER_NAME, serverName);
                     serverProperties.put(ServerProperties.PROP_DATABASE_PORT, port);
                     serverProperties.put(ServerProperties.PROP_DATABASE_DB_NAME, dbName);
@@ -158,10 +156,10 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
             String quartzSelectWithLockSQL = "SELECT * FROM {0}LOCKS ROWLOCK WHERE LOCK_NAME = ? FOR UPDATE";
             String quartzLockHandlerClass = "org.quartz.impl.jdbcjobstore.StdRowLockSemaphore";
 
-            if (isPostgres) {
+            if (supportedDbType == SupportedDatabaseType.POSTGRES) {
                 dialect = "org.hibernate.dialect.PostgreSQLDialect";
                 quartzDriverDelegateClass = "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate";
-            } else if (isOracle) {
+            } else if (supportedDbType == SupportedDatabaseType.ORACLE) {
                 dialect = "org.hibernate.dialect.Oracle10gDialect";
                 quartzDriverDelegateClass = "org.quartz.impl.jdbcjobstore.oracle.OracleDelegate";
             }
@@ -178,16 +176,19 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         // test the connection to make sure everything is OK - note that if we are in auto-install mode,
         // the password will have been obfuscated, so we need to de-obfucate it in order to use it.
         // make sure the server properties map itself has an obfuscated password
-        String dbUrl = serverProperties.get(ServerProperties.PROP_DATABASE_CONNECTION_URL);
-        String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
-        String dbPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+        final String dbUrl = serverProperties.get(ServerProperties.PROP_DATABASE_CONNECTION_URL);
+        final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
+        String clearTextDbPassword;
+        String obfuscatedDbPassword;
         if (autoInstallMode) {
-            dbPassword = ServerInstallUtil.deobfuscatePassword(dbPassword);
+            obfuscatedDbPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+            clearTextDbPassword = ServerInstallUtil.deobfuscatePassword(obfuscatedDbPassword);
         } else {
-            serverProperties.put(ServerProperties.PROP_DATABASE_PASSWORD,
-                ServerInstallUtil.obfuscatePassword(dbPassword));
+            clearTextDbPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+            obfuscatedDbPassword = ServerInstallUtil.obfuscatePassword(clearTextDbPassword);
+            serverProperties.put(ServerProperties.PROP_DATABASE_PASSWORD, obfuscatedDbPassword);
         }
-        String testConnectionErrorMessage = testConnection(dbUrl, dbUsername, dbPassword);
+        final String testConnectionErrorMessage = testConnection(dbUrl, dbUsername, clearTextDbPassword);
         if (testConnectionErrorMessage != null) {
             throw new Exception("Cannot connect to the database: " + testConnectionErrorMessage);
         }
@@ -200,7 +201,7 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         // If in auto-install mode, we can be told to overwrite, skip or auto (meaning "keep" if schema exists)
         ServerInstallUtil.ExistingSchemaOption existingSchemaOptionEnum;
         if (autoInstallMode) {
-            String s = serverProperties.get(ServerProperties.PROP_AUTOINSTALL_DATABASE);
+            final String s = serverProperties.get(ServerProperties.PROP_AUTOINSTALL_DATABASE);
             if (s == null || s.equalsIgnoreCase("auto")) {
                 existingSchemaOptionEnum = ServerInstallUtil.ExistingSchemaOption.KEEP;
             } else {
@@ -214,26 +215,30 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         }
 
         if (ServerInstallUtil.ExistingSchemaOption.SKIP != existingSchemaOptionEnum) {
-            if (isDatabaseSchemaExist(dbUrl, dbUsername, dbPassword)) {
+            if (isDatabaseSchemaExist(dbUrl, dbUsername, clearTextDbPassword)) {
                 if (ExistingSchemaOption.OVERWRITE == existingSchemaOptionEnum) {
-                    ServerInstallUtil.createNewDatabaseSchema(serverProperties, serverDetails, dbPassword, getLogDir());
-                } else {
-                    ServerInstallUtil.upgradeExistingDatabaseSchema(serverProperties, serverDetails, dbPassword,
+                    ServerInstallUtil.createNewDatabaseSchema(serverProperties, serverDetails, clearTextDbPassword,
                         getLogDir());
+                } else {
+                    ServerInstallUtil.upgradeExistingDatabaseSchema(serverProperties, serverDetails,
+                        clearTextDbPassword, getLogDir());
                 }
             } else {
-                ServerInstallUtil.createNewDatabaseSchema(serverProperties, serverDetails, dbPassword, getLogDir());
+                ServerInstallUtil.createNewDatabaseSchema(serverProperties, serverDetails, clearTextDbPassword,
+                    getLogDir());
             }
         }
 
         // ensure the server info is up to date and stored in the DB
-        ServerInstallUtil.storeServerDetails(serverProperties, dbPassword, serverDetails);
+        ServerInstallUtil.storeServerDetails(serverProperties, clearTextDbPassword, serverDetails);
 
         // create a keystore whose cert has a CN of this server's public endpoint address
         ServerInstallUtil.createKeystore(serverDetails, getAppServerConfigDir());
 
         // now create our deployment services and our main EAR
-        // TODO: finish this
+        deployServices(serverProperties);
+
+        // TODO: deploy the EAR
         return;
     }
 
@@ -251,7 +256,7 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
     public ServerDetails getServerDetails(String connectionUrl, String username, String password, String serverName)
         throws Exception {
         try {
-            ServerDetails sd = ServerInstallUtil.getServerDetails(connectionUrl, username, password, serverName);
+            final ServerDetails sd = ServerInstallUtil.getServerDetails(connectionUrl, username, password, serverName);
             if (ServerInstallUtil.isEmpty(sd.getName())) {
                 try {
                     sd.setEndpointAddress(InetAddress.getLocalHost().getCanonicalHostName());
@@ -285,18 +290,18 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
 
     @Override
     public String testConnection(String connectionUrl, String username, String password) throws Exception {
-        String results = ServerInstallUtil.testConnection(connectionUrl, username, password);
+        final String results = ServerInstallUtil.testConnection(connectionUrl, username, password);
         return results;
     }
 
     @Override
     public HashMap<String, String> getServerProperties() throws Exception {
-        File serverPropertiesFile = getServerPropertiesFile();
-        PropertiesFileUpdate propsFile = new PropertiesFileUpdate(serverPropertiesFile.getAbsolutePath());
-        Properties props = propsFile.loadExistingProperties();
+        final File serverPropertiesFile = getServerPropertiesFile();
+        final PropertiesFileUpdate propsFile = new PropertiesFileUpdate(serverPropertiesFile.getAbsolutePath());
+        final Properties props = propsFile.loadExistingProperties();
 
         // force some hardcoded defaults for IBM JVMs that must have specific values
-        boolean isIBM = System.getProperty("java.vendor", "").contains("IBM");
+        final boolean isIBM = System.getProperty("java.vendor", "").contains("IBM");
         if (isIBM) {
             for (String algPropName : ServerProperties.IBM_ALGOROTHM_SETTINGS) {
                 props.setProperty(algPropName, "IbmX509");
@@ -304,13 +309,22 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         }
 
         // GWT can't handle Properties - convert to HashMap
-        HashMap<String, String> map = new HashMap<String, String>(props.size());
+        final HashMap<String, String> map = new HashMap<String, String>(props.size());
         for (Object property : props.keySet()) {
             map.put(property.toString(), props.getProperty(property.toString()));
         }
         return map;
     }
 
+    @Override
+    public void setSystemProperty(String name, String value) throws Exception {
+        try {
+            new JBossASClient(getClient()).setSystemProperty(name, value);
+        } catch (Exception e) {
+            throw new Exception(ThrowableUtil.getAllMessages(e));
+        }
+    }
+
     /**
      * Save the given properties to the server's .properties file.
      *
@@ -322,11 +336,11 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
      * @throws Exception if failed to save the properties to the .properties file
      */
     private void saveServerProperties(HashMap<String, String> serverProperties) throws Exception {
-        File serverPropertiesFile = getServerPropertiesFile();
-        PropertiesFileUpdate propsFile = new PropertiesFileUpdate(serverPropertiesFile.getAbsolutePath());
+        final File serverPropertiesFile = getServerPropertiesFile();
+        final PropertiesFileUpdate propsFile = new PropertiesFileUpdate(serverPropertiesFile.getAbsolutePath());
 
         // GWT can't handle Properties - so we use HashMap but convert to Properties internally
-        Properties props = new Properties();
+        final Properties props = new Properties();
         for (Map.Entry<String, String> entry : serverProperties.entrySet()) {
             props.setProperty(entry.getKey(), entry.getValue());
         }
@@ -336,7 +350,7 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
         // we need to put them as system properties now so when we hot deploy,
         // the replacement variables in the config files pick up the new values
         for (Map.Entry<String, String> entry : serverProperties.entrySet()) {
-            System.setProperty(entry.getKey(), entry.getValue());
+            setSystemProperty(entry.getKey(), entry.getValue());
         }
 
         return;
@@ -344,43 +358,43 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
 
     @Override
     public String getAppServerVersion() throws Exception {
-        JBossASClient client = new JBossASClient(getClient());
-        String version = client.getStringAttribute("release-version", Address.root());
+        final JBossASClient client = new JBossASClient(getClient());
+        final String version = client.getStringAttribute("release-version", Address.root());
         return version;
     }
 
     @Override
     public String getOperatingSystem() throws Exception {
-        JBossASClient client = new JBossASClient(getClient());
-        String[] address = { "core-service", "platform-mbean", "type", "operating-system" };
-        String osName = client.getStringAttribute("name", Address.root().add(address));
+        final JBossASClient client = new JBossASClient(getClient());
+        final String[] address = { "core-service", "platform-mbean", "type", "operating-system" };
+        final String osName = client.getStringAttribute("name", Address.root().add(address));
         return osName;
     }
 
     private String getAppServerHomeDir() throws Exception {
-        JBossASClient client = new JBossASClient(getClient());
-        String[] address = { "core-service", "server-environment" };
-        String dir = client.getStringAttribute(true, "home-dir", Address.root().add(address));
+        final JBossASClient client = new JBossASClient(getClient());
+        final String[] address = { "core-service", "server-environment" };
+        final String dir = client.getStringAttribute(true, "home-dir", Address.root().add(address));
         return dir;
     }
 
     private String getAppServerConfigDir() throws Exception {
-        JBossASClient client = new JBossASClient(getClient());
-        String[] address = { "core-service", "server-environment" };
-        String dir = client.getStringAttribute(true, "config-dir", Address.root().add(address));
+        final JBossASClient client = new JBossASClient(getClient());
+        final String[] address = { "core-service", "server-environment" };
+        final String dir = client.getStringAttribute(true, "config-dir", Address.root().add(address));
         return dir;
     }
 
     private String getLogDir() throws Exception {
-        File asHomeDir = new File(getAppServerHomeDir());
-        File logDir = new File(asHomeDir, "../logs"); // this is RHQ's log dir, not JBossAS's log dir
+        final File asHomeDir = new File(getAppServerHomeDir());
+        final File logDir = new File(asHomeDir, "../logs"); // this is RHQ's log dir, not JBossAS's log dir
         logDir.mkdirs(); // create it in case it doesn't yet exist
         return logDir.getAbsolutePath();
     }
 
     private File getServerPropertiesFile() throws Exception {
-        File appServerHomeDir = new File(getAppServerHomeDir());
-        File serverPropertiesFile = new File(appServerHomeDir, "../bin/rhq-server.properties");
+        final File appServerHomeDir = new File(getAppServerHomeDir());
+        final File serverPropertiesFile = new File(appServerHomeDir, "../bin/rhq-server.properties");
         return serverPropertiesFile;
     }
 
@@ -470,18 +484,23 @@ public class InstallerGWTServiceImpl extends RemoteServiceServlet implements Ins
     }
 
     private ModelControllerClient getClient() {
-        ModelControllerClient client = ManagementService.getClient();
+        final ModelControllerClient client = ManagementService.getClient();
         return client;
     }
 
-    private void createDatasourceSecurityDomain(String username, String password) throws Exception {
-        final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(getClient());
-        final String securityDomain = RHQ_SECURITY_DOMAIN;
-        if (!client.isSecurityDomain(securityDomain)) {
-            client.createNewSecureIdentitySecurityDomainRequest(securityDomain, username, password);
-            log("Security domain [" + securityDomain + "] created");
-        } else {
-            log("Security domain [" + securityDomain + "] already exists, skipping the creation request");
+    private void deployServices(HashMap<String, String> serverProperties) throws Exception {
+        try {
+            // create the security domain needed by the datasources
+            ServerInstallUtil.createDatasourceSecurityDomain(getClient(), serverProperties);
+
+            // create the JDBC driver configurations for use by datasources
+            ServerInstallUtil.createNewJdbcDrivers(getClient(), serverProperties);
+
+            // create the datasources
+            ServerInstallUtil.createNewDatasources(getClient(), serverProperties);
+        } catch (Exception e) {
+            log("deployServices failed", e);
+            throw new Exception("Failed to deploy services: " + ThrowableUtil.getAllMessages(e));
         }
     }
 }
diff --git a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
index 15ed1a7..b4c8bef 100644
--- a/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
+++ b/modules/enterprise/gui/installer/src/main/java/org/rhq/enterprise/gui/installer/server/servlet/ServerInstallUtil.java
@@ -42,6 +42,13 @@ import org.apache.commons.logging.LogFactory;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.helper.ProjectHelper2;
 
+import org.jboss.as.controller.client.ModelControllerClient;
+import org.jboss.dmr.ModelNode;
+
+import org.rhq.common.jbossas.client.controller.DatasourceJBossASClient;
+import org.rhq.common.jbossas.client.controller.FailureException;
+import org.rhq.common.jbossas.client.controller.JBossASClient;
+import org.rhq.common.jbossas.client.controller.SecurityDomainJBossASClient;
 import org.rhq.core.db.DatabaseType;
 import org.rhq.core.db.DatabaseTypeFactory;
 import org.rhq.core.db.DbUtil;
@@ -66,6 +73,236 @@ public class ServerInstallUtil {
         OVERWRITE, KEEP, SKIP
     };
 
+    public enum SupportedDatabaseType {
+        POSTGRES, ORACLE
+    };
+
+    private static final String RHQ_DATASOURCE_NAME_NOTX = "NoTxRHQDS";
+    private static final String RHQ_DATASOURCE_NAME_XA = "RHQDS";
+    private static final String RHQ_SECURITY_DOMAIN = "RHQDSSecurityDomain";
+    private static final String JDBC_DRIVER_POSTGRES = "postgres";
+    private static final String JDBC_DRIVER_ORACLE = "oracle";
+
+    /**
+     * Give the server properties, this returns the type of database that will be connected to.
+     * 
+     * @param serverProperties
+     * @return the type of DB
+     */
+    public static SupportedDatabaseType getSupportedDatabaseType(HashMap<String, String> serverProperties) {
+        return getSupportedDatabaseType(serverProperties.get(ServerProperties.PROP_DATABASE_TYPE));
+    }
+
+    /**
+     * Give the database type string, this returns the type of database that it refers to.
+     * 
+     * @param dbType the database type string
+     * @return the type of DB
+     */
+    public static SupportedDatabaseType getSupportedDatabaseType(String dbType) {
+        if (dbType == null) {
+            return null;
+        }
+        if (dbType.toLowerCase().indexOf("postgres") > -1) {
+            return SupportedDatabaseType.POSTGRES;
+        } else if (dbType.toLowerCase().indexOf("oracle") > -1) {
+            return SupportedDatabaseType.ORACLE;
+        }
+        return null;
+    }
+
+    /**
+     * Creates the security domain for the datasources. This is needed to support
+     * obfuscation of the password in the configuration file.
+     *
+     * @param mcc the JBossAS management client
+     * @param serverProperties contains the obfuscated password to store in the security domain
+     * @throws Exception
+     */
+    public static void createDatasourceSecurityDomain(ModelControllerClient mcc,
+        HashMap<String, String> serverProperties) throws Exception {
+
+        final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
+        final String obfuscatedPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+        final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+        final String securityDomain = RHQ_SECURITY_DOMAIN;
+        if (!client.isSecurityDomain(securityDomain)) {
+            client.createNewSecureIdentitySecurityDomainRequest(securityDomain, dbUsername, obfuscatedPassword);
+            LOG.info("Security domain [" + securityDomain + "] created");
+        } else {
+            LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
+        }
+    }
+
+    /**
+     * Creates JDBC driver configurations so the datasources can properly connect to the backend databases.
+     * This will attempt to create drivers for all supported databases, not just for the database type that
+     * is currently configured.
+     *
+     * @param mcc
+     * @param serverProperties
+     * @throws Exception
+     */
+    public static void createNewJdbcDrivers(ModelControllerClient mcc, HashMap<String, String> serverProperties)
+        throws Exception {
+
+        final DatasourceJBossASClient client = new DatasourceJBossASClient(mcc);
+
+        final ModelNode postgresDriverRequest = client.createNewJdbcDriverRequest(JDBC_DRIVER_POSTGRES,
+            "org.rhq.postgres", "org.postgresql.xa.PGXADataSource");
+        final ModelNode oracleDriverRequest = client.createNewJdbcDriverRequest(JDBC_DRIVER_ORACLE, "org.rhq.oracle",
+            "oracle.jdbc.xa.client.OracleXADataSource");
+
+        // if we are to use Oracle, we throw an exception if we can't create the Oracle datasource. We also try to
+        // create the Postgres datasource but because it isn't needed, we don't throw exceptions if that fails, we
+        // just log a warning.
+        // The reverse is true if we are to use Postgres (that is, we ensure Postgres driver is created, but not Oracle).
+        ModelNode results;
+        final SupportedDatabaseType supportedDbType = getSupportedDatabaseType(serverProperties);
+        switch (supportedDbType) {
+        case POSTGRES: {
+            if (client.isJDBCDriver(JDBC_DRIVER_POSTGRES)) {
+                LOG.info("Postgres JDBC driver is already deployed");
+            } else {
+                results = client.execute(postgresDriverRequest);
+                if (!DatasourceJBossASClient.isSuccess(results)) {
+                    throw new FailureException(results, "Failed to create postgres database driver");
+                } else {
+                    LOG.info("Deployed Postgres JDBC driver");
+                }
+            }
+
+            if (client.isJDBCDriver(JDBC_DRIVER_ORACLE)) {
+                LOG.info("Oracle JDBC driver is already deployed");
+            } else {
+                results = client.execute(oracleDriverRequest);
+                if (!DatasourceJBossASClient.isSuccess(results)) {
+                    LOG.warn("Could not create Oracle JDBC Driver - you will not be able to switch to an Oracle DB later: "
+                        + JBossASClient.getFailureDescription(results));
+                } else {
+                    LOG.info("Deployed Oracle JDBC driver for future use");
+                }
+            }
+            break;
+        }
+        case ORACLE: {
+            if (client.isJDBCDriver(JDBC_DRIVER_ORACLE)) {
+                LOG.info("Oracle JDBC driver is already deployed");
+            } else {
+                results = client.execute(oracleDriverRequest);
+                if (!DatasourceJBossASClient.isSuccess(results)) {
+                    throw new FailureException(results, "Failed to create oracle database driver");
+                } else {
+                    LOG.info("Deployed Oracle JDBC driver");
+                }
+            }
+            if (client.isJDBCDriver(JDBC_DRIVER_POSTGRES)) {
+                LOG.info("Postgres JDBC driver is already deployed");
+            } else {
+                results = client.execute(postgresDriverRequest);
+                if (!DatasourceJBossASClient.isSuccess(results)) {
+                    LOG.warn("Could not create Postgres JDBC Driver - you will not be able to switch to a Postgres DB later: "
+                        + JBossASClient.getFailureDescription(results));
+                } else {
+                    LOG.info("Deployed Postgres JDBC driver for future use");
+                }
+            }
+            break;
+        }
+        default:
+            throw new RuntimeException("bad db type"); // this should never happen; should have never gotten to this point with a bad type
+        }
+
+    }
+
+    /**
+     * Creates the datasources needed by the RHQ Server.
+     *
+     * @param mcc the JBossAS management client
+     * @param serverProperties properties to help determine the properties of the datasources to be created
+     * @throws Exception
+     */
+    public static void createNewDatasources(ModelControllerClient mcc, HashMap<String, String> serverProperties)
+        throws Exception {
+
+        final SupportedDatabaseType supportedDbType = getSupportedDatabaseType(serverProperties);
+        switch (supportedDbType) {
+        case POSTGRES: {
+            createNewDatasources_Postgres(mcc);
+            break;
+        }
+        case ORACLE: {
+            createNewDatasources_Oracle(mcc);
+            break;
+        }
+        default:
+            throw new RuntimeException("bad db type"); // this should never happen; should have never gotten to this point with a bad type
+        }
+
+        LOG.info("Created datasources");
+    }
+
+    private static void createNewDatasources_Postgres(ModelControllerClient mcc) throws Exception {
+        final HashMap<String, String> props = new HashMap<String, String>(4);
+        final DatasourceJBossASClient client = new DatasourceJBossASClient(mcc);
+
+        props.put("char.encoding", "UTF-8");
+
+        ModelNode noTxDsRequest = client.createNewDatasourceRequest(RHQ_DATASOURCE_NAME_NOTX, 30000,
+            "${rhq.server.database.connection-url:jdbc:postgres://127.0.0.1:5432/rhq}", JDBC_DRIVER_POSTGRES,
+            "org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter", 15, false, 2, 5, 75,
+            RHQ_SECURITY_DOMAIN, "-unused-stale-conn-checker-", "TRANSACTION_READ_COMMITTED",
+            "org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker", props);
+        noTxDsRequest.remove("stale-connection-checker-class-name"); // we don't have one of these for postgres
+
+        props.clear();
+        props.put("ServerName", "${rhq.server.database.server-name:127.0.0.1}");
+        props.put("PortNumber", "${rhq.server.database.port:5432}");
+        props.put("DatabaseName", "${rhq.server.database.db-name:rhq}");
+
+        ModelNode xaDsRequest = client.createNewXADatasourceRequest(RHQ_DATASOURCE_NAME_XA, 30000,
+            JDBC_DRIVER_POSTGRES, "org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter", 15, 5,
+            50, 75, RHQ_SECURITY_DOMAIN, "-unused-stale-conn-checker-", "TRANSACTION_READ_COMMITTED",
+            "org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker", props);
+        xaDsRequest.remove("stale-connection-checker-class-name"); // we don't have one of these for postgres
+
+        ModelNode batch = DatasourceJBossASClient.createBatchRequest(noTxDsRequest, xaDsRequest);
+        ModelNode results = client.execute(batch);
+        if (!DatasourceJBossASClient.isSuccess(results)) {
+            throw new FailureException(results, "Failed to create Postgres datasources");
+        }
+    }
+
+    private static void createNewDatasources_Oracle(ModelControllerClient mcc) throws Exception {
+        final HashMap<String, String> props = new HashMap<String, String>(2);
+        final DatasourceJBossASClient client = new DatasourceJBossASClient(mcc);
+
+        props.put("char.encoding", "UTF-8");
+        props.put("SetBigStringTryClob", "true");
+
+        ModelNode noTxDsRequest = client.createNewDatasourceRequest(RHQ_DATASOURCE_NAME_NOTX, 30000,
+            "${rhq.server.database.connection-url:jdbc:oracle:thin:@127.0.0.1:1521:rhq}", JDBC_DRIVER_ORACLE,
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter", 15, false, 2, 5, 75,
+            RHQ_SECURITY_DOMAIN, "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker",
+            "TRANSACTION_READ_COMMITTED", "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker",
+            props);
+
+        props.clear();
+        props.put("URL", "${rhq.server.database.connection-url:jdbc:oracle:thin:@127.0.0.1:1521:rhq}");
+        props.put("ConnectionProperties", "SetBigStringTryClob=true");
+
+        ModelNode xaDsRequest = client.createNewXADatasourceRequest(RHQ_DATASOURCE_NAME_XA, 30000, JDBC_DRIVER_ORACLE,
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter", 15, 5, 50, 75, RHQ_SECURITY_DOMAIN,
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker", "TRANSACTION_READ_COMMITTED",
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker", props);
+
+        ModelNode batch = DatasourceJBossASClient.createBatchRequest(noTxDsRequest, xaDsRequest);
+        ModelNode results = client.execute(batch);
+        if (!DatasourceJBossASClient.isSuccess(results)) {
+            throw new FailureException(results, "Failed to create Oracle datasources");
+        }
+    }
+
     /**
      * Determines if we are in auto-install mode. This means the properties file is
      * fully configured and the installation can begin without asking the user
@@ -377,6 +614,7 @@ public class ServerInstallUtil {
             updateOrInsertServer(db, conn, serverDetails);
 
         } catch (SQLException e) {
+            // TODO: should we throw an exception here? This would abort the rest of the installation
             LOG.info("Unable to store server entry in the database: " + ThrowableUtil.getAllMessages(e));
         } finally {
             if (null != db) {
diff --git a/modules/enterprise/gui/installer/src/test/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClientTest.java b/modules/enterprise/gui/installer/src/test/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClientTest.java
new file mode 100644
index 0000000..708b673
--- /dev/null
+++ b/modules/enterprise/gui/installer/src/test/java/org/rhq/common/jbossas/client/controller/DatasourceJBossASClientTest.java
@@ -0,0 +1,112 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 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.common.jbossas.client.controller;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.annotations.Test;
+
+import org.jboss.as.controller.client.ModelControllerClient;
+import org.jboss.as.controller.client.OperationMessageHandler;
+import org.jboss.dmr.ModelNode;
+
+import org.rhq.enterprise.gui.installer.client.shared.ServerProperties;
+import org.rhq.enterprise.gui.installer.server.servlet.ServerInstallUtil;
+
+ at Test
+public class DatasourceJBossASClientTest {
+    private static final ModelNode mockSuccess;
+    static {
+        mockSuccess = new ModelNode();
+        mockSuccess.get(JBossASClient.OUTCOME).set(JBossASClient.OUTCOME_SUCCESS);
+    }
+
+    public void testCreateDatasourcesDMR() throws Exception {
+        ModelControllerClient mcc = mock(ModelControllerClient.class);
+
+        // note that this doesn't test actually creating anything - it just tests the DMR can be parsed successfully
+        when(mcc.execute(any(ModelNode.class), any(OperationMessageHandler.class))).thenAnswer(new Answer<ModelNode>() {
+            public ModelNode answer(InvocationOnMock invocation) throws Throwable {
+                System.out.println("~~~~~~~\n" + invocation.getArguments()[0]);
+                return mockSuccess;
+            }
+        });
+
+        HashMap<String, String> serverProperties = new HashMap<String, String>();
+        serverProperties.put(ServerProperties.PROP_DATABASE_TYPE, "Oracle");
+        ServerInstallUtil.createNewDatasources(mcc, serverProperties);
+
+        serverProperties.put(ServerProperties.PROP_DATABASE_TYPE, "PostgreSQL");
+        ServerInstallUtil.createNewDatasources(mcc, serverProperties);
+    }
+
+    public void testCreateNewDatasourceDMR() throws Exception {
+        ModelControllerClient mcc = mock(ModelControllerClient.class);
+
+        // note that this doesn't test actually creating anything - it just tests the DMR can be parsed successfully
+        when(mcc.execute(any(ModelNode.class), any(OperationMessageHandler.class))).thenReturn(mockSuccess);
+
+        DatasourceJBossASClient client = new DatasourceJBossASClient(mcc);
+
+        HashMap<String, String> connProps = new HashMap<String, String>(2);
+        connProps.put("char.encoding", "UTF-8");
+        connProps.put("SetBigStringTryClob", "true");
+
+        ModelNode request = client.createNewDatasourceRequest("NoTxRHQDS", 30000,
+            "${rhq.server.database.connection-url:jdbc:oracle:thin:@127.0.0.1:1521:rhq}", "oracle",
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter", 15, false, 2, 5, 75,
+            "RHQDSSecurityDomain", "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker",
+            "TRANSACTION_READ_COMMITTED", "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker",
+            connProps);
+
+        System.out.println("==============\n" + request);
+
+        ModelNode results = client.execute(request);
+        assert JBossASClient.isSuccess(results);
+    }
+
+    public void testCreateNewXADatasourceDMR() throws Exception {
+        ModelControllerClient mcc = mock(ModelControllerClient.class);
+
+        // note that this doesn't test actually creating anything - it just tests the DMR can be parsed successfully
+        when(mcc.execute(any(ModelNode.class), any(OperationMessageHandler.class))).thenReturn(mockSuccess);
+
+        DatasourceJBossASClient client = new DatasourceJBossASClient(mcc);
+
+        HashMap<String, String> xaDSProps = new HashMap<String, String>(2);
+        xaDSProps.put("URL", "${rhq.server.database.connection-url:jdbc:oracle:thin:@127.0.0.1:1521:rhq}");
+        xaDSProps.put("ConnectionProperties", "SetBigStringTryClob=true");
+
+        ModelNode request = client.createNewXADatasourceRequest("RHQDS", 30000, "oracle",
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter", 15, 2, 5, 75, "RHQDSSecurityDomain",
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker", "TRANSACTION_READ_COMMITTED",
+            "org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker", xaDSProps);
+
+        System.out.println("==============\n" + request);
+
+        ModelNode results = client.execute(request);
+        assert JBossASClient.isSuccess(results);
+    }
+}




More information about the rhq-commits mailing list