org.opennms.features.topology.netutils.internal.ping.PingWindow.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.features.topology.netutils.internal.ping.PingWindow.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2012-2014 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2014 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.features.topology.netutils.internal.ping;

import java.net.InetAddress;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.opennms.netmgt.icmp.proxy.LocationAwarePingClient;
import org.opennms.netmgt.icmp.proxy.PingStringUtils;
import org.opennms.netmgt.icmp.proxy.PingSummary;

import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.ProgressBar;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;

/**
 * The PingWindow class creates a Vaadin Sub-window with a form and results section
 * for the Ping functionality of a Vertex.
 *
 * @author Leonardo Bell
 * @author Philip Grenon
 * @author Markus von Rden
 * @version 2.0
 */
public class PingWindow extends Window {

    /**
     * As soon as we start the ping command, we must poll for state changes, as the ping is executed asynchronously.
     * The POLL_INTERVAL determines the poll interval in milliseconds.
     */
    public static final int POLL_INTERVAL = 1000;

    /**
     * If a ping is started, it is indicated.
     */
    private final ProgressBar progressIndicator;

    /**
     * Cancels the current ping
     */
    private final Button cancelButton;

    /**
     * Starts a ping
     */
    private final Button pingButton;

    /**
     * The form to configure the Ping command.
     */
    private final PingForm pingForm;

    private CompletableFuture<PingSummary> pingFuture;

    /**
     * Creates the PingWindow to make ping requests.
     *
     * @param locations All available locations to ping from. Must not be null.
     * @param defaultLocation The location to pre-select from the locations. Ensure <code>defaultLocation</code> is also available in the <code>locations</code> list.
     * @param ipAddresses All available ipAddresses. Must not be null or empty.
     * @param defaultIp The default ip to pre-select from the ip addresses. Ensure <code>defaultIp</code> is also available in the <code>ipAddresses</code> list.
     * @param pingClient The LocationAwarePingClient to ping. Must not be null.
     */
    public PingWindow(LocationAwarePingClient pingClient, List<String> locations, List<InetAddress> ipAddresses,
            String defaultLocation, InetAddress defaultIp, String caption) {
        Objects.requireNonNull(pingClient);
        Objects.requireNonNull(ipAddresses);
        Objects.requireNonNull(defaultIp);
        Objects.requireNonNull(locations);
        Objects.requireNonNull(defaultLocation);
        Objects.requireNonNull(caption);

        // Remember initial poll interval, as we poll as soon as we start pinging
        final int initialPollInterval = UI.getCurrent().getPollInterval();

        // Ping Form
        pingForm = new PingForm(locations, defaultLocation, ipAddresses, defaultIp);

        // Result
        final TextArea resultArea = new TextArea();
        resultArea.setRows(15);
        resultArea.setSizeFull();

        // Progress Indicator
        progressIndicator = new ProgressBar();
        progressIndicator.setIndeterminate(true);

        // Buttons
        cancelButton = new Button("Cancel");
        cancelButton.addClickListener((event) -> {
            cancel(pingFuture);
            resultArea.setValue(resultArea.getValue() + "\n" + "Ping cancelled by user");
            getUI().setPollInterval(initialPollInterval);
            setRunning(false);
        });
        pingButton = new Button("Ping");
        pingButton.addClickListener((event) -> {
            try {
                final PingRequest pingRequest = pingForm.getPingRequest();

                resultArea.setValue(""); // Clear
                setRunning(true);
                getUI().setPollInterval(POLL_INTERVAL);

                pingFuture = pingClient.ping(pingRequest.getInetAddress()).withRetries(pingRequest.getRetries())
                        .withPacketSize(pingRequest.getPacketSize())
                        .withTimeout(pingRequest.getTimeout(), TimeUnit.MILLISECONDS)
                        .withLocation(pingRequest.getLocation())
                        .withNumberOfRequests(pingRequest.getNumberRequests())
                        .withProgressCallback((newSequence, summary) -> {
                            getUI().accessSynchronously(() -> {
                                if (pingFuture != null && !pingFuture.isCancelled()) {
                                    setRunning(!summary.isComplete());
                                    resultArea.setValue(PingStringUtils.renderAll(summary));
                                    if (summary.isComplete()) {
                                        getUI().setPollInterval(initialPollInterval);
                                    }
                                }
                            });
                        }).execute();
            } catch (FieldGroup.CommitException e) {
                Notification.show("Validation errors",
                        "Please correct them. Make sure all required fields are set.",
                        Notification.Type.ERROR_MESSAGE);
            }
        });

        // Button Layout
        final HorizontalLayout buttonLayout = new HorizontalLayout();
        buttonLayout.setSpacing(true);
        buttonLayout.addComponent(pingButton);
        buttonLayout.addComponent(cancelButton);
        buttonLayout.addComponent(progressIndicator);

        // Root Layout
        final VerticalLayout rootLayout = new VerticalLayout();
        rootLayout.setSpacing(true);
        rootLayout.setMargin(true);
        rootLayout.addComponent(pingForm);
        rootLayout.addComponent(buttonLayout);
        rootLayout.addComponent(new Label("<b>Results</b>", ContentMode.HTML));
        rootLayout.addComponent(resultArea);
        rootLayout.setExpandRatio(resultArea, 1.0f);

        // Window Config
        setCaption(caption);
        setResizable(false);
        setModal(true);
        setWidth(800, Unit.PIXELS);
        setHeight(600, Unit.PIXELS);
        setContent(rootLayout);
        center();
        setRunning(false);

        // Set back to default, when closing
        addCloseListener((CloseListener) e -> {
            cancel(pingFuture);
            getUI().setPollInterval(initialPollInterval);
        });
    }

    private static void cancel(CompletableFuture pingFuture) {
        if (pingFuture != null) {
            pingFuture.cancel(true);
        }
    }

    private void setRunning(boolean running) {
        cancelButton.setEnabled(running);
        progressIndicator.setVisible(running);
        pingButton.setEnabled(!running);
        pingForm.setEnabled(!running);
    }

    public void open() {
        UI.getCurrent().addWindow(this);
    }
}