ARTEMIS-751 Simplification of the AMQP implementation

Since we don't need client implementations any longer, given the maturity level of
qpid jms, these classes can go, as a result a lot of the interfaces can be removed.

As part of this I am removing proton-plug, and reorganizing the packages in a way I think it
makes more sense and easier to other developers to understand and maintain it.

https://issues.apache.org/jira/browse/ARTEMIS-751
This commit is contained in:
Clebert Suconic 2016-09-23 17:25:36 -04:00
parent 4e349693f4
commit a838bf0479
120 changed files with 770 additions and 5212 deletions

View File

@ -22,6 +22,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.jboss.logging.Logger;
public class ByteUtil {
@ -29,6 +30,52 @@ public class ByteUtil {
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
public static void debugFrame(Logger logger, String message, ByteBuf byteIn) {
if (logger.isTraceEnabled()) {
int location = byteIn.readerIndex();
// debugging
byte[] frame = new byte[byteIn.writerIndex()];
byteIn.readBytes(frame);
try {
logger.trace(message + "\n" + ByteUtil.formatGroup(ByteUtil.bytesToHex(frame), 8, 16));
}
catch (Exception e) {
logger.warn(e.getMessage(), e);
}
byteIn.readerIndex(location);
}
}
public static String formatGroup(String str, int groupSize, int lineBreak) {
StringBuffer buffer = new StringBuffer();
int line = 1;
buffer.append("/* 1 */ \"");
for (int i = 0; i < str.length(); i += groupSize) {
buffer.append(str.substring(i, i + Math.min(str.length() - i, groupSize)));
if ((i + groupSize) % lineBreak == 0) {
buffer.append("\" +\n/* ");
line++;
if (line < 10) {
buffer.append(" ");
}
buffer.append(Integer.toString(line) + " */ \"");
}
else if ((i + groupSize) % groupSize == 0 && str.length() - i > groupSize) {
buffer.append("\" + \"");
}
}
buffer.append("\";");
return buffer.toString();
}
public static String maxString(String value, int size) {
if (value.length() < size) {
return value;
@ -38,6 +85,16 @@ public class ByteUtil {
}
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static String bytesToHex(byte[] bytes, int groupSize) {
char[] hexChars = new char[bytes.length * 2 + numberOfGroups(bytes, groupSize)];
int outPos = 0;

View File

@ -58,7 +58,6 @@
<include>org.apache.activemq:artemis-native</include>
<include>org.apache.activemq:artemis-amqp-protocol</include>
<include>org.apache.activemq:artemis-openwire-protocol</include>
<include>org.apache.activemq:artemis-proton-plug</include>
<include>org.apache.activemq:artemis-hornetq-protocol</include>
<include>org.apache.activemq:artemis-hqclient-protocol</include>
<include>org.apache.activemq:artemis-stomp-protocol</include>

View File

@ -63,7 +63,6 @@
<feature>artemis-core</feature>
<bundle>wrap:mvn:org.apache.qpid/proton-j/${proton.version}</bundle>
<bundle>wrap:mvn:org.apache.qpid/qpid-jms-client/${qpid.jms.version}</bundle>
<bundle>mvn:org.apache.activemq/artemis-proton-plug/${pom.version}</bundle>
<bundle>mvn:org.apache.activemq/artemis-amqp-protocol/${pom.version}</bundle>
</feature>

View File

@ -74,11 +74,6 @@
<artifactId>artemis-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-proton-plug</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>proton-j</artifactId>

View File

@ -14,12 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.plug;
package org.apache.activemq.artemis.protocol.amqp.broker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -33,15 +30,15 @@ import io.netty.channel.ChannelFutureListener;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.buffers.impl.ChannelBufferWrapper;
import org.apache.activemq.artemis.core.protocol.proton.ActiveMQProtonRemotingConnection;
import org.apache.activemq.artemis.core.protocol.proton.ProtonProtocolManager;
import org.apache.activemq.artemis.core.protocol.proton.sasl.ActiveMQPlainSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.PlainSASL;
import org.apache.activemq.artemis.core.remoting.CloseListener;
import org.apache.activemq.artemis.core.remoting.FailureListener;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
import org.apache.activemq.artemis.core.transaction.impl.XidImpl;
import org.apache.activemq.artemis.protocol.amqp.proton.AmqpSupport;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.apache.activemq.artemis.utils.UUIDGenerator;
@ -49,28 +46,18 @@ import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.AmqpError;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPConnectionContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.SASLResult;
import org.proton.plug.ServerSASL;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.handler.ExtCapability;
import org.proton.plug.logger.ActiveMQAMQPProtocolMessageBundle;
import org.proton.plug.sasl.AnonymousServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ExtCapability;
import org.apache.activemq.artemis.protocol.amqp.logger.ActiveMQAMQPProtocolMessageBundle;
import static org.proton.plug.AmqpSupport.CONTAINER_ID;
import static org.proton.plug.AmqpSupport.INVALID_FIELD;
import static org.proton.plug.context.AbstractConnectionContext.CONNECTION_OPEN_FAILED;
public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback, FailureListener, CloseListener {
private static final Logger logger = Logger.getLogger(ActiveMQProtonConnectionCallback.class);
private static final List<String> connectedContainers = Collections.synchronizedList(new ArrayList());
public class AMQPConnectionCallback implements FailureListener, CloseListener {
private static final Logger logger = Logger.getLogger(AMQPConnectionCallback.class);
private ConcurrentMap<XidImpl, Transaction> transactions = new ConcurrentHashMap<>();
private static final Logger log = Logger.getLogger(ActiveMQProtonConnectionCallback.class);
private final ProtonProtocolManager manager;
private final Connection connection;
@ -89,32 +76,30 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
private ActiveMQServer server;
public ActiveMQProtonConnectionCallback(ProtonProtocolManager manager,
Connection connection,
Executor closeExecutor,
ActiveMQServer server) {
public AMQPConnectionCallback(ProtonProtocolManager manager,
Connection connection,
Executor closeExecutor,
ActiveMQServer server) {
this.manager = manager;
this.connection = connection;
this.closeExecutor = closeExecutor;
this.server = server;
}
@Override
public ServerSASL[] getSASLMechnisms() {
ServerSASL[] result;
if (isSupportsAnonymous()) {
result = new ServerSASL[]{new ActiveMQPlainSASL(manager.getServer().getSecurityStore()), new AnonymousServerSASL()};
result = new ServerSASL[]{new PlainSASL(manager.getServer().getSecurityStore()), new AnonymousServerSASL()};
}
else {
result = new ServerSASL[]{new ActiveMQPlainSASL(manager.getServer().getSecurityStore())};
result = new ServerSASL[]{new PlainSASL(manager.getServer().getSecurityStore())};
}
return result;
}
@Override
public boolean isSupportsAnonymous() {
boolean supportsAnonymous = false;
try {
@ -127,7 +112,6 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
return supportsAnonymous;
}
@Override
public void close() {
try {
if (registeredConnectionId.getAndSet(false)) {
@ -157,12 +141,10 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
}
}
@Override
public void setConnection(AMQPConnectionContext connection) {
this.amqpConnection = connection;
}
@Override
public AMQPConnectionContext getConnection() {
return amqpConnection;
}
@ -176,7 +158,6 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
this.protonConnectionDelegate = protonConnectionDelegate;
}
@Override
public void onTransport(ByteBuf byteBuf, AMQPConnectionContext amqpConnection) {
final int size = byteBuf.writerIndex();
@ -200,28 +181,25 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
amqpConnection.outputDone(size);
}
@Override
public AMQPSessionCallback createSessionCallback(AMQPConnectionContext connection) {
return new ProtonSessionIntegrationCallback(this, manager, connection, this.connection, closeExecutor);
return new AMQPSessionCallback(this, manager, connection, this.connection, closeExecutor);
}
@Override
public void sendSASLSupported() {
connection.write(ActiveMQBuffers.wrappedBuffer(new byte[]{'A', 'M', 'Q', 'P', 3, 1, 0, 0}));
}
@Override
public boolean validateConnection(org.apache.qpid.proton.engine.Connection connection, SASLResult saslResult) {
remoteContainerId = connection.getRemoteContainer();
boolean idOK = server.addClientConnection(remoteContainerId, ExtCapability.needUniqueConnection(connection));
if (!idOK) {
//https://issues.apache.org/jira/browse/ARTEMIS-728
Map<Symbol, Object> connProp = new HashMap<>();
connProp.put(CONNECTION_OPEN_FAILED, "true");
connProp.put(AmqpSupport.CONNECTION_OPEN_FAILED, "true");
connection.setProperties(connProp);
connection.getCondition().setCondition(AmqpError.INVALID_FIELD);
Map<Symbol, Symbol> info = new HashMap<>();
info.put(INVALID_FIELD, CONTAINER_ID);
info.put(AmqpSupport.INVALID_FIELD, AmqpSupport.CONTAINER_ID);
connection.getCondition().setInfo(info);
return false;
}
@ -244,7 +222,6 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
close();
}
@Override
public Binary newTransaction() {
XidImpl xid = newXID();
Transaction transaction = new TransactionImpl(xid, server.getStorageManager(), -1);
@ -252,7 +229,6 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
return new Binary(xid.getGlobalTransactionId());
}
@Override
public Transaction getTransaction(Binary txid) throws ActiveMQAMQPException {
XidImpl xid = newXID(txid.getArray());
Transaction tx = transactions.get(xid);
@ -264,7 +240,6 @@ public class ActiveMQProtonConnectionCallback implements AMQPConnectionCallback,
return tx;
}
@Override
public void removeTransaction(Binary txid) {
XidImpl xid = newXID(txid.getArray());
transactions.remove(xid);

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.plug;
package org.apache.activemq.artemis.protocol.amqp.broker;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@ -28,8 +28,8 @@ import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.core.io.IOCallback;
import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.protocol.proton.ProtonProtocolManager;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.EncodedMessage;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException;
import org.apache.activemq.artemis.protocol.amqp.converter.message.EncodedMessage;
import org.apache.activemq.artemis.core.server.BindingQueryResult;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.QueueQueryResult;
@ -39,6 +39,7 @@ import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.protocol.amqp.sasl.PlainSASLResult;
import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
@ -55,21 +56,18 @@ import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.proton.plug.AMQPConnectionContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.AMQPSessionContext;
import org.proton.plug.SASLResult;
import org.proton.plug.context.ProtonPlugSender;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.exceptions.ActiveMQAMQPInternalErrorException;
import org.proton.plug.exceptions.ActiveMQAMQPResourceLimitExceededException;
import org.proton.plug.sasl.PlainSASLResult;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPSessionContext;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.proton.ProtonServerSenderContext;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPResourceLimitExceededException;
public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, SessionCallback {
public class AMQPSessionCallback implements SessionCallback {
protected final IDGenerator consumerIDGenerator = new SimpleIDGenerator(0);
private final ActiveMQProtonConnectionCallback protonSPI;
private final AMQPConnectionCallback protonSPI;
private final ProtonProtocolManager manager;
@ -85,11 +83,11 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
private final AtomicBoolean draining = new AtomicBoolean(false);
public ProtonSessionIntegrationCallback(ActiveMQProtonConnectionCallback protonSPI,
ProtonProtocolManager manager,
AMQPConnectionContext connection,
Connection transportConnection,
Executor executor) {
public AMQPSessionCallback(AMQPConnectionCallback protonSPI,
ProtonProtocolManager manager,
AMQPConnectionContext connection,
Connection transportConnection,
Executor executor) {
this.protonSPI = protonSPI;
this.manager = manager;
this.connection = connection;
@ -102,13 +100,12 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
return transportConnection.isWritable(callback);
}
@Override
public void onFlowConsumer(Object consumer, int credits, final boolean drain) {
ServerConsumerImpl serverConsumer = (ServerConsumerImpl) consumer;
if (drain) {
// If the draining is already running, then don't do anything
if (draining.compareAndSet(false, true)) {
final ProtonPlugSender plugSender = (ProtonPlugSender) serverConsumer.getProtocolContext();
final ProtonServerSenderContext plugSender = (ProtonServerSenderContext) serverConsumer.getProtocolContext();
serverConsumer.forceDelivery(1, new Runnable() {
@Override
public void run() {
@ -132,7 +129,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
@Override
public void init(AMQPSessionContext protonSession, SASLResult saslResult) throws Exception {
this.protonSession = protonSession;
@ -161,13 +157,11 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
@Override
public void start() {
}
@Override
public Object createSender(ProtonPlugSender protonSender,
public Object createSender(ProtonServerSenderContext protonSender,
String queue,
String filter,
boolean browserOnly) throws Exception {
@ -185,29 +179,24 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
return consumer;
}
@Override
public void startSender(Object brokerConsumer) throws Exception {
ServerConsumer serverConsumer = (ServerConsumer) brokerConsumer;
// flow control is done at proton
serverConsumer.receiveCredits(-1);
}
@Override
public void createTemporaryQueue(String queueName) throws Exception {
serverSession.createQueue(SimpleString.toSimpleString(queueName), SimpleString.toSimpleString(queueName), null, true, false);
}
@Override
public void createTemporaryQueue(String address, String queueName, String filter) throws Exception {
serverSession.createQueue(SimpleString.toSimpleString(address), SimpleString.toSimpleString(queueName), SimpleString.toSimpleString(filter), true, false);
}
@Override
public void createDurableQueue(String address, String queueName, String filter) throws Exception {
serverSession.createQueue(SimpleString.toSimpleString(address), SimpleString.toSimpleString(queueName), SimpleString.toSimpleString(filter), false, true);
}
@Override
public QueueQueryResult queueQuery(String queueName, boolean autoCreate) throws Exception {
QueueQueryResult queueQueryResult = serverSession.executeQueueQuery(SimpleString.toSimpleString(queueName));
@ -223,7 +212,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
return queueQueryResult;
}
@Override
public boolean bindingQuery(String address) throws Exception {
BindingQueryResult bindingQueryResult = serverSession.executeBindingQuery(SimpleString.toSimpleString(address));
if (!bindingQueryResult.isExists() && bindingQueryResult.isAutoCreateJmsQueues()) {
@ -238,7 +226,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
return bindingQueryResult.isExists();
}
@Override
public void closeSender(final Object brokerConsumer) throws Exception {
final ServerConsumer consumer = ((ServerConsumer) brokerConsumer);
@ -276,17 +263,14 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public ProtonJMessage encodeMessage(Object message, int deliveryCount) throws Exception {
return (ProtonJMessage) manager.getConverter().outbound((ServerMessage) message, deliveryCount);
}
@Override
public String tempQueueName() {
return UUIDGenerator.getInstance().generateStringUUID();
}
@Override
public void close() throws Exception {
//need to check here as this can be called if init fails
if (serverSession != null) {
@ -300,7 +284,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public void ack(Transaction transaction, Object brokerConsumer, Object message) throws Exception {
if (transaction == null) {
transaction = serverSession.getCurrentTransaction();
@ -314,7 +297,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public void cancel(Object brokerConsumer, Object message, boolean updateCounts) throws Exception {
recoverContext();
try {
@ -325,12 +307,10 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public void resumeDelivery(Object consumer) {
((ServerConsumer) consumer).receiveCredits(-1);
}
@Override
public void serverSend(final Transaction transaction,
final Receiver receiver,
final Delivery delivery,
@ -406,12 +386,10 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public String getPubSubPrefix() {
return manager.getPubSubPrefix();
}
@Override
public void offerProducerCredit(final String address, final int credits, final int threshold, final Receiver receiver) {
try {
final PagingStore store = manager.getServer().getPagingManager().getPageStore(new SimpleString(address));
@ -430,7 +408,6 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public void deleteQueue(String queueName) throws Exception {
manager.getServer().destroyQueue(new SimpleString(queueName));
}
@ -461,7 +438,7 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
message.removeProperty(ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString());
ProtonPlugSender plugSender = (ProtonPlugSender) consumer.getProtocolContext();
ProtonServerSenderContext plugSender = (ProtonServerSenderContext) consumer.getProtocolContext();
try {
return plugSender.deliverMessage(message, deliveryCount);
@ -503,7 +480,7 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
@Override
public boolean hasCredits(ServerConsumer consumer) {
ProtonPlugSender plugSender = (ProtonPlugSender) consumer.getProtocolContext();
ProtonServerSenderContext plugSender = (ProtonServerSenderContext) consumer.getProtocolContext();
if (plugSender != null && plugSender.getSender().getCredit() > 0) {
return true;
@ -513,25 +490,21 @@ public class ProtonSessionIntegrationCallback implements AMQPSessionCallback, Se
}
}
@Override
public Transaction getTransaction(Binary txid) throws ActiveMQAMQPException {
return protonSPI.getTransaction(txid);
}
@Override
public Binary newTransaction() {
return protonSPI.newTransaction();
}
@Override
public void commitTX(Binary txid) throws Exception {
Transaction tx = protonSPI.getTransaction(txid);
tx.commit(true);
protonSPI.removeTransaction(txid);
}
@Override
public void rollbackTX(Binary txid, boolean lastMessageReceived) throws Exception {
Transaction tx = protonSPI.getTransaction(txid);
tx.rollback();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton;
package org.apache.activemq.artemis.protocol.amqp.broker;
import java.util.concurrent.Executor;
@ -24,7 +24,7 @@ import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
import org.apache.activemq.artemis.spi.core.protocol.AbstractRemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.proton.plug.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
/**
* This is a Server's Connection representation used by ActiveMQ Artemis.

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton;
package org.apache.activemq.artemis.protocol.amqp.broker;
import java.util.Arrays;
import java.util.List;
@ -25,8 +25,8 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.BaseInterceptor;
import org.apache.activemq.artemis.api.core.Interceptor;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.core.protocol.proton.converter.ProtonMessageConverter;
import org.apache.activemq.artemis.core.protocol.proton.plug.ActiveMQProtonConnectionCallback;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConstants;
import org.apache.activemq.artemis.protocol.amqp.converter.ProtonMessageConverter;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyServerConnection;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.management.Notification;
@ -39,11 +39,7 @@ import org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.proton.plug.AMQPServerConnectionContext;
import org.proton.plug.context.server.ProtonServerConnectionContextFactory;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_CHANNEL_MAX;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_MAX_FRAME_SIZE;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
/**
* A proton protocol manager, basically reads the Proton Input and maps proton resources to ActiveMQ Artemis resources
@ -64,7 +60,7 @@ public class ProtonProtocolManager implements ProtocolManager<Interceptor>, Noti
* */
private String pubSubPrefix = ActiveMQDestination.JMS_TOPIC_ADDRESS_PREFIX;
private int maxFrameSize = DEFAULT_MAX_FRAME_SIZE;
private int maxFrameSize = AMQPConstants.Connection.DEFAULT_MAX_FRAME_SIZE;
public ProtonProtocolManager(ProtonProtocolManagerFactory factory, ActiveMQServer server) {
this.factory = factory;
@ -104,7 +100,7 @@ public class ProtonProtocolManager implements ProtocolManager<Interceptor>, Noti
@Override
public ConnectionEntry createConnectionEntry(Acceptor acceptorUsed, Connection remotingConnection) {
ActiveMQProtonConnectionCallback connectionCallback = new ActiveMQProtonConnectionCallback(this, remotingConnection, server.getExecutorFactory().getExecutor(), server);
AMQPConnectionCallback connectionCallback = new AMQPConnectionCallback(this, remotingConnection, server.getExecutorFactory().getExecutor(), server);
long ttl = ActiveMQClient.DEFAULT_CONNECTION_TTL;
if (server.getConfiguration().getConnectionTTLOverride() != -1) {
@ -112,8 +108,8 @@ public class ProtonProtocolManager implements ProtocolManager<Interceptor>, Noti
}
String id = server.getConfiguration().getName();
AMQPServerConnectionContext amqpConnection = ProtonServerConnectionContextFactory.getFactory().
createConnection(connectionCallback, id, (int) ttl, getMaxFrameSize(), DEFAULT_CHANNEL_MAX, server.getExecutorFactory().getExecutor(), server.getScheduledPool());
AMQPConnectionContext amqpConnection =
new AMQPConnectionContext(connectionCallback, id, (int) ttl, getMaxFrameSize(), AMQPConstants.Connection.DEFAULT_CHANNEL_MAX, server.getExecutorFactory().getExecutor(), server.getScheduledPool());
Executor executor = server.getExecutorFactory().getExecutor();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton;
package org.apache.activemq.artemis.protocol.amqp.broker;
import org.apache.activemq.artemis.api.core.BaseInterceptor;
import org.apache.activemq.artemis.api.core.Interceptor;

View File

@ -14,13 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context;
import org.apache.qpid.proton.engine.Sender;
public interface ProtonPlugSender {
int deliverMessage(Object message, int deliveryCount) throws Exception;
Sender getSender();
}
/**
* This package includes classes used to interact with the broker.
* The ProtocolManager will be here, and some classes that will interact with the PostOffice
* and other internal components directly.
*/
package org.apache.activemq.artemis.protocol.amqp.broker;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter;
package org.apache.activemq.artemis.protocol.amqp.converter;
import javax.jms.BytesMessage;
import javax.jms.Destination;
@ -26,14 +26,14 @@ import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import org.apache.activemq.artemis.core.buffers.impl.ResetLimitWrappedActiveMQBuffer;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerDestination;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSBytesMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMapMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSObjectMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSStreamMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSTextMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.JMSVendor;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerDestination;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMapMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.message.JMSVendor;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSBytesMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSObjectMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSStreamMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSTextMessage;
import org.apache.activemq.artemis.core.server.ServerMessage;
import org.apache.activemq.artemis.core.server.impl.ServerMessageImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

View File

@ -14,15 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter;
package org.apache.activemq.artemis.protocol.amqp.converter;
import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.AMQPNativeOutboundTransformer;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.EncodedMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.InboundTransformer;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.JMSMappingInboundTransformer;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.JMSMappingOutboundTransformer;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.message.AMQPNativeOutboundTransformer;
import org.apache.activemq.artemis.protocol.amqp.converter.message.EncodedMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.message.InboundTransformer;
import org.apache.activemq.artemis.protocol.amqp.converter.message.JMSMappingInboundTransformer;
import org.apache.activemq.artemis.protocol.amqp.converter.message.JMSMappingOutboundTransformer;
import org.apache.activemq.artemis.core.server.ServerMessage;
import org.apache.activemq.artemis.spi.core.protocol.MessageConverter;
import org.apache.activemq.artemis.utils.IDGenerator;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.BytesMessage;
import javax.jms.JMSException;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.JMSException;
import javax.jms.MapMessage;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.DeliveryMode;
import javax.jms.Destination;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.core.message.impl.MessageInternal;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.JMSException;
import javax.jms.MessageEOFException;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.jms;
package org.apache.activemq.artemis.protocol.amqp.converter.jms;
import javax.jms.JMSException;
import javax.jms.TextMessage;

View File

@ -18,11 +18,11 @@
* under the License.
*
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.UnsignedLong;
import org.proton.plug.exceptions.ActiveMQAMQPIllegalStateException;
import java.nio.ByteBuffer;
import java.util.UUID;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
public class AMQPMessageTypes {
public static final String AMQP_TYPE_KEY = "amqp:type";

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import javax.jms.Message;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.qpid.proton.amqp.UnsignedInteger;
import org.apache.qpid.proton.amqp.messaging.Header;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.message.Message;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Decimal128;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.messaging.AmqpSequence;

View File

@ -14,10 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import org.apache.activemq.artemis.core.message.impl.MessageInternal;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.UnsignedByte;
@ -34,7 +35,6 @@ import org.apache.qpid.proton.amqp.messaging.Properties;
import org.apache.qpid.proton.amqp.messaging.Section;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.jboss.logging.Logger;
import org.proton.plug.exceptions.ActiveMQAMQPIllegalStateException;
import javax.jms.BytesMessage;
import javax.jms.DeliveryMode;
@ -142,9 +142,9 @@ public class JMSMappingOutboundTransformer extends OutboundTransformer {
body = new AmqpValue(((ObjectMessage) msg).getObject());
}
if (body == null && msg instanceof org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage) {
if (body == null && msg instanceof ServerJMSMessage) {
MessageInternal internalMessage = ((org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage) msg).getInnerMessage();
MessageInternal internalMessage = ((ServerJMSMessage) msg).getInnerMessage();
if (!internalMessage.containsProperty("AMQP_MESSAGE_FORMAT")) {
int readerIndex = internalMessage.getBodyBuffer().readerIndex();
try {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
import javax.jms.BytesMessage;
import javax.jms.Destination;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.converter.message;
package org.apache.activemq.artemis.protocol.amqp.converter.message;
public abstract class OutboundTransformer {

View File

@ -14,11 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug;
public interface ClientSASL {
byte[] getBytes();
String getName();
}
/**
* This package will include classes used to make convertions between Artemis and AMQP.
*/
package org.apache.activemq.artemis.protocol.amqp.converter;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.exceptions;
package org.apache.activemq.artemis.protocol.amqp.exceptions;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.qpid.proton.amqp.transport.AmqpError;

View File

@ -14,15 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.logger;
package org.apache.activemq.artemis.protocol.amqp.logger;
import org.proton.plug.exceptions.ActiveMQAMQPIllegalStateException;
import org.proton.plug.exceptions.ActiveMQAMQPInternalErrorException;
import org.proton.plug.exceptions.ActiveMQAMQPInvalidFieldException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInvalidFieldException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageBundle;
import org.jboss.logging.Messages;
import org.proton.plug.exceptions.ActiveMQAMQPNotFoundException;
/**
* Logger Code 11

View File

@ -14,10 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context;
package org.apache.activemq.artemis.protocol.amqp.proton;
import static org.proton.plug.AmqpSupport.PRODUCT;
import static org.proton.plug.AmqpSupport.VERSION;
import io.netty.buffer.ByteBuf;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPConnectionCallback;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.EventHandler;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ProtonHandler;
import org.apache.activemq.artemis.utils.ByteUtil;
import org.apache.activemq.artemis.utils.VersionLoader;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transaction.Coordinator;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.apache.qpid.proton.engine.Transport;
import org.jboss.logging.Logger;
import org.apache.activemq.artemis.protocol.amqp.proton.handler.ExtCapability;
import java.util.HashMap;
import java.util.Map;
@ -27,30 +45,9 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import io.netty.buffer.ByteBuf;
import org.apache.activemq.artemis.utils.VersionLoader;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Session;
import org.apache.qpid.proton.engine.Transport;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPConnectionContext;
import org.proton.plug.SASLResult;
import org.proton.plug.context.server.ProtonServerSenderContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.handler.ProtonHandler;
import org.proton.plug.handler.impl.DefaultEventHandler;
import org.proton.plug.util.ByteUtil;
public class AMQPConnectionContext extends ProtonInitializable {
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_CHANNEL_MAX;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_IDLE_TIMEOUT;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_MAX_FRAME_SIZE;
public abstract class AbstractConnectionContext extends ProtonInitializable implements AMQPConnectionContext {
private static final Logger log = Logger.getLogger(AbstractConnectionContext.class);
private static final Logger log = Logger.getLogger(AMQPConnectionContext.class);
public static final Symbol CONNECTION_OPEN_FAILED = Symbol.valueOf("amqp:connection-establishment-failed");
public static final String AMQP_CONTAINER_ID = "amqp-container-id";
@ -62,30 +59,28 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
private final Map<Symbol, Object> connectionProperties = new HashMap<>();
private final ScheduledExecutorService scheduledPool;
private final Map<Session, AbstractProtonSessionContext> sessions = new ConcurrentHashMap<>();
private final Map<Session, AMQPSessionContext> sessions = new ConcurrentHashMap<>();
protected LocalListener listener = new LocalListener();
public AbstractConnectionContext(AMQPConnectionCallback connectionCallback, Executor dispatchExecutor, ScheduledExecutorService scheduledPool) {
this(connectionCallback, null, DEFAULT_IDLE_TIMEOUT, DEFAULT_MAX_FRAME_SIZE, DEFAULT_CHANNEL_MAX, dispatchExecutor, scheduledPool);
}
public AbstractConnectionContext(AMQPConnectionCallback connectionCallback,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
this.connectionCallback = connectionCallback;
public AMQPConnectionContext(AMQPConnectionCallback connectionSP,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
this.connectionCallback = connectionSP;
this.containerId = (containerId != null) ? containerId : UUID.randomUUID().toString();
connectionProperties.put(PRODUCT, "apache-activemq-artemis");
connectionProperties.put(VERSION, VersionLoader.getVersion().getFullVersion());
connectionProperties.put(AmqpSupport.PRODUCT, "apache-activemq-artemis");
connectionProperties.put(AmqpSupport.VERSION, VersionLoader.getVersion().getFullVersion());
this.scheduledPool = scheduledPool;
connectionCallback.setConnection(this);
this.handler = ProtonHandler.Factory.create(dispatchExecutor);
this.handler = new ProtonHandler(dispatchExecutor);
Transport transport = handler.getTransport();
transport.setEmitFlowEventOnSend(false);
if (idleTimeout > 0) {
@ -96,12 +91,17 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
handler.addEventHandler(listener);
}
@Override
protected AMQPSessionContext newSessionExtension(Session realSession) throws ActiveMQAMQPException {
AMQPSessionCallback sessionSPI = connectionCallback.createSessionCallback(this);
AMQPSessionContext protonSession = new AMQPSessionContext(sessionSPI, this, realSession);
return protonSession;
}
public SASLResult getSASLResult() {
return handler.getSASLResult();
}
@Override
public void inputBuffer(ByteBuf buffer) {
if (log.isTraceEnabled()) {
ByteUtil.debugFrame(log, "Buffer Received ", buffer);
@ -114,41 +114,33 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
connectionCallback.close();
}
/**
* See comment at {@link org.proton.plug.AMQPConnectionContext#isSyncOnFlush()}
*/
@Override
public boolean isSyncOnFlush() {
return false;
}
@Override
public Object getLock() {
return handler.getLock();
}
@Override
public int capacity() {
return handler.capacity();
}
@Override
public void outputDone(int bytes) {
handler.outputDone(bytes);
}
@Override
public void flush() {
handler.flush();
}
@Override
public void close() {
handler.close();
}
protected AbstractProtonSessionContext getSessionExtension(Session realSession) throws ActiveMQAMQPException {
AbstractProtonSessionContext sessionExtension = sessions.get(realSession);
protected AMQPSessionContext getSessionExtension(Session realSession) throws ActiveMQAMQPException {
AMQPSessionContext sessionExtension = sessions.get(realSession);
if (sessionExtension == null) {
// how this is possible? Log a warn here
sessionExtension = newSessionExtension(realSession);
@ -158,16 +150,16 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
return sessionExtension;
}
protected abstract void remoteLinkOpened(Link link) throws Exception;
protected abstract AbstractProtonSessionContext newSessionExtension(Session realSession) throws ActiveMQAMQPException;
@Override
protected boolean validateConnection(Connection connection) {
return connectionCallback.validateConnection(connection, handler.getSASLResult());
}
public boolean checkDataReceived() {
return handler.checkDataReceived();
}
@Override
public long getCreationTime() {
return handler.getCreationTime();
}
@ -176,7 +168,7 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
ByteBuf bytes;
// handler.outputBuffer has the lock
while ((bytes = handler.outputBuffer()) != null) {
connectionCallback.onTransport(bytes, AbstractConnectionContext.this);
connectionCallback.onTransport(bytes, this);
}
}
@ -188,15 +180,90 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
return null;
}
protected boolean validateConnection(Connection connection) {
return true;
}
protected void initInternal() throws Exception {
}
protected void remoteLinkOpened(Link link) throws Exception {
AMQPSessionContext protonSession = (AMQPSessionContext) getSessionExtension(link.getSession());
link.setSource(link.getRemoteSource());
link.setTarget(link.getRemoteTarget());
if (link instanceof Receiver) {
Receiver receiver = (Receiver) link;
if (link.getRemoteTarget() instanceof Coordinator) {
Coordinator coordinator = (Coordinator) link.getRemoteTarget();
protonSession.addTransactionHandler(coordinator, receiver);
}
else {
protonSession.addReceiver(receiver);
}
}
else {
Sender sender = (Sender) link;
protonSession.addSender(sender);
sender.offer(1);
}
}
public Symbol[] getConnectionCapabilitiesOffered() {
return ExtCapability.getCapabilities();
}
// This listener will perform a bunch of things here
class LocalListener extends DefaultEventHandler {
class LocalListener implements EventHandler {
@Override
public void onInit(Connection connection) throws Exception {
}
@Override
public void onLocalOpen(Connection connection) throws Exception {
}
@Override
public void onLocalClose(Connection connection) throws Exception {
}
@Override
public void onFinal(Connection connection) throws Exception {
}
@Override
public void onInit(Session session) throws Exception {
}
@Override
public void onFinal(Session session) throws Exception {
}
@Override
public void onInit(Link link) throws Exception {
}
@Override
public void onLocalOpen(Link link) throws Exception {
}
@Override
public void onLocalClose(Link link) throws Exception {
}
@Override
public void onFinal(Link link) throws Exception {
}
@Override
public void onAuthInit(ProtonHandler handler, Connection connection, boolean sasl) {
@ -230,7 +297,7 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
connection.close();
}
else {
connection.setContext(AbstractConnectionContext.this);
connection.setContext(AMQPConnectionContext.this);
connection.setContainer(containerId);
connection.setProperties(connectionProperties);
connection.setOfferedCapabilities(getConnectionCapabilitiesOffered());
@ -265,7 +332,7 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
public void onRemoteClose(Connection connection) {
synchronized (getLock()) {
connection.close();
for (AbstractProtonSessionContext protonSession : sessions.values()) {
for (AMQPSessionContext protonSession : sessions.values()) {
protonSession.close();
}
sessions.clear();
@ -298,7 +365,7 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
session.close();
}
AbstractProtonSessionContext sessionContext = (AbstractProtonSessionContext) session.getContext();
AMQPSessionContext sessionContext = (AMQPSessionContext)session.getContext();
if (sessionContext != null) {
sessionContext.close();
sessions.remove(session);
@ -353,8 +420,5 @@ public abstract class AbstractConnectionContext extends ProtonInitializable impl
}
}
@Override
public Symbol[] getConnectionCapabilitiesOffered() {
return null;
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context;
package org.apache.activemq.artemis.protocol.amqp.proton;
/**
* Constants derived from the AMQP spec

View File

@ -0,0 +1,221 @@
/*
* 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.protocol.amqp.proton;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transaction.Coordinator;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.jboss.logging.Logger;
public class AMQPSessionContext extends ProtonInitializable {
private static final Logger log = Logger.getLogger(AMQPSessionContext.class);
protected final AMQPConnectionContext connection;
protected final AMQPSessionCallback sessionSPI;
protected final Session session;
private long currentTag = 0;
protected Map<Receiver, ProtonServerReceiverContext> receivers = new HashMap<>();
protected Map<Sender, ProtonServerSenderContext> senders = new HashMap<>();
protected boolean closed = false;
public AMQPSessionContext(AMQPSessionCallback sessionSPI,
AMQPConnectionContext connection,
Session session) {
this.connection = connection;
this.sessionSPI = sessionSPI;
this.session = session;
}
protected Map<Object, ProtonServerSenderContext> serverSenders = new HashMap<>();
@Override
public void initialise() throws Exception {
if (!isInitialized()) {
super.initialise();
if (sessionSPI != null) {
try {
sessionSPI.init(this, connection.getSASLResult());
}
catch (Exception e) {
throw new ActiveMQAMQPInternalErrorException(e.getMessage(), e);
}
}
}
}
/**
* @param consumer
* @param queueName
*/
public void disconnect(Object consumer, String queueName) {
ProtonServerSenderContext protonConsumer = senders.remove(consumer);
if (protonConsumer != null) {
try {
protonConsumer.close(false);
}
catch (ActiveMQAMQPException e) {
protonConsumer.getSender().setTarget(null);
protonConsumer.getSender().setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
}
}
}
/**
* The consumer object from the broker or the key used to store the sender
*
* @param message
* @param consumer
* @param deliveryCount
* @return the number of bytes sent
*/
public int serverDelivery(Object message, Object consumer, int deliveryCount) throws Exception {
ProtonServerSenderContext protonSender = serverSenders.get(consumer);
if (protonSender != null) {
return protonSender.deliverMessage(message, deliveryCount);
}
return 0;
}
public byte[] getTag() {
return Long.toHexString(currentTag++).getBytes();
}
public void replaceTag(byte[] tag) {
// TODO: do we need to reuse this?
}
public void close() {
if (closed) {
return;
}
// Making a copy to avoid ConcurrentModificationException during the iteration
Set<ProtonServerReceiverContext> receiversCopy = new HashSet<>();
receiversCopy.addAll(receivers.values());
for (ProtonServerReceiverContext protonProducer : receiversCopy) {
try {
protonProducer.close(false);
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
receivers.clear();
Set<ProtonServerSenderContext> protonSendersClone = new HashSet<>();
protonSendersClone.addAll(senders.values());
for (ProtonServerSenderContext protonConsumer : protonSendersClone) {
try {
protonConsumer.close(false);
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
senders.clear();
try {
if (sessionSPI != null) {
sessionSPI.close();
}
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
closed = true;
}
public void removeReceiver(Receiver receiver) {
receivers.remove(receiver);
}
public void addTransactionHandler(Coordinator coordinator, Receiver receiver) {
ProtonTransactionHandler transactionHandler = new ProtonTransactionHandler(sessionSPI);
coordinator.setCapabilities(Symbol.getSymbol("amqp:local-transactions"),
Symbol.getSymbol("amqp:multi-txns-per-ssn"),
Symbol.getSymbol("amqp:multi-ssns-per-txn"));
receiver.setContext(transactionHandler);
receiver.open();
receiver.flow(100);
}
public void addSender(Sender sender) throws Exception {
ProtonServerSenderContext protonSender = new ProtonServerSenderContext(connection, sender, this, sessionSPI);
try {
protonSender.initialise();
senders.put(sender, protonSender);
serverSenders.put(protonSender.getBrokerConsumer(), protonSender);
sender.setContext(protonSender);
sender.open();
protonSender.start();
}
catch (ActiveMQAMQPException e) {
senders.remove(sender);
sender.setSource(null);
sender.setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
sender.close();
}
}
public void removeSender(Sender sender) throws ActiveMQAMQPException {
senders.remove(sender);
ProtonServerSenderContext senderRemoved = senders.remove(sender);
if (senderRemoved != null) {
serverSenders.remove(senderRemoved.getBrokerConsumer());
}
}
public void addReceiver(Receiver receiver) throws Exception {
try {
ProtonServerReceiverContext protonReceiver = new ProtonServerReceiverContext(sessionSPI, connection, this, receiver);
protonReceiver.initialise();
receivers.put(receiver, protonReceiver);
receiver.setContext(protonReceiver);
receiver.open();
}
catch (ActiveMQAMQPException e) {
receivers.remove(receiver);
receiver.setTarget(null);
receiver.setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
receiver.close();
}
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug;
package org.apache.activemq.artemis.protocol.amqp.proton;
import org.apache.qpid.proton.amqp.DescribedType;
import org.apache.qpid.proton.amqp.Symbol;

View File

@ -14,11 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context;
package org.apache.activemq.artemis.protocol.amqp.proton;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Delivery;
import org.proton.plug.exceptions.ActiveMQAMQPException;
/**
* An interface to handle deliveries, either messages, acks or transaction calls

View File

@ -14,13 +14,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.test.minimalclient;
package org.apache.activemq.artemis.protocol.amqp.proton;
import org.proton.plug.AMQPClientConnectionContext;
public class ProtonInitializable {
public interface Connector {
private boolean initialized = false;
void start();
public boolean isInitialized() {
return initialized;
}
AMQPClientConnectionContext connect(String host, int port) throws Exception;
public void initialise() throws Exception {
if (!initialized) {
initialized = true;
}
}
}

View File

@ -14,10 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context.server;
package org.apache.activemq.artemis.protocol.amqp.proton;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
import org.apache.activemq.artemis.protocol.amqp.logger.ActiveMQAMQPProtocolMessageBundle;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException;
import org.apache.activemq.artemis.protocol.amqp.util.DeliveryUtil;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Rejected;
@ -26,21 +32,22 @@ import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Receiver;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonReceiverContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.exceptions.ActiveMQAMQPInternalErrorException;
import org.proton.plug.exceptions.ActiveMQAMQPNotFoundException;
import org.proton.plug.logger.ActiveMQAMQPProtocolMessageBundle;
import static org.proton.plug.util.DeliveryUtil.readDelivery;
public class ProtonServerReceiverContext extends AbstractProtonReceiverContext {
public class ProtonServerReceiverContext extends ProtonInitializable implements ProtonDeliveryHandler {
private static final Logger log = Logger.getLogger(ProtonServerReceiverContext.class);
protected final AMQPConnectionContext connection;
protected final AMQPSessionContext protonSession;
protected final Receiver receiver;
protected String address;
protected final AMQPSessionCallback sessionSPI;
/*
The maximum number of credits we will allocate to clients.
This number is also used by the broker when refresh client credits.
@ -51,10 +58,13 @@ public class ProtonServerReceiverContext extends AbstractProtonReceiverContext {
private static int minCreditRefresh = 30;
public ProtonServerReceiverContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
AbstractProtonSessionContext protonSession,
AMQPConnectionContext connection,
AMQPSessionContext protonSession,
Receiver receiver) {
super(sessionSPI, connection, protonSession, receiver);
this.connection = connection;
this.protonSession = protonSession;
this.receiver = receiver;
this.sessionSPI = sessionSPI;
}
@Override
@ -128,7 +138,7 @@ public class ProtonServerReceiverContext extends AbstractProtonReceiverContext {
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.heapBuffer(10 * 1024);
try {
synchronized (connection.getLock()) {
readDelivery(receiver, buffer);
DeliveryUtil.readDelivery(receiver, buffer);
receiver.advance();
@ -158,4 +168,44 @@ public class ProtonServerReceiverContext extends AbstractProtonReceiverContext {
}
}
@Override
public void close(boolean remoteLinkClose) throws ActiveMQAMQPException {
protonSession.removeReceiver(receiver);
}
@Override
public void close(ErrorCondition condition) throws ActiveMQAMQPException {
receiver.setCondition(condition);
close(false);
}
public void flow(int credits, int threshold) {
// Use the SessionSPI to allocate producer credits, or default, always allocate credit.
if (sessionSPI != null) {
sessionSPI.offerProducerCredit(address, credits, threshold, receiver);
}
else {
synchronized (connection.getLock()) {
receiver.flow(credits);
connection.flush();
}
}
}
public void drain(int credits) {
synchronized (connection.getLock()) {
receiver.drain(credits);
}
connection.flush();
}
public int drained() {
return receiver.drained();
}
public boolean isDraining() {
return receiver.draining();
}
}

View File

@ -14,15 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context.server;
package org.apache.activemq.artemis.protocol.amqp.proton;
import java.util.Map;
import java.util.Objects;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPInternalErrorException;
import org.apache.activemq.artemis.protocol.amqp.util.CreditsSemaphore;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPNotFoundException;
import org.apache.activemq.artemis.core.server.QueueQueryResult;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.jms.client.ActiveMQConnection;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
import org.apache.activemq.artemis.protocol.amqp.logger.ActiveMQAMQPProtocolMessageBundle;
import org.apache.activemq.artemis.selector.filter.FilterException;
import org.apache.activemq.artemis.selector.impl.SelectorParser;
import org.apache.qpid.proton.amqp.DescribedType;
@ -44,22 +52,10 @@ import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.AmqpSupport;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonContextSender;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.context.ProtonPlugSender;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.exceptions.ActiveMQAMQPIllegalStateException;
import org.proton.plug.exceptions.ActiveMQAMQPInternalErrorException;
import org.proton.plug.exceptions.ActiveMQAMQPNotFoundException;
import org.proton.plug.logger.ActiveMQAMQPProtocolMessageBundle;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPIllegalStateException;
import org.apache.activemq.artemis.protocol.amqp.util.NettyWritable;
import static org.proton.plug.AmqpSupport.JMS_SELECTOR_FILTER_IDS;
import static org.proton.plug.AmqpSupport.findFilter;
public class ProtonServerSenderContext extends AbstractProtonContextSender implements ProtonPlugSender {
public class ProtonServerSenderContext extends ProtonInitializable implements ProtonDeliveryHandler {
private static final Logger log = Logger.getLogger(ProtonServerSenderContext.class);
@ -69,11 +65,23 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
private Object brokerConsumer;
public ProtonServerSenderContext(AbstractConnectionContext connection,
protected final AMQPSessionContext protonSession;
protected final Sender sender;
protected final AMQPConnectionContext connection;
protected boolean closed = false;
protected final AMQPSessionCallback sessionSPI;
protected CreditsSemaphore creditsSemaphore = new CreditsSemaphore(0);
public ProtonServerSenderContext(AMQPConnectionContext connection,
Sender sender,
AbstractProtonSessionContext protonSession,
AMQPSessionContext protonSession,
AMQPSessionCallback server) {
super(connection, sender, protonSession, server);
super();
this.connection = connection;
this.sender = sender;
this.protonSession = protonSession;
this.sessionSPI = server;
}
public Object getBrokerConsumer() {
@ -82,16 +90,19 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
@Override
public void onFlow(int currentCredits, boolean drain) {
super.onFlow(currentCredits, drain);
this.creditsSemaphore.setCredits(currentCredits);
sessionSPI.onFlowConsumer(brokerConsumer, currentCredits, drain);
}
public Sender getSender() {
return sender;
}
/*
* start the session
* */
@Override
public void start() throws ActiveMQAMQPException {
super.start();
sessionSPI.start();
// protonSession.getServerSession().start();
//todo add flow control
@ -125,7 +136,7 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
* even tho the filter is a map it will only return a single filter unless a nolocal is also provided
* */
if (source != null) {
Map.Entry<Symbol, DescribedType> filter = findFilter(source.getFilter(), JMS_SELECTOR_FILTER_IDS);
Map.Entry<Symbol, DescribedType> filter = AmqpSupport.findFilter(source.getFilter(), AmqpSupport.JMS_SELECTOR_FILTER_IDS);
if (filter != null) {
selector = filter.getValue().getDescribed().toString();
// Validate the Selector.
@ -146,7 +157,7 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
boolean isPubSub = hasCapabilities(TOPIC, source) || isPubSub(source);
if (isPubSub) {
if (findFilter(source.getFilter(), AmqpSupport.NO_LOCAL_FILTER_IDS) != null) {
if (AmqpSupport.findFilter(source.getFilter(), AmqpSupport.NO_LOCAL_FILTER_IDS) != null) {
String remoteContainerId = sender.getSession().getConnection().getRemoteContainer();
String noLocalFilter = ActiveMQConnection.CONNECTION_ID_PROPERTY_NAME.toString() + "<>'" + remoteContainerId + "'";
if (selector != null) {
@ -280,7 +291,13 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
* */
@Override
public void close(ErrorCondition condition) throws ActiveMQAMQPException {
super.close(condition);
closed = true;
protonSession.removeSender(sender);
synchronized (connection.getLock()) {
sender.close();
}
connection.flush();
try {
sessionSPI.closeSender(brokerConsumer);
}
@ -295,7 +312,6 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
* */
@Override
public void close(boolean remoteLinkClose) throws ActiveMQAMQPException {
super.close(remoteLinkClose);
try {
sessionSPI.closeSender(brokerConsumer);
//if this is a link close rather than a connection close or detach, we need to delete any durable resources for
@ -406,16 +422,13 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
}
}
@Override
public synchronized void checkState() {
super.checkState();
sessionSPI.resumeDelivery(brokerConsumer);
}
/**
* handle an out going message from ActiveMQ Artemis, send via the Proton Sender
*/
@Override
public int deliverMessage(Object message, int deliveryCount) throws Exception {
if (closed) {
System.err.println("Message can't be delivered as it's closed");
@ -448,5 +461,53 @@ public class ProtonServerSenderContext extends AbstractProtonContextSender imple
}
return false;
}
protected int performSend(ProtonJMessage serverMessage, Object context) {
if (!creditsSemaphore.tryAcquire()) {
try {
creditsSemaphore.acquire();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
// nothing to be done here.. we just keep going
throw new IllegalStateException(e.getMessage(), e);
}
}
//presettle means we can ack the message on the dealer side before we send it, i.e. for browsers
boolean preSettle = sender.getRemoteSenderSettleMode() == SenderSettleMode.SETTLED;
//we only need a tag if we are going to ack later
byte[] tag = preSettle ? new byte[0] : protonSession.getTag();
ByteBuf nettyBuffer = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);
try {
serverMessage.encode(new NettyWritable(nettyBuffer));
int size = nettyBuffer.writerIndex();
synchronized (connection.getLock()) {
final Delivery delivery;
delivery = sender.delivery(tag, 0, tag.length);
delivery.setContext(context);
// this will avoid a copy.. patch provided by Norman using buffer.array()
sender.send(nettyBuffer.array(), nettyBuffer.arrayOffset() + nettyBuffer.readerIndex(), nettyBuffer.readableBytes());
if (preSettle) {
delivery.settle();
}
else {
sender.advance();
}
}
connection.flush();
return size;
}
finally {
nettyBuffer.release();
}
}
}

View File

@ -14,10 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.context;
package org.apache.activemq.artemis.protocol.amqp.proton;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
import org.apache.activemq.artemis.protocol.amqp.logger.ActiveMQAMQPProtocolMessageBundle;
import org.apache.activemq.artemis.protocol.amqp.util.DeliveryUtil;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Accepted;
@ -31,12 +34,7 @@ import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.message.impl.MessageImpl;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.logger.ActiveMQAMQPProtocolMessageBundle;
import static org.proton.plug.util.DeliveryUtil.decodeMessageImpl;
import static org.proton.plug.util.DeliveryUtil.readDelivery;
import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException;
/**
* handles an amqp Coordinator to deal with transaction boundaries etc
@ -63,11 +61,11 @@ public class ProtonTransactionHandler implements ProtonDeliveryHandler {
return;
}
readDelivery(receiver, buffer);
DeliveryUtil.readDelivery(receiver, buffer);
receiver.advance();
MessageImpl msg = decodeMessageImpl(buffer);
MessageImpl msg = DeliveryUtil.decodeMessageImpl(buffer);
Object action = ((AmqpValue) msg.getBody()).getValue();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.handler;
package org.apache.activemq.artemis.protocol.amqp.proton.handler;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Delivery;

View File

@ -14,14 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.handler;
package org.apache.activemq.artemis.protocol.amqp.proton.handler;
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.engine.Transport;
/**
* TODO : this needs a better home
*/
public final class Events {
public static void dispatchTransport(Transport transport, EventHandler handler) throws Exception {

View File

@ -14,18 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.handler;
package org.apache.activemq.artemis.protocol.amqp.proton.handler;
import org.apache.activemq.artemis.protocol.amqp.proton.AmqpSupport;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.engine.Connection;
import static org.proton.plug.AmqpSupport.DELAYED_DELIVERY;
import static org.proton.plug.AmqpSupport.SOLE_CONNECTION_CAPABILITY;
public class ExtCapability {
public static final Symbol[] capabilities = new Symbol[] {
SOLE_CONNECTION_CAPABILITY, DELAYED_DELIVERY
AmqpSupport.SOLE_CONNECTION_CAPABILITY, AmqpSupport.DELAYED_DELIVERY
};
public static Symbol[] getCapabilities() {
@ -36,7 +34,7 @@ public class ExtCapability {
Symbol[] extCapabilities = connection.getRemoteDesiredCapabilities();
if (extCapabilities != null) {
for (Symbol sym : extCapabilities) {
if (sym.compareTo(SOLE_CONNECTION_CAPABILITY) == 0) {
if (sym.compareTo(AmqpSupport.SOLE_CONNECTION_CAPABILITY) == 0) {
return true;
}
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.handler.impl;
package org.apache.activemq.artemis.protocol.amqp.proton.handler;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@ -25,6 +25,10 @@ import java.util.concurrent.TimeUnit;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.activemq.artemis.protocol.amqp.proton.ProtonInitializable;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
import org.apache.activemq.artemis.utils.ByteUtil;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Collector;
@ -34,21 +38,10 @@ import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.engine.Sasl;
import org.apache.qpid.proton.engine.Transport;
import org.jboss.logging.Logger;
import org.proton.plug.ClientSASL;
import org.proton.plug.ServerSASL;
import org.proton.plug.handler.EventHandler;
import org.proton.plug.handler.Events;
import org.proton.plug.handler.ProtonHandler;
import org.proton.plug.context.ProtonInitializable;
import org.proton.plug.SASLResult;
import org.proton.plug.util.ByteUtil;
/**
* Clebert Suconic
*/
public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHandler {
public class ProtonHandler extends ProtonInitializable {
private static final Logger log = Logger.getLogger(ProtonHandlerImpl.class);
private static final Logger log = Logger.getLogger(ProtonHandler.class);
private static final byte SASL = 0x03;
@ -89,14 +82,13 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
private int offset = 0;
public ProtonHandlerImpl(Executor dispatchExecutor) {
public ProtonHandler(Executor dispatchExecutor) {
this.dispatchExecutor = dispatchExecutor;
this.creationTime = System.currentTimeMillis();
transport.bind(connection);
connection.collect(collector);
}
@Override
public long tick(boolean firstTick) {
if (!firstTick) {
try {
@ -117,35 +109,29 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
return transport.tick(TimeUnit.NANOSECONDS.toMillis(System.nanoTime()));
}
@Override
public int capacity() {
synchronized (lock) {
return transport.capacity();
}
}
@Override
public Object getLock() {
return lock;
}
@Override
public Transport getTransport() {
return transport;
}
@Override
public Connection getConnection() {
return connection;
}
@Override
public ProtonHandler addEventHandler(EventHandler handler) {
handlers.add(handler);
return this;
}
@Override
public void createServerSASL(ServerSASL[] handlers) {
this.serverSasl = transport.sasl();
saslHandlers = new HashMap<>();
@ -160,12 +146,10 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
}
@Override
public SASLResult getSASLResult() {
return saslResult;
}
@Override
public void inputBuffer(ByteBuf buffer) {
dataReceived = true;
synchronized (lock) {
@ -211,7 +195,6 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
}
}
@Override
public boolean checkDataReceived() {
boolean res = dataReceived;
@ -220,12 +203,10 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
return res;
}
@Override
public long getCreationTime() {
return creationTime;
}
@Override
public void outputDone(int bytes) {
synchronized (lock) {
transport.pop(bytes);
@ -240,7 +221,6 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
flush();
}
@Override
public ByteBuf outputBuffer() {
synchronized (lock) {
@ -271,17 +251,6 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
}
}
@Override
public void createClientSasl(ClientSASL clientSASL) {
if (clientSASL != null) {
clientSasl = transport.sasl();
clientSasl.setMechanisms(clientSASL.getName());
byte[] initialSasl = clientSASL.getBytes();
clientSasl.send(initialSasl, 0, initialSasl.length);
}
}
@Override
public void flush() {
synchronized (lock) {
transport.process();
@ -293,7 +262,6 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
dispatchExecutor.execute(dispatchRunnable);
}
@Override
public void close() {
synchronized (lock) {
connection.close();
@ -361,7 +329,7 @@ public class ProtonHandlerImpl extends ProtonInitializable implements ProtonHand
// while processing events (for instance onTransport)
// while a client is also trying to write here
while ((ev = popEvent()) != null) {
for (EventHandler h : handlers) {
for ( EventHandler h : handlers) {
if (log.isTraceEnabled()) {
log.trace("Handling " + ev + " towards " + h);
}

View File

@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.test;
public class Constants {
public static final int PORT = 5672;
}
/**
* This package includes classes used on the interaction with Proton, including Context classes that will be translated
* through the model event.
*/
package org.apache.activemq.artemis.protocol.amqp.proton;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.sasl;
import org.proton.plug.SASLResult;
import org.proton.plug.ServerSASL;
package org.apache.activemq.artemis.protocol.amqp.sasl;
public class AnonymousServerSASL implements ServerSASL {

View File

@ -14,16 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton.sasl;
package org.apache.activemq.artemis.protocol.amqp.sasl;
import org.apache.activemq.artemis.core.security.SecurityStore;
import org.proton.plug.sasl.ServerSASLPlain;
public class ActiveMQPlainSASL extends ServerSASLPlain {
public class PlainSASL extends ServerSASLPlain {
private final SecurityStore securityStore;
public ActiveMQPlainSASL(SecurityStore securityStore) {
public PlainSASL(SecurityStore securityStore) {
this.securityStore = securityStore;
}

View File

@ -14,9 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.sasl;
import org.proton.plug.SASLResult;
package org.apache.activemq.artemis.protocol.amqp.sasl;
public class PlainSASLResult implements SASLResult {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug;
package org.apache.activemq.artemis.protocol.amqp.sasl;
public interface SASLResult {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug;
package org.apache.activemq.artemis.protocol.amqp.sasl;
public interface ServerSASL {

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.sasl;
import org.proton.plug.SASLResult;
import org.proton.plug.ServerSASL;
package org.apache.activemq.artemis.protocol.amqp.sasl;
public class ServerSASLPlain implements ServerSASL {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import org.apache.qpid.proton.codec.AMQPDefinedTypes;
import org.apache.qpid.proton.codec.DecoderImpl;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import io.netty.buffer.ByteBuf;
import org.apache.qpid.proton.engine.Receiver;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import java.nio.ByteBuffer;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import java.nio.ByteBuffer;

View File

@ -1 +1 @@
org.apache.activemq.artemis.core.protocol.proton.ProtonProtocolManagerFactory
org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManagerFactory

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.core.protocol.proton;
package org.apache.activemq.artemis.protocol.amqp.converter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -28,9 +28,13 @@ import java.util.Map;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSObjectMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.message.EncodedMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMapMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSObjectMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.message.EncodedMessage;
import org.apache.activemq.artemis.core.server.impl.ServerMessageImpl;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSBytesMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSStreamMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSTextMessage;
import org.apache.blacklist.ABadClass;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
@ -42,17 +46,12 @@ import org.apache.qpid.proton.message.ProtonJMessage;
import org.apache.qpid.proton.message.impl.MessageImpl;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.core.protocol.proton.converter.ProtonMessageConverter;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSBytesMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMapMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSStreamMessage;
import org.apache.activemq.artemis.core.protocol.proton.converter.jms.ServerJMSTextMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMessage;
import org.apache.activemq.artemis.core.server.ServerMessage;
import org.apache.activemq.artemis.utils.SimpleIDGenerator;
import org.junit.Assert;
import org.junit.Test;
import org.proton.plug.util.NettyWritable;
import org.apache.activemq.artemis.protocol.amqp.util.NettyWritable;
public class TestConversions extends Assert {

View File

@ -14,15 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.sasl;
import org.proton.plug.ClientSASL;
package org.apache.activemq.artemis.protocol.amqp.sasl;
/**
* This is a simple implementation provided with just user/password
* TODO: this interface will probaby change as we are challenged with more SASL cases where there is a communication between client and server to determine the authentication
* This will generate what a client would generate for bytes on Plain sasl. Used on test
*/
public class ClientSASLPlain implements ClientSASL {
public class ClientSASLPlain {
private String username;
private String password;
@ -32,12 +29,10 @@ public class ClientSASLPlain implements ClientSASL {
this.password = password;
}
@Override
public String getName() {
return "PLAIN";
}
@Override
public byte[] getBytes() {
if (username == null) {

View File

@ -14,13 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.test.sasl;
package org.apache.activemq.artemis.protocol.amqp.sasl;
import org.junit.Assert;
import org.junit.Test;
import org.proton.plug.sasl.ClientSASLPlain;
import org.proton.plug.sasl.PlainSASLResult;
import org.proton.plug.sasl.ServerSASLPlain;
public class PlainSASLTest {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.proton.plug.test.util;
package org.apache.activemq.artemis.protocol.amqp.util;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -22,7 +22,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Assert;
import org.junit.Test;
import org.proton.plug.util.CreditsSemaphore;
public class CreditsSemaphoreTest {

View File

@ -1,137 +0,0 @@
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>artemis-protocols</artifactId>
<groupId>org.apache.activemq</groupId>
<version>1.5.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>artemis-proton-plug</artifactId>
<name>ActiveMQ Artemis Proton Protocol</name>
<properties>
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
</properties>
<dependencies>
<!-- JMS Client because of some conversions that are done -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-jms-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-core-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging-processor</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!--
JBoss Logging
-->
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
<scope>test</scope>
</dependency>
<!-- this is for the log assertion -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-commons</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>proton-j</artifactId>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-client</artifactId>
<version>0.24</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.qpid</groupId>
<artifactId>qpid-jms-client</artifactId>
<version>0.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_2.0_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- We use the proton plug test classes in some of the Artemis Integration tests -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<packaging>bundle</packaging>
</project>

View File

@ -1,36 +0,0 @@
/*
* 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.proton.plug;
import org.proton.plug.exceptions.ActiveMQAMQPException;
/**
* This is valid only on a client connection.
*/
public interface AMQPClientConnectionContext extends AMQPConnectionContext {
/**
* This will send an open and block for its return on AMQP protocol.
*
* @throws Exception
*/
void clientOpen(ClientSASL sasl) throws Exception;
AMQPClientSessionContext createClientSession() throws ActiveMQAMQPException;
void setContainer(String containerID);
}

View File

@ -1,34 +0,0 @@
/*
* 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.proton.plug;
import java.util.concurrent.TimeUnit;
import org.apache.qpid.proton.message.ProtonJMessage;
public interface AMQPClientReceiverContext {
ProtonJMessage receiveMessage(int time, TimeUnit unit) throws Exception;
void flow(int credits);
void drain(int i);
int drained();
boolean isDraining();
}

View File

@ -1,27 +0,0 @@
/*
* 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.proton.plug;
import org.apache.qpid.proton.message.ProtonJMessage;
public interface AMQPClientSenderContext {
void send(ProtonJMessage message);
String getAddress();
}

View File

@ -1,30 +0,0 @@
/*
* 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.proton.plug;
import org.proton.plug.exceptions.ActiveMQAMQPException;
public interface AMQPClientSessionContext extends AMQPSessionContext {
AMQPClientSenderContext createSender(String address, boolean preSettled) throws ActiveMQAMQPException;
AMQPClientSenderContext createDynamicSender(boolean preSettled) throws ActiveMQAMQPException;
AMQPClientReceiverContext createReceiver(String address) throws ActiveMQAMQPException;
AMQPClientReceiverContext createReceiver(String name, String address) throws ActiveMQAMQPException;
}

View File

@ -1,58 +0,0 @@
/*
* 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.proton.plug;
import io.netty.buffer.ByteBuf;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.engine.Connection;
import org.proton.plug.exceptions.ActiveMQAMQPException;
public interface AMQPConnectionCallback {
void close();
/**
* this is called when bytes are available to be sent to the client.
* you have to callback {@link org.proton.plug.AMQPConnectionContext#outputDone(int)} after you're done with this buffer
*
* @param bytes
*/
void onTransport(ByteBuf bytes, AMQPConnectionContext connection);
AMQPSessionCallback createSessionCallback(AMQPConnectionContext connection);
void setConnection(AMQPConnectionContext connection);
AMQPConnectionContext getConnection();
ServerSASL[] getSASLMechnisms();
boolean isSupportsAnonymous();
void sendSASLSupported();
boolean validateConnection(Connection connection, SASLResult saslResult);
Binary newTransaction();
Transaction getTransaction(Binary txid) throws ActiveMQAMQPException;
void removeTransaction(Binary txid);
}

View File

@ -1,71 +0,0 @@
/*
* 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.proton.plug;
import org.apache.qpid.proton.amqp.Symbol;
import io.netty.buffer.ByteBuf;
public interface AMQPConnectionContext {
void close();
Object getLock();
boolean checkDataReceived();
long getCreationTime();
SASLResult getSASLResult();
/**
* Load and return a <code>[]Symbol</code> that contains the connection capabilities
* offered to new connections
*
* @return the capabilities that are offered to new remote peers on connect.
*/
Symbol[] getConnectionCapabilitiesOffered();
/**
* Even though we are currently always sending packets asynchronsouly
* we have a possibility to start trusting on the network flow control
* and always sync on the send of the packet
*
* This is for future use and should be kept returning false.
*
* We will have to do some testing before we make this return true
*/
boolean isSyncOnFlush();
int capacity();
/**
* This is for the Remoting layer to push bytes on the AMQP Connection
* The buffer readerIndex should be at the latest read byte after this method is called
*/
void inputBuffer(ByteBuf buffer);
void flush();
/**
* To be called when the bytes were sent down the stream (flushed on the socket for example)
*
* @param numberOfBytes
*/
void outputDone(int numberOfBytes);
}

View File

@ -1,39 +0,0 @@
/*
* 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.proton.plug;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
public abstract class AMQPConnectionContextFactory {
/**
* @return
*/
public abstract AMQPConnectionContext createConnection(AMQPConnectionCallback connectionCallback,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool);
/**
* @return
*/
public abstract AMQPConnectionContext createConnection(AMQPConnectionCallback connectionCallback, Executor dispatchExecutor, ScheduledExecutorService scheduledPool);
}

View File

@ -1,21 +0,0 @@
/*
* 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.proton.plug;
public interface AMQPServerConnectionContext extends AMQPConnectionContext {
}

View File

@ -1,112 +0,0 @@
/*
* 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.proton.plug;
import io.netty.buffer.ByteBuf;
import org.apache.activemq.artemis.core.server.QueueQueryResult;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.proton.plug.context.ProtonPlugSender;
import org.proton.plug.exceptions.ActiveMQAMQPException;
/**
* These are methods where the Proton Plug component will call your server
*/
public interface AMQPSessionCallback {
void init(AMQPSessionContext session, SASLResult saslResult) throws Exception;
void start();
void onFlowConsumer(Object consumer, int credits, boolean drain);
Object createSender(ProtonPlugSender protonSender, String queue, String filer, boolean browserOnly) throws Exception;
void startSender(Object brokerConsumer) throws Exception;
void createTemporaryQueue(String queueName) throws Exception;
void createTemporaryQueue(String address, String queueName, String filter) throws Exception;
void createDurableQueue(String address, String queueName, String filter) throws Exception;
void offerProducerCredit(String address, int credits, int threshold, Receiver receiver);
void deleteQueue(String address) throws Exception;
/**
* Returns true if a queue is found with matching name, if autoCreate=true and autoCreateJMSQueues is switched on then
* this method will auto create the queue, with name=queueName, address=queueName, filter=null.
*
* @param queueName
* @param autoCreate
* @return
* @throws Exception
*/
QueueQueryResult queueQuery(String queueName, boolean autoCreate) throws Exception;
boolean bindingQuery(String address) throws Exception;
void closeSender(Object brokerConsumer) throws Exception;
// This one can be a lot improved
ProtonJMessage encodeMessage(Object message, int deliveryCount) throws Exception;
String tempQueueName();
Transaction getTransaction(Binary txid) throws ActiveMQAMQPException;
Binary newTransaction();
void commitTX(Binary txid) throws Exception;
void rollbackTX(Binary txid, boolean lastMessageReceived) throws Exception;
void close() throws Exception;
void ack(Transaction transaction, Object brokerConsumer, Object message) throws Exception;
/**
* @param brokerConsumer
* @param message
* @param updateCounts this identified if the cancel was because of a failure or just cleaning up the
* client's cache.
* in some implementations you could call this failed
*/
void cancel(Object brokerConsumer, Object message, boolean updateCounts) throws Exception;
void resumeDelivery(Object consumer);
/**
* @param delivery
* @param address
* @param messageFormat
* @param messageEncoded a Heap Buffer ByteBuffer (safe to convert into byte[])
*/
void serverSend(Transaction transaction,
Receiver receiver,
Delivery delivery,
String address,
int messageFormat,
ByteBuf messageEncoded) throws Exception;
String getPubSubPrefix();
}

View File

@ -1,34 +0,0 @@
/*
* 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.proton.plug;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.proton.plug.exceptions.ActiveMQAMQPException;
public interface AMQPSessionContext {
byte[] getTag();
void replaceTag(byte[] tag);
void close();
void removeSender(Sender sender) throws ActiveMQAMQPException;
void removeReceiver(Receiver receiver);
}

View File

@ -1,153 +0,0 @@
/*
* 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.proton.plug.context;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.amqp.transport.SenderSettleMode;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.util.CreditsSemaphore;
import org.proton.plug.util.NettyWritable;
/**
* A this is a wrapper around an ActiveMQ Artemis ServerConsumer for handling outgoing messages and incoming acks via a Proton Sender
*/
public abstract class AbstractProtonContextSender extends ProtonInitializable implements ProtonDeliveryHandler {
protected final AbstractProtonSessionContext protonSession;
protected final Sender sender;
protected final AbstractConnectionContext connection;
protected boolean closed = false;
protected final AMQPSessionCallback sessionSPI;
protected CreditsSemaphore creditsSemaphore = new CreditsSemaphore(0);
public AbstractProtonContextSender(AbstractConnectionContext connection,
Sender sender,
AbstractProtonSessionContext protonSession,
AMQPSessionCallback server) {
this.connection = connection;
this.sender = sender;
this.protonSession = protonSession;
this.sessionSPI = server;
}
@Override
public void onFlow(int credits, boolean drain) {
this.creditsSemaphore.setCredits(credits);
}
/*
* start the session
* */
public void start() throws ActiveMQAMQPException {
sessionSPI.start();
// protonSession.getServerSession().start();
}
/*
* close the session
* */
@Override
public void close(boolean linkRemoteClose) throws ActiveMQAMQPException {
closed = true;
protonSession.removeSender(sender);
synchronized (connection.getLock()) {
sender.close();
}
connection.flush();
}
/*
* close the session
* */
@Override
public void close(ErrorCondition condition) throws ActiveMQAMQPException {
closed = true;
sender.setCondition(condition);
close(false);
}
@Override
/*
* handle an incoming Ack from Proton, basically pass to ActiveMQ Artemis to handle
* */ public abstract void onMessage(Delivery delivery) throws ActiveMQAMQPException;
/*
* check the state of the consumer, i.e. are there any more messages. only really needed for browsers?
* */
public void checkState() {
}
public Sender getSender() {
return sender;
}
protected int performSend(ProtonJMessage serverMessage, Object context) {
if (!creditsSemaphore.tryAcquire()) {
try {
creditsSemaphore.acquire();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
// nothing to be done here.. we just keep going
throw new IllegalStateException(e.getMessage(), e);
}
}
//presettle means we can ack the message on the dealer side before we send it, i.e. for browsers
boolean preSettle = sender.getRemoteSenderSettleMode() == SenderSettleMode.SETTLED;
//we only need a tag if we are going to ack later
byte[] tag = preSettle ? new byte[0] : protonSession.getTag();
ByteBuf nettyBuffer = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);
try {
serverMessage.encode(new NettyWritable(nettyBuffer));
int size = nettyBuffer.writerIndex();
synchronized (connection.getLock()) {
final Delivery delivery;
delivery = sender.delivery(tag, 0, tag.length);
delivery.setContext(context);
// this will avoid a copy.. patch provided by Norman using buffer.array()
sender.send(nettyBuffer.array(), nettyBuffer.arrayOffset() + nettyBuffer.readerIndex(), nettyBuffer.readableBytes());
if (preSettle) {
delivery.settle();
}
else {
sender.advance();
}
}
connection.flush();
return size;
}
finally {
nettyBuffer.release();
}
}
}

View File

@ -1,88 +0,0 @@
/*
* 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.proton.plug.context;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Receiver;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.exceptions.ActiveMQAMQPException;
/**
* handles incoming messages via a Proton Receiver and forwards them to ActiveMQ
*/
public abstract class AbstractProtonReceiverContext extends ProtonInitializable implements ProtonDeliveryHandler {
protected final AbstractConnectionContext connection;
protected final AbstractProtonSessionContext protonSession;
protected final Receiver receiver;
protected String address;
protected final AMQPSessionCallback sessionSPI;
public AbstractProtonReceiverContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
AbstractProtonSessionContext protonSession,
Receiver receiver) {
this.connection = connection;
this.protonSession = protonSession;
this.receiver = receiver;
this.sessionSPI = sessionSPI;
}
@Override
public void close(boolean remoteLinkClose) throws ActiveMQAMQPException {
protonSession.removeReceiver(receiver);
}
@Override
public void close(ErrorCondition condition) throws ActiveMQAMQPException {
receiver.setCondition(condition);
close(false);
}
public void flow(int credits, int threshold) {
// Use the SessionSPI to allocate producer credits, or default, always allocate credit.
if (sessionSPI != null) {
sessionSPI.offerProducerCredit(address, credits, threshold, receiver);
}
else {
synchronized (connection.getLock()) {
receiver.flow(credits);
connection.flush();
}
}
}
public void drain(int credits) {
synchronized (connection.getLock()) {
receiver.drain(credits);
}
connection.flush();
}
public int drained() {
return receiver.drained();
}
public boolean isDraining() {
return receiver.draining();
}
}

View File

@ -1,161 +0,0 @@
/*
* 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.proton.plug.context;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.jboss.logging.Logger;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.AMQPSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.exceptions.ActiveMQAMQPInternalErrorException;
/**
* ProtonSession is a direct representation of the session on the broker.
* It has a link between a ProtonSession and a Broker or Client Session
* The Broker Session is linked through the ProtonSessionSPI
*/
public abstract class AbstractProtonSessionContext extends ProtonInitializable implements AMQPSessionContext {
private static final Logger log = Logger.getLogger(AbstractProtonSessionContext.class);
protected final AbstractConnectionContext connection;
protected final AMQPSessionCallback sessionSPI;
protected final Session session;
private long currentTag = 0;
protected Map<Receiver, AbstractProtonReceiverContext> receivers = new HashMap<>();
protected Map<Sender, AbstractProtonContextSender> senders = new HashMap<>();
protected boolean closed = false;
public AbstractProtonSessionContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
Session session) {
this.connection = connection;
this.sessionSPI = sessionSPI;
this.session = session;
}
@Override
public void initialise() throws Exception {
if (!isInitialized()) {
super.initialise();
if (sessionSPI != null) {
try {
sessionSPI.init(this, connection.getSASLResult());
}
catch (Exception e) {
throw new ActiveMQAMQPInternalErrorException(e.getMessage(), e);
}
}
}
}
/**
* TODO: maybe it needs to go?
*
* @param consumer
* @param queueName
*/
public void disconnect(Object consumer, String queueName) {
AbstractProtonContextSender protonConsumer = senders.remove(consumer);
if (protonConsumer != null) {
try {
protonConsumer.close(false);
}
catch (ActiveMQAMQPException e) {
protonConsumer.getSender().setTarget(null);
protonConsumer.getSender().setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
}
}
}
@Override
public byte[] getTag() {
return Long.toHexString(currentTag++).getBytes();
}
@Override
public void replaceTag(byte[] tag) {
// TODO: do we need to reuse this?
}
@Override
public void close() {
if (closed) {
return;
}
// Making a copy to avoid ConcurrentModificationException during the iteration
Set<AbstractProtonReceiverContext> receiversCopy = new HashSet<>();
receiversCopy.addAll(receivers.values());
for (AbstractProtonReceiverContext protonProducer : receiversCopy) {
try {
protonProducer.close(false);
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
receivers.clear();
Set<AbstractProtonContextSender> protonSendersClone = new HashSet<>();
protonSendersClone.addAll(senders.values());
for (AbstractProtonContextSender protonConsumer : protonSendersClone) {
try {
protonConsumer.close(false);
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
}
senders.clear();
try {
if (sessionSPI != null) {
sessionSPI.close();
}
}
catch (Exception e) {
log.warn(e.getMessage(), e);
}
closed = true;
}
@Override
public void removeSender(Sender sender) throws ActiveMQAMQPException {
senders.remove(sender);
}
@Override
public void removeReceiver(Receiver receiver) {
receivers.remove(receiver);
}
}

View File

@ -1,67 +0,0 @@
/*
* 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.proton.plug.context;
import java.util.concurrent.TimeUnit;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.exceptions.ActiveMQAMQPIllegalStateException;
import org.proton.plug.exceptions.ActiveMQAMQPTimeoutException;
import org.proton.plug.util.FutureRunnable;
public class ProtonInitializable {
private Runnable afterInit;
private boolean initialized = false;
public void afterInit(Runnable afterInit) {
this.afterInit = afterInit;
}
public boolean isInitialized() {
return initialized;
}
public void initialise() throws Exception {
if (!initialized) {
initialized = true;
try {
if (afterInit != null) {
afterInit.run();
}
}
finally {
afterInit = null;
}
}
}
public void waitWithTimeout(FutureRunnable latch) throws ActiveMQAMQPException {
try {
// TODO Configure this
if (!latch.await(30, TimeUnit.SECONDS)) {
throw new ActiveMQAMQPTimeoutException("Timed out waiting for response");
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ActiveMQAMQPIllegalStateException(e.getMessage());
}
}
}

View File

@ -1,107 +0,0 @@
/*
* 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.proton.plug.context.client;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Session;
import org.proton.plug.AMQPClientConnectionContext;
import org.proton.plug.AMQPClientSessionContext;
import org.proton.plug.ClientSASL;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.context.ProtonInitializable;
import org.proton.plug.util.FutureRunnable;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
public class ProtonClientConnectionContext extends AbstractConnectionContext implements AMQPClientConnectionContext {
public ProtonClientConnectionContext(AMQPConnectionCallback connectionCallback, Executor dispatchExecutor, ScheduledExecutorService scheduledPool) {
super(connectionCallback, dispatchExecutor, scheduledPool);
}
public ProtonClientConnectionContext(AMQPConnectionCallback connectionCallback,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
super(connectionCallback, containerId, idleTimeout, maxFrameSize, channelMax, dispatchExecutor, scheduledPool);
}
// Maybe a client interface?
@Override
public void clientOpen(ClientSASL sasl) throws Exception {
FutureRunnable future = new FutureRunnable(1);
synchronized (handler.getLock()) {
this.afterInit(future);
if (sasl != null) {
handler.createClientSasl(sasl);
}
handler.getConnection().open();
}
flush();
waitWithTimeout(future);
}
@Override
public AMQPClientSessionContext createClientSession() throws ActiveMQAMQPException {
FutureRunnable futureRunnable = new FutureRunnable(1);
ProtonClientSessionContext sessionImpl;
synchronized (handler.getLock()) {
Session session = handler.getConnection().session();
sessionImpl = (ProtonClientSessionContext) getSessionExtension(session);
sessionImpl.afterInit(futureRunnable);
session.open();
}
flush();
waitWithTimeout(futureRunnable);
return sessionImpl;
}
@Override
public void setContainer(String containerID) {
handler.getConnection().setContainer(containerID);
}
@Override
protected AbstractProtonSessionContext newSessionExtension(Session realSession) throws ActiveMQAMQPException {
AMQPSessionCallback sessionSPI = connectionCallback.createSessionCallback(this);
AbstractProtonSessionContext protonSession = new ProtonClientSessionContext(sessionSPI, this, realSession);
return protonSession;
}
@Override
protected void remoteLinkOpened(Link link) throws Exception {
Object context = link.getContext();
if (context != null && context instanceof ProtonInitializable) {
((ProtonInitializable) context).initialise();
}
}
}

View File

@ -1,50 +0,0 @@
/*
* 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.proton.plug.context.client;
import org.proton.plug.AMQPConnectionContext;
import org.proton.plug.AMQPConnectionContextFactory;
import org.proton.plug.AMQPConnectionCallback;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
public class ProtonClientConnectionContextFactory extends AMQPConnectionContextFactory {
private static final AMQPConnectionContextFactory theInstance = new ProtonClientConnectionContextFactory();
public static AMQPConnectionContextFactory getFactory() {
return theInstance;
}
@Override
public AMQPConnectionContext createConnection(AMQPConnectionCallback connectionCallback, Executor dispatchExecutor, ScheduledExecutorService scheduledPool) {
return new ProtonClientConnectionContext(connectionCallback, dispatchExecutor, scheduledPool);
}
@Override
public AMQPConnectionContext createConnection(AMQPConnectionCallback connectionCallback,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
return new ProtonClientConnectionContext(connectionCallback, containerId, idleTimeout, maxFrameSize, channelMax, dispatchExecutor, scheduledPool);
}
}

View File

@ -1,76 +0,0 @@
/*
* 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.proton.plug.context.client;
import java.util.concurrent.TimeUnit;
import org.apache.qpid.proton.amqp.messaging.Accepted;
import org.apache.qpid.proton.amqp.transport.SenderSettleMode;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.proton.plug.AMQPClientSenderContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonContextSender;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.util.FutureRunnable;
public class ProtonClientContext extends AbstractProtonContextSender implements AMQPClientSenderContext {
FutureRunnable catchUpRunnable = new FutureRunnable();
public ProtonClientContext(AbstractConnectionContext connection,
Sender sender,
AbstractProtonSessionContext protonSession,
AMQPSessionCallback server) {
super(connection, sender, protonSession, server);
}
@Override
public void onMessage(Delivery delivery) throws ActiveMQAMQPException {
if (delivery.getRemoteState() instanceof Accepted) {
if (delivery.getContext() instanceof FutureRunnable) {
((FutureRunnable) delivery.getContext()).countDown();
}
}
}
@Override
public void send(ProtonJMessage message) {
if (sender.getSenderSettleMode() != SenderSettleMode.SETTLED) {
catchUpRunnable.countUp();
}
performSend(message, catchUpRunnable);
}
public boolean sync(long timeout, TimeUnit unit) {
try {
return catchUpRunnable.await(timeout, unit);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
@Override
public String getAddress() {
return sender.getRemoteTarget().getAddress();
}
}

View File

@ -1,92 +0,0 @@
/*
* 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.proton.plug.context.client;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.apache.qpid.proton.amqp.messaging.Accepted;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.message.ProtonJMessage;
import org.apache.qpid.proton.message.impl.MessageImpl;
import org.proton.plug.AMQPClientReceiverContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonReceiverContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import static org.proton.plug.util.DeliveryUtil.readDelivery;
import static org.proton.plug.util.DeliveryUtil.decodeMessageImpl;
public class ProtonClientReceiverContext extends AbstractProtonReceiverContext implements AMQPClientReceiverContext {
public ProtonClientReceiverContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
AbstractProtonSessionContext protonSession,
Receiver receiver) {
super(sessionSPI, connection, protonSession, receiver);
}
@Override
public void onFlow(int credits, boolean drain) {
}
LinkedBlockingDeque<MessageImpl> queues = new LinkedBlockingDeque<>();
/*
* called when Proton receives a message to be delivered via a Delivery.
*
* This may be called more than once per deliver so we have to cache the buffer until we have received it all.
*
* */
@Override
public void onMessage(Delivery delivery) throws ActiveMQAMQPException {
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.heapBuffer(1024);
try {
synchronized (connection.getLock()) {
readDelivery(receiver, buffer);
MessageImpl clientMessage = decodeMessageImpl(buffer);
// This second method could be better
// clientMessage.decode(buffer.nioBuffer());
receiver.advance();
delivery.disposition(Accepted.getInstance());
queues.add(clientMessage);
}
}
finally {
buffer.release();
}
}
@Override
public ProtonJMessage receiveMessage(int time, TimeUnit unit) throws Exception {
return queues.poll(time, unit);
}
@Override
public void flow(int credits) {
flow(credits, Integer.MAX_VALUE);
}
}

View File

@ -1,145 +0,0 @@
/*
* 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.proton.plug.context.client;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.Accepted;
import org.apache.qpid.proton.amqp.messaging.DeleteOnClose;
import org.apache.qpid.proton.amqp.messaging.Rejected;
import org.apache.qpid.proton.amqp.messaging.Source;
import org.apache.qpid.proton.amqp.messaging.Target;
import org.apache.qpid.proton.amqp.messaging.TerminusDurability;
import org.apache.qpid.proton.amqp.messaging.TerminusExpiryPolicy;
import org.apache.qpid.proton.amqp.transport.SenderSettleMode;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.proton.plug.AMQPClientReceiverContext;
import org.proton.plug.AMQPClientSenderContext;
import org.proton.plug.AMQPClientSessionContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.AmqpSupport;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.util.FutureRunnable;
public class ProtonClientSessionContext extends AbstractProtonSessionContext implements AMQPClientSessionContext {
public ProtonClientSessionContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
Session session) {
super(sessionSPI, connection, session);
}
@Override
public AMQPClientSenderContext createSender(String address, boolean preSettled) throws ActiveMQAMQPException {
FutureRunnable futureRunnable = new FutureRunnable(1);
ProtonClientContext amqpSender;
synchronized (connection.getLock()) {
Sender sender = session.sender(address);
sender.setSenderSettleMode(SenderSettleMode.SETTLED);
Target target = new Target();
target.setAddress(address);
sender.setTarget(target);
amqpSender = new ProtonClientContext(connection, sender, this, sessionSPI);
amqpSender.afterInit(futureRunnable);
sender.setContext(amqpSender);
sender.open();
}
connection.flush();
waitWithTimeout(futureRunnable);
return amqpSender;
}
@Override
public AMQPClientSenderContext createDynamicSender(boolean preSettled) throws ActiveMQAMQPException {
FutureRunnable futureRunnable = new FutureRunnable(1);
ProtonClientContext amqpSender;
synchronized (connection.getLock()) {
final String senderName = "Dynamic-" + UUID.randomUUID().toString();
Sender sender = session.sender(senderName);
sender.setSenderSettleMode(SenderSettleMode.SETTLED);
Symbol[] outcomes = new Symbol[]{Accepted.DESCRIPTOR_SYMBOL, Rejected.DESCRIPTOR_SYMBOL};
Source source = new Source();
source.setAddress(senderName);
source.setOutcomes(outcomes);
Target target = new Target();
target.setDynamic(true);
target.setDurable(TerminusDurability.NONE);
target.setExpiryPolicy(TerminusExpiryPolicy.LINK_DETACH);
// Set the dynamic node lifetime-policy
Map<Symbol, Object> dynamicNodeProperties = new HashMap<>();
dynamicNodeProperties.put(AmqpSupport.LIFETIME_POLICY, DeleteOnClose.getInstance());
target.setDynamicNodeProperties(dynamicNodeProperties);
amqpSender = new ProtonClientContext(connection, sender, this, sessionSPI);
amqpSender.afterInit(futureRunnable);
sender.setSource(source);
sender.setTarget(target);
sender.setContext(amqpSender);
sender.open();
}
connection.flush();
waitWithTimeout(futureRunnable);
return amqpSender;
}
@Override
public AMQPClientReceiverContext createReceiver(String address) throws ActiveMQAMQPException {
return createReceiver(address, address);
}
@Override
public AMQPClientReceiverContext createReceiver(String name, String address) throws ActiveMQAMQPException {
FutureRunnable futureRunnable = new FutureRunnable(1);
ProtonClientReceiverContext amqpReceiver;
synchronized (connection.getLock()) {
Receiver receiver = session.receiver(name);
Source source = new Source();
source.setAddress(address);
receiver.setSource(source);
amqpReceiver = new ProtonClientReceiverContext(sessionSPI, connection, this, receiver);
receiver.setContext(amqpReceiver);
amqpReceiver.afterInit(futureRunnable);
receiver.open();
}
connection.flush();
waitWithTimeout(futureRunnable);
return amqpReceiver;
}
}

View File

@ -1,94 +0,0 @@
/*
* 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.proton.plug.context.server;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transaction.Coordinator;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPServerConnectionContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.handler.ExtCapability;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
public class ProtonServerConnectionContext extends AbstractConnectionContext implements AMQPServerConnectionContext {
public ProtonServerConnectionContext(AMQPConnectionCallback connectionSP, Executor dispatchExecutor, ScheduledExecutorService scheduledPool) {
super(connectionSP, dispatchExecutor, scheduledPool);
}
public ProtonServerConnectionContext(AMQPConnectionCallback connectionSP,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
super(connectionSP, containerId, idleTimeout, maxFrameSize, channelMax, dispatchExecutor, scheduledPool);
}
@Override
protected AbstractProtonSessionContext newSessionExtension(Session realSession) throws ActiveMQAMQPException {
AMQPSessionCallback sessionSPI = connectionCallback.createSessionCallback(this);
AbstractProtonSessionContext protonSession = new ProtonServerSessionContext(sessionSPI, this, realSession);
return protonSession;
}
@Override
protected boolean validateConnection(Connection connection) {
return connectionCallback.validateConnection(connection, handler.getSASLResult());
}
@Override
protected void remoteLinkOpened(Link link) throws Exception {
ProtonServerSessionContext protonSession = (ProtonServerSessionContext) getSessionExtension(link.getSession());
link.setSource(link.getRemoteSource());
link.setTarget(link.getRemoteTarget());
if (link instanceof Receiver) {
Receiver receiver = (Receiver) link;
if (link.getRemoteTarget() instanceof Coordinator) {
Coordinator coordinator = (Coordinator) link.getRemoteTarget();
protonSession.addTransactionHandler(coordinator, receiver);
}
else {
protonSession.addReceiver(receiver);
}
}
else {
Sender sender = (Sender) link;
protonSession.addSender(sender);
sender.offer(1);
}
}
@Override
public Symbol[] getConnectionCapabilitiesOffered() {
return ExtCapability.getCapabilities();
}
}

View File

@ -1,53 +0,0 @@
/*
* 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.proton.plug.context.server;
import org.proton.plug.AMQPConnectionContextFactory;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPServerConnectionContext;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_IDLE_TIMEOUT;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_CHANNEL_MAX;
import static org.proton.plug.context.AMQPConstants.Connection.DEFAULT_MAX_FRAME_SIZE;
public class ProtonServerConnectionContextFactory extends AMQPConnectionContextFactory {
private static final ProtonServerConnectionContextFactory theInstance = new ProtonServerConnectionContextFactory();
public static ProtonServerConnectionContextFactory getFactory() {
return theInstance;
}
@Override
public AMQPServerConnectionContext createConnection(AMQPConnectionCallback connectionCallback, Executor dispatchExecutor, ScheduledExecutorService scheduledPool) {
return createConnection(connectionCallback, null, DEFAULT_IDLE_TIMEOUT, DEFAULT_MAX_FRAME_SIZE, DEFAULT_CHANNEL_MAX, dispatchExecutor, scheduledPool);
}
@Override
public AMQPServerConnectionContext createConnection(AMQPConnectionCallback connectionCallback,
String containerId,
int idleTimeout,
int maxFrameSize,
int channelMax,
Executor dispatchExecutor,
ScheduledExecutorService scheduledPool) {
return new ProtonServerConnectionContext(connectionCallback, containerId, idleTimeout, maxFrameSize, channelMax, dispatchExecutor, scheduledPool);
}
}

View File

@ -1,117 +0,0 @@
/*
* 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.proton.plug.context.server;
import java.util.HashMap;
import java.util.Map;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transaction.Coordinator;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Receiver;
import org.apache.qpid.proton.engine.Sender;
import org.apache.qpid.proton.engine.Session;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.context.AbstractConnectionContext;
import org.proton.plug.context.AbstractProtonContextSender;
import org.proton.plug.context.AbstractProtonReceiverContext;
import org.proton.plug.context.AbstractProtonSessionContext;
import org.proton.plug.context.ProtonTransactionHandler;
import org.proton.plug.exceptions.ActiveMQAMQPException;
public class ProtonServerSessionContext extends AbstractProtonSessionContext {
public ProtonServerSessionContext(AMQPSessionCallback sessionSPI,
AbstractConnectionContext connection,
Session session) {
super(sessionSPI, connection, session);
}
protected Map<Object, AbstractProtonContextSender> serverSenders = new HashMap<>();
/**
* The consumer object from the broker or the key used to store the sender
*
* @param message
* @param consumer
* @param deliveryCount
* @return the number of bytes sent
*/
public int serverDelivery(Object message, Object consumer, int deliveryCount) throws Exception {
ProtonServerSenderContext protonSender = (ProtonServerSenderContext) serverSenders.get(consumer);
if (protonSender != null) {
return protonSender.deliverMessage(message, deliveryCount);
}
return 0;
}
public void addTransactionHandler(Coordinator coordinator, Receiver receiver) {
ProtonTransactionHandler transactionHandler = new ProtonTransactionHandler(sessionSPI);
coordinator.setCapabilities(Symbol.getSymbol("amqp:local-transactions"),
Symbol.getSymbol("amqp:multi-txns-per-ssn"),
Symbol.getSymbol("amqp:multi-ssns-per-txn"));
receiver.setContext(transactionHandler);
receiver.open();
receiver.flow(100);
}
public void addSender(Sender sender) throws Exception {
ProtonServerSenderContext protonSender = new ProtonServerSenderContext(connection, sender, this, sessionSPI);
try {
protonSender.initialise();
senders.put(sender, protonSender);
serverSenders.put(protonSender.getBrokerConsumer(), protonSender);
sender.setContext(protonSender);
sender.open();
protonSender.start();
}
catch (ActiveMQAMQPException e) {
senders.remove(sender);
sender.setSource(null);
sender.setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
sender.close();
}
}
@Override
public void removeSender(Sender sender) throws ActiveMQAMQPException {
ProtonServerSenderContext senderRemoved = (ProtonServerSenderContext) senders.remove(sender);
if (senderRemoved != null) {
serverSenders.remove(senderRemoved.getBrokerConsumer());
}
}
public void addReceiver(Receiver receiver) throws Exception {
try {
AbstractProtonReceiverContext protonReceiver = new ProtonServerReceiverContext(sessionSPI, connection, this, receiver);
protonReceiver.initialise();
receivers.put(receiver, protonReceiver);
receiver.setContext(protonReceiver);
receiver.open();
}
catch (ActiveMQAMQPException e) {
receivers.remove(receiver);
receiver.setTarget(null);
receiver.setCondition(new ErrorCondition(e.getAmqpError(), e.getMessage()));
receiver.close();
}
}
}

View File

@ -1,133 +0,0 @@
/*
* 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.proton.plug.handler;
import java.util.concurrent.Executor;
import io.netty.buffer.ByteBuf;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Transport;
import org.proton.plug.ClientSASL;
import org.proton.plug.ServerSASL;
import org.proton.plug.SASLResult;
import org.proton.plug.handler.impl.ProtonHandlerImpl;
/**
* This is a definition of the public interface for {@link org.proton.plug.handler.impl.ProtonHandlerImpl}
*/
public interface ProtonHandler {
long tick(boolean firstTick);
final class Factory {
public static ProtonHandler create(Executor dispatchExecutor) {
return new ProtonHandlerImpl(dispatchExecutor);
}
}
/**
* It returns true if the transport connection has any capacity available
*
* @return
*/
int capacity();
Transport getTransport();
Connection getConnection();
/**
* Add an event handler to the chain
*
* @param handler
* @return
*/
ProtonHandler addEventHandler(EventHandler handler);
void createClientSasl(ClientSASL clientSASL);
/**
* To be used on server connections. To define SASL integration.
*
* @param handlers
*/
void createServerSASL(ServerSASL[] handlers);
/**
* To return the SASL Mechanism that was successful with the connection.
* This should contain any state such as user and password
*
* @return
*/
SASLResult getSASLResult();
/**
* The input on the Handler.
* Notice that buffer will be positioned up to where we needed
*
* @param buffer
*/
void inputBuffer(ByteBuf buffer);
/**
* To be used at your discretion to verify if the client was active since you last checked
* it can be used to implement server TTL cleanup and verifications
*
* @return
*/
boolean checkDataReceived();
/**
* Return the creation time of the handler
*
* @return
*/
long getCreationTime();
/**
* To be called after you used the outputBuffer
*
* @param bytes number of bytes you used already on the output
*/
void outputDone(int bytes);
/**
* it will return pending bytes you have on the Transport
* after you are done with it you must call {@link #outputDone(int)}
*
* @return
*/
ByteBuf outputBuffer();
/**
* It will process the transport and cause events to be called
*/
void flush();
/**
* It will close the connection and flush events
*/
void close();
/**
* Get the object used to lock transport, connection and events operations
*
* @return
*/
Object getLock();
}

View File

@ -1,144 +0,0 @@
/*
* 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.proton.plug.handler.impl;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Delivery;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Session;
import org.apache.qpid.proton.engine.Transport;
import org.proton.plug.handler.EventHandler;
/**
* This is useful for cases where you only want to implement a few methods
*/
public abstract class DefaultEventHandler implements EventHandler {
@Override
public void onInit(Connection connection) throws Exception {
}
@Override
public void onLocalOpen(Connection connection) throws Exception {
}
@Override
public void onRemoteOpen(Connection connection) throws Exception {
}
@Override
public void onLocalClose(Connection connection) throws Exception {
}
@Override
public void onRemoteClose(Connection connection) throws Exception {
}
@Override
public void onFinal(Connection connection) throws Exception {
}
@Override
public void onInit(Session session) throws Exception {
}
@Override
public void onLocalOpen(Session session) throws Exception {
}
@Override
public void onRemoteOpen(Session session) throws Exception {
}
@Override
public void onLocalClose(Session session) throws Exception {
}
@Override
public void onRemoteClose(Session session) throws Exception {
}
@Override
public void onFinal(Session session) throws Exception {
}
@Override
public void onInit(Link link) throws Exception {
}
@Override
public void onLocalOpen(Link link) throws Exception {
}
@Override
public void onRemoteOpen(Link link) throws Exception {
}
@Override
public void onLocalClose(Link link) throws Exception {
}
@Override
public void onRemoteClose(Link link) throws Exception {
}
@Override
public void onFlow(Link link) throws Exception {
}
@Override
public void onFinal(Link link) throws Exception {
}
@Override
public void onRemoteDetach(Link link) throws Exception {
}
@Override
public void onDetach(Link link) throws Exception {
}
@Override
public void onDelivery(Delivery delivery) throws Exception {
}
@Override
public void onTransport(Transport transport) throws Exception {
}
}

View File

@ -1,130 +0,0 @@
/*
* 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.proton.plug.util;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.jboss.logging.Logger;
public class ByteUtil {
public static void debugFrame(Logger logger, String message, ByteBuf byteIn) {
if (logger.isTraceEnabled()) {
int location = byteIn.readerIndex();
// debugging
byte[] frame = new byte[byteIn.writerIndex()];
byteIn.readBytes(frame);
try {
logger.trace(message + "\n" + ByteUtil.formatGroup(ByteUtil.bytesToHex(frame), 8, 16));
}
catch (Exception e) {
logger.warn(e.getMessage(), e);
}
byteIn.readerIndex(location);
}
}
public static String formatGroup(String str, int groupSize, int lineBreak) {
StringBuffer buffer = new StringBuffer();
int line = 1;
buffer.append("/* 1 */ \"");
for (int i = 0; i < str.length(); i += groupSize) {
buffer.append(str.substring(i, i + Math.min(str.length() - i, groupSize)));
if ((i + groupSize) % lineBreak == 0) {
buffer.append("\" +\n/* ");
line++;
if (line < 10) {
buffer.append(" ");
}
buffer.append(Integer.toString(line) + " */ \"");
}
else if ((i + groupSize) % groupSize == 0 && str.length() - i > groupSize) {
buffer.append("\" + \"");
}
}
buffer.append("\";");
return buffer.toString();
}
protected static final char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
public static byte[] longToBytes(long x) {
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.heapBuffer(8, 8);
buffer.writeLong(x);
return buffer.array();
}
public static String maxString(String value, int size) {
if (value.length() < size) {
return value;
}
else {
return value.substring(0, size / 2) + " ... " + value.substring(value.length() - size / 2);
}
}
public static String bytesToHex(byte[] bytes, int groupSize) {
char[] hexChars = new char[bytes.length * 2 + numberOfGroups(bytes, groupSize)];
int outPos = 0;
for (int j = 0; j < bytes.length; j++) {
if (j > 0 && j % groupSize == 0) {
hexChars[outPos++] = ' ';
}
int v = bytes[j] & 0xFF;
hexChars[outPos++] = hexArray[v >>> 4];
hexChars[outPos++] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
private static int numberOfGroups(byte[] bytes, int groupSize) {
int groups = bytes.length / groupSize;
if (bytes.length % groupSize == 0) {
groups--;
}
return groups;
}
}

View File

@ -1,61 +0,0 @@
/*
* 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.proton.plug.util;
import java.util.concurrent.TimeUnit;
public class FutureRunnable implements Runnable {
private final ReusableLatch latch;
public FutureRunnable(final int initialIterations) {
latch = new ReusableLatch(initialIterations);
}
public FutureRunnable() {
this(0);
}
@Override
public void run() {
latch.countDown();
}
public void countUp() {
latch.countUp();
}
public void countDown() {
latch.countDown();
}
public int getCount() {
return latch.getCount();
}
public void await() throws InterruptedException {
latch.await();
}
public boolean await(long timeWait, TimeUnit timeUnit) throws InterruptedException {
return latch.await(timeWait, timeUnit);
}
public boolean await(long milliseconds) throws InterruptedException {
return latch.await(milliseconds);
}
}

View File

@ -1,130 +0,0 @@
/*
* 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.proton.plug.util;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* <p>This class will use the framework provided to by AbstractQueuedSynchronizer.</p>
* <p>AbstractQueuedSynchronizer is the framework for any sort of concurrent synchronization, such as Semaphores, events, etc, based on AtomicIntegers.</p>
* <p>This class works just like CountDownLatch, with the difference you can also increase the counter</p>
* <p>It could be used for sync points when one process is feeding the latch while another will wait when everything is done. (e.g. waiting IO completions to finish)</p>
* <p>On ActiveMQ Artemis we have the requirement of increment and decrement a counter until the user fires a ready handler (commit). At that point we just act as a regular countDown.</p>
* <p>Note: This latch is reusable. Once it reaches zero, you can call up again, and reuse it on further waits.</p>
* <p>For example: prepareTransaction will wait for the current completions, and further adds will be called on the latch. Later on when commit is called you can reuse the same latch.</p>
*/
public class ReusableLatch {
/**
* Look at the doc and examples provided by AbstractQueuedSynchronizer for more information
*
* @see AbstractQueuedSynchronizer
*/
@SuppressWarnings("serial")
private static class CountSync extends AbstractQueuedSynchronizer {
private CountSync(int count) {
setState(count);
}
public int getCount() {
return getState();
}
public void setCount(final int count) {
setState(count);
}
@Override
public int tryAcquireShared(final int numberOfAqcquires) {
return getState() == 0 ? 1 : -1;
}
public void add() {
for (;;) {
int actualState = getState();
int newState = actualState + 1;
if (compareAndSetState(actualState, newState)) {
return;
}
}
}
@Override
public boolean tryReleaseShared(final int numberOfReleases) {
for (;;) {
int actualState = getState();
if (actualState == 0) {
return true;
}
int newState = actualState - numberOfReleases;
if (newState < 0) {
newState = 0;
}
if (compareAndSetState(actualState, newState)) {
return newState == 0;
}
}
}
}
private final CountSync control;
public ReusableLatch() {
this(0);
}
public ReusableLatch(final int count) {
control = new CountSync(count);
}
public int getCount() {
return control.getCount();
}
public void setCount(final int count) {
control.setCount(count);
}
public void countUp() {
control.add();
}
public void countDown() {
control.releaseShared(1);
}
public void countDown(final int count) {
control.releaseShared(count);
}
public void await() throws InterruptedException {
control.acquireSharedInterruptibly(1);
}
public boolean await(final long milliseconds) throws InterruptedException {
return control.tryAcquireSharedNanos(1, TimeUnit.MILLISECONDS.toNanos(milliseconds));
}
public boolean await(final long timeWait, TimeUnit timeUnit) throws InterruptedException {
return control.tryAcquireSharedNanos(1, timeUnit.toNanos(timeWait));
}
}

View File

@ -1,137 +0,0 @@
/*
* 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.proton.plug.context;
import java.util.concurrent.Executors;
import io.netty.buffer.ByteBuf;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.Link;
import org.apache.qpid.proton.engine.Session;
import org.junit.Test;
import org.proton.plug.AMQPConnectionCallback;
import org.proton.plug.AMQPConnectionContext;
import org.proton.plug.AMQPSessionCallback;
import org.proton.plug.SASLResult;
import org.proton.plug.ServerSASL;
import org.proton.plug.exceptions.ActiveMQAMQPException;
import org.proton.plug.handler.EventHandler;
public class AbstractConnectionContextTest {
@Test
public void testListenerDoesntThrowNPEWhenClosingLinkWithNullContext() throws Exception {
TestConnectionContext connectionContext = new TestConnectionContext(new TestConnectionCallback());
EventHandler listener = connectionContext.getListener();
Connection protonConnection = Connection.Factory.create();
Session protonSession = protonConnection.session();
Link link = protonSession.receiver("link");
link.setContext(null);
listener.onRemoteClose(link);
}
private class TestConnectionContext extends AbstractConnectionContext {
private TestConnectionContext(AMQPConnectionCallback connectionCallback) {
super(connectionCallback, Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory()), null);
}
@Override
protected void remoteLinkOpened(Link link) throws Exception {
}
@Override
protected AbstractProtonSessionContext newSessionExtension(Session realSession) throws ActiveMQAMQPException {
return null;
}
public EventHandler getListener() {
return listener;
}
}
private class TestConnectionCallback implements AMQPConnectionCallback {
@Override
public void close() {
}
@Override
public Binary newTransaction() {
return null;
}
@Override
public Transaction getTransaction(Binary txid) throws ActiveMQAMQPException {
return null;
}
@Override
public void removeTransaction(Binary txid) {
}
@Override
public void onTransport(ByteBuf bytes, AMQPConnectionContext connection) {
}
@Override
public AMQPSessionCallback createSessionCallback(AMQPConnectionContext connection) {
return null;
}
@Override
public void setConnection(AMQPConnectionContext connection) {
}
@Override
public AMQPConnectionContext getConnection() {
return null;
}
@Override
public ServerSASL[] getSASLMechnisms() {
return null;
}
@Override
public boolean isSupportsAnonymous() {
return true;
}
@Override
public void sendSASLSupported() {
}
@Override
public boolean validateConnection(Connection connection, SASLResult saslResult) {
return true;
}
}
}

View File

@ -1,93 +0,0 @@
/*
* 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.proton.plug.test;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.Session;
import java.lang.ref.WeakReference;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.jboss.logging.Logger;
import org.proton.plug.test.minimalserver.DumbServer;
import org.proton.plug.test.minimalserver.MinimalServer;
public class AbstractJMSTest {
private static final Logger log = Logger.getLogger(AbstractJMSTest.class);
protected final boolean useSASL;
protected String address = "exampleQueue";
protected MinimalServer server = new MinimalServer();
public AbstractJMSTest(boolean useSASL) {
this.useSASL = useSASL;
}
public void tearDown() throws Exception {
server.stop();
DumbServer.clear();
}
public static void forceGC() {
System.out.println("#test forceGC");
WeakReference<Object> dumbReference = new WeakReference<>(new Object());
// A loop that will wait GC, using the minimalserver time as possible
while (dumbReference.get() != null) {
System.gc();
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
}
}
System.out.println("#test forceGC Done");
}
protected Connection createConnection() throws JMSException {
final ConnectionFactory factory = createConnectionFactory();
final Connection connection = factory.createConnection();
connection.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException exception) {
log.warn(exception.getMessage(), exception);
}
});
connection.start();
return connection;
}
protected ConnectionFactory createConnectionFactory() {
if (useSASL) {
return new JmsConnectionFactory("aaaaaaaa", "aaaaaaa", "amqp://localhost:5672");
}
else {
return new JmsConnectionFactory( "amqp://localhost:5672");
}
}
protected Queue createQueue(Session session) throws Exception {
return session.createQueue(address);
}
}

Some files were not shown because too many files have changed in this diff Show More