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.util.ArrayList;
021
022import org.apache.activemq.broker.BrokerService;
023import org.apache.activemq.command.Command;
024
025/**
026 * Used to assign the best implementation of a AmqpProtocolConverter to the
027 * AmqpTransport based on the AmqpHeader that the client sends us.
028 */
029public class AMQPProtocolDiscriminator implements IAmqpProtocolConverter {
030
031    public static final int DEFAULT_PREFETCH = 1000;
032
033    private final AmqpTransport transport;
034    private final BrokerService brokerService;
035
036    private int prefetch = 0;
037    private int producerCredit = DEFAULT_PREFETCH;
038
039    interface Discriminator {
040        boolean matches(AmqpHeader header);
041
042        IAmqpProtocolConverter create(AmqpTransport transport, BrokerService brokerService);
043    }
044
045    static final private ArrayList<Discriminator> DISCRIMINATORS = new ArrayList<Discriminator>();
046    static {
047        DISCRIMINATORS.add(new Discriminator() {
048
049            @Override
050            public IAmqpProtocolConverter create(AmqpTransport transport, BrokerService brokerService) {
051                return new AmqpProtocolConverter(transport, brokerService);
052            }
053
054            @Override
055            public boolean matches(AmqpHeader header) {
056                switch (header.getProtocolId()) {
057                    case 0:
058                    case 3:
059                        if (header.getMajor() == 1 && header.getMinor() == 0 && header.getRevision() == 0) {
060                            return true;
061                        }
062                }
063                return false;
064            }
065        });
066    }
067
068    final private ArrayList<Command> pendingCommands = new ArrayList<Command>();
069
070    public AMQPProtocolDiscriminator(AmqpTransport transport, BrokerService brokerService) {
071        this.transport = transport;
072        this.brokerService = brokerService;
073    }
074
075    @Override
076    public void onAMQPData(Object command) throws Exception {
077        if (command.getClass() == AmqpHeader.class) {
078            AmqpHeader header = (AmqpHeader) command;
079
080            Discriminator match = null;
081            for (Discriminator discriminator : DISCRIMINATORS) {
082                if (discriminator.matches(header)) {
083                    match = discriminator;
084                }
085            }
086
087            // Lets use first in the list if none are a good match.
088            if (match == null) {
089                match = DISCRIMINATORS.get(0);
090            }
091
092            IAmqpProtocolConverter next = match.create(transport, brokerService);
093            next.setPrefetch(prefetch);
094            next.setProducerCredit(producerCredit);
095            transport.setProtocolConverter(next);
096            for (Command send : pendingCommands) {
097                next.onActiveMQCommand(send);
098            }
099            pendingCommands.clear();
100            next.onAMQPData(command);
101        } else {
102            throw new IllegalStateException();
103        }
104    }
105
106    @Override
107    public void onAMQPException(IOException error) {
108    }
109
110    @Override
111    public void onActiveMQCommand(Command command) throws Exception {
112        pendingCommands.add(command);
113    }
114
115    @Override
116    public void updateTracer() {
117    }
118
119    @Override
120    public void setPrefetch(int prefetch) {
121        this.prefetch = prefetch;
122    }
123
124    @Override
125    public void setProducerCredit(int producerCredit) {
126        this.producerCredit = producerCredit;
127    }
128}