/*
* 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.jms.client;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSRuntimeException;
import javax.jms.JMSSecurityException;
import javax.jms.JMSSecurityRuntimeException;
import javax.jms.QueueConnection;
import javax.jms.TopicConnection;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
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 java.io.Externalizable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
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.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
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.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;
/**
* <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 {
private ServerLocator serverLocator;
private String clientID;
private int dupsOKBatchSize = ActiveMQClient.DEFAULT_ACK_BATCH_SIZE;
private int transactionBatchSize = ActiveMQClient.DEFAULT_ACK_BATCH_SIZE;
private boolean readOnly;
private String user;
private String password;
private String protocolManagerFactoryStr;
private String deserializationBlackList;
private String deserializationWhiteList;
private boolean finalizeChecks;
@Override
public void writeExternal(ObjectOutput out) throws IOException {
URI uri = toURI();
try {
out.writeUTF(uri.toASCIIString());
} catch (Exception e) {
if (e instanceof IOException) {
throw (IOException) e;
}
throw new IOException(e);
}
}
public URI toURI() throws IOException {
ConnectionFactoryParser parser = new ConnectionFactoryParser();
String scheme;
if (serverLocator.getDiscoveryGroupConfiguration() != null) {
if (serverLocator.getDiscoveryGroupConfiguration().getBroadcastEndpointFactory() instanceof UDPBroadcastEndpointFactory) {
scheme = "udp";
} else {
scheme = "jgroups";
}
} else {
if (serverLocator.allInVM()) {
scheme = "vm";
} else {
scheme = "tcp";
}
}
URI uri;
try {
uri = parser.createSchema(scheme, this);
} catch (Exception e) {
if (e instanceof IOException) {
throw (IOException) e;
}
throw new IOException(e);
}
return uri;
}
public String getProtocolManagerFactoryStr() {
return protocolManagerFactoryStr;
}
public void setProtocolManagerFactoryStr(final String protocolManagerFactoryStr) {
if (protocolManagerFactoryStr != null && !protocolManagerFactoryStr.trim().isEmpty() &&
!protocolManagerFactoryStr.equals("undefined")) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
ClientProtocolManagerFactory protocolManagerFactory = (ClientProtocolManagerFactory) ClassloadingUtil.newInstanceFromClassLoader(protocolManagerFactoryStr);
serverLocator.setProtocolManagerFactory(protocolManagerFactory);
return null;
}
});
this.protocolManagerFactoryStr = protocolManagerFactoryStr;
}
}
public ActiveMQConnectionFactory disableFinalizeChecks() {
this.finalizeChecks = false;
return this;
}
public boolean isFinalizeChecks() {
return finalizeChecks;
}
@Override
public String getDeserializationBlackList() {
return deserializationBlackList;
}
@Override
public void setDeserializationBlackList(String blackList) {
this.deserializationBlackList = blackList;
}
@Override
public String getDeserializationWhiteList() {
return deserializationWhiteList;
}
@Override
public void setDeserializationWhiteList(String whiteList) {
this.deserializationWhiteList = whiteList;
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
String url = in.readUTF();
ConnectionFactoryParser parser = new ConnectionFactoryParser();
ServerLocatorParser locatorParser = new ServerLocatorParser();
try {
URI uri = new URI(url);
serverLocator = locatorParser.newObject(uri, null);
parser.populateObject(uri, this);
} catch (Exception e) {
throw new InvalidObjectException(e.getMessage());
}
}
/**
* This will use a default URI from {@link DefaultConnectionProperties}
*/
public ActiveMQConnectionFactory() {
this(DefaultConnectionProperties.DEFAULT_BROKER_URL);
}
public ActiveMQConnectionFactory(String url) {
ConnectionFactoryParser cfParser = new ConnectionFactoryParser();
try {
URI uri = cfParser.expandURI(url);
serverLocator = ServerLocatorImpl.newLocator(uri);
cfParser.populateObject(uri, this);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
if (getUser() == null) {
setUser(DefaultConnectionProperties.DEFAULT_USER);
}
if (getPassword() == null) {
setPassword(DefaultConnectionProperties.DEFAULT_PASSWORD);
}
}
/**
* For compatibility and users used to this kind of constructor
*/
public ActiveMQConnectionFactory(String url, String user, String password) {
this(url);
setUser(user).setPassword(password);
}
public ActiveMQConnectionFactory(final ServerLocator serverLocator) {
this.serverLocator = serverLocator;
serverLocator.disableFinalizeCheck();
}
public ActiveMQConnectionFactory(final boolean ha, final DiscoveryGroupConfiguration groupConfiguration) {
if (ha) {
serverLocator = ActiveMQClient.createServerLocatorWithHA(groupConfiguration);
} else {
serverLocator = ActiveMQClient.createServerLocatorWithoutHA(groupConfiguration);
}
serverLocator.disableFinalizeCheck();
}
public ActiveMQConnectionFactory(final boolean ha, final TransportConfiguration... initialConnectors) {
if (ha) {
serverLocator = ActiveMQClient.createServerLocatorWithHA(initialConnectors);
} else {
serverLocator = ActiveMQClient.createServerLocatorWithoutHA(initialConnectors);
}
serverLocator.disableFinalizeCheck();
}
@Override
public Connection createConnection() throws JMSException {
return createConnection(user, password);
}
@Override
public Connection createConnection(final String username, final String password) throws JMSException {
return createConnectionInternal(username, password, false, ActiveMQConnection.TYPE_GENERIC_CONNECTION);
}
@Override
public JMSContext createContext() {
return createContext(user, password);
}
@Override
public JMSContext createContext(final int sessionMode) {
return createContext(user, password, sessionMode);
}
@Override
public JMSContext createContext(final String userName, final String password) {
return createContext(userName, password, JMSContext.AUTO_ACKNOWLEDGE);
}
@Override
public JMSContext createContext(String userName, String password, int sessionMode) {
validateSessionMode(sessionMode);
try {
ActiveMQConnection connection = createConnectionInternal(userName, password, false, ActiveMQConnection.TYPE_GENERIC_CONNECTION);
return connection.createContext(sessionMode);
} catch (JMSSecurityException e) {
throw new JMSSecurityRuntimeException(e.getMessage(), e.getErrorCode(), e);
} catch (JMSException e) {
throw JmsExceptionUtils.convertToRuntimeException(e);
}
}
private static void validateSessionMode(int mode) {
switch (mode) {
case JMSContext.AUTO_ACKNOWLEDGE:
case JMSContext.CLIENT_ACKNOWLEDGE:
case JMSContext.DUPS_OK_ACKNOWLEDGE:
case JMSContext.SESSION_TRANSACTED:
case ActiveMQJMSConstants.PRE_ACKNOWLEDGE:
case ActiveMQJMSConstants.INDIVIDUAL_ACKNOWLEDGE: {
return;
}
default:
throw new JMSRuntimeException("Invalid Session Mode: " + mode);
}
}
public QueueConnection createQueueConnection() throws JMSException {
return createQueueConnection(null, null);
}
public QueueConnection createQueueConnection(final String username, final String password) throws JMSException {
return createConnectionInternal(username, password, false, ActiveMQConnection.TYPE_QUEUE_CONNECTION);
}
// TopicConnectionFactory implementation --------------------------------------------------------
public TopicConnection createTopicConnection() throws JMSException {
return createTopicConnection(null, null);
}
public TopicConnection createTopicConnection(final String username, final String password) throws JMSException {
return createConnectionInternal(username, password, false, ActiveMQConnection.TYPE_TOPIC_CONNECTION);
}
// XAConnectionFactory implementation -----------------------------------------------------------
@Override
public XAConnection createXAConnection() throws JMSException {
return createXAConnection(null, null);
}
@Override
public XAConnection createXAConnection(final String username, final String password) throws JMSException {
return (XAConnection) createConnectionInternal(username, password, true, ActiveMQConnection.TYPE_GENERIC_CONNECTION);
}
@Override
public XAJMSContext createXAContext() {
return createXAContext(null, null);
}
@Override
public XAJMSContext createXAContext(String userName, String password) {
try {
ActiveMQConnection connection = createConnectionInternal(userName, password, true, ActiveMQConnection.TYPE_GENERIC_CONNECTION);
return connection.createXAContext();
} catch (JMSSecurityException e) {
throw new JMSSecurityRuntimeException(e.getMessage(), e.getErrorCode(), e);
} catch (JMSException e) {
throw JmsExceptionUtils.convertToRuntimeException(e);
}
}
// XAQueueConnectionFactory implementation ------------------------------------------------------
public XAQueueConnection createXAQueueConnection() throws JMSException {
return createXAQueueConnection(null, null);
}
public XAQueueConnection createXAQueueConnection(final String username, final String password) throws JMSException {
return (XAQueueConnection) createConnectionInternal(username, password, true, ActiveMQConnection.TYPE_QUEUE_CONNECTION);
}
// XATopicConnectionFactory implementation ------------------------------------------------------
public XATopicConnection createXATopicConnection() throws JMSException {
return createXATopicConnection(null, null);
}
public XATopicConnection createXATopicConnection(final String username, final String password) throws JMSException {
return (XATopicConnection) createConnectionInternal(username, password, true, ActiveMQConnection.TYPE_TOPIC_CONNECTION);
}
@Override
public Reference getReference() throws NamingException {
return new Reference(this.getClass().getCanonicalName(), new SerializableObjectRefAddr("ActiveMQ-CF", this), ConnectionFactoryObjectFactory.class.getCanonicalName(), null);
}
public boolean isHA() {
return serverLocator.isHA();
}
public synchronized String getConnectionLoadBalancingPolicyClassName() {
return serverLocator.getConnectionLoadBalancingPolicyClassName();
}
public synchronized void setConnectionLoadBalancingPolicyClassName(final String connectionLoadBalancingPolicyClassName) {
checkWrite();
serverLocator.setConnectionLoadBalancingPolicyClassName(connectionLoadBalancingPolicyClassName);
}
public synchronized TransportConfiguration[] getStaticConnectors() {
return serverLocator.getStaticTransportConfigurations();
}
public synchronized DiscoveryGroupConfiguration getDiscoveryGroupConfiguration() {
return serverLocator.getDiscoveryGroupConfiguration();
}
public synchronized String getClientID() {
return clientID;
}
public synchronized void setClientID(final String clientID) {
checkWrite();
this.clientID = clientID;
}
public synchronized int getDupsOKBatchSize() {
return dupsOKBatchSize;
}
public synchronized void setDupsOKBatchSize(final int dupsOKBatchSize) {
checkWrite();
this.dupsOKBatchSize = dupsOKBatchSize;
}
public synchronized int getTransactionBatchSize() {
return transactionBatchSize;
}
public synchronized void setTransactionBatchSize(final int transactionBatchSize) {
checkWrite();
this.transactionBatchSize = transactionBatchSize;
}
public synchronized long getClientFailureCheckPeriod() {
return serverLocator.getClientFailureCheckPeriod();
}
public synchronized void setClientFailureCheckPeriod(final long clientFailureCheckPeriod) {
checkWrite();
serverLocator.setClientFailureCheckPeriod(clientFailureCheckPeriod);
}
public synchronized long getConnectionTTL() {
return serverLocator.getConnectionTTL();
}
public synchronized void setConnectionTTL(final long connectionTTL) {
checkWrite();
serverLocator.setConnectionTTL(connectionTTL);
}
public synchronized long getCallTimeout() {
return serverLocator.getCallTimeout();
}
public synchronized void setCallTimeout(final long callTimeout) {
checkWrite();
serverLocator.setCallTimeout(callTimeout);
}
public synchronized long getCallFailoverTimeout() {
return serverLocator.getCallFailoverTimeout();
}
public synchronized void setCallFailoverTimeout(final long callTimeout) {
checkWrite();
serverLocator.setCallFailoverTimeout(callTimeout);
}
public synchronized int getConsumerWindowSize() {
return serverLocator.getConsumerWindowSize();
}
public synchronized void setConsumerWindowSize(final int consumerWindowSize) {
checkWrite();
serverLocator.setConsumerWindowSize(consumerWindowSize);
}
public synchronized int getConsumerMaxRate() {
return serverLocator.getConsumerMaxRate();
}
public synchronized void setConsumerMaxRate(final int consumerMaxRate) {
checkWrite();
serverLocator.setConsumerMaxRate(consumerMaxRate);
}
public synchronized int getConfirmationWindowSize() {
return serverLocator.getConfirmationWindowSize();
}
public synchronized void setConfirmationWindowSize(final int confirmationWindowSize) {
checkWrite();
serverLocator.setConfirmationWindowSize(confirmationWindowSize);
}
public synchronized int getProducerMaxRate() {
return serverLocator.getProducerMaxRate();
}
public synchronized void setProducerMaxRate(final int producerMaxRate) {
checkWrite();
serverLocator.setProducerMaxRate(producerMaxRate);
}
public synchronized int getProducerWindowSize() {
return serverLocator.getProducerWindowSize();
}
public synchronized void setProducerWindowSize(final int producerWindowSize) {
checkWrite();
serverLocator.setProducerWindowSize(producerWindowSize);
}
/**
* @param cacheLargeMessagesClient
*/
public synchronized void setCacheLargeMessagesClient(final boolean cacheLargeMessagesClient) {
checkWrite();
serverLocator.setCacheLargeMessagesClient(cacheLargeMessagesClient);
}
public synchronized boolean isCacheLargeMessagesClient() {
return serverLocator.isCacheLargeMessagesClient();
}
public synchronized int getMinLargeMessageSize() {
return serverLocator.getMinLargeMessageSize();
}
public synchronized void setMinLargeMessageSize(final int minLargeMessageSize) {
checkWrite();
serverLocator.setMinLargeMessageSize(minLargeMessageSize);
}
public synchronized boolean isBlockOnAcknowledge() {
return serverLocator.isBlockOnAcknowledge();
}
public synchronized void setBlockOnAcknowledge(final boolean blockOnAcknowledge) {
checkWrite();
serverLocator.setBlockOnAcknowledge(blockOnAcknowledge);
}
public synchronized boolean isBlockOnNonDurableSend() {
return serverLocator.isBlockOnNonDurableSend();
}
public synchronized void setBlockOnNonDurableSend(final boolean blockOnNonDurableSend) {
checkWrite();
serverLocator.setBlockOnNonDurableSend(blockOnNonDurableSend);
}
public synchronized boolean isBlockOnDurableSend() {
return serverLocator.isBlockOnDurableSend();
}
public synchronized void setBlockOnDurableSend(final boolean blockOnDurableSend) {
checkWrite();
serverLocator.setBlockOnDurableSend(blockOnDurableSend);
}
public synchronized boolean isAutoGroup() {
return serverLocator.isAutoGroup();
}
public synchronized void setAutoGroup(final boolean autoGroup) {
checkWrite();
serverLocator.setAutoGroup(autoGroup);
}
public synchronized boolean isPreAcknowledge() {
return serverLocator.isPreAcknowledge();
}
public synchronized void setPreAcknowledge(final boolean preAcknowledge) {
checkWrite();
serverLocator.setPreAcknowledge(preAcknowledge);
}
public synchronized long getRetryInterval() {
return serverLocator.getRetryInterval();
}
public synchronized void setRetryInterval(final long retryInterval) {
checkWrite();
serverLocator.setRetryInterval(retryInterval);
}
public synchronized long getMaxRetryInterval() {
return serverLocator.getMaxRetryInterval();
}
public synchronized void setMaxRetryInterval(final long retryInterval) {
checkWrite();
serverLocator.setMaxRetryInterval(retryInterval);
}
public synchronized double getRetryIntervalMultiplier() {
return serverLocator.getRetryIntervalMultiplier();
}
public synchronized void setRetryIntervalMultiplier(final double retryIntervalMultiplier) {
checkWrite();
serverLocator.setRetryIntervalMultiplier(retryIntervalMultiplier);
}
public synchronized int getReconnectAttempts() {
return serverLocator.getReconnectAttempts();
}
public synchronized void setReconnectAttempts(final int reconnectAttempts) {
checkWrite();
serverLocator.setReconnectAttempts(reconnectAttempts);
}
public synchronized void setInitialConnectAttempts(final int reconnectAttempts) {
checkWrite();
serverLocator.setInitialConnectAttempts(reconnectAttempts);
}
public synchronized int getInitialConnectAttempts() {
return serverLocator.getInitialConnectAttempts();
}
public synchronized boolean isFailoverOnInitialConnection() {
return serverLocator.isFailoverOnInitialConnection();
}
public synchronized void setFailoverOnInitialConnection(final boolean failover) {
checkWrite();
serverLocator.setFailoverOnInitialConnection(failover);
}
public synchronized boolean isUseGlobalPools() {
return serverLocator.isUseGlobalPools();
}
public synchronized void setUseGlobalPools(final boolean useGlobalPools) {
checkWrite();
serverLocator.setUseGlobalPools(useGlobalPools);
}
public synchronized int getScheduledThreadPoolMaxSize() {
return serverLocator.getScheduledThreadPoolMaxSize();
}
public synchronized void setScheduledThreadPoolMaxSize(final int scheduledThreadPoolMaxSize) {
checkWrite();
serverLocator.setScheduledThreadPoolMaxSize(scheduledThreadPoolMaxSize);
}
public synchronized int getThreadPoolMaxSize() {
return serverLocator.getThreadPoolMaxSize();
}
public synchronized void setThreadPoolMaxSize(final int threadPoolMaxSize) {
checkWrite();
serverLocator.setThreadPoolMaxSize(threadPoolMaxSize);
}
public synchronized int getInitialMessagePacketSize() {
return serverLocator.getInitialMessagePacketSize();
}
public synchronized void setInitialMessagePacketSize(final int size) {
checkWrite();
serverLocator.setInitialMessagePacketSize(size);
}
/**
* @param interceptorList a comma separated string of incoming interceptor class names to be used. Each interceptor needs a default Constructor to be used with this method.
*/
public void setIncomingInterceptorList(String interceptorList) {
checkWrite();
serverLocator.setIncomingInterceptorList(interceptorList);
}
public String getIncomingInterceptorList() {
return serverLocator.getIncomingInterceptorList();
}
/**
* @param interceptorList a comma separated string of incoming interceptor class names to be used. Each interceptor needs a default Constructor to be used with this method.
*/
public void setOutgoingInterceptorList(String interceptorList) {
serverLocator.setOutgoingInterceptorList(interceptorList);
}
public String getOutgoingInterceptorList() {
return serverLocator.getOutgoingInterceptorList();
}
public ActiveMQConnectionFactory setUser(String user) {
checkWrite();
this.user = user;
return this;
}
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public ActiveMQConnectionFactory setPassword(String password) {
checkWrite();
this.password = password;
return this;
}
public void setGroupID(final String groupID) {
serverLocator.setGroupID(groupID);
}
public String getGroupID() {
return serverLocator.getGroupID();
}
public boolean isCompressLargeMessage() {
return serverLocator.isCompressLargeMessage();
}
public void setCompressLargeMessage(boolean avoidLargeMessages) {
serverLocator.setCompressLargeMessage(avoidLargeMessages);
}
@Override
public void close() {
ServerLocator locator0 = serverLocator;
if (locator0 != null)
locator0.close();
}
public ServerLocator getServerLocator() {
return serverLocator;
}
public int getFactoryType() {
return JMSFactoryType.CF.intValue();
}
// Package protected ----------------------------------------------------------------------------
// Protected ------------------------------------------------------------------------------------
protected synchronized ActiveMQConnection createConnectionInternal(final String username,
final String password,
final boolean isXA,
final int type) throws JMSException {
readOnly = true;
ClientSessionFactory factory;
try {
factory = serverLocator.createSessionFactory();
} catch (Exception e) {
JMSException jmse = new JMSException("Failed to create session factory");
jmse.initCause(e);
jmse.setLinkedException(e);
throw jmse;
}
ActiveMQConnection connection = null;
if (isXA) {
if (type == ActiveMQConnection.TYPE_GENERIC_CONNECTION) {
connection = new ActiveMQXAConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
} else if (type == ActiveMQConnection.TYPE_QUEUE_CONNECTION) {
connection = new ActiveMQXAConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
} else if (type == ActiveMQConnection.TYPE_TOPIC_CONNECTION) {
connection = new ActiveMQXAConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
}
} else {
if (type == ActiveMQConnection.TYPE_GENERIC_CONNECTION) {
connection = new ActiveMQConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
} else if (type == ActiveMQConnection.TYPE_QUEUE_CONNECTION) {
connection = new ActiveMQConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
} else if (type == ActiveMQConnection.TYPE_TOPIC_CONNECTION) {
connection = new ActiveMQConnection(this, username, password, type, clientID, dupsOKBatchSize, transactionBatchSize, factory);
}
}
if (connection == null) {
throw new JMSException("Failed to create connection: invalid type " + type);
}
connection.setReference(this);
try {
connection.authorize();
} catch (JMSException e) {
try {
connection.close();
} catch (JMSException me) {
}
throw e;
}
return connection;
}
@Override
public String toString() {
return "ActiveMQConnectionFactory [serverLocator=" + serverLocator +
", clientID=" +
clientID +
", consumerWindowSize = " +
getConsumerWindowSize() +
", dupsOKBatchSize=" +
dupsOKBatchSize +
", transactionBatchSize=" +
transactionBatchSize +
", readOnly=" +
readOnly +
"]";
}
// Private --------------------------------------------------------------------------------------
private void checkWrite() {
if (readOnly) {
throw new IllegalStateException("Cannot set attribute on ActiveMQConnectionFactory after it has been used");
}
}
@Override
protected void finalize() throws Throwable {
try {
serverLocator.close();
} catch (Exception e) {
e.printStackTrace();
//not much we can do here
}
super.finalize();
}
}