Skip to content

Commit

Permalink
[WFLY-10640] driver-datasource-class-name and driver-xa-datasource-cl…
Browse files Browse the repository at this point in the history
…ass-name need to be validated when updating
  • Loading branch information
gaol committed Aug 28, 2018
1 parent 44413ef commit 6f7be35
Show file tree
Hide file tree
Showing 10 changed files with 362 additions and 66 deletions.
Expand Up @@ -910,11 +910,15 @@ public interface ConnectorLogger extends BasicLogger {
void unexceptedWorkerCompletionError(String errorMessage, @Cause Throwable t); void unexceptedWorkerCompletionError(String errorMessage, @Cause Throwable t);


@Message(id = 114, value = "Failed to load datasource class: %s") @Message(id = 114, value = "Failed to load datasource class: %s")
IllegalStateException failedToLoadDataSourceClass(String clsName, @Cause Throwable t); OperationFailedException failedToLoadDataSourceClass(String clsName, @Cause Throwable t);


@Message(id = 115, value = "Module for driver [%s] or one of it dependencies is missing: [%s]") @Message(id = 115, value = "Module for driver [%s] or one of it dependencies is missing: [%s]")
String missingDependencyInModuleDriver(String moduleName, String missingModule); String missingDependencyInModuleDriver(String moduleName, String missingModule);


@Message(id = 116, value = "Failed to load module for RA [%s] - the module or one of its dependencies is missing [%s]") @Message(id = 116, value = "Failed to load module for RA [%s] - the module or one of its dependencies is missing [%s]")
String raModuleNotFound(String moduleName, String missingModule); String raModuleNotFound(String moduleName, String missingModule);

@Message(id = 117, value = "%s is not a valid %s implementation")
OperationFailedException notAValidDataSourceClass(String clz, String dsClz);

} }
Expand Up @@ -42,13 +42,15 @@
import javax.resource.spi.ManagedConnectionFactory; import javax.resource.spi.ManagedConnectionFactory;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import javax.sql.DataSource; import javax.sql.DataSource;
import javax.sql.XADataSource;


import org.jboss.as.connector.logging.ConnectorLogger; import org.jboss.as.connector.logging.ConnectorLogger;
import org.jboss.as.connector.metadata.api.common.Credential; import org.jboss.as.connector.metadata.api.common.Credential;
import org.jboss.as.connector.security.ElytronSubjectFactory; import org.jboss.as.connector.security.ElytronSubjectFactory;
import org.jboss.as.connector.services.driver.InstalledDriver; import org.jboss.as.connector.services.driver.InstalledDriver;
import org.jboss.as.connector.services.driver.registry.DriverRegistry; import org.jboss.as.connector.services.driver.registry.DriverRegistry;
import org.jboss.as.connector.util.Injection; import org.jboss.as.connector.util.Injection;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.core.security.ServerSecurityManager; import org.jboss.as.core.security.ServerSecurityManager;
import org.jboss.as.naming.deployment.ContextNames; import org.jboss.as.naming.deployment.ContextNames;
import org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnectionFactory; import org.jboss.jca.adapters.jdbc.BaseWrapperManagedConnectionFactory;
Expand Down Expand Up @@ -93,8 +95,8 @@
import org.jboss.msc.service.StopContext; import org.jboss.msc.service.StopContext;
import org.jboss.msc.value.InjectedValue; import org.jboss.msc.value.InjectedValue;
import org.jboss.security.SubjectFactory; import org.jboss.security.SubjectFactory;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.common.function.ExceptionSupplier; import org.wildfly.common.function.ExceptionSupplier;
import org.wildfly.security.auth.client.AuthenticationContext;
import org.wildfly.security.credential.source.CredentialSource; import org.wildfly.security.credential.source.CredentialSource;
import org.wildfly.security.manager.WildFlySecurityManager; import org.wildfly.security.manager.WildFlySecurityManager;
import org.wildfly.security.manager.action.ClearContextClassLoaderAction; import org.wildfly.security.manager.action.ClearContextClassLoaderAction;
Expand Down Expand Up @@ -364,6 +366,20 @@ public CommonDeployment deploy(ServiceContainer serviceContainer) throws DeployE


DataSources dataSources = null; DataSources dataSources = null;
if (dataSourceConfig != null) { if (dataSourceConfig != null) {
String dsClsName = dataSourceConfig.getDataSourceClass();
if (dsClsName != null) {
try {
Class<? extends DataSource> dsCls = driverClassLoader().loadClass(dsClsName).asSubclass(DataSource.class);
JdbcDriverAdd.checkDSCls(dsCls, DataSource.class);
} catch (OperationFailedException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(e);
} catch (ClassCastException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(ConnectorLogger.ROOT_LOGGER.notAValidDataSourceClass(dsClsName, DataSource.class.getName()));
} catch (ClassNotFoundException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(ConnectorLogger.ROOT_LOGGER.failedToLoadDataSourceClass(dsClsName, e));
}
}

String driverName = dataSourceConfig.getDriver(); String driverName = dataSourceConfig.getDriver();
InstalledDriver installedDriver = driverRegistry.getValue().getInstalledDriver(driverName); InstalledDriver installedDriver = driverRegistry.getValue().getInstalledDriver(driverName);
if (installedDriver != null) { if (installedDriver != null) {
Expand All @@ -377,6 +393,20 @@ public CommonDeployment deploy(ServiceContainer serviceContainer) throws DeployE
} }
dataSources = new DatasourcesImpl(Arrays.asList(dataSourceConfig), null, drivers); dataSources = new DatasourcesImpl(Arrays.asList(dataSourceConfig), null, drivers);
} else if (xaDataSourceConfig != null) { } else if (xaDataSourceConfig != null) {
String xaDSClsName = xaDataSourceConfig.getXaDataSourceClass();
if (xaDSClsName != null) {
try {
Class<? extends XADataSource> xaDsCls = driverClassLoader().loadClass(xaDSClsName).asSubclass(XADataSource.class);
JdbcDriverAdd.checkDSCls(xaDsCls, XADataSource.class);
} catch (OperationFailedException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(e);
} catch (ClassCastException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(ConnectorLogger.ROOT_LOGGER.notAValidDataSourceClass(xaDSClsName, XADataSource.class.getName()));
} catch (ClassNotFoundException e) {
throw ConnectorLogger.ROOT_LOGGER.cannotDeploy(ConnectorLogger.ROOT_LOGGER.failedToLoadDataSourceClass(xaDSClsName, e));
}
}

String driverName = xaDataSourceConfig.getDriver(); String driverName = xaDataSourceConfig.getDriver();
InstalledDriver installedDriver = driverRegistry.getValue().getInstalledDriver(driverName); InstalledDriver installedDriver = driverRegistry.getValue().getInstalledDriver(driverName);
if (installedDriver != null) { if (installedDriver != null) {
Expand Down
Expand Up @@ -35,9 +35,13 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;


import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.sql.Driver; import java.sql.Driver;
import java.util.ServiceLoader; import java.util.ServiceLoader;


import javax.sql.DataSource;
import javax.sql.XADataSource;

import org.jboss.as.connector.logging.ConnectorLogger; import org.jboss.as.connector.logging.ConnectorLogger;
import org.jboss.as.connector.services.driver.DriverService; import org.jboss.as.connector.services.driver.DriverService;
import org.jboss.as.connector.services.driver.InstalledDriver; import org.jboss.as.connector.services.driver.InstalledDriver;
Expand Down Expand Up @@ -107,6 +111,24 @@ protected void performRuntime(OperationContext context, ModelNode operation, Mod
throw new OperationFailedException(ConnectorLogger.ROOT_LOGGER.failedToLoadModuleDriver(moduleName), e); throw new OperationFailedException(ConnectorLogger.ROOT_LOGGER.failedToLoadModuleDriver(moduleName), e);
} }


if (dataSourceClassName != null) {
Class<? extends DataSource> dsCls;
try {
dsCls = module.getClassLoader().loadClass(dataSourceClassName).asSubclass(DataSource.class);
} catch (ClassNotFoundException | ClassCastException e) {
throw SUBSYSTEM_DATASOURCES_LOGGER.failedToLoadDataSourceClass(dataSourceClassName, e);
}
checkDSCls(dsCls, DataSource.class);
}
if (xaDataSourceClassName != null) {
Class<? extends XADataSource> dsCls;
try {
dsCls = module.getClassLoader().loadClass(xaDataSourceClassName).asSubclass(XADataSource.class);
} catch (ClassNotFoundException | ClassCastException e) {
throw SUBSYSTEM_DATASOURCES_LOGGER.failedToLoadDataSourceClass(xaDataSourceClassName, e);
}
checkDSCls(dsCls, XADataSource.class);
}
if (driverClassName == null) { if (driverClassName == null) {
final ServiceLoader<Driver> serviceLoader = module.loadService(Driver.class); final ServiceLoader<Driver> serviceLoader = module.loadService(Driver.class);
boolean driverLoaded = false; boolean driverLoaded = false;
Expand Down Expand Up @@ -160,5 +182,11 @@ public static void startDriverServices(final ServiceTarget target, final ModuleI
builder.install(); builder.install();
} }


static <T> void checkDSCls(Class<? extends T> dsCls, Class<T> t) throws OperationFailedException {
if (Modifier.isInterface(dsCls.getModifiers()) || Modifier.isAbstract(dsCls.getModifiers())) {
throw SUBSYSTEM_DATASOURCES_LOGGER.notAValidDataSourceClass(dsCls.getName(), t.getName());
}
}



} }
Expand Up @@ -27,14 +27,12 @@
import static org.jboss.as.controller.client.helpers.ClientConstants.OP_ADDR; import static org.jboss.as.controller.client.helpers.ClientConstants.OP_ADDR;
import static org.jboss.as.controller.client.helpers.ClientConstants.READ_ATTRIBUTE_OPERATION; import static org.jboss.as.controller.client.helpers.ClientConstants.READ_ATTRIBUTE_OPERATION;


import com.google.common.collect.Iterables;
import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.controller.client.helpers.Operations; import org.jboss.as.controller.client.helpers.Operations;
import org.jboss.as.test.integration.management.base.ContainerResourceMgmtTestBase; import org.jboss.as.test.integration.management.base.ContainerResourceMgmtTestBase;
import org.jboss.dmr.ModelNode; import org.jboss.dmr.ModelNode;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;


Expand All @@ -44,7 +42,6 @@
@RunWith(Arquillian.class) @RunWith(Arquillian.class)
@RunAsClient @RunAsClient
public class DataSourceClassInfoTestCase extends ContainerResourceMgmtTestBase { public class DataSourceClassInfoTestCase extends ContainerResourceMgmtTestBase {
private static final String DRIVER_WITH_WRONG_DS_CLASS_NAME = "h2-wrong-ds-class";


private ModelNode getDsClsInfoOperation(String driverName) { private ModelNode getDsClsInfoOperation(String driverName) {
ModelNode driverAddress = new ModelNode(); ModelNode driverAddress = new ModelNode();
Expand Down Expand Up @@ -155,61 +152,4 @@ public void testGetInstalledDriver() throws Exception {
Assert.assertEquals("int", dsInfo.get("loginTimeout").asString()); Assert.assertEquals("int", dsInfo.get("loginTimeout").asString());
} }


@Test
@Ignore("https://issues.jboss.org/browse/WFCORE-3682")
public void testGetDsClsInfoWithWrongDataSourceClass() throws Exception {
ModelNode driverWithWrongDsClsAddr = new ModelNode();
driverWithWrongDsClsAddr.add("subsystem", "datasources");
driverWithWrongDsClsAddr.add("jdbc-driver", DRIVER_WITH_WRONG_DS_CLASS_NAME);

addH2DriverWithWrongDsClass(driverWithWrongDsClsAddr);

ModelNode op = Operations.createReadResourceOperation(driverWithWrongDsClsAddr);
op.get(INCLUDE_RUNTIME).set(true);

try {
ModelNode result = getManagementClient().getControllerClient().execute(op);
Assert.assertNotNull(result);
Assert.assertEquals("failed", result.get("outcome").asString());
Assert.assertTrue(result.hasDefined("failure-description"));
} finally {
removeDriver(driverWithWrongDsClsAddr);
}
}

@Test
public void testGetDsClsInfoByReadAttributeWithWrongDataSourceClass() throws Exception {
ModelNode driverWithWrongDsClsAddr = new ModelNode();
driverWithWrongDsClsAddr.add("subsystem", "datasources");
driverWithWrongDsClsAddr.add("jdbc-driver", DRIVER_WITH_WRONG_DS_CLASS_NAME);

addH2DriverWithWrongDsClass(driverWithWrongDsClsAddr);

ModelNode op = Operations.createReadAttributeOperation(driverWithWrongDsClsAddr, "datasource-class-info");

try {
ModelNode result = getManagementClient().getControllerClient().execute(op);
Assert.assertNotNull(result);
Assert.assertEquals("failed", result.get("outcome").asString());
Assert.assertTrue(result.hasDefined("failure-description"));
} finally {
removeDriver(driverWithWrongDsClsAddr);
}
}

private void addH2DriverWithWrongDsClass(ModelNode driverAddress) throws Exception {
ModelNode op = Operations.createAddOperation(driverAddress);
op.get("driver-name").set(Iterables.getLast(driverAddress.asList()).get("jdbc-driver"));
op.get("driver-module-name").set("com.h2database.h2");
op.get("driver-xa-datasource-class-name").set("non.existing.class");

ModelNode result = getManagementClient().getControllerClient().execute(op);
Assert.assertNotNull(result);
Assert.assertEquals("success", result.get("outcome").asString());
}

private void removeDriver(ModelNode driverAddress) throws Exception {
ModelNode op = Operations.createRemoveOperation(driverAddress);
getManagementClient().getControllerClient().execute(op);
}
} }
@@ -0,0 +1,141 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2018, Red Hat, Inc., 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.as.test.integration.jca.datasource;

import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;

import java.sql.Driver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.test.integration.jca.JcaMgmtBase;
import org.jboss.as.test.integration.management.util.MgmtOperationException;
import org.jboss.as.test.integration.management.util.ModelUtil;
import org.jboss.dmr.ModelNode;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
* Test the situation when abstract DataSource class is specified when creating a data source.
*
* @author lgao
*/
@RunWith(Arquillian.class)
@RunAsClient
public class DatasourceWrongDsClassTestCase extends JcaMgmtBase {

private static final String DEPLOYMENT = "dummydriver";

@Deployment(name = DEPLOYMENT)
public static JavaArchive jdbcArchive() throws Exception {
JavaArchive ja = ShrinkWrap.create(JavaArchive.class, DEPLOYMENT + ".jar");
ja.addClasses(DummyDataSource.class, DummyXADataSource.class, TestDriver.class);
ja.addAsServiceProviderAndClasses(Driver.class, TestDriver.class);
return ja;
}

@Test
public void testWrongDSClass() throws Exception {
String driverName = DEPLOYMENT + ".jar";
ModelNode address = getDataSourceAddress("wrongClsDs");
ModelNode operation = getDataSourceOperation(address, "java:/wrongClsDs", driverName, DummyDataSource.class.getName());
try {
executeOperation(operation);
Assert.fail("Not supposed to succeed");
} catch (MgmtOperationException e) {
ModelNode result = e.getResult();
Assert.assertEquals("failed", result.get("outcome").asString());
String failDesc = result.get("failure-description").asString();
Assert.assertTrue(failDesc.contains("WFLYJCA0117"));
return;
}
Assert.fail("Not supposed to be here");
}

@Test
public void testWrongXADSClass() throws Exception {
String driverName = DEPLOYMENT + ".jar";
ModelNode address = getXADataSourceAddress("wrongXAClsDs");
ModelNode operation = getXADataSourceOperation(address, "java:/wrongXAClsDs", driverName, DummyXADataSource.class.getName());
try {
executeOperation(operation);
Assert.fail("Not supposed to succeed");
} catch (MgmtOperationException e) {
ModelNode result = e.getResult();
Assert.assertEquals("failed", result.get("outcome").asString());
return;
}
Assert.fail("Not supposed to be here");
}

private ModelNode getXADataSourceAddress(String xaDsName) {
ModelNode address = new ModelNode()
.add(SUBSYSTEM, "datasources")
.add("xa-data-source", xaDsName);
return address;
}

private ModelNode getDataSourceAddress(String dsName) {
ModelNode address = new ModelNode()
.add(SUBSYSTEM, "datasources")
.add("data-source", dsName);
return address;
}

private ModelNode getDataSourceOperation(ModelNode address, String jndiName, String driverName, String dsClsName) {
ModelNode operation = new ModelNode();
operation.get(OP).set(ADD);
operation.get(OP_ADDR).set(address);
operation.get("jndi-name").set(jndiName);
operation.get("driver-name").set(driverName);
operation.get("datasource-class").set(dsClsName);
return operation;
}

private ModelNode getXADataSourceOperation(ModelNode address, String jndiName, String driverName, String xaDsClsName) {
ModelNode addOp = new ModelNode();
addOp.get(OP).set(ADD);
addOp.get(OP_ADDR).set(address);
addOp.get("jndi-name").set(jndiName);
addOp.get("driver-name").set(driverName);
addOp.get("xa-datasource-class").set(xaDsClsName);

ModelNode connProps = new ModelNode();
connProps.get(OP).set(ADD);
ModelNode connPropAdd = address.add("connection-properties", "url");
connProps.get(OP_ADDR).set(connPropAdd);
connProps.get("value").set("dummy");
List<ModelNode> operationList = new ArrayList<>(Arrays.asList(addOp, connProps));
return ModelUtil.createCompositeNode(operationList.toArray(new ModelNode[1]));
}
}
@@ -0,0 +1,34 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2018, Red Hat, Inc., 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.as.test.integration.jca.datasource;

import javax.sql.DataSource;

/**
* Dummy abstract DataSource, used to verify that it cannot be specified during data source setup.
*
* @author <a href="mailto:lgao@redhat.com>Lin Gao</a>
*/
public abstract class DummyDataSource implements DataSource {

}

0 comments on commit 6f7be35

Please sign in to comment.