/* * JBoss, Home of Professional Open Source. * Copyright 2011, 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.wildfly.extension.messaging.activemq.jms; import static java.util.Collections.EMPTY_LIST; import static org.jboss.as.naming.deployment.ContextNames.BindInfo; import static org.wildfly.extension.messaging.activemq.BinderServiceUtil.installAliasBinderService; import static org.wildfly.extension.messaging.activemq.MessagingServices.getActiveMQServiceName; import static org.wildfly.extension.messaging.activemq.jms.ConnectionFactoryAttributes.Pooled.REBALANCE_CONNECTIONS_PROP_NAME; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.activemq.artemis.api.core.BroadcastEndpointFactory; import org.apache.activemq.artemis.api.core.ChannelBroadcastEndpointFactory; import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.jboss.as.connector.metadata.common.CredentialImpl; import org.jboss.as.connector.metadata.common.SecurityImpl; import org.jboss.as.connector.metadata.deployment.ResourceAdapterDeployment; import org.jboss.as.connector.services.mdr.AS7MetadataRepository; import org.jboss.as.connector.services.resourceadapters.ResourceAdapterActivatorService; import org.jboss.as.connector.services.resourceadapters.deployment.registry.ResourceAdapterDeploymentRegistry; import org.jboss.as.connector.subsystems.jca.JcaSubsystemConfiguration; import org.jboss.as.connector.util.ConnectorServices; import org.jboss.as.controller.OperationContext; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.security.CredentialReference; import org.jboss.as.naming.deployment.ContextNames; import org.jboss.as.naming.service.NamingService; import org.jboss.as.network.SocketBinding; import org.jboss.as.security.service.SecurityBootstrapService; import org.jboss.as.server.Services; import org.jboss.as.txn.service.TxnServices; import org.jboss.dmr.ModelNode; import org.jboss.jca.common.api.metadata.Defaults; import org.jboss.jca.common.api.metadata.common.FlushStrategy; import org.jboss.jca.common.api.metadata.common.Pool; import org.jboss.jca.common.api.metadata.common.Recovery; import org.jboss.jca.common.api.metadata.common.Security; import org.jboss.jca.common.api.metadata.common.TimeOut; import org.jboss.jca.common.api.metadata.common.TransactionSupportEnum; import org.jboss.jca.common.api.metadata.common.Validation; import org.jboss.jca.common.api.metadata.resourceadapter.Activation; import org.jboss.jca.common.api.metadata.resourceadapter.AdminObject; import org.jboss.jca.common.api.metadata.resourceadapter.ConnectionDefinition; import org.jboss.jca.common.api.metadata.spec.Activationspec; import org.jboss.jca.common.api.metadata.spec.AuthenticationMechanism; import org.jboss.jca.common.api.metadata.spec.ConfigProperty; import org.jboss.jca.common.api.metadata.spec.Connector; import org.jboss.jca.common.api.metadata.spec.CredentialInterfaceEnum; import org.jboss.jca.common.api.metadata.spec.Icon; import org.jboss.jca.common.api.metadata.spec.InboundResourceAdapter; import org.jboss.jca.common.api.metadata.spec.LocalizedXsdString; import org.jboss.jca.common.api.metadata.spec.MessageListener; import org.jboss.jca.common.api.metadata.spec.Messageadapter; import org.jboss.jca.common.api.metadata.spec.OutboundResourceAdapter; import org.jboss.jca.common.api.metadata.spec.RequiredConfigProperty; import org.jboss.jca.common.api.metadata.spec.ResourceAdapter; import org.jboss.jca.common.api.metadata.spec.SecurityPermission; import org.jboss.jca.common.api.metadata.spec.XsdString; import org.jboss.jca.common.api.validator.ValidateException; import org.jboss.jca.common.metadata.common.PoolImpl; import org.jboss.jca.common.metadata.common.TimeOutImpl; import org.jboss.jca.common.metadata.common.ValidationImpl; import org.jboss.jca.common.metadata.common.XaPoolImpl; import org.jboss.jca.common.metadata.resourceadapter.ActivationImpl; import org.jboss.jca.common.metadata.resourceadapter.ConnectionDefinitionImpl; import org.jboss.jca.common.metadata.spec.ActivationSpecImpl; import org.jboss.jca.common.metadata.spec.AuthenticationMechanismImpl; import org.jboss.jca.common.metadata.spec.ConfigPropertyImpl; import org.jboss.jca.common.metadata.spec.ConnectorImpl; import org.jboss.jca.common.metadata.spec.InboundResourceAdapterImpl; import org.jboss.jca.common.metadata.spec.MessageAdapterImpl; import org.jboss.jca.common.metadata.spec.MessageListenerImpl; import org.jboss.jca.common.metadata.spec.OutboundResourceAdapterImpl; import org.jboss.jca.common.metadata.spec.RequiredConfigPropertyImpl; import org.jboss.jca.common.metadata.spec.ResourceAdapterImpl; import org.jboss.jca.core.api.connectionmanager.ccm.CachedConnectionManager; import org.jboss.jca.core.api.management.ManagementRepository; import org.jboss.jca.core.spi.rar.ResourceAdapterRepository; import org.jboss.jca.core.spi.transaction.TransactionIntegration; import org.jboss.msc.inject.Injector; import org.jboss.msc.inject.MapInjector; import org.jboss.msc.service.Service; import org.jboss.msc.service.ServiceBuilder; import org.jboss.msc.service.ServiceContainer; import org.jboss.msc.service.ServiceController; import org.jboss.msc.service.ServiceName; import org.jboss.msc.service.ServiceTarget; import org.jboss.msc.service.StartContext; import org.jboss.msc.service.StartException; import org.jboss.msc.service.StopContext; import org.jboss.msc.value.InjectedValue; import org.wildfly.common.function.ExceptionSupplier; import org.wildfly.extension.messaging.activemq.ActiveMQActivationService; import org.wildfly.extension.messaging.activemq.JGroupsChannelLocator; import org.wildfly.extension.messaging.activemq.MessagingServices; import org.wildfly.extension.messaging.activemq.logging.MessagingLogger; import org.wildfly.security.credential.PasswordCredential; import org.wildfly.security.credential.source.CredentialSource; import org.wildfly.security.password.interfaces.ClearPassword; /** * A service which translates a pooled connection factory into a resource adapter driven connection pool * * @author <a href="mailto:andy.taylor@jboss.com">Andy Taylor</a> * @author <a href="mailto:jbertram@redhat.com">Justin Bertram</a> * @author Jason T. Greene * Date: 5/13/11 * Time: 2:21 PM */ public class PooledConnectionFactoryService implements Service<Void> { private static final List<LocalizedXsdString> EMPTY_LOCL = Collections.emptyList(); public static final String CONNECTOR_CLASSNAME = "connectorClassName"; public static final String CONNECTION_PARAMETERS = "connectionParameters"; private static final String ACTIVEMQ_ACTIVATION = "org.apache.activemq.artemis.ra.inflow.ActiveMQActivationSpec"; private static final String ACTIVEMQ_CONN_DEF = "ActiveMQConnectionDefinition"; private static final String ACTIVEMQ_RESOURCE_ADAPTER = "org.apache.activemq.artemis.ra.ActiveMQResourceAdapter"; private static final String RAMANAGED_CONN_FACTORY = "org.apache.activemq.artemis.ra.ActiveMQRAManagedConnectionFactory"; private static final String RA_CONN_FACTORY = "org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactory"; private static final String RA_CONN_FACTORY_IMPL = "org.apache.activemq.artemis.ra.ActiveMQRAConnectionFactoryImpl"; private static final String JMS_SESSION = "javax.jms.Session"; private static final String ACTIVEMQ_RA_SESSION = "org.apache.activemq.artemis.ra.ActiveMQRASession"; private static final String BASIC_PASS = "BasicPassword"; private static final String JMS_QUEUE = "javax.jms.Queue"; private static final String STRING_TYPE = "java.lang.String"; private static final String INTEGER_TYPE = "java.lang.Integer"; private static final String LONG_TYPE = "java.lang.Long"; private static final String SESSION_DEFAULT_TYPE = "SessionDefaultType"; private static final String TRY_LOCK = "UseTryLock"; private static final String JMS_MESSAGE_LISTENER = "javax.jms.MessageListener"; private static final String DEFAULT_MAX_RECONNECTS = "5"; public static final String GROUP_ADDRESS = "discoveryAddress"; public static final String DISCOVERY_INITIAL_WAIT_TIMEOUT = "discoveryInitialWaitTimeout"; public static final String GROUP_PORT = "discoveryPort"; public static final String REFRESH_TIMEOUT = "discoveryRefreshTimeout"; public static final String DISCOVERY_LOCAL_BIND_ADDRESS = "discoveryLocalBindAddress"; public static final String JGROUPS_CHANNEL_LOCATOR_CLASS = "jgroupsChannelLocatorClass"; public static final String JGROUPS_CHANNEL_NAME = "jgroupsChannelName"; public static final String JGROUPS_CHANNEL_REF_NAME = "jgroupsChannelRefName"; private Injector<Object> transactionManager = new InjectedValue<Object>(); private List<String> connectors; private String discoveryGroupName; private List<PooledConnectionFactoryConfigProperties> adapterParams; private String name; private Map<String, SocketBinding> socketBindings = new HashMap<String, SocketBinding>(); private InjectedValue<ActiveMQServer> activeMQServer = new InjectedValue<>(); private BindInfo bindInfo; private final boolean pickAnyConnectors; private List<String> jndiAliases; private String txSupport; private int minPoolSize; private int maxPoolSize; private String serverName; private final String jgroupsChannelName; private final boolean createBinderService; private final String managedConnectionPoolClassName; // can be null. In that case the behaviour is depending on the IronJacamar container setting. private final Boolean enlistmentTrace; private InjectedValue<ExceptionSupplier<CredentialSource, Exception>> credentialSourceSupplier = new InjectedValue<>(); public PooledConnectionFactoryService(String name, List<String> connectors, String discoveryGroupName, String serverName, String jgroupsChannelName, List<PooledConnectionFactoryConfigProperties> adapterParams, List<String> jndiNames, String txSupport, int minPoolSize, int maxPoolSize, String managedConnectionPoolClassName, Boolean enlistmentTrace) { this.name = name; this.connectors = connectors; this.discoveryGroupName = discoveryGroupName; this.serverName = serverName; this.jgroupsChannelName = jgroupsChannelName; this.adapterParams = adapterParams; initJNDIBindings(jndiNames); createBinderService = true; this.txSupport = txSupport; this.minPoolSize = minPoolSize; this.maxPoolSize = maxPoolSize; this.managedConnectionPoolClassName = managedConnectionPoolClassName; this.enlistmentTrace = enlistmentTrace; this.pickAnyConnectors = false; } public PooledConnectionFactoryService(String name, List<String> connectors, String discoveryGroupName, String serverName, String jgroupsChannelName, List<PooledConnectionFactoryConfigProperties> adapterParams, BindInfo bindInfo, String txSupport, int minPoolSize, int maxPoolSize, String managedConnectionPoolClassName, Boolean enlistmentTrace, boolean pickAnyConnectors) { this.name = name; this.connectors = connectors; this.discoveryGroupName = discoveryGroupName; this.serverName = serverName; this.jgroupsChannelName = jgroupsChannelName; this.adapterParams = adapterParams; this.bindInfo = bindInfo; this.jndiAliases = EMPTY_LIST; this.createBinderService = false; this.txSupport = txSupport; this.minPoolSize = minPoolSize; this.maxPoolSize = maxPoolSize; this.managedConnectionPoolClassName = managedConnectionPoolClassName; this.enlistmentTrace = enlistmentTrace; this.pickAnyConnectors = pickAnyConnectors; } private void initJNDIBindings(List<String> jndiNames) { // create the definition with the 1st jndi names and create jndi aliases for the rest String jndiName = jndiNames.get(0); this.bindInfo = ContextNames.bindInfoFor(jndiName); this.jndiAliases = new ArrayList<String>(); if (jndiNames.size() > 1) { jndiAliases = jndiNames.subList(1, jndiNames.size()); } } static ServiceName getResourceAdapterActivatorsServiceName(String name) { return ConnectorServices.RESOURCE_ADAPTER_ACTIVATOR_SERVICE.append(name); } InjectedValue<ExceptionSupplier<CredentialSource, Exception>> getCredentialSourceSupplierInjector() { return credentialSourceSupplier; } public static void installService(ServiceTarget serviceTarget, String name, String serverName, List<String> connectors, String discoveryGroupName, String jgroupsChannelName, List<PooledConnectionFactoryConfigProperties> adapterParams, BindInfo bindInfo, String txSupport, int minPoolSize, int maxPoolSize, String managedConnectionPoolClassName, Boolean enlistmentTrace, boolean pickAnyConnectors) { ServiceName serverServiceName = MessagingServices.getActiveMQServiceName(serverName); ServiceName serviceName = JMSServices.getPooledConnectionFactoryBaseServiceName(serverServiceName).append(name); PooledConnectionFactoryService service = new PooledConnectionFactoryService(name, connectors, discoveryGroupName, serverName, jgroupsChannelName, adapterParams, bindInfo, txSupport, minPoolSize, maxPoolSize, managedConnectionPoolClassName, enlistmentTrace, pickAnyConnectors); installService0(serviceTarget, serverServiceName, serviceName, service); } public static void installService(OperationContext context, String name, String serverName, List<String> connectors, String discoveryGroupName, String jgroupsChannelName, List<PooledConnectionFactoryConfigProperties> adapterParams, List<String> jndiNames, String txSupport, int minPoolSize, int maxPoolSize, String managedConnectionPoolClassName, Boolean enlistmentTrace, ModelNode model) throws OperationFailedException { ServiceName serverServiceName = MessagingServices.getActiveMQServiceName(serverName); ServiceName serviceName = JMSServices.getPooledConnectionFactoryBaseServiceName(serverServiceName).append(name); PooledConnectionFactoryService service = new PooledConnectionFactoryService(name, connectors, discoveryGroupName, serverName, jgroupsChannelName, adapterParams, jndiNames, txSupport, minPoolSize, maxPoolSize, managedConnectionPoolClassName, enlistmentTrace); installService0(context, serverServiceName, serviceName, service, model); } private static void installService0(ServiceTarget serviceTarget, ServiceName serverServiceName, ServiceName serviceName, PooledConnectionFactoryService service) { ServiceBuilder serviceBuilder = createServiceBuilder(serviceTarget, serverServiceName, serviceName, service); serviceBuilder.install(); } private static void installService0(OperationContext context, ServiceName serverServiceName, ServiceName serviceName, PooledConnectionFactoryService service, ModelNode model) throws OperationFailedException { ServiceBuilder serviceBuilder = createServiceBuilder(context.getServiceTarget(), serverServiceName, serviceName, service); ModelNode credentialReference = ConnectionFactoryAttributes.Pooled.CREDENTIAL_REFERENCE.resolveModelAttribute(context, model); if (credentialReference.isDefined()) { service.getCredentialSourceSupplierInjector().inject(CredentialReference.getCredentialSourceSupplier(context, ConnectionFactoryAttributes.Pooled.CREDENTIAL_REFERENCE, model, serviceBuilder)); } serviceBuilder.install(); } private static ServiceBuilder createServiceBuilder(ServiceTarget serviceTarget, ServiceName serverServiceName, ServiceName serviceName, PooledConnectionFactoryService service) { ServiceBuilder serviceBuilder = serviceTarget .addService(serviceName, service) .addDependency(TxnServices.JBOSS_TXN_TRANSACTION_MANAGER, service.transactionManager) .addDependency(serverServiceName, ActiveMQServer.class, service.activeMQServer) .addDependency(ActiveMQActivationService.getServiceName(serverServiceName)) .addDependency(JMSServices.getJmsManagerBaseServiceName(serverServiceName)) // ensures that Artemis client thread pools are not stopped before any deployment depending on a pooled-connection-factory .addDependency(MessagingServices.ACTIVEMQ_CLIENT_THREAD_POOL) // WFLY-6652 this dependency ensures that Artemis will be able to destroy any queues created on behalf of a // pooled-connection-factory client during server stop .addDependency(SecurityBootstrapService.SERVICE_NAME) .setInitialMode(ServiceController.Mode.PASSIVE); return serviceBuilder; } public Void getValue() throws IllegalStateException, IllegalArgumentException { return null; } public void start(StartContext context) throws StartException { ServiceTarget serviceTarget = context.getChildTarget(); try { createService(serviceTarget, context.getController().getServiceContainer()); } catch (Exception e) { throw MessagingLogger.ROOT_LOGGER.failedToCreate(e, "resource adapter"); } } private void createService(ServiceTarget serviceTarget, ServiceContainer container) throws Exception { InputStream is = null; InputStream isIj = null; List<ConfigProperty> properties = new ArrayList<ConfigProperty>(); try { StringBuilder connectorClassname = new StringBuilder(); StringBuilder connectorParams = new StringBuilder(); // if there is no discovery-group and the connector list is empty, // pick the first connector available if pickAnyConnectors is true if (discoveryGroupName == null && connectors.isEmpty() && pickAnyConnectors) { Set<String> connectorNames = activeMQServer.getValue().getConfiguration().getConnectorConfigurations().keySet(); if (connectorNames.size() > 0) { String connectorName = connectorNames.iterator().next(); MessagingLogger.ROOT_LOGGER.connectorForPooledConnectionFactory(name, connectorName); connectors.add(connectorName); } } for (String connector : connectors) { TransportConfiguration tc = activeMQServer.getValue().getConfiguration().getConnectorConfigurations().get(connector); if(tc == null) { throw MessagingLogger.ROOT_LOGGER.connectorNotDefined(connector); } if (connectorClassname.length() > 0) { connectorClassname.append(","); connectorParams.append(","); } connectorClassname.append(tc.getFactoryClassName()); Map<String, Object> params = tc.getParams(); boolean multiple = false; for (Map.Entry<String, Object> entry : params.entrySet()) { if (multiple) { connectorParams.append(";"); } connectorParams.append(entry.getKey()).append("=").append(entry.getValue()); multiple = true; } } if (connectorClassname.length() > 0) { properties.add(simpleProperty15(CONNECTOR_CLASSNAME, STRING_TYPE, connectorClassname.toString())); } if (connectorParams.length() > 0) { properties.add(simpleProperty15(CONNECTION_PARAMETERS, STRING_TYPE, connectorParams.toString())); } if(discoveryGroupName != null) { DiscoveryGroupConfiguration discoveryGroupConfiguration = activeMQServer.getValue().getConfiguration().getDiscoveryGroupConfigurations().get(discoveryGroupName); BroadcastEndpointFactory bgCfg = discoveryGroupConfiguration.getBroadcastEndpointFactory(); if (bgCfg instanceof UDPBroadcastEndpointFactory) { UDPBroadcastEndpointFactory udpCfg = (UDPBroadcastEndpointFactory) bgCfg; properties.add(simpleProperty15(GROUP_ADDRESS, STRING_TYPE, udpCfg.getGroupAddress())); properties.add(simpleProperty15(GROUP_PORT, INTEGER_TYPE, "" + udpCfg.getGroupPort())); properties.add(simpleProperty15(DISCOVERY_LOCAL_BIND_ADDRESS, STRING_TYPE, "" + udpCfg.getLocalBindAddress())); } else if (bgCfg instanceof ChannelBroadcastEndpointFactory) { properties.add(simpleProperty15(JGROUPS_CHANNEL_LOCATOR_CLASS, STRING_TYPE, JGroupsChannelLocator.class.getName())); properties.add(simpleProperty15(JGROUPS_CHANNEL_NAME, STRING_TYPE, jgroupsChannelName)); properties.add(simpleProperty15(JGROUPS_CHANNEL_REF_NAME, STRING_TYPE, serverName + '/' + jgroupsChannelName)); } properties.add(simpleProperty15(DISCOVERY_INITIAL_WAIT_TIMEOUT, LONG_TYPE, "" + discoveryGroupConfiguration.getDiscoveryInitialWaitTimeout())); properties.add(simpleProperty15(REFRESH_TIMEOUT, LONG_TYPE, "" + discoveryGroupConfiguration.getRefreshTimeout())); } boolean hasReconnect = false; final List<ConfigProperty> inboundProperties = new ArrayList<>(); final String reconnectName = ConnectionFactoryAttributes.Pooled.RECONNECT_ATTEMPTS_PROP_NAME; for (PooledConnectionFactoryConfigProperties adapterParam : adapterParams) { hasReconnect |= reconnectName.equals(adapterParam.getName()); ConfigProperty p = simpleProperty15(adapterParam.getName(), adapterParam.getType(), adapterParam.getValue()); if (adapterParam.getName().equals(REBALANCE_CONNECTIONS_PROP_NAME)) { boolean rebalanceConnections = Boolean.parseBoolean(adapterParam.getValue()); if (rebalanceConnections) { inboundProperties.add(p); } } else { properties.add(p); } } // The default -1, which will hang forever until a server appears if (!hasReconnect) { properties.add(simpleProperty15(reconnectName, Integer.class.getName(), DEFAULT_MAX_RECONNECTS)); } configureCredential(properties); WildFlyRecoveryRegistry.container = container; OutboundResourceAdapter outbound = createOutbound(); InboundResourceAdapter inbound = createInbound(inboundProperties); ResourceAdapter ra = createResourceAdapter15(properties, outbound, inbound); Connector cmd = createConnector15(ra); TransactionSupportEnum transactionSupport = getTransactionSupport(txSupport); ConnectionDefinition common = createConnDef(transactionSupport, bindInfo.getBindName(), minPoolSize, maxPoolSize, managedConnectionPoolClassName, enlistmentTrace); Activation activation = createActivation(common, transactionSupport); ResourceAdapterActivatorService activator = new ResourceAdapterActivatorService(cmd, activation, PooledConnectionFactoryService.class.getClassLoader(), name); activator.setBindInfo(bindInfo); activator.setCreateBinderService(createBinderService); ServiceController<ResourceAdapterDeployment> controller = Services.addServerExecutorDependency( serviceTarget.addService(getResourceAdapterActivatorsServiceName(name), activator), activator.getExecutorServiceInjector()) .addDependency(ActiveMQActivationService.getServiceName(getActiveMQServiceName(serverName))) .addDependency(ConnectorServices.IRONJACAMAR_MDR, AS7MetadataRepository.class, activator.getMdrInjector()) .addDependency(ConnectorServices.RA_REPOSITORY_SERVICE, ResourceAdapterRepository.class, activator.getRaRepositoryInjector()) .addDependency(ConnectorServices.MANAGEMENT_REPOSITORY_SERVICE, ManagementRepository.class, activator.getManagementRepositoryInjector()) .addDependency(ConnectorServices.RESOURCE_ADAPTER_REGISTRY_SERVICE, ResourceAdapterDeploymentRegistry.class, activator.getRegistryInjector()) .addDependency(ConnectorServices.TRANSACTION_INTEGRATION_SERVICE, TransactionIntegration.class, activator.getTxIntegrationInjector()) .addDependency(ConnectorServices.CONNECTOR_CONFIG_SERVICE, JcaSubsystemConfiguration.class, activator.getConfigInjector()) // No legacy security services needed as this activation's sole connection definition // does not configure a legacy security domain /* .addDependency(SubjectFactoryService.SERVICE_NAME, SubjectFactory.class, activator.getSubjectFactoryInjector()) */ .addDependency(ConnectorServices.CCM_SERVICE, CachedConnectionManager.class, activator.getCcmInjector()).addDependency(NamingService.SERVICE_NAME) .addDependency(TxnServices.JBOSS_TXN_TRANSACTION_MANAGER) .addDependency(ConnectorServices.BOOTSTRAP_CONTEXT_SERVICE.append("default")) .setInitialMode(ServiceController.Mode.PASSIVE).install(); createJNDIAliases(bindInfo, jndiAliases, controller); // Mock the deployment service to allow it to start serviceTarget.addService(ConnectorServices.RESOURCE_ADAPTER_DEPLOYER_SERVICE_PREFIX.append(name), Service.NULL).install(); } finally { if (is != null) is.close(); if (isIj != null) isIj.close(); } } /** * Configure password from a credential-reference (as an alternative to the password attribute) * and add it to the RA properties. */ private void configureCredential(List<ConfigProperty> properties) { // if a credential-reference has been defined, get the password property from it if (credentialSourceSupplier.getOptionalValue() != null) { try { CredentialSource credentialSource = credentialSourceSupplier.getValue().get(); if (credentialSource != null) { char[] password = credentialSource.getCredential(PasswordCredential.class).getPassword(ClearPassword.class).getPassword(); if (password != null) { // add the password property properties.add(simpleProperty15("password", String.class.getName(), new String(password))); } } } catch (Exception e) { throw new RuntimeException(e); } } } private void createJNDIAliases(final BindInfo bindInfo, List<String> aliases, ServiceController<ResourceAdapterDeployment> controller) { for (final String alias : aliases) { // do not install the alias' binder service if it is already registered if (controller.getServiceContainer().getService(ContextNames.bindInfoFor(alias).getBinderServiceName()) == null) { installAliasBinderService(controller.getServiceContainer(), bindInfo, alias); } } } private static TransactionSupportEnum getTransactionSupport(String txSupport) { try { return TransactionSupportEnum.valueOf(txSupport); } catch (RuntimeException e) { return TransactionSupportEnum.LocalTransaction; } } private static Activation createActivation(ConnectionDefinition common, TransactionSupportEnum transactionSupport) { List<ConnectionDefinition> definitions = Collections.singletonList(common); return new ActivationImpl(null, null, transactionSupport, definitions, Collections.<AdminObject>emptyList(), Collections.<String, String>emptyMap(), Collections.<String>emptyList(), null, null); } private static ConnectionDefinition createConnDef(TransactionSupportEnum transactionSupport, String jndiName, int minPoolSize, int maxPoolSize, String managedConnectionPoolClassName, Boolean enlistmentTrace) throws ValidateException { Integer minSize = (minPoolSize == -1) ? null : minPoolSize; Integer maxSize = (maxPoolSize == -1) ? null : maxPoolSize; boolean prefill = false; boolean useStrictMin = false; FlushStrategy flushStrategy = FlushStrategy.FAILING_CONNECTION_ONLY; Boolean isXA = Boolean.FALSE; final Pool pool; if (transactionSupport == TransactionSupportEnum.XATransaction) { pool = new XaPoolImpl(minSize, Defaults.INITIAL_POOL_SIZE, maxSize, prefill, useStrictMin, flushStrategy, null, Defaults.FAIR, Defaults.IS_SAME_RM_OVERRIDE, Defaults.INTERLEAVING, Defaults.PAD_XID, Defaults.WRAP_XA_RESOURCE, Defaults.NO_TX_SEPARATE_POOL); isXA = Boolean.TRUE; } else { pool = new PoolImpl(minSize, Defaults.INITIAL_POOL_SIZE, maxSize, prefill, useStrictMin, flushStrategy, null, Defaults.FAIR); } TimeOut timeOut = new TimeOutImpl(null, null, null, null, null) { }; // <security> // <application /> // </security> // => PoolStrategy.POOL_BY_CRI Security security = new SecurityImpl(null, null, true, false); // register the XA Connection *without* recovery. ActiveMQ already takes care of the registration with the correct credentials // when its ResourceAdapter is started Recovery recovery = new Recovery(new CredentialImpl(null, null, null, false, null), null, Boolean.TRUE); Validation validation = new ValidationImpl(Defaults.VALIDATE_ON_MATCH, null, null, false); // do no track return new ConnectionDefinitionImpl(Collections.<String, String>emptyMap(), RAMANAGED_CONN_FACTORY, jndiName, ACTIVEMQ_CONN_DEF, true, true, true, Defaults.SHARABLE, Defaults.ENLISTMENT, Defaults.CONNECTABLE, false, managedConnectionPoolClassName, enlistmentTrace, pool, timeOut, validation, security, recovery, isXA); } private static Connector createConnector15(ResourceAdapter ra) { return new ConnectorImpl(Connector.Version.V_15, null, str("Red Hat"), str("JMS 1.1 Server"), str("1.0"), null, ra, null, false, EMPTY_LOCL, EMPTY_LOCL, Collections.<Icon>emptyList(), null); } private ResourceAdapter createResourceAdapter15(List<ConfigProperty> properties, OutboundResourceAdapter outbound, InboundResourceAdapter inbound) { return new ResourceAdapterImpl(str(ACTIVEMQ_RESOURCE_ADAPTER), properties, outbound, inbound, Collections.<org.jboss.jca.common.api.metadata.spec.AdminObject>emptyList(), Collections.<SecurityPermission>emptyList(), null); } private InboundResourceAdapter createInbound(List<ConfigProperty> inboundProps) { List<RequiredConfigProperty> destination = Collections.<RequiredConfigProperty>singletonList(new RequiredConfigPropertyImpl(EMPTY_LOCL, str("destination"), null)); Activationspec activation15 = new ActivationSpecImpl(str(ACTIVEMQ_ACTIVATION), destination, inboundProps, null); List<MessageListener> messageListeners = Collections.<MessageListener>singletonList(new MessageListenerImpl(str(JMS_MESSAGE_LISTENER), activation15, null)); Messageadapter message = new MessageAdapterImpl(messageListeners, null); return new InboundResourceAdapterImpl(message, null); } private static OutboundResourceAdapter createOutbound() { List<org.jboss.jca.common.api.metadata.spec.ConnectionDefinition> definitions = new ArrayList<org.jboss.jca.common.api.metadata.spec.ConnectionDefinition>(); List<ConfigProperty> props = new ArrayList<ConfigProperty>(); props.add(simpleProperty15(SESSION_DEFAULT_TYPE, STRING_TYPE, JMS_QUEUE)); props.add(simpleProperty15(TRY_LOCK, INTEGER_TYPE, "0")); definitions.add(new org.jboss.jca.common.metadata.spec.ConnectionDefinitionImpl(str(RAMANAGED_CONN_FACTORY), props, str(RA_CONN_FACTORY), str(RA_CONN_FACTORY_IMPL), str(JMS_SESSION), str(ACTIVEMQ_RA_SESSION), null)); AuthenticationMechanism basicPassword = new AuthenticationMechanismImpl(Collections.<LocalizedXsdString>emptyList(), str(BASIC_PASS), CredentialInterfaceEnum.PasswordCredential, null, null); return new OutboundResourceAdapterImpl(definitions, TransactionSupportEnum.XATransaction, Collections.singletonList(basicPassword), false, null, null, null); } private static XsdString str(String str) { return new XsdString(str, null); } private static ConfigProperty simpleProperty15(String name, String type, String value) { return new ConfigPropertyImpl(EMPTY_LOCL, str(name), str(type), str(value), null, null, null, null, false, null, null, null, null); } public void stop(StopContext context) { // Service context takes care of this } public Injector<Object> getTransactionManager() { return transactionManager; } Injector<SocketBinding> getSocketBindingInjector(String name) { return new MapInjector<String, SocketBinding>(socketBindings, name); } public Injector<ActiveMQServer> getActiveMQServer() { return activeMQServer; } }