/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.integration.jms.connection;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.JGroupsFileBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.JGroupsPropertiesBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.server.config.ConnectionFactoryConfiguration;
import org.apache.activemq.artemis.jms.server.config.impl.ConnectionFactoryConfigurationImpl;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class ConnectionFactorySerializationTest extends JMSTestBase {
// Constants -----------------------------------------------------
// Static --------------------------------------------------------
// Attributes ----------------------------------------------------
protected static ActiveMQConnectionFactory cf;
// Constructors --------------------------------------------------
@Override
@Before
public void setUp() throws Exception {
super.setUp();
}
// Public --------------------------------------------------------
@Test
public void testConnectionFactoryUDP() throws Exception {
createDiscoveryFactoryUDP();
cf = (ActiveMQConnectionFactory) namingContext.lookup("/MyConnectionFactory");
// apparently looking up the connection factory with the org.apache.activemq.artemis.jms.tests.tools.container.InVMInitialContextFactory
// is not enough to actually serialize it so we serialize it manually
byte[] x = serialize(cf);
ActiveMQConnectionFactory y = deserialize(x, ActiveMQConnectionFactory.class);
checkEquals(cf, y);
DiscoveryGroupConfiguration dgc = y.getDiscoveryGroupConfiguration();
Assert.assertEquals(dgc.getName(), "dg1");
Assert.assertEquals(dgc.getDiscoveryInitialWaitTimeout(), 5000);
Assert.assertEquals(dgc.getRefreshTimeout(), 5000);
Assert.assertTrue(dgc.getBroadcastEndpointFactory() instanceof UDPBroadcastEndpointFactory);
UDPBroadcastEndpointFactory befc = (UDPBroadcastEndpointFactory) dgc.getBroadcastEndpointFactory();
Assert.assertEquals(Integer.parseInt(System.getProperty("org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory.localBindPort", "-1")), befc.getLocalBindPort());
Assert.assertEquals(System.getProperty("org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory.localBindAddress"), befc.getLocalBindAddress());
Assert.assertEquals(getUDPDiscoveryPort(), befc.getGroupPort());
Assert.assertEquals(getUDPDiscoveryAddress(), befc.getGroupAddress());
}
@Test
public void testConnectionFactoryJgroupsFile() throws Exception {
createDiscoveryFactoryJGroupsFile();
cf = (ActiveMQConnectionFactory) namingContext.lookup("/MyConnectionFactory");
// apparently looking up the connection factory with the org.apache.activemq.artemis.jms.tests.tools.container.InVMInitialContextFactory
// is not enough to actually serialize it so we serialize it manually
byte[] x = serialize(cf);
ActiveMQConnectionFactory y = deserialize(x, ActiveMQConnectionFactory.class);
checkEquals(cf, y);
DiscoveryGroupConfiguration dgc = y.getDiscoveryGroupConfiguration();
Assert.assertEquals(dgc.getName(), "dg1");
Assert.assertEquals(dgc.getDiscoveryInitialWaitTimeout(), 5000);
Assert.assertEquals(dgc.getRefreshTimeout(), 5000);
Assert.assertTrue(dgc.getBroadcastEndpointFactory() instanceof JGroupsFileBroadcastEndpointFactory);
JGroupsFileBroadcastEndpointFactory befc = (JGroupsFileBroadcastEndpointFactory) dgc.getBroadcastEndpointFactory();
Assert.assertEquals("myChannel", befc.getChannelName());
Assert.assertEquals("/META-INF/myfile.xml", befc.getFile());
}
@Test
public void testConnectionFactoryJgroupsProperties() throws Exception {
createDiscoveryFactoryJGroupsProperties();
cf = (ActiveMQConnectionFactory) namingContext.lookup("/MyConnectionFactory");
// apparently looking up the connection factory with the org.apache.activemq.artemis.jms.tests.tools.container.InVMInitialContextFactory
// is not enough to actually serialize it so we serialize it manually
byte[] x = serialize(cf);
ActiveMQConnectionFactory y = deserialize(x, ActiveMQConnectionFactory.class);
checkEquals(cf, y);
DiscoveryGroupConfiguration dgc = y.getDiscoveryGroupConfiguration();
Assert.assertEquals(dgc.getName(), "dg1");
Assert.assertEquals(dgc.getDiscoveryInitialWaitTimeout(), 5000);
Assert.assertEquals(dgc.getRefreshTimeout(), 5000);
Assert.assertTrue(dgc.getBroadcastEndpointFactory() instanceof JGroupsPropertiesBroadcastEndpointFactory);
JGroupsPropertiesBroadcastEndpointFactory befc = (JGroupsPropertiesBroadcastEndpointFactory) dgc.getBroadcastEndpointFactory();
Assert.assertEquals("myChannel", befc.getChannelName());
Assert.assertEquals("param=1,param2=2", befc.getProperties());
}
@Test
public void testConnectionFactoryStatic1() throws Exception {
createStaticFactory(true);
cf = (ActiveMQConnectionFactory) namingContext.lookup("/MyConnectionFactory");
// apparently looking up the connection factory with the org.apache.activemq.artemis.jms.tests.tools.container.InVMInitialContextFactory
// is not enough to actually serialize it so we serialize it manually
byte[] x = serialize(cf);
ActiveMQConnectionFactory y = deserialize(x, ActiveMQConnectionFactory.class);
checkEquals(cf, y);
Assert.assertEquals(cf.isHA(), y.isHA());
TransportConfiguration[] staticConnectors = y.getStaticConnectors();
Assert.assertEquals(staticConnectors.length, 2);
TransportConfiguration tc0 = cf.getStaticConnectors()[0];
TransportConfiguration y0 = y.getStaticConnectors()[0];
Map<String, Object> ctParams = tc0.getParams();
Map<String, Object> y0Params = y0.getParams();
Assert.assertEquals(ctParams.size(), y0Params.size());
for (String key : y0Params.keySet()) {
Assert.assertEquals(ctParams.get(key), y0Params.get(key));
}
}
private void createDiscoveryFactoryUDP() throws Exception {
// Deploy a connection factory with discovery
List<String> bindings = new ArrayList<>();
bindings.add("MyConnectionFactory");
final String groupAddress = getUDPDiscoveryAddress();
final int port = getUDPDiscoveryPort();
String localBindAddress = getLocalHost().getHostAddress();
UDPBroadcastEndpointFactory config = new UDPBroadcastEndpointFactory().setGroupAddress(groupAddress).setGroupPort(port).setLocalBindAddress(localBindAddress).setLocalBindPort(8580);
DiscoveryGroupConfiguration dcConfig = new DiscoveryGroupConfiguration().setName("dg1").setRefreshTimeout(5000).setDiscoveryInitialWaitTimeout(5000).setBroadcastEndpointFactory(config);
jmsServer.getActiveMQServer().getConfiguration().getDiscoveryGroupConfigurations().put(dcConfig.getName(), dcConfig);
jmsServer.createConnectionFactory("MyConnectionFactory", false, JMSFactoryType.CF, dcConfig.getName(), "/MyConnectionFactory");
}
private void createDiscoveryFactoryJGroupsFile() throws Exception {
// Deploy a connection factory with discovery
List<String> bindings = new ArrayList<>();
bindings.add("MyConnectionFactory");
JGroupsFileBroadcastEndpointFactory config = new JGroupsFileBroadcastEndpointFactory().setChannelName("myChannel").setFile("/META-INF/myfile.xml");
DiscoveryGroupConfiguration dcConfig = new DiscoveryGroupConfiguration().setName("dg1").setRefreshTimeout(5000).setDiscoveryInitialWaitTimeout(5000).setBroadcastEndpointFactory(config);
jmsServer.getActiveMQServer().getConfiguration().getDiscoveryGroupConfigurations().put(dcConfig.getName(), dcConfig);
jmsServer.createConnectionFactory("MyConnectionFactory", false, JMSFactoryType.CF, dcConfig.getName(), "/MyConnectionFactory");
}
private void createDiscoveryFactoryJGroupsProperties() throws Exception {
// Deploy a connection factory with discovery
List<String> bindings = new ArrayList<>();
bindings.add("MyConnectionFactory");
JGroupsPropertiesBroadcastEndpointFactory config = new JGroupsPropertiesBroadcastEndpointFactory().setChannelName("myChannel").setProperties("param=1,param2=2");
DiscoveryGroupConfiguration dcConfig = new DiscoveryGroupConfiguration().setName("dg1").setRefreshTimeout(5000).setDiscoveryInitialWaitTimeout(5000).setBroadcastEndpointFactory(config);
jmsServer.getActiveMQServer().getConfiguration().getDiscoveryGroupConfigurations().put(dcConfig.getName(), dcConfig);
jmsServer.createConnectionFactory("MyConnectionFactory", false, JMSFactoryType.CF, dcConfig.getName(), "/MyConnectionFactory");
}
private void createStaticFactory(boolean b) throws Exception {
HashMap<String, Object> params = new HashMap<>();
Set<String> allowableConnectorKeys = TransportConstants.ALLOWABLE_CONNECTOR_KEYS;
for (String allowableConnectorKey : allowableConnectorKeys) {
String value = RandomUtil.randomString();
params.put(allowableConnectorKey, value);
}
params.put("host", "localhost0");
params.put("port", "1234");
TransportConfiguration main = new TransportConfiguration(NETTY_CONNECTOR_FACTORY, params);
jmsServer.getActiveMQServer().getConfiguration().getConnectorConfigurations().put(main.getName(), main);
HashMap<String, Object> params2 = new HashMap<>();
for (String allowableConnectorKey : allowableConnectorKeys) {
String value = RandomUtil.randomString();
params2.put(allowableConnectorKey, value);
}
params2.put("host", "localhost1");
params2.put("port", "5678");
TransportConfiguration main2 = new TransportConfiguration(NETTY_CONNECTOR_FACTORY, params2);
jmsServer.getActiveMQServer().getConfiguration().getConnectorConfigurations().put(main2.getName(), main2);
ArrayList<String> connectorNames = new ArrayList<>();
connectorNames.add(main.getName());
connectorNames.add(main2.getName());
ConnectionFactoryConfiguration configuration = new ConnectionFactoryConfigurationImpl().setName("MyConnectionFactory").setHA(b).setConnectorNames(connectorNames).setClientID("clientID").setClientFailureCheckPeriod(-1).setConnectionTTL(-2).setFactoryType(JMSFactoryType.CF).setCallTimeout(-3).setCallFailoverTimeout(-4).setCacheLargeMessagesClient(b).setMinLargeMessageSize(-5).setConsumerWindowSize(-6).setConsumerMaxRate(-7).setConfirmationWindowSize(-8).setProducerWindowSize(-9).setProducerMaxRate(-10).setBlockOnAcknowledge(b).setBlockOnDurableSend(b).setBlockOnNonDurableSend(b).setAutoGroup(b).setPreAcknowledge(b).setLoadBalancingPolicyClassName("foobar").setTransactionBatchSize(-11).setDupsOKBatchSize(-12).setUseGlobalPools(b).setScheduledThreadPoolMaxSize(-13).setThreadPoolMaxSize(-14).setRetryInterval(-15).setRetryIntervalMultiplier(-16).setMaxRetryInterval(-17).setReconnectAttempts(-18).setFailoverOnInitialConnection(b).setGroupID("groupID");
jmsServer.createConnectionFactory(false, configuration, "/MyConnectionFactory");
}
private void populate(StringBuilder sb,
BeanUtilsBean bean,
ActiveMQConnectionFactory factory) throws IllegalAccessException, InvocationTargetException {
PropertyDescriptor[] descriptors = bean.getPropertyUtils().getPropertyDescriptors(factory);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getWriteMethod() != null && descriptor.getReadMethod() != null) {
if (descriptor.getPropertyType() == String.class) {
String value = RandomUtil.randomString();
bean.setProperty(factory, descriptor.getName(), value);
sb.append("&").append(descriptor.getName()).append("=").append(value);
} else if (descriptor.getPropertyType() == int.class) {
int value = RandomUtil.randomPositiveInt();
bean.setProperty(factory, descriptor.getName(), value);
sb.append("&").append(descriptor.getName()).append("=").append(value);
} else if (descriptor.getPropertyType() == long.class) {
long value = RandomUtil.randomPositiveLong();
bean.setProperty(factory, descriptor.getName(), value);
sb.append("&").append(descriptor.getName()).append("=").append(value);
} else if (descriptor.getPropertyType() == double.class) {
double value = RandomUtil.randomDouble();
bean.setProperty(factory, descriptor.getName(), value);
sb.append("&").append(descriptor.getName()).append("=").append(value);
}
}
}
}
private static void checkEquals(Object factory,
Object factory2) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
BeanUtilsBean bean = new BeanUtilsBean();
PropertyDescriptor[] descriptors = bean.getPropertyUtils().getPropertyDescriptors(factory);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getWriteMethod() != null && descriptor.getReadMethod() != null) {
Assert.assertEquals(descriptor.getName() + " incorrect", bean.getProperty(factory, descriptor.getName()), bean.getProperty(factory2, descriptor.getName()));
}
}
}
private static <T extends Serializable> byte[] serialize(T obj) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
return baos.toByteArray();
}
private static <T extends Serializable> T deserialize(byte[] b,
Class<T> cl) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(b);
ObjectInputStream ois = new ObjectInputStream(bais);
Object o = ois.readObject();
return cl.cast(o);
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
protected static InetAddress getLocalHost() throws UnknownHostException {
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
} catch (ArrayIndexOutOfBoundsException e) { //this is workaround for mac osx bug see AS7-3223 and JGRP-1404
addr = InetAddress.getByName(null);
}
return addr;
}
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
}