Skip to content

Commit

Permalink
ARTEMIS-1516 - Ensure JNDI via Tomcat Resource works
Browse files Browse the repository at this point in the history
Apply fix so that when using JNDI via tomcat resource it works. 
Replace original extract of JNDIStorable taken from Qpid, and use ActiveMQ5's as fits better to address this issue. (which primary use case is users migrating from 5.x)
Refactored ActiveMQConnectionFactory to externalise and turn into reference by StringRefAddr's instead of custom RefAddr which isnt standard.
Refactored ActiveMQDestinations similar
Refactored ActiveMQDestination to remove redundent and duplicated name field and ensured getters still behave the same
  • Loading branch information
michaelandrepearce authored and clebertsuconic committed Dec 19, 2017
1 parent 03ed49e commit 3ef9804
Show file tree
Hide file tree
Showing 32 changed files with 949 additions and 197 deletions.
Expand Up @@ -19,12 +19,14 @@

import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtilsBean;
Expand Down Expand Up @@ -69,6 +71,38 @@ public static <P> P setData(P obj, Map<String, Object> data) throws Exception {
return obj;
}

public static <P> P setProperties(P bean, Properties properties)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
synchronized (beanUtils) {
PropertyDescriptor[] descriptors = beanUtils.getPropertyUtils().getPropertyDescriptors(bean);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getReadMethod() != null && isWriteable(descriptor, null)) {
String value = properties.getProperty(descriptor.getName());
if (value != null) {
beanUtils.setProperty(bean, descriptor.getName(), value);
}
}
}
}
return bean;
}

public static <P> Properties getProperties(P bean, Properties properties)
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
synchronized (beanUtils) {
PropertyDescriptor[] descriptors = beanUtils.getPropertyUtils().getPropertyDescriptors(bean);
for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getReadMethod() != null && isWriteable(descriptor, null)) {
String value = beanUtils.getProperty(bean, descriptor.getName());
if (value != null) {
properties.put(descriptor.getName(), value);
}
}
}
}
return properties;
}

public static void setData(URI uri,
HashMap<String, Object> properties,
Set<String> allowableProperties,
Expand Down
Expand Up @@ -30,17 +30,17 @@
import javax.jms.XAJMSContext;
import javax.jms.XAQueueConnection;
import javax.jms.XATopicConnection;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.Context;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;

import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
Expand All @@ -51,18 +51,18 @@
import org.apache.activemq.artemis.api.jms.ActiveMQJMSConstants;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.jms.referenceable.ConnectionFactoryObjectFactory;
import org.apache.activemq.artemis.jms.referenceable.SerializableObjectRefAddr;
import org.apache.activemq.artemis.jndi.JNDIStorable;
import org.apache.activemq.artemis.spi.core.remoting.ClientProtocolManagerFactory;
import org.apache.activemq.artemis.uri.ConnectionFactoryParser;
import org.apache.activemq.artemis.uri.ServerLocatorParser;
import org.apache.activemq.artemis.utils.ClassloadingUtil;
import org.apache.activemq.artemis.utils.uri.BeanSupport;

/**
* <p>ActiveMQ Artemis implementation of a JMS ConnectionFactory.</p>
* <p>This connection factory will use defaults defined by {@link DefaultConnectionProperties}.
*/
public class ActiveMQConnectionFactory implements ConnectionFactoryOptions, Externalizable, Referenceable, ConnectionFactory, XAConnectionFactory, AutoCloseable {
public class ActiveMQConnectionFactory extends JNDIStorable implements ConnectionFactoryOptions, Externalizable, ConnectionFactory, XAConnectionFactory, AutoCloseable {

private static final long serialVersionUID = -7554006056207377105L;

Expand Down Expand Up @@ -206,10 +206,14 @@ public ActiveMQConnectionFactory() {
this(DefaultConnectionProperties.DEFAULT_BROKER_URL);
}

public ActiveMQConnectionFactory(String url) {
public ActiveMQConnectionFactory(String brokerURL) {
setBrokerURL(brokerURL);
}

private void setBrokerURL(String brokerURL) {
ConnectionFactoryParser cfParser = new ConnectionFactoryParser();
try {
URI uri = cfParser.expandURI(url);
URI uri = cfParser.expandURI(brokerURL);
serverLocator = ServerLocatorImpl.newLocator(uri);
cfParser.populateObject(uri, this);
} catch (Exception e) {
Expand Down Expand Up @@ -380,8 +384,36 @@ public XATopicConnection createXATopicConnection(final String username, final St
}

@Override
public Reference getReference() throws NamingException {
return new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-CF", this), ConnectionFactoryObjectFactory.class.getCanonicalName(), null);
protected void buildFromProperties(Properties props) {
String url = props.getProperty(Context.PROVIDER_URL);
if (url == null || url.isEmpty()) {
url = props.getProperty("brokerURL");
}
if (url != null && url.length() > 0) {
setBrokerURL(url);
}
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException(Context.PROVIDER_URL + " or " + "brokerURL is required");
}
try {
BeanSupport.setProperties(this, props);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}

@Override
protected void populateProperties(Properties props) {
try {
URI uri = toURI();
if (uri != null) {
props.put(Context.PROVIDER_URL, uri.toASCIIString());
props.put("brokerURL", uri.toASCIIString());
}
BeanSupport.getProperties(this, props);
} catch (IOException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}

public boolean isHA() {
Expand Down
Expand Up @@ -19,21 +19,18 @@
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.JMSRuntimeException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.Serializable;
import java.util.Properties;
import java.util.UUID;

import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.jms.referenceable.DestinationObjectFactory;
import org.apache.activemq.artemis.jms.referenceable.SerializableObjectRefAddr;
import org.apache.activemq.artemis.jndi.JNDIStorable;

/**
* ActiveMQ Artemis implementation of a JMS Destination.
*/
public class ActiveMQDestination implements Destination, Serializable, Referenceable {
public class ActiveMQDestination extends JNDIStorable implements Destination, Serializable {
// Constants -----------------------------------------------------

// Static --------------------------------------------------------
Expand Down Expand Up @@ -78,27 +75,27 @@ public static ActiveMQDestination createDestination(String name, TYPE defaultTyp
case TEMP_TOPIC:
return new ActiveMQTopic(name, true);
case DESTINATION:
return new ActiveMQDestination(name, name, TYPE.DESTINATION, null);
return new ActiveMQDestination(name, TYPE.DESTINATION, null);
default:
throw new IllegalArgumentException("Invalid default destination type: " + defaultType);
}
}

public static Destination fromPrefixedName(final String address) {
if (address.startsWith(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX)) {
String name = address.substring(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX.length());
return createQueue(name);
} else if (address.startsWith(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX.length());
return createTopic(name);
} else if (address.startsWith(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryQueue(name, name, null);
} else if (address.startsWith(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX)) {
String name = address.substring(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryTopic(name, name, null);
public static Destination fromPrefixedName(final String name) {
if (name.startsWith(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX)) {
String address = name.substring(ActiveMQDestination.QUEUE_QUALIFIED_PREFIX.length());
return createQueue(address);
} else if (name.startsWith(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX)) {
String address = name.substring(ActiveMQDestination.TOPIC_QUALIFIED_PREFIX.length());
return createTopic(address);
} else if (name.startsWith(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX)) {
String address = name.substring(ActiveMQDestination.TEMP_QUEUE_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryQueue(address, null);
} else if (name.startsWith(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX)) {
String address = name.substring(ActiveMQDestination.TEMP_TOPIC_QUALIFED_PREFIX.length());
return new ActiveMQTemporaryTopic(address, null);
} else {
return new ActiveMQDestination(address, address, TYPE.DESTINATION, null);
return new ActiveMQDestination(name, TYPE.DESTINATION, null);
}
}

Expand Down Expand Up @@ -191,58 +188,48 @@ public static SimpleString createTopicAddressFromName(final String name) {
return new SimpleString(TOPIC_QUALIFIED_PREFIX + name);
}

public static ActiveMQQueue createQueue(final String name) {
return new ActiveMQQueue(name);
public static ActiveMQQueue createQueue(final String address) {
return new ActiveMQQueue(address);
}

public static ActiveMQTopic createTopic(final String name) {
return new ActiveMQTopic(name);
public static ActiveMQTopic createTopic(final String address) {
return new ActiveMQTopic(address);
}

public static ActiveMQTemporaryQueue createTemporaryQueue(final String name, final ActiveMQSession session) {
return new ActiveMQTemporaryQueue(name, name, session);
public static ActiveMQTemporaryQueue createTemporaryQueue(final String address, final ActiveMQSession session) {
return new ActiveMQTemporaryQueue(address, session);
}

public static ActiveMQTemporaryQueue createTemporaryQueue(final String name) {
return createTemporaryQueue(name, null);
public static ActiveMQTemporaryQueue createTemporaryQueue(final String address) {
return createTemporaryQueue(address, null);
}

public static ActiveMQTemporaryQueue createTemporaryQueue(final ActiveMQSession session) {
String name = UUID.randomUUID().toString();
String address = UUID.randomUUID().toString();

return createTemporaryQueue(name, session);
return createTemporaryQueue(address, session);
}

public static ActiveMQTemporaryTopic createTemporaryTopic(final ActiveMQSession session) {
String name = UUID.randomUUID().toString();
String address = UUID.randomUUID().toString();

return createTemporaryTopic(name, session);
return createTemporaryTopic(address, session);
}

public static ActiveMQTemporaryTopic createTemporaryTopic(String name, final ActiveMQSession session) {
return new ActiveMQTemporaryTopic(name, name, session);
public static ActiveMQTemporaryTopic createTemporaryTopic(String address, final ActiveMQSession session) {
return new ActiveMQTemporaryTopic(address, session);
}

public static ActiveMQTemporaryTopic createTemporaryTopic(String name) {
return createTemporaryTopic(name, null);
public static ActiveMQTemporaryTopic createTemporaryTopic(String address) {
return createTemporaryTopic(address, null);
}

// Attributes ----------------------------------------------------

/**
* The JMS name
*/
protected final String name;

/**
* The core address
*/
private final String address;

/**
* SimpleString version of address
*/
private final SimpleString simpleAddress;
private SimpleString simpleAddress;

private final TYPE type;

Expand All @@ -251,25 +238,34 @@ public static ActiveMQTemporaryTopic createTemporaryTopic(String name) {
// Constructors --------------------------------------------------

protected ActiveMQDestination(final String address,
final String name,
final TYPE type,
final ActiveMQSession session) {
this.address = address;
this.simpleAddress = SimpleString.toSimpleString(address);

this.name = name;
this.type = type;

simpleAddress = new SimpleString(address);
this.session = session;
}

protected ActiveMQDestination(final SimpleString address,
final TYPE type,
final ActiveMQSession session) {
this.simpleAddress = address;

this.type = type;

this.session = session;
}

// Referenceable implementation ---------------------------------------
public void setAddress(String address) {
setSimpleAddress(SimpleString.toSimpleString(address));
}

@Override
public Reference getReference() throws NamingException {
return new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-DEST", this), DestinationObjectFactory.class.getCanonicalName(), null);
public void setSimpleAddress(SimpleString address) {
if (address == null) {
throw new IllegalArgumentException("address cannot be null");
}
this.simpleAddress = address;
}

public void delete() throws JMSException {
Expand All @@ -293,15 +289,15 @@ public boolean isQueue() {
// Public --------------------------------------------------------

public String getAddress() {
return address;
return simpleAddress.toString();
}

public SimpleString getSimpleAddress() {
return simpleAddress;
}

public String getName() {
return name;
return simpleAddress.toString();
}

public boolean isTemporary() {
Expand All @@ -324,12 +320,22 @@ public boolean equals(final Object o) {

ActiveMQDestination that = (ActiveMQDestination) o;

return address.equals(that.address);
return simpleAddress.equals(that.simpleAddress);
}

@Override
public int hashCode() {
return address.hashCode();
return simpleAddress.hashCode();
}

@Override
protected void buildFromProperties(Properties props) {
setAddress(props.getProperty("address"));
}

@Override
protected void populateProperties(Properties props) {
props.put("address", getAddress());
}

// Package protected ---------------------------------------------
Expand Down

0 comments on commit 3ef9804

Please sign in to comment.