/* * JBoss, Home of Professional Open Source. * Copyright 2010, 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.connector.subsystems.datasources; import static org.jboss.as.connector.logging.ConnectorLogger.SUBSYSTEM_DATASOURCES_LOGGER; import static org.jboss.as.connector.subsystems.common.pool.Constants.BACKGROUNDVALIDATION; import static org.jboss.as.connector.subsystems.common.pool.Constants.BACKGROUNDVALIDATIONMILLIS; import static org.jboss.as.connector.subsystems.common.pool.Constants.BLOCKING_TIMEOUT_WAIT_MILLIS; import static org.jboss.as.connector.subsystems.common.pool.Constants.CAPACITY_DECREMENTER_CLASS; import static org.jboss.as.connector.subsystems.common.pool.Constants.CAPACITY_DECREMENTER_PROPERTIES; import static org.jboss.as.connector.subsystems.common.pool.Constants.CAPACITY_INCREMENTER_CLASS; import static org.jboss.as.connector.subsystems.common.pool.Constants.CAPACITY_INCREMENTER_PROPERTIES; import static org.jboss.as.connector.subsystems.common.pool.Constants.IDLETIMEOUTMINUTES; import static org.jboss.as.connector.subsystems.common.pool.Constants.INITIAL_POOL_SIZE; import static org.jboss.as.connector.subsystems.common.pool.Constants.MAX_POOL_SIZE; import static org.jboss.as.connector.subsystems.common.pool.Constants.MIN_POOL_SIZE; import static org.jboss.as.connector.subsystems.common.pool.Constants.POOL_FAIR; import static org.jboss.as.connector.subsystems.common.pool.Constants.POOL_FLUSH_STRATEGY; import static org.jboss.as.connector.subsystems.common.pool.Constants.POOL_PREFILL; import static org.jboss.as.connector.subsystems.common.pool.Constants.POOL_USE_STRICT_MIN; import static org.jboss.as.connector.subsystems.common.pool.Constants.USE_FAST_FAIL; import static org.jboss.as.connector.subsystems.datasources.Constants.ALLOCATION_RETRY; import static org.jboss.as.connector.subsystems.datasources.Constants.ALLOCATION_RETRY_WAIT_MILLIS; import static org.jboss.as.connector.subsystems.datasources.Constants.ALLOW_MULTIPLE_USERS; import static org.jboss.as.connector.subsystems.datasources.Constants.AUTHENTICATION_CONTEXT; import static org.jboss.as.connector.subsystems.datasources.Constants.CHECK_VALID_CONNECTION_SQL; import static org.jboss.as.connector.subsystems.datasources.Constants.CONNECTABLE; import static org.jboss.as.connector.subsystems.datasources.Constants.CONNECTION_LISTENER_CLASS; import static org.jboss.as.connector.subsystems.datasources.Constants.CONNECTION_LISTENER_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.CONNECTION_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.CONNECTION_URL; import static org.jboss.as.connector.subsystems.datasources.Constants.CREDENTIAL_REFERENCE; import static org.jboss.as.connector.subsystems.datasources.Constants.DATASOURCES; import static org.jboss.as.connector.subsystems.datasources.Constants.DATASOURCE_CLASS; import static org.jboss.as.connector.subsystems.datasources.Constants.DATASOURCE_DRIVER; import static org.jboss.as.connector.subsystems.datasources.Constants.DATA_SOURCE; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_CLASS; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_CLASS_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_DATASOURCE_CLASS_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_MAJOR_VERSION; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_MINOR_VERSION; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_MODULE_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.DRIVER_XA_DATASOURCE_CLASS_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.ELYTRON_ENABLED; import static org.jboss.as.connector.subsystems.datasources.Constants.ENABLED; import static org.jboss.as.connector.subsystems.datasources.Constants.ENLISTMENT_TRACE; import static org.jboss.as.connector.subsystems.datasources.Constants.EXCEPTION_SORTER_CLASSNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.EXCEPTION_SORTER_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.INTERLEAVING; import static org.jboss.as.connector.subsystems.datasources.Constants.JDBC_DRIVER_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.JNDI_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.JTA; import static org.jboss.as.connector.subsystems.datasources.Constants.MCP; import static org.jboss.as.connector.subsystems.datasources.Constants.MODULE_SLOT; import static org.jboss.as.connector.subsystems.datasources.Constants.NEW_CONNECTION_SQL; import static org.jboss.as.connector.subsystems.datasources.Constants.NO_RECOVERY; import static org.jboss.as.connector.subsystems.datasources.Constants.NO_TX_SEPARATE_POOL; import static org.jboss.as.connector.subsystems.datasources.Constants.PAD_XID; import static org.jboss.as.connector.subsystems.datasources.Constants.PASSWORD; import static org.jboss.as.connector.subsystems.datasources.Constants.PREPARED_STATEMENTS_CACHE_SIZE; import static org.jboss.as.connector.subsystems.datasources.Constants.QUERY_TIMEOUT; import static org.jboss.as.connector.subsystems.datasources.Constants.REAUTHPLUGIN_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.REAUTH_PLUGIN_CLASSNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_AUTHENTICATION_CONTEXT; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_CREDENTIAL_REFERENCE; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_ELYTRON_ENABLED; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_PASSWORD; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_SECURITY_DOMAIN; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVERY_USERNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVER_PLUGIN_CLASSNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.RECOVER_PLUGIN_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.SAME_RM_OVERRIDE; import static org.jboss.as.connector.subsystems.datasources.Constants.SECURITY_DOMAIN; import static org.jboss.as.connector.subsystems.datasources.Constants.SET_TX_QUERY_TIMEOUT; import static org.jboss.as.connector.subsystems.datasources.Constants.SHARE_PREPARED_STATEMENTS; import static org.jboss.as.connector.subsystems.datasources.Constants.SPY; import static org.jboss.as.connector.subsystems.datasources.Constants.STALE_CONNECTION_CHECKER_CLASSNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.STALE_CONNECTION_CHECKER_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.STATISTICS_ENABLED; import static org.jboss.as.connector.subsystems.datasources.Constants.TRACKING; import static org.jboss.as.connector.subsystems.datasources.Constants.TRACK_STATEMENTS; import static org.jboss.as.connector.subsystems.datasources.Constants.TRANSACTION_ISOLATION; import static org.jboss.as.connector.subsystems.datasources.Constants.URL_DELIMITER; import static org.jboss.as.connector.subsystems.datasources.Constants.URL_PROPERTY; import static org.jboss.as.connector.subsystems.datasources.Constants.URL_SELECTOR_STRATEGY_CLASS_NAME; import static org.jboss.as.connector.subsystems.datasources.Constants.USERNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.USE_CCM; import static org.jboss.as.connector.subsystems.datasources.Constants.USE_JAVA_CONTEXT; import static org.jboss.as.connector.subsystems.datasources.Constants.USE_TRY_LOCK; import static org.jboss.as.connector.subsystems.datasources.Constants.VALIDATE_ON_MATCH; import static org.jboss.as.connector.subsystems.datasources.Constants.VALID_CONNECTION_CHECKER_CLASSNAME; import static org.jboss.as.connector.subsystems.datasources.Constants.VALID_CONNECTION_CHECKER_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.WRAP_XA_RESOURCE; import static org.jboss.as.connector.subsystems.datasources.Constants.XADATASOURCE_PROPERTIES; import static org.jboss.as.connector.subsystems.datasources.Constants.XA_DATASOURCE; import static org.jboss.as.connector.subsystems.datasources.Constants.XA_DATASOURCE_CLASS; import static org.jboss.as.connector.subsystems.datasources.Constants.XA_RESOURCE_TIMEOUT; 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.parsing.ParseUtils.requireNoContent; import java.util.List; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import org.jboss.as.controller.Extension; import org.jboss.as.controller.ExtensionContext; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.SimpleAttributeDefinition; import org.jboss.as.controller.SubsystemRegistration; import org.jboss.as.controller.descriptions.ModelDescriptionConstants; import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver; import org.jboss.as.controller.parsing.ExtensionParsingContext; import org.jboss.as.controller.persistence.SubsystemMarshallingContext; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import org.jboss.jca.common.api.metadata.common.Capacity; import org.jboss.jca.common.api.metadata.common.Recovery; import org.jboss.jca.common.api.metadata.ds.DataSource; import org.jboss.jca.common.api.metadata.ds.DataSources; import org.jboss.jca.common.api.metadata.ds.Driver; import org.jboss.jca.common.api.metadata.ds.DsPool; import org.jboss.jca.common.api.metadata.ds.DsSecurity; import org.jboss.jca.common.api.metadata.ds.Validation; import org.jboss.jca.common.api.metadata.ds.XaDataSource; import org.jboss.staxmapper.XMLElementReader; import org.jboss.staxmapper.XMLElementWriter; import org.jboss.staxmapper.XMLExtendedStreamReader; import org.jboss.staxmapper.XMLExtendedStreamWriter; /** * @author <a href="mailto:stefano.maestri@redhat.com">Stefano Maestri</a> * @author <a href="mailto:darran.lofthouse@jboss.com">Darran Lofthouse</a> * @author John Bailey */ public class DataSourcesExtension implements Extension { public static final String SUBSYSTEM_NAME = Constants.DATASOURCES; private static final String RESOURCE_NAME = DataSourcesExtension.class.getPackage().getName() + ".LocalDescriptions"; private static final ModelVersion CURRENT_MODEL_VERSION = ModelVersion.create(5, 0, 0); static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) { StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME); for (String kp : keyPrefix) { prefix.append('.').append(kp); } return new StandardResourceDescriptionResolver(prefix.toString(), RESOURCE_NAME, DataSourcesExtension.class.getClassLoader(), true, false); } @Override public void initialize(final ExtensionContext context) { SUBSYSTEM_DATASOURCES_LOGGER.debugf("Initializing Datasources Extension"); boolean registerRuntimeOnly = context.isRuntimeOnlyRegistrationValid(); // Register the remoting subsystem final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, CURRENT_MODEL_VERSION); final ManagementResourceRegistration registration = subsystem.registerSubsystemModel(DataSourcesSubsystemRootDefinition.createInstance(registerRuntimeOnly)); subsystem.registerXMLElementWriter(new DataSourceSubsystemParser()); if (registerRuntimeOnly) { subsystem.registerDeploymentModel(DataSourcesSubsystemRootDefinition.createDeployedInstance(registerRuntimeOnly)); } if (context.isRegisterTransformers()) { DataSourcesSubsystemRootDefinition.registerTransformers(subsystem); } } @Override public void initializeParsers(final ExtensionParsingContext context) { context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_1_1.getUriString(), DataSourceSubsystemParser::new); context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_1_2.getUriString(), DataSourceSubsystemParser::new); context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_2_0.getUriString(), DataSourceSubsystemParser::new); context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_3_0.getUriString(), DataSourceSubsystemParser::new); context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_4_0.getUriString(), DataSourceSubsystemParser::new); context.setSubsystemXmlMapping(SUBSYSTEM_NAME, Namespace.DATASOURCES_5_0.getUriString(), DataSourceSubsystemParser::new); } public static final class DataSourceSubsystemParser implements XMLStreamConstants, XMLElementReader<List<ModelNode>>, XMLElementWriter<SubsystemMarshallingContext> { /** * {@inheritDoc} */ @Override public void writeContent(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException { context.startSubsystemElement(Namespace.CURRENT.getUriString(), false); ModelNode node = context.getModelNode(); writer.writeStartElement(DATASOURCES); if (node.hasDefined(DATA_SOURCE) || node.hasDefined(XA_DATASOURCE)) { if (node.hasDefined(DATA_SOURCE)) { writeDS(writer, false, node.get(DATA_SOURCE)); } if (node.hasDefined(XA_DATASOURCE)) { writeDS(writer, true, node.get(XA_DATASOURCE)); } } if (node.hasDefined(JDBC_DRIVER_NAME)) { writer.writeStartElement(DataSources.Tag.DRIVERS.getLocalName()); ModelNode drivers = node.get(JDBC_DRIVER_NAME); for (String driverName : drivers.keys()) { ModelNode driver = drivers.get(driverName); writer.writeStartElement(DataSources.Tag.DRIVER.getLocalName()); writer.writeAttribute(Driver.Attribute.NAME.getLocalName(), driver.require(DRIVER_NAME.getName()).asString()); if (has(driver, DRIVER_MODULE_NAME.getName())) { String moduleName = driver.get(DRIVER_MODULE_NAME.getName()).asString(); if (has(driver, MODULE_SLOT.getName())) { moduleName = moduleName + ":" + driver.get(MODULE_SLOT.getName()).asString(); } writer.writeAttribute(Driver.Attribute.MODULE.getLocalName(), moduleName); } writeAttributeIfHas(writer, driver, Driver.Attribute.MAJOR_VERSION, DRIVER_MAJOR_VERSION.getName()); writeAttributeIfHas(writer, driver, Driver.Attribute.MINOR_VERSION, DRIVER_MINOR_VERSION.getName()); writeElementIfHas(writer, driver, Driver.Tag.DRIVER_CLASS.getLocalName(), DRIVER_CLASS_NAME.getName()); writeElementIfHas(writer, driver, Driver.Tag.XA_DATASOURCE_CLASS.getLocalName(), DRIVER_XA_DATASOURCE_CLASS_NAME.getName()); writeElementIfHas(writer, driver, Driver.Tag.DATASOURCE_CLASS.getLocalName(), DRIVER_DATASOURCE_CLASS_NAME.getName()); writer.writeEndElement(); } writer.writeEndElement(); } writer.writeEndElement(); writer.writeEndElement(); } private void writeDS(XMLExtendedStreamWriter writer, boolean isXADataSource, ModelNode datasources) throws XMLStreamException { for (String dsName : datasources.keys()) { final ModelNode dataSourceNode = datasources.get(dsName); writer.writeStartElement(isXADataSource ? DataSources.Tag.XA_DATASOURCE.getLocalName() : DataSources.Tag.DATASOURCE.getLocalName()); JTA.marshallAsAttribute(dataSourceNode, writer); JNDI_NAME.marshallAsAttribute(dataSourceNode, writer); writer.writeAttribute("pool-name", dsName); ENABLED.marshallAsAttribute(dataSourceNode, writer); USE_JAVA_CONTEXT.marshallAsAttribute(dataSourceNode, writer); SPY.marshallAsAttribute(dataSourceNode, writer); USE_CCM.marshallAsAttribute(dataSourceNode, writer); CONNECTABLE.marshallAsAttribute(dataSourceNode, writer); TRACKING.marshallAsAttribute(dataSourceNode, writer); MCP.marshallAsAttribute(dataSourceNode, writer); ENLISTMENT_TRACE.marshallAsAttribute(dataSourceNode, writer); STATISTICS_ENABLED.marshallAsAttribute(dataSourceNode, writer); if (!isXADataSource) { CONNECTION_URL.marshallAsElement(dataSourceNode, writer); DRIVER_CLASS.marshallAsElement(dataSourceNode, writer); DATASOURCE_CLASS.marshallAsElement(dataSourceNode, writer); if (dataSourceNode.hasDefined(CONNECTION_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(CONNECTION_PROPERTIES.getName()).asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().get("value").asString(), DataSource.Tag.CONNECTION_PROPERTY.getLocalName()); } } } if (isXADataSource) { if (dataSourceNode.hasDefined(XADATASOURCE_PROPERTIES.getName())) { for (Property prop : dataSourceNode.get(XADATASOURCE_PROPERTIES.getName()).asPropertyList()) { writeProperty(writer, dataSourceNode, prop.getName(), prop .getValue().get("value").asString(), XaDataSource.Tag.XA_DATASOURCE_PROPERTY.getLocalName()); } } XA_DATASOURCE_CLASS.marshallAsElement(dataSourceNode, writer); } DATASOURCE_DRIVER.marshallAsElement(dataSourceNode, writer); if (isXADataSource) { URL_DELIMITER.marshallAsElement(dataSourceNode, writer); URL_PROPERTY.marshallAsElement(dataSourceNode, writer); URL_SELECTOR_STRATEGY_CLASS_NAME.marshallAsElement(dataSourceNode, writer); } NEW_CONNECTION_SQL.marshallAsElement(dataSourceNode, writer); TRANSACTION_ISOLATION.marshallAsElement(dataSourceNode, writer); if (!isXADataSource) { URL_DELIMITER.marshallAsElement(dataSourceNode, writer); URL_SELECTOR_STRATEGY_CLASS_NAME.marshallAsElement(dataSourceNode, writer); } boolean poolRequired = INITIAL_POOL_SIZE.isMarshallable(dataSourceNode) || MIN_POOL_SIZE.isMarshallable(dataSourceNode) || MAX_POOL_SIZE.isMarshallable(dataSourceNode) || POOL_PREFILL.isMarshallable(dataSourceNode) || POOL_FAIR.isMarshallable(dataSourceNode) || POOL_USE_STRICT_MIN.isMarshallable(dataSourceNode) || POOL_FLUSH_STRATEGY.isMarshallable(dataSourceNode) || ALLOW_MULTIPLE_USERS.isMarshallable(dataSourceNode) || CONNECTION_LISTENER_CLASS.isMarshallable(dataSourceNode) || CONNECTION_LISTENER_PROPERTIES.isMarshallable(dataSourceNode); if (isXADataSource) { poolRequired = poolRequired || SAME_RM_OVERRIDE.isMarshallable(dataSourceNode) || INTERLEAVING.isMarshallable(dataSourceNode) || NO_TX_SEPARATE_POOL.isMarshallable(dataSourceNode) || PAD_XID.isMarshallable(dataSourceNode) || WRAP_XA_RESOURCE.isMarshallable(dataSourceNode); } final boolean capacityRequired = CAPACITY_INCREMENTER_CLASS.isMarshallable(dataSourceNode) || CAPACITY_INCREMENTER_PROPERTIES.isMarshallable(dataSourceNode) || CAPACITY_DECREMENTER_CLASS.isMarshallable(dataSourceNode) || CAPACITY_DECREMENTER_PROPERTIES.isMarshallable(dataSourceNode); poolRequired = poolRequired || capacityRequired; if (poolRequired) { writer.writeStartElement(isXADataSource ? XaDataSource.Tag.XA_POOL.getLocalName() : DataSource.Tag.POOL .getLocalName()); MIN_POOL_SIZE.marshallAsElement(dataSourceNode, writer); INITIAL_POOL_SIZE.marshallAsElement(dataSourceNode, writer); MAX_POOL_SIZE.marshallAsElement(dataSourceNode, writer); POOL_PREFILL.marshallAsElement(dataSourceNode, writer); POOL_FAIR.marshallAsElement(dataSourceNode, writer); POOL_USE_STRICT_MIN.marshallAsElement(dataSourceNode, writer); POOL_FLUSH_STRATEGY.marshallAsElement(dataSourceNode, writer); ALLOW_MULTIPLE_USERS.marshallAsElement(dataSourceNode, writer); if (dataSourceNode.hasDefined(CONNECTION_LISTENER_CLASS.getName())) { writer.writeStartElement(DsPool.Tag.CONNECTION_LISTENER.getLocalName()); writer.writeAttribute(org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(CONNECTION_LISTENER_CLASS.getName()).asString()); if (dataSourceNode.hasDefined(CONNECTION_LISTENER_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(CONNECTION_LISTENER_PROPERTIES.getName()) .asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } if (capacityRequired) { writer.writeStartElement(DsPool.Tag.CAPACITY.getLocalName()); if (dataSourceNode.hasDefined(CAPACITY_INCREMENTER_CLASS.getName())) { writer.writeStartElement(Capacity.Tag.INCREMENTER.getLocalName()); CAPACITY_INCREMENTER_CLASS.marshallAsAttribute(dataSourceNode, writer); CAPACITY_INCREMENTER_PROPERTIES.marshallAsElement(dataSourceNode, writer); writer.writeEndElement(); } if (dataSourceNode.hasDefined(CAPACITY_DECREMENTER_CLASS.getName())) { writer.writeStartElement(Capacity.Tag.DECREMENTER.getLocalName()); CAPACITY_DECREMENTER_CLASS.marshallAsAttribute(dataSourceNode, writer); CAPACITY_DECREMENTER_PROPERTIES.marshallAsElement(dataSourceNode, writer); writer.writeEndElement(); } writer.writeEndElement(); } if (isXADataSource) { SAME_RM_OVERRIDE.marshallAsElement(dataSourceNode, writer); INTERLEAVING.marshallAsElement(dataSourceNode, writer); NO_TX_SEPARATE_POOL.marshallAsElement(dataSourceNode, writer); PAD_XID.marshallAsElement(dataSourceNode, writer); WRAP_XA_RESOURCE.marshallAsElement(dataSourceNode, writer); } writer.writeEndElement(); } boolean securityRequired = USERNAME.isMarshallable(dataSourceNode) || PASSWORD.isMarshallable(dataSourceNode) || CREDENTIAL_REFERENCE.isMarshallable(dataSourceNode) || SECURITY_DOMAIN.isMarshallable(dataSourceNode) || ELYTRON_ENABLED.isMarshallable(dataSourceNode) || REAUTH_PLUGIN_CLASSNAME.isMarshallable(dataSourceNode) || REAUTHPLUGIN_PROPERTIES.isMarshallable(dataSourceNode); if (securityRequired) { writer.writeStartElement(DataSource.Tag.SECURITY.getLocalName()); USERNAME.marshallAsElement(dataSourceNode, writer); PASSWORD.marshallAsElement(dataSourceNode, writer); SECURITY_DOMAIN.marshallAsElement(dataSourceNode, writer); CREDENTIAL_REFERENCE.marshallAsElement(dataSourceNode, writer); ELYTRON_ENABLED.marshallAsElement(dataSourceNode, writer); AUTHENTICATION_CONTEXT.marshallAsElement(dataSourceNode, writer); if (dataSourceNode.hasDefined(REAUTH_PLUGIN_CLASSNAME.getName())) { writer.writeStartElement(DsSecurity.Tag.REAUTH_PLUGIN.getLocalName()); writer.writeAttribute( org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(REAUTH_PLUGIN_CLASSNAME.getName()).asString()); if (dataSourceNode.hasDefined(REAUTHPLUGIN_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(REAUTHPLUGIN_PROPERTIES.getName()).asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } writer.writeEndElement(); } boolean recoveryRequired = RECOVERY_USERNAME.isMarshallable(dataSourceNode) || RECOVERY_PASSWORD.isMarshallable(dataSourceNode) || RECOVERY_SECURITY_DOMAIN.isMarshallable(dataSourceNode) || RECOVERY_ELYTRON_ENABLED.isMarshallable(dataSourceNode) || RECOVER_PLUGIN_CLASSNAME.isMarshallable(dataSourceNode) || RECOVERY_CREDENTIAL_REFERENCE.isMarshallable(dataSourceNode) || NO_RECOVERY.isMarshallable(dataSourceNode) || RECOVER_PLUGIN_PROPERTIES.isMarshallable(dataSourceNode); if (recoveryRequired && isXADataSource) { writer.writeStartElement(XaDataSource.Tag.RECOVERY.getLocalName()); NO_RECOVERY.marshallAsAttribute(dataSourceNode, writer); if (hasAnyOf(dataSourceNode, RECOVERY_USERNAME, RECOVERY_PASSWORD, RECOVERY_SECURITY_DOMAIN, RECOVERY_ELYTRON_ENABLED, RECOVERY_CREDENTIAL_REFERENCE)) { writer.writeStartElement(Recovery.Tag.RECOVER_CREDENTIAL.getLocalName()); RECOVERY_USERNAME.marshallAsElement(dataSourceNode, writer); RECOVERY_PASSWORD.marshallAsElement(dataSourceNode, writer); RECOVERY_ELYTRON_ENABLED.marshallAsElement(dataSourceNode, writer); RECOVERY_AUTHENTICATION_CONTEXT.marshallAsElement(dataSourceNode, writer); RECOVERY_SECURITY_DOMAIN.marshallAsElement(dataSourceNode, writer); RECOVERY_CREDENTIAL_REFERENCE.marshallAsElement(dataSourceNode, writer); writer.writeEndElement(); } if (hasAnyOf(dataSourceNode, RECOVER_PLUGIN_CLASSNAME)) { writer.writeStartElement(Recovery.Tag.RECOVER_PLUGIN.getLocalName()); writer.writeAttribute( org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(RECOVER_PLUGIN_CLASSNAME.getName()).asString()); if (dataSourceNode.hasDefined(RECOVER_PLUGIN_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(RECOVER_PLUGIN_PROPERTIES.getName()).asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } writer.writeEndElement(); } boolean validationRequired = VALID_CONNECTION_CHECKER_CLASSNAME.isMarshallable(dataSourceNode) || VALID_CONNECTION_CHECKER_PROPERTIES.isMarshallable(dataSourceNode) || CHECK_VALID_CONNECTION_SQL.isMarshallable(dataSourceNode) || VALIDATE_ON_MATCH.isMarshallable(dataSourceNode) || BACKGROUNDVALIDATION.isMarshallable(dataSourceNode) || BACKGROUNDVALIDATIONMILLIS.isMarshallable(dataSourceNode) || USE_FAST_FAIL.isMarshallable(dataSourceNode) || STALE_CONNECTION_CHECKER_CLASSNAME.isMarshallable(dataSourceNode) || STALE_CONNECTION_CHECKER_PROPERTIES.isMarshallable(dataSourceNode) || EXCEPTION_SORTER_CLASSNAME.isMarshallable(dataSourceNode) || EXCEPTION_SORTER_PROPERTIES.isMarshallable(dataSourceNode); if (validationRequired) { writer.writeStartElement(DataSource.Tag.VALIDATION.getLocalName()); if (dataSourceNode.hasDefined(VALID_CONNECTION_CHECKER_CLASSNAME.getName())) { writer.writeStartElement(Validation.Tag.VALID_CONNECTION_CHECKER.getLocalName()); writer.writeAttribute( org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(VALID_CONNECTION_CHECKER_CLASSNAME.getName()).asString()); if (dataSourceNode.hasDefined(VALID_CONNECTION_CHECKER_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(VALID_CONNECTION_CHECKER_PROPERTIES.getName()) .asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } CHECK_VALID_CONNECTION_SQL.marshallAsElement(dataSourceNode, writer); VALIDATE_ON_MATCH.marshallAsElement(dataSourceNode, writer); BACKGROUNDVALIDATION.marshallAsElement(dataSourceNode, writer); BACKGROUNDVALIDATIONMILLIS.marshallAsElement(dataSourceNode, writer); USE_FAST_FAIL.marshallAsElement(dataSourceNode, writer); if (dataSourceNode.hasDefined(STALE_CONNECTION_CHECKER_CLASSNAME.getName())) { writer.writeStartElement(Validation.Tag.STALE_CONNECTION_CHECKER.getLocalName()); writer.writeAttribute(org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(STALE_CONNECTION_CHECKER_CLASSNAME.getName()).asString()); if (dataSourceNode.hasDefined(STALE_CONNECTION_CHECKER_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(STALE_CONNECTION_CHECKER_PROPERTIES.getName()) .asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } if (dataSourceNode.hasDefined(EXCEPTION_SORTER_CLASSNAME.getName())) { writer.writeStartElement(Validation.Tag.EXCEPTION_SORTER.getLocalName()); writer.writeAttribute( org.jboss.jca.common.api.metadata.common.Extension.Attribute.CLASS_NAME.getLocalName(), dataSourceNode.get(EXCEPTION_SORTER_CLASSNAME.getName()).asString()); if (dataSourceNode.hasDefined(EXCEPTION_SORTER_PROPERTIES.getName())) { for (Property connectionProperty : dataSourceNode.get(EXCEPTION_SORTER_PROPERTIES.getName()) .asPropertyList()) { writeProperty(writer, dataSourceNode, connectionProperty.getName(), connectionProperty .getValue().asString(), org.jboss.jca.common.api.metadata.common.Extension.Tag.CONFIG_PROPERTY .getLocalName()); } } writer.writeEndElement(); } writer.writeEndElement(); } boolean timeoutRequired = BLOCKING_TIMEOUT_WAIT_MILLIS.isMarshallable(dataSourceNode) || IDLETIMEOUTMINUTES.isMarshallable(dataSourceNode) || SET_TX_QUERY_TIMEOUT.isMarshallable(dataSourceNode) || QUERY_TIMEOUT.isMarshallable(dataSourceNode) || USE_TRY_LOCK.isMarshallable(dataSourceNode) || ALLOCATION_RETRY.isMarshallable(dataSourceNode) || ALLOCATION_RETRY_WAIT_MILLIS.isMarshallable(dataSourceNode) || XA_RESOURCE_TIMEOUT.isMarshallable(dataSourceNode); if (timeoutRequired) { writer.writeStartElement(DataSource.Tag.TIMEOUT.getLocalName()); SET_TX_QUERY_TIMEOUT.marshallAsElement(dataSourceNode, writer); BLOCKING_TIMEOUT_WAIT_MILLIS.marshallAsElement(dataSourceNode, writer); IDLETIMEOUTMINUTES.marshallAsElement(dataSourceNode, writer); QUERY_TIMEOUT.marshallAsElement(dataSourceNode, writer); USE_TRY_LOCK.marshallAsElement(dataSourceNode, writer); ALLOCATION_RETRY.marshallAsElement(dataSourceNode, writer); ALLOCATION_RETRY_WAIT_MILLIS.marshallAsElement(dataSourceNode, writer); XA_RESOURCE_TIMEOUT.marshallAsElement(dataSourceNode, writer); writer.writeEndElement(); } boolean statementRequired = hasAnyOf(dataSourceNode, TRACK_STATEMENTS, PREPARED_STATEMENTS_CACHE_SIZE, SHARE_PREPARED_STATEMENTS); if (statementRequired) { writer.writeStartElement(DataSource.Tag.STATEMENT.getLocalName()); TRACK_STATEMENTS.marshallAsElement(dataSourceNode, writer); PREPARED_STATEMENTS_CACHE_SIZE.marshallAsElement(dataSourceNode, writer); SHARE_PREPARED_STATEMENTS.marshallAsElement(dataSourceNode, writer); writer.writeEndElement(); } writer.writeEndElement(); } } private void writeAttributeIfHas(final XMLExtendedStreamWriter writer, final ModelNode node, final Driver.Attribute attr, final String identifier) throws XMLStreamException { if (has(node, identifier)) { writer.writeAttribute(attr.getLocalName(), node.get(identifier).asString()); } } private void writeProperty(XMLExtendedStreamWriter writer, ModelNode node, String name, String value, String localName) throws XMLStreamException { writer.writeStartElement(localName); writer.writeAttribute("name", name); writer.writeCharacters(value); writer.writeEndElement(); } private void writeElementIfHas(XMLExtendedStreamWriter writer, ModelNode node, String localName, String identifier) throws XMLStreamException { if (has(node, identifier)) { writer.writeStartElement(localName); String content = node.get(identifier).asString(); if (content.indexOf('\n') > -1) { writer.writeCharacters(content); } else { // Use the method where staxmapper won't add new lines char[] chars = content.toCharArray(); writer.writeCharacters(chars, 0, chars.length); } writer.writeEndElement(); } } private boolean hasAnyOf(ModelNode node, SimpleAttributeDefinition... names) { for (SimpleAttributeDefinition current : names) { if (has(node, current.getName())) { return true; } } return false; } private boolean has(ModelNode node, String name) { return node.has(name) && node.get(name).isDefined(); } @Override public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException { final ModelNode address = new ModelNode(); address.add(ModelDescriptionConstants.SUBSYSTEM, DATASOURCES); address.protect(); final ModelNode subsystem = new ModelNode(); subsystem.get(OP).set(ADD); subsystem.get(OP_ADDR).set(address); list.add(subsystem); try { String localName = null; localName = reader.getLocalName(); Element element = Element.forName(reader.getLocalName()); SUBSYSTEM_DATASOURCES_LOGGER.tracef("%s -> %s", localName, element); switch (element) { case SUBSYSTEM: { final DsParser parser = new DsParser(); parser.parse(reader, list, address); requireNoContent(reader); break; } } } catch (Exception e) { throw new XMLStreamException(e); } } } }