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; 018 019import java.io.IOException; 020import java.security.cert.X509Certificate; 021import java.util.concurrent.locks.ReentrantLock; 022 023import org.apache.activemq.broker.BrokerService; 024import org.apache.activemq.command.Command; 025import org.apache.activemq.transport.Transport; 026import org.apache.activemq.transport.TransportFilter; 027import org.apache.activemq.transport.TransportListener; 028import org.apache.activemq.transport.tcp.SslTransport; 029import org.apache.activemq.util.IOExceptionSupport; 030import org.apache.activemq.wireformat.WireFormat; 031import org.apache.qpid.proton.jms.InboundTransformer; 032import org.slf4j.Logger; 033import org.slf4j.LoggerFactory; 034 035/** 036 * The AMQPTransportFilter normally sits on top of a TcpTransport that has been 037 * configured with the AmqpWireFormat and is used to convert AMQP commands to 038 * ActiveMQ commands. All of the conversion work is done by delegating to the 039 * AMQPProtocolConverter 040 */ 041public class AmqpTransportFilter extends TransportFilter implements AmqpTransport { 042 private static final Logger LOG = LoggerFactory.getLogger(AmqpTransportFilter.class); 043 static final Logger TRACE_BYTES = LoggerFactory.getLogger(AmqpTransportFilter.class.getPackage().getName() + ".BYTES"); 044 static final Logger TRACE_FRAMES = LoggerFactory.getLogger(AmqpTransportFilter.class.getPackage().getName() + ".FRAMES"); 045 private IAmqpProtocolConverter protocolConverter; 046 private AmqpWireFormat wireFormat; 047 048 private boolean trace; 049 private String transformer = InboundTransformer.TRANSFORMER_NATIVE; 050 private final ReentrantLock lock = new ReentrantLock(); 051 052 public AmqpTransportFilter(Transport next, WireFormat wireFormat, BrokerService brokerService) { 053 super(next); 054 this.protocolConverter = new AMQPProtocolDiscriminator(this, brokerService); 055 if (wireFormat instanceof AmqpWireFormat) { 056 this.wireFormat = (AmqpWireFormat) wireFormat; 057 } 058 } 059 060 @Override 061 public void oneway(Object o) throws IOException { 062 try { 063 final Command command = (Command) o; 064 lock.lock(); 065 try { 066 protocolConverter.onActiveMQCommand(command); 067 } finally { 068 lock.unlock(); 069 } 070 } catch (Exception e) { 071 throw IOExceptionSupport.create(e); 072 } 073 } 074 075 @Override 076 public void onException(IOException error) { 077 lock.lock(); 078 try { 079 protocolConverter.onAMQPException(error); 080 } finally { 081 lock.unlock(); 082 } 083 } 084 085 @Override 086 public void sendToActiveMQ(IOException error) { 087 super.onException(error); 088 } 089 090 @Override 091 public void onCommand(Object command) { 092 try { 093 if (trace) { 094 TRACE_BYTES.trace("Received: \n{}", command); 095 } 096 lock.lock(); 097 try { 098 protocolConverter.onAMQPData(command); 099 } finally { 100 lock.unlock(); 101 } 102 } catch (IOException e) { 103 handleException(e); 104 } catch (Exception e) { 105 onException(IOExceptionSupport.create(e)); 106 } 107 } 108 109 @Override 110 public void sendToActiveMQ(Command command) { 111 assert lock.isHeldByCurrentThread(); 112 TransportListener l = transportListener; 113 if (l != null) { 114 l.onCommand(command); 115 } 116 } 117 118 @Override 119 public void sendToAmqp(Object command) throws IOException { 120 assert lock.isHeldByCurrentThread(); 121 if (trace) { 122 TRACE_BYTES.trace("Sending: \n{}", command); 123 } 124 Transport n = next; 125 if (n != null) { 126 n.oneway(command); 127 } 128 } 129 130 @Override 131 public X509Certificate[] getPeerCertificates() { 132 if (next instanceof SslTransport) { 133 X509Certificate[] peerCerts = ((SslTransport) next).getPeerCertificates(); 134 if (trace && peerCerts != null) { 135 LOG.debug("Peer Identity has been verified\n"); 136 } 137 return peerCerts; 138 } 139 return null; 140 } 141 142 @Override 143 public boolean isTrace() { 144 return trace; 145 } 146 147 public void setTrace(boolean trace) { 148 this.trace = trace; 149 this.protocolConverter.updateTracer(); 150 } 151 152 @Override 153 public AmqpWireFormat getWireFormat() { 154 return this.wireFormat; 155 } 156 157 public void handleException(IOException e) { 158 super.onException(e); 159 } 160 161 @Override 162 public String getTransformer() { 163 return transformer; 164 } 165 166 public void setTransformer(String transformer) { 167 this.transformer = transformer; 168 } 169 170 @Override 171 public IAmqpProtocolConverter getProtocolConverter() { 172 return protocolConverter; 173 } 174 175 @Override 176 public void setProtocolConverter(IAmqpProtocolConverter protocolConverter) { 177 this.protocolConverter = protocolConverter; 178 } 179 180 public void setPrefetch(int prefetch) { 181 protocolConverter.setPrefetch(prefetch); 182 } 183 184 public void setProducerCredit(int producerCredit) { 185 protocolConverter.setProducerCredit(producerCredit); 186 } 187}