net.di2e.ddf.argo.probe.generator.ProbeGenerator.java Source code

Java tutorial

Introduction

Here is the source code for net.di2e.ddf.argo.probe.generator.ProbeGenerator.java

Source

/**
 * Copyright (C) 2015 Pink Summit, LLC (info@pinksummit.com)
 *
 * Licensed 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 net.di2e.ddf.argo.probe.generator;

import java.io.IOException;
import java.io.StringWriter;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXB;

import net.di2e.ddf.argo.common.ArgoConstants;
import net.di2e.ddf.argo.jaxb.probe.Probe;
import net.di2e.ddf.argo.jaxb.probe.Probe.Ra;
import net.di2e.ddf.argo.jaxb.probe.Probe.Ra.RespondTo;
import net.di2e.ddf.argo.jaxb.probe.Probe.Scids;

import org.apache.commons.io.IOUtils;
import org.codice.ddf.configuration.impl.ConfigurationWatcherImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProbeGenerator {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProbeGenerator.class);

    private static final String DEFAULT_SERVICE_CONTRACT_ID = "urn:uuid:b10b8c34-76f4-4e1d-938d-20eee3377d22";

    private static final int NUM_OF_EXECUTOR_THREADS = 1;

    private int port = 4003;
    private String address = "230.0.0.1";
    private int ttl = 255;
    private int sendFrequency = 300;
    private List<String> respondToList = null;

    private String responseFormat = "XML";
    private List<String> serviceContractIds = null;

    private ConfigurationWatcherImpl platformConfiguration = null;

    private ProbeSender sender = new ProbeSender();
    private ScheduledFuture<?> currentTask;
    private ScheduledThreadPoolExecutor executor;

    public ProbeGenerator(String to, ConfigurationWatcherImpl config) {
        if (config == null) {
            throw new IllegalArgumentException(
                    "The ConfigurationWatcherImpl parameter cannot be null for ProbeGenerator constructor");
        }
        serviceContractIds = new ArrayList<String>();
        serviceContractIds.add(DEFAULT_SERVICE_CONTRACT_ID);
        platformConfiguration = config;
        respondToList = new ArrayList<String>();
        respondToList.add(ArgoConstants.DEFAULT_RESPOND_TO);
    }

    /**
     * Starts the timer to send out probes on a set interval.
     */
    public void start() {
        executor = new ScheduledThreadPoolExecutor(NUM_OF_EXECUTOR_THREADS);
        LOGGER.debug("Starting ProbeGenerator to send out probe every {} seconds.", sendFrequency);
        currentTask = executor.scheduleAtFixedRate(sender, 1, sendFrequency, TimeUnit.SECONDS);
    }

    /**
     * Stops the timer and cancels any probes from being sent out.
     */
    public void stop() {
        LOGGER.debug("Shutting down ProbeGenerator");
        executor.shutdownNow();
    }

    public void setMulticastAddress(String multicastAddress) {
        LOGGER.debug("Shutting down ProbeGenerator");
        address = multicastAddress;
    }

    public void setMulticastPort(int p) {
        LOGGER.debug("{} setting multicast port from '{}' to '{}'", ArgoConstants.LOG_CONFIG_UPDATE_PREFIX,
                this.port, p);
        this.port = p;
    }

    public void setSendFrequency(int freq) {
        if (this.sendFrequency != freq) {
            LOGGER.debug("{} setting send frequence port from '{}' to '{}' and restarting probe generator thread",
                    ArgoConstants.LOG_CONFIG_UPDATE_PREFIX, sendFrequency, freq);
            this.sendFrequency = freq;
            currentTask.cancel(true);
            if (sendFrequency > 0) {
                currentTask = executor.scheduleAtFixedRate(sender, 1, sendFrequency, TimeUnit.SECONDS);
            } else {
                LOGGER.info(
                        "Turning off the probe generator, so Argo probes will no longer be sent because frequence was set to {}",
                        sendFrequency);
            }
        }
    }

    public void setProbeTTL(int seconds) {
        LOGGER.debug("{} setting probe TTL from '{}' to '{}'", ArgoConstants.LOG_CONFIG_UPDATE_PREFIX, ttl,
                seconds);
        this.ttl = seconds;
    }

    public void setRespondTo(List<String> toList) {
        LOGGER.debug("{} setting probe respondTo from '{}' to '{}'", ArgoConstants.LOG_CONFIG_UPDATE_PREFIX,
                respondToList, toList);
        this.respondToList = toList;
    }

    public void setResponseFormat(String format) {
        LOGGER.debug("{} setting probe responseFormat from '{}' to '{}'", ArgoConstants.LOG_CONFIG_UPDATE_PREFIX,
                responseFormat, format);
        this.responseFormat = format;
    }

    public void setServiceContractIds(List<String> ids) {
        LOGGER.debug("{} setting Service Contract ID from '{}' to '{}'", ArgoConstants.LOG_CONFIG_UPDATE_PREFIX,
                serviceContractIds, ids);
        this.serviceContractIds = ids;
    }

    public String expandRespondToAddress(String respondTo) {
        String address = null;
        if (respondTo != null) {
            if (respondTo.startsWith("/")) {
                address = platformConfiguration.getProtocol() + platformConfiguration.getHostname() + ":"
                        + platformConfiguration.getPort() + respondTo;
            } else {
                address = respondTo;
            }
        }
        LOGGER.debug(
                "Expanding the respondTo address in the probe to '{}' based on the respondTo configuration value '{}'",
                address, respondTo);
        return address;
    }

    private class ProbeSender implements Runnable {

        public void run() {
            MulticastSocket socket = null;
            if (respondToList != null && !respondToList.isEmpty()) {
                for (String respondToString : respondToList) {
                    try {
                        socket = new MulticastSocket();
                        socket.setTimeToLive(ttl);
                        Probe probe = new Probe();
                        probe.setId("urn:uuid:" + UUID.randomUUID());
                        String sitename = platformConfiguration.getSiteName();
                        probe.setClient(sitename);
                        Ra responseAddress = new Ra();
                        RespondTo respondTo = new RespondTo();
                        respondTo.setLabel(sitename);
                        respondTo.setValue(expandRespondToAddress(respondToString));
                        responseAddress.getRespondTo().add(respondTo);
                        probe.setRa(responseAddress);

                        probe.setRespondToPayloadType(responseFormat);
                        if (serviceContractIds != null) {
                            Scids scids = new Scids();
                            for (String serviceContractId : serviceContractIds) {
                                scids.getServiceContractID().add(serviceContractId);
                            }
                            probe.setScids(scids);
                        }

                        StringWriter writer = new StringWriter();
                        JAXB.marshal(probe, writer);
                        String probeXml = writer.toString();
                        byte[] bytes = probeXml.getBytes(StandardCharsets.UTF_8);
                        DatagramPacket packet = new DatagramPacket(bytes, bytes.length,
                                InetAddress.getByName(address), port);
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Sending multicast packet out to {}:{}", address, port);
                            LOGGER.debug("Sending probe message: {}", probeXml);
                        }

                        socket.send(packet);
                    } catch (IOException | DataBindingException e) {
                        LOGGER.warn(
                                "Encountered an error while trying to send out the probe. Could not send multicast message.",
                                e);
                    } finally {
                        IOUtils.closeQuietly(socket);
                    }
                }
            }
        }
    }

}