001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.activemq.transport.amqp.protocol; 018 019import org.apache.activemq.command.LocalTransactionId; 020import org.apache.activemq.transport.amqp.AmqpProtocolException; 021import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode; 022import org.apache.qpid.proton.engine.Delivery; 023import org.apache.qpid.proton.engine.Receiver; 024import org.fusesource.hawtbuf.Buffer; 025import org.fusesource.hawtbuf.ByteArrayOutputStream; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029/** 030 * Abstract base that provides common services for AMQP Receiver types. 031 */ 032public abstract class AmqpAbstractReceiver extends AmqpAbstractLink<Receiver> { 033 034 private static final Logger LOG = LoggerFactory.getLogger(AmqpAbstractReceiver.class); 035 036 protected ByteArrayOutputStream current = new ByteArrayOutputStream(); 037 protected final byte[] recvBuffer = new byte[1024 * 8]; 038 protected final int configuredCredit; 039 040 /** 041 * Handle create of new AMQP Receiver instance. 042 * 043 * @param session 044 * the AmqpSession that servers as the parent of this Link. 045 * @param endpoint 046 * the Receiver endpoint being managed by this class. 047 */ 048 public AmqpAbstractReceiver(AmqpSession session, Receiver endpoint) { 049 super(session, endpoint); 050 this.configuredCredit = session.getConnection().getConfiguredReceiverCredit(); 051 052 // We don't support second so enforce it as First and let remote decide what to do 053 this.endpoint.setReceiverSettleMode(ReceiverSettleMode.FIRST); 054 055 // Match what the sender mode is 056 this.endpoint.setSenderSettleMode(endpoint.getRemoteSenderSettleMode()); 057 } 058 059 @Override 060 public void detach() { 061 } 062 063 @Override 064 public void flow() throws Exception { 065 } 066 067 /** 068 * Returns the amount of receiver credit that has been configured for this AMQP 069 * transport. If no value was configured on the TransportConnector URI then a 070 * sensible default is used. 071 * 072 * @return the configured receiver credit to grant. 073 */ 074 public int getConfiguredReceiverCredit() { 075 return configuredCredit; 076 } 077 078 /** 079 * Provide the receiver endpoint with the given amount of credits. 080 * 081 * @param credits 082 * the credit value to pass on to the wrapped Receiver. 083 */ 084 public void flow(int credits) { 085 getEndpoint().flow(credits); 086 } 087 088 @Override 089 public void commit(LocalTransactionId txnId) throws Exception { 090 } 091 092 @Override 093 public void rollback(LocalTransactionId txnId) throws Exception { 094 } 095 096 @Override 097 public void delivery(Delivery delivery) throws Exception { 098 099 if (!delivery.isReadable()) { 100 LOG.debug("Delivery was not readable!"); 101 return; 102 } 103 104 if (current == null) { 105 current = new ByteArrayOutputStream(); 106 } 107 108 int count; 109 while ((count = getEndpoint().recv(recvBuffer, 0, recvBuffer.length)) > 0) { 110 current.write(recvBuffer, 0, count); 111 112 if (current.size() > session.getMaxFrameSize()) { 113 throw new AmqpProtocolException("Frame size of " + current.size() + " larger than max allowed " + session.getMaxFrameSize()); 114 } 115 } 116 117 // Expecting more deliveries.. 118 if (count == 0) { 119 return; 120 } 121 122 try { 123 processDelivery(delivery, current.toBuffer()); 124 } finally { 125 getEndpoint().advance(); 126 current = null; 127 } 128 } 129 130 protected abstract void processDelivery(Delivery delivery, Buffer deliveryBytes) throws Exception; 131 132}