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:
parent
4e349693f4
commit
a838bf0479
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
|
@ -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();
|
|
@ -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.
|
|
@ -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();
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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";
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 {
|
|
@ -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;
|
|
@ -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 {
|
||||
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
@ -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;
|
|
@ -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 {
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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 {
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -1 +1 @@
|
|||
org.apache.activemq.artemis.core.protocol.proton.ProtonProtocolManagerFactory
|
||||
org.apache.activemq.artemis.protocol.amqp.broker.ProtonProtocolManagerFactory
|
|
@ -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 {
|
||||
|
|
@ -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) {
|
|
@ -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 {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue