amqp.AmqpEventSource.java Source code

Java tutorial

Introduction

Here is the source code for amqp.AmqpEventSource.java

Source

/**
 * Licensed to Cloudera, Inc. under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  Cloudera, Inc. 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 amqp;

import com.cloudera.flume.conf.Context;
import com.cloudera.flume.conf.SourceFactory;
import com.cloudera.flume.core.Event;
import com.cloudera.flume.core.EventSource;
import com.cloudera.flume.util.CommandLineParser;
import com.cloudera.util.Pair;
import com.rabbitmq.client.ConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * This class is used to consume message from an AMQP broker and create {@link Event}s from the raw
 * body of the message. Uses RabbitMQ's AQMP client to connect to said broker.
 * <p/>
 * Note that the majority of the work is done in {@link AmqpConsumer}.
 */
public class AmqpEventSource extends EventSource.Base {

    private static final Logger LOG = LoggerFactory.getLogger(AmqpEventSource.class);

    /**
     * Time to wait in between polls for event
     *
     * @see #next()
     */
    private static final int WAIT_IN_MILLS = 100;

    private final AmqpConsumer consumer;

    public AmqpEventSource(String host, int port, String virtualHost, String userName, String password,
            String exchangeName, String exchangeType, boolean durableExchange, String queueName, boolean durable,
            boolean exclusive, boolean autoDelete, boolean useMessageTimestamp, String... bindings) {
        consumer = new AmqpConsumer(host, port, virtualHost, userName, password, exchangeName, exchangeType,
                durableExchange, queueName, durable, exclusive, autoDelete, useMessageTimestamp, bindings);
    }

    public AmqpEventSource(ConnectionFactory connectionFactory, String exchangeName, String queueName,
            String... bindings) {
        consumer = new AmqpConsumer(connectionFactory, exchangeName, queueName, bindings);
    }

    @Override
    public void close() throws IOException {
        if (!consumer.isRunning()) {
            LOG.warn("AmqpEventSource is already closed. Ignoring second close.");
        } else {
            consumer.stopConsumer();
        }
    }

    @Override
    public void open() throws IOException {
        if (consumer.isRunning()) {
            LOG.warn("AmqpEventSource is already open. Ignoring second open.");
        } else {
            consumer.startConsumer();
        }
    }

    /**
     * This method will return the next {@link Event} available from the configured AMQP Queue blocking until
     * one is available. Note that this method will return early if the thread from which next is called
     * is interrupted.
     *
     * @return event or null if we are interrupted or closed
     * @throws IOException
     */
    public Event next() throws IOException {
        Event event = null;

        // as long as the consumer is running, or has pending events, we need to drain them
        while ((consumer.isRunning() || consumer.hasPendingEvents()) && event == null) {
            try {
                event = consumer.getNextEvent(WAIT_IN_MILLS, TimeUnit.MILLISECONDS);

                if (event != null) {
                    updateEventProcessingStats(event);
                }
            } catch (InterruptedException e) {
                // someone interrupted us - return null event
            }
        }

        return event;
    }

    public static SourceFactory.SourceBuilder builder() {
        return new SourceFactory.SourceBuilder() {
            @Override
            public EventSource build(String... args) {
                return build(null, args);
            }

            @Override
            public EventSource build(Context ctx, String... args) {
                if (args.length < 1 || args.length > 13) {
                    throw new IllegalArgumentException("amqp(exchangeName=\"exchangeName\" " + "[,host=\"host\"] "
                            + "[,port=port] " + "[,virtualHost=\"virtualHost\"] " + "[,userName=\"user\"] "
                            + "[,password=\"password\"] " + "[,exchangeType=\"direct\"] "
                            + "[,durableExchange=false] " + "[,queueName=\"queueName\"] " + "[,durableQueue=false] "
                            + "[,exclusiveQueue=false] " + "[,autoDeleteQueue=false] "
                            + "[,bindings=\"binding1,binding2,bindingN\"] " + "[,useMessageTimestamp=false])");
                }

                CommandLineParser parser = new CommandLineParser(args);

                String host = parser.getOptionValue("host", ConnectionFactory.DEFAULT_HOST);
                int port = parser.getOptionValue("port", ConnectionFactory.DEFAULT_AMQP_PORT);
                String virtualHost = parser.getOptionValue("virtualHost", ConnectionFactory.DEFAULT_VHOST);
                String userName = parser.getOptionValue("userName", ConnectionFactory.DEFAULT_USER);
                String password = parser.getOptionValue("password", ConnectionFactory.DEFAULT_PASS);
                String exchangeName = parser.getOptionValue("exchangeName");
                String exchangeType = parser.getOptionValue("exchangeType", AmqpConsumer.DEFAULT_EXCHANGE_TYPE);
                boolean durableExchange = parser.getOptionValue("durableExchange", true);
                String queueName = parser.getOptionValue("queueName");
                boolean durableQueue = parser.getOptionValue("durableQueue", false);
                boolean exclusiveQueue = parser.getOptionValue("exclusiveQueue", false);
                boolean autoDeleteQueue = parser.getOptionValue("autoDeleteQueue", false);
                String[] bindings = parser.getOptionValues("bindings");
                boolean useMessageTimestamp = parser.getOptionValue("useMessageTimestamp", false);

                // exchange name is the only required parameter
                if (exchangeName == null) {
                    throw new IllegalArgumentException("exchangeName must be set for AMQP source");
                }

                return new AmqpEventSource(host, port, virtualHost, userName, password, exchangeName, exchangeType,
                        durableExchange, queueName, durableQueue, exclusiveQueue, autoDeleteQueue,
                        useMessageTimestamp, bindings);
            }
        };
    }

    /**
     * This is a special function used by the SourceFactory to pull in this class
     * as a plugin source.
     */
    public static List<Pair<String, SourceFactory.SourceBuilder>> getSourceBuilders() {
        List<Pair<String, SourceFactory.SourceBuilder>> builders = new ArrayList<Pair<String, SourceFactory.SourceBuilder>>();
        builders.add(new Pair<String, SourceFactory.SourceBuilder>("amqp", builder()));
        return builders;
    }
}