/* * JBoss, Home of Professional Open Source. * Copyright 2015, 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.legacy; import static org.wildfly.extension.messaging.activemq.CommonAttributes.LEGACY; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jms.ConnectionFactory; import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.hornetq.api.config.HornetQDefaultConfiguration; import org.hornetq.api.core.BroadcastEndpointFactoryConfiguration; import org.hornetq.api.core.DiscoveryGroupConfiguration; import org.hornetq.api.core.TransportConfiguration; import org.hornetq.api.core.UDPBroadcastGroupConfiguration; import org.hornetq.api.jms.HornetQJMSClient; import org.hornetq.api.jms.JMSFactoryType; import org.hornetq.core.remoting.impl.netty.TransportConstants; import org.hornetq.jms.client.HornetQConnectionFactory; import org.jboss.msc.service.Service; 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.extension.messaging.activemq.ActiveMQActivationService; import org.wildfly.extension.messaging.activemq.jms.JMSServices; import org.wildfly.extension.messaging.activemq.logging.MessagingLogger; /** * @author <a href="http://jmesnil.net/">Jeff Mesnil</a> (c) 2015 Red Hat inc. */ public class LegacyConnectionFactoryService implements Service<ConnectionFactory> { /** * Map ActiveMQ parameters key (using CameCalse convention) to HornetQ parameter keys (using lisp-case convention) */ private static final Map<String, String> PARAM_KEY_MAPPING = new HashMap<>(); static { PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.SSL_ENABLED_PROP_NAME, TransportConstants.SSL_ENABLED_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_ENABLED_PROP_NAME, TransportConstants.HTTP_ENABLED_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_CLIENT_IDLE_PROP_NAME, TransportConstants.HTTP_CLIENT_IDLE_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_CLIENT_IDLE_SCAN_PERIOD, TransportConstants.HTTP_CLIENT_IDLE_SCAN_PERIOD); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_REQUIRES_SESSION_ID, TransportConstants.HTTP_REQUIRES_SESSION_ID); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_UPGRADE_ENABLED_PROP_NAME, TransportConstants.HTTP_UPGRADE_ENABLED_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.HTTP_UPGRADE_ENDPOINT_PROP_NAME, TransportConstants.HTTP_UPGRADE_ENDPOINT_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.USE_SERVLET_PROP_NAME, TransportConstants.USE_SERVLET_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.SERVLET_PATH, TransportConstants.SERVLET_PATH); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.USE_NIO_PROP_NAME, TransportConstants.USE_NIO_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.USE_NIO_GLOBAL_WORKER_POOL_PROP_NAME, TransportConstants.USE_NIO_GLOBAL_WORKER_POOL_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.LOCAL_ADDRESS_PROP_NAME, TransportConstants.LOCAL_ADDRESS_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, TransportConstants.KEYSTORE_PROVIDER_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.KEYSTORE_PATH_PROP_NAME, TransportConstants.KEYSTORE_PATH_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, TransportConstants.KEYSTORE_PASSWORD_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TRUSTSTORE_PATH_PROP_NAME, TransportConstants.TRUSTSTORE_PATH_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME, TransportConstants.ENABLED_CIPHER_SUITES_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.ENABLED_PROTOCOLS_PROP_NAME, TransportConstants.ENABLED_PROTOCOLS_PROP_NAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TCP_NODELAY_PROPNAME, TransportConstants.TCP_NODELAY_PROPNAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME, TransportConstants.TCP_SENDBUFFER_SIZE_PROPNAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME, TransportConstants.TCP_RECEIVEBUFFER_SIZE_PROPNAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.NIO_REMOTING_THREADS_PROPNAME, TransportConstants.NIO_REMOTING_THREADS_PROPNAME); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.BATCH_DELAY, TransportConstants.BATCH_DELAY); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.NIO_REMOTING_THREADS_PROPNAME, TransportConstants.NIO_REMOTING_THREADS_PROPNAME); PARAM_KEY_MAPPING.put( ActiveMQDefaultConfiguration.getPropMaskPassword(), HornetQDefaultConfiguration.getPropMaskPassword()); PARAM_KEY_MAPPING.put( ActiveMQDefaultConfiguration.getPropPasswordCodec(), HornetQDefaultConfiguration.getPropPasswordCodec()); PARAM_KEY_MAPPING.put( org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.NETTY_CONNECT_TIMEOUT, TransportConstants.NETTY_CONNECT_TIMEOUT); } private final InjectedValue<ActiveMQServer> injectedActiveMQServer = new InjectedValue<ActiveMQServer>(); private final HornetQConnectionFactory uncompletedConnectionFactory; private final String discoveryGroupName; private final List<String> connectors; private HornetQConnectionFactory connectionFactory; public LegacyConnectionFactoryService(HornetQConnectionFactory uncompletedConnectionFactory, String discoveryGroupName, List<String> connectors) { this.uncompletedConnectionFactory = uncompletedConnectionFactory; this.discoveryGroupName = discoveryGroupName; this.connectors = connectors; } @Override public void start(StartContext context) throws StartException { ActiveMQServer activeMQServer = injectedActiveMQServer.getValue(); DiscoveryGroupConfiguration discoveryGroupConfiguration = null; if (discoveryGroupName != null) { if (activeMQServer.getConfiguration().getDiscoveryGroupConfigurations().keySet().contains(discoveryGroupName)) { discoveryGroupConfiguration = translateDiscoveryGroupConfiguration(activeMQServer.getConfiguration().getDiscoveryGroupConfigurations().get(discoveryGroupName)); } else { throw MessagingLogger.ROOT_LOGGER.discoveryGroupIsNotDefined(discoveryGroupName); } } TransportConfiguration[] transportConfigurations = translateTransportGroupConfigurations(activeMQServer.getConfiguration().getConnectorConfigurations(), connectors); JMSFactoryType factoryType = JMSFactoryType.valueOf(uncompletedConnectionFactory.getFactoryType()); if (uncompletedConnectionFactory.isHA()) { if (discoveryGroupConfiguration != null) { connectionFactory = HornetQJMSClient.createConnectionFactoryWithHA(discoveryGroupConfiguration, factoryType); } else { connectionFactory = HornetQJMSClient.createConnectionFactoryWithHA(factoryType, transportConfigurations); } } else { if (discoveryGroupConfiguration != null) { connectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(discoveryGroupConfiguration, factoryType); } else { connectionFactory = HornetQJMSClient.createConnectionFactoryWithoutHA(factoryType, transportConfigurations); } } connectionFactory.setAutoGroup(uncompletedConnectionFactory.isAutoGroup()); connectionFactory.setBlockOnAcknowledge(uncompletedConnectionFactory.isBlockOnAcknowledge()); connectionFactory.setBlockOnDurableSend(uncompletedConnectionFactory.isBlockOnDurableSend()); connectionFactory.setBlockOnNonDurableSend(uncompletedConnectionFactory.isBlockOnNonDurableSend()); connectionFactory.setCacheLargeMessagesClient(uncompletedConnectionFactory.isCacheLargeMessagesClient()); connectionFactory.setCallFailoverTimeout(uncompletedConnectionFactory.getCallFailoverTimeout()); connectionFactory.setCallTimeout(uncompletedConnectionFactory.getCallTimeout()); connectionFactory.setClientFailureCheckPeriod(uncompletedConnectionFactory.getClientFailureCheckPeriod()); connectionFactory.setClientID(uncompletedConnectionFactory.getClientID()); connectionFactory.setCompressLargeMessage(uncompletedConnectionFactory.isCompressLargeMessage()); connectionFactory.setConfirmationWindowSize(uncompletedConnectionFactory.getConfirmationWindowSize()); connectionFactory.setConnectionLoadBalancingPolicyClassName(uncompletedConnectionFactory.getConnectionLoadBalancingPolicyClassName()); connectionFactory.setConnectionTTL(uncompletedConnectionFactory.getConnectionTTL()); connectionFactory.setConsumerMaxRate(uncompletedConnectionFactory.getConsumerMaxRate()); connectionFactory.setConsumerWindowSize(uncompletedConnectionFactory.getConsumerWindowSize()); connectionFactory.setConfirmationWindowSize(uncompletedConnectionFactory.getConfirmationWindowSize()); connectionFactory.setDupsOKBatchSize(uncompletedConnectionFactory.getDupsOKBatchSize()); connectionFactory.setFailoverOnInitialConnection(uncompletedConnectionFactory.isFailoverOnInitialConnection()); connectionFactory.setGroupID(uncompletedConnectionFactory.getGroupID()); connectionFactory.setInitialConnectAttempts(uncompletedConnectionFactory.getInitialConnectAttempts()); connectionFactory.setInitialMessagePacketSize(uncompletedConnectionFactory.getInitialMessagePacketSize()); connectionFactory.setMaxRetryInterval(uncompletedConnectionFactory.getMaxRetryInterval()); connectionFactory.setMinLargeMessageSize(uncompletedConnectionFactory.getMinLargeMessageSize()); connectionFactory.setPreAcknowledge(uncompletedConnectionFactory.isPreAcknowledge()); connectionFactory.setProducerMaxRate(uncompletedConnectionFactory.getProducerMaxRate()); connectionFactory.setProducerWindowSize(uncompletedConnectionFactory.getProducerWindowSize()); connectionFactory.setReconnectAttempts(uncompletedConnectionFactory.getReconnectAttempts()); connectionFactory.setRetryInterval(uncompletedConnectionFactory.getRetryInterval()); connectionFactory.setRetryIntervalMultiplier(uncompletedConnectionFactory.getRetryIntervalMultiplier()); connectionFactory.setScheduledThreadPoolMaxSize(uncompletedConnectionFactory.getScheduledThreadPoolMaxSize()); connectionFactory.setThreadPoolMaxSize(uncompletedConnectionFactory.getThreadPoolMaxSize()); connectionFactory.setTransactionBatchSize(uncompletedConnectionFactory.getTransactionBatchSize()); connectionFactory.setUseGlobalPools(uncompletedConnectionFactory.isUseGlobalPools()); } @Override public void stop(StopContext context) { connectionFactory = null; } @Override public ConnectionFactory getValue() throws IllegalStateException, IllegalArgumentException { return connectionFactory; } public static LegacyConnectionFactoryService installService(final String name, final ServiceName activeMQServerServiceName, final ServiceTarget serviceTarget, final HornetQConnectionFactory uncompletedConnectionFactory, final String discoveryGroupName, final List<String> connectors) { final LegacyConnectionFactoryService service = new LegacyConnectionFactoryService(uncompletedConnectionFactory, discoveryGroupName, connectors); final ServiceName serviceName = JMSServices.getConnectionFactoryBaseServiceName(activeMQServerServiceName).append(LEGACY, name); serviceTarget.addService(serviceName, service) .addDependency(ActiveMQActivationService.getServiceName(activeMQServerServiceName)) .addDependency(activeMQServerServiceName, ActiveMQServer.class, service.injectedActiveMQServer) .setInitialMode(ServiceController.Mode.PASSIVE) .install(); return service; } private DiscoveryGroupConfiguration translateDiscoveryGroupConfiguration(org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration newDiscoveryGroupConfiguration) throws StartException { org.apache.activemq.artemis.api.core.BroadcastEndpointFactory newBroadcastEndpointFactory = newDiscoveryGroupConfiguration.getBroadcastEndpointFactory(); BroadcastEndpointFactoryConfiguration legacyBroadcastEndpointFactory; if (newBroadcastEndpointFactory instanceof org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory) { org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory factory = (org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory) newBroadcastEndpointFactory; legacyBroadcastEndpointFactory = new UDPBroadcastGroupConfiguration( factory.getGroupAddress(), factory.getGroupPort(), factory.getLocalBindAddress(), factory.getLocalBindPort()); } else if (newBroadcastEndpointFactory instanceof org.apache.activemq.artemis.api.core.ChannelBroadcastEndpointFactory) { org.apache.activemq.artemis.api.core.ChannelBroadcastEndpointFactory factory = (org.apache.activemq.artemis.api.core.ChannelBroadcastEndpointFactory) newBroadcastEndpointFactory; legacyBroadcastEndpointFactory = new org.hornetq.api.core.JGroupsBroadcastGroupConfiguration( factory.getChannel(), factory.getChannelName()); } else { throw MessagingLogger.ROOT_LOGGER.unsupportedBroadcastGroupConfigurationForLegacy(newBroadcastEndpointFactory.getClass().getName()); } return new DiscoveryGroupConfiguration(newDiscoveryGroupConfiguration.getName(), newDiscoveryGroupConfiguration.getRefreshTimeout(), newDiscoveryGroupConfiguration.getDiscoveryInitialWaitTimeout(), legacyBroadcastEndpointFactory); } private TransportConfiguration[] translateTransportGroupConfigurations(Map<String, org.apache.activemq.artemis.api.core.TransportConfiguration> connectorConfigurations, List<String> connectors) throws StartException { List<org.hornetq.api.core.TransportConfiguration> legacyConnectorConfigurations = new ArrayList<>(); for (String connectorName : connectors) { org.apache.activemq.artemis.api.core.TransportConfiguration newTransportConfiguration = connectorConfigurations.get(connectorName); String legacyFactoryClassName = translateFactoryClassName(newTransportConfiguration.getFactoryClassName()); Map legacyParams = translateParams(newTransportConfiguration.getParams()); org.hornetq.api.core.TransportConfiguration legacyTransportConfiguration = new org.hornetq.api.core.TransportConfiguration( legacyFactoryClassName, legacyParams, newTransportConfiguration.getName()); legacyConnectorConfigurations.add(legacyTransportConfiguration); } return legacyConnectorConfigurations.toArray(new org.hornetq.api.core.TransportConfiguration[legacyConnectorConfigurations.size()]); } private String translateFactoryClassName(String newFactoryClassName) throws StartException { if (newFactoryClassName.equals(org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory.class.getName())) { return org.hornetq.core.remoting.impl.netty.NettyConnectorFactory.class.getName(); } else { throw MessagingLogger.ROOT_LOGGER.unsupportedConnectorFactoryForLegacy(newFactoryClassName.getClass().getName()); } } private Map translateParams(Map<String, Object> newParams) { Map<String, Object> legacyParams = new HashMap<>(); for (Map.Entry<String, Object> newEntry : newParams.entrySet()) { String newKey = newEntry.getKey(); Object value = newEntry.getValue(); String legacyKey = PARAM_KEY_MAPPING.getOrDefault(newKey, newKey); if (org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.ACTIVEMQ_SERVER_NAME.equals(legacyKey)) { // property specific to ActiveMQ that can not be mapped to HornetQ continue; } legacyParams.put(legacyKey, value); } return legacyParams; } }