de.dal33t.powerfolder.ui.preferences.NetworkSettingsTab.java Source code

Java tutorial

Introduction

Here is the source code for de.dal33t.powerfolder.ui.preferences.NetworkSettingsTab.java

Source

/*
 * Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
 *
 * This file is part of PowerFolder.
 *
 * PowerFolder is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * PowerFolder 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
 *
 * $Id$
 */
package de.dal33t.powerfolder.ui.preferences;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.StringTokenizer;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import de.dal33t.powerfolder.ConfigurationEntry;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.NetworkingMode;
import de.dal33t.powerfolder.PFComponent;
import de.dal33t.powerfolder.net.ConnectionListener;
import de.dal33t.powerfolder.transfer.TransferManager;
import de.dal33t.powerfolder.ui.action.BaseAction;
import de.dal33t.powerfolder.ui.panel.LineSpeedSelectionPanel;
import de.dal33t.powerfolder.ui.util.SimpleComponentFactory;
import de.dal33t.powerfolder.util.StringUtils;
import de.dal33t.powerfolder.util.Translation;
import de.dal33t.powerfolder.util.net.UDTSocket;
import de.dal33t.powerfolder.util.os.Win32.FirewallUtil;

public class NetworkSettingsTab extends PFComponent implements PreferenceTab {

    private JPanel panel;
    private JComboBox<String> networkingModeCombo;
    private JCheckBox relayedConnectionCB;
    private JCheckBox udtConnectionCB;
    private LineSpeedSelectionPanel wanSpeed;
    private LineSpeedSelectionPanel lanSpeed;
    private JButton httpProxyButton;
    private JCheckBox randomPortCB;
    private JTextField advPortTF;
    private JCheckBox openPortCB;
    private JComboBox bindAddressCombo;
    private LANList lanList;

    private boolean needsRestart;

    public NetworkSettingsTab(Controller controller) {
        super(controller);
        initComponents();
    }

    public String getTabName() {
        return Translation.getTranslation("exp.preferences.network.title");
    }

    public boolean needsRestart() {
        return needsRestart;
    }

    public void undoChanges() {

    }

    public boolean validate() {
        return true;
    }

    private void initComponents() {
        String[] options = new String[NetworkingMode.values().length];
        options[NetworkingMode.PRIVATEMODE.ordinal()] = Translation.getTranslation("general.network_mode.private");
        options[NetworkingMode.LANONLYMODE.ordinal()] = Translation.getTranslation("general.network_mode.lan_only");
        options[NetworkingMode.SERVERONLYMODE.ordinal()] = Translation
                .getTranslation("general.network_mode.server_only");
        networkingModeCombo = new JComboBox<>(options);

        NetworkingMode currentNetworkingMode = getController().getNetworkingMode();
        String tooltip = getTooltip(currentNetworkingMode);
        networkingModeCombo.setSelectedIndex(currentNetworkingMode.ordinal());
        networkingModeCombo.setToolTipText(tooltip);
        networkingModeCombo.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                NetworkingMode selectedNetworkingMode = NetworkingMode.values()[networkingModeCombo
                        .getSelectedIndex()];
                networkingModeCombo.setToolTipText(getTooltip(selectedNetworkingMode));
                enableDisableComponents(NetworkingMode.LANONLYMODE == selectedNetworkingMode);
            }
        });

        String port = ConfigurationEntry.NET_BIND_PORT.getValue(getController());
        if (port == null) {
            port = Integer.toString(ConnectionListener.DEFAULT_PORT);
        }
        advPortTF = new JTextField(port) {
            protected Document createDefaultModel() {
                return new NumberAndCommaDocument();
            }
        };
        advPortTF.setToolTipText(Translation.getTranslation("exp.preferences.network.adv_port_tooltip"));
        randomPortCB = SimpleComponentFactory
                .createCheckBox(Translation.getTranslation("exp.preferences.network.random_port"));
        randomPortCB.setToolTipText(Translation.getTranslation("exp.preferences.network.random_port_tooltip"));
        randomPortCB.setSelected(ConfigurationEntry.NET_BIND_RANDOM_PORT.getValueBoolean(getController()));

        advPortTF.setEnabled(!randomPortCB.isSelected());

        randomPortCB.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                advPortTF.setEnabled(!randomPortCB.isSelected());
            }
        });

        if (FirewallUtil.isFirewallAccessible()) {
            openPortCB = SimpleComponentFactory
                    .createCheckBox(Translation.getTranslation("exp.preferences.network.open_port"));
            openPortCB.setToolTipText(Translation.getTranslation("exp.preferences.network.open_port_tooltip"));
            openPortCB.setSelected(ConfigurationEntry.NET_FIREWALL_OPENPORT.getValueBoolean(getController()));
        }

        relayedConnectionCB = SimpleComponentFactory
                .createCheckBox(Translation.getTranslation("exp.preferences.network.use_relayed_connections"));
        relayedConnectionCB
                .setSelected(ConfigurationEntry.RELAYED_CONNECTIONS_ENABLED.getValueBoolean(getController()));

        udtConnectionCB = SimpleComponentFactory
                .createCheckBox(Translation.getTranslation("exp.preferences.network.use_relayed_connections"));
        udtConnectionCB.setSelected(ConfigurationEntry.UDT_CONNECTIONS_ENABLED.getValueBoolean(getController()));

        HttpProxyAction action = new HttpProxyAction(getController());
        httpProxyButton = new JButton(action);

        wanSpeed = new LineSpeedSelectionPanel(getController(), true, true);

        lanSpeed = new LineSpeedSelectionPanel(getController(), false, true);

        enableDisableComponents(getController().isLanOnly());

        TransferManager tm = getController().getTransferManager();

        wanSpeed.setSpeedKBPS(ConfigurationEntry.TRANSFER_LIMIT_AUTODETECT.getValueBoolean(getController()),
                tm.getUploadCPSForWAN() / 1024, tm.getDownloadCPSForWAN() / 1024);

        lanSpeed.setSpeedKBPS(false, tm.getUploadCPSForLAN() / 1024, tm.getDownloadCPSForLAN() / 1024);

        String cfgBind = ConfigurationEntry.NET_BIND_ADDRESS.getValue(getController());
        bindAddressCombo = new JComboBox();
        bindAddressCombo.addItem(Translation.getTranslation("exp.preferences.network.bind_any"));
        // Fill in all known InetAddresses of this machine
        try {
            Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
            while (e.hasMoreElements()) {
                NetworkInterface ni = e.nextElement();
                Enumeration<InetAddress> ie = ni.getInetAddresses();
                while (ie.hasMoreElements()) {
                    InetAddress addr = ie.nextElement();
                    if (!(addr instanceof Inet4Address)) {
                        continue;
                    }
                    bindAddressCombo.addItem(new InterfaceChoice(ni, addr));
                    if (!StringUtils.isEmpty(cfgBind)) {
                        if (addr.getHostAddress().equals(cfgBind)) {
                            bindAddressCombo.setSelectedIndex(bindAddressCombo.getItemCount() - 1);
                        }
                    }
                }
            }
        } catch (SocketException e1) {
            logWarning("SocketException. " + e1);
        } catch (Error e1) {
            logWarning("Error. " + e1);
        }

        lanList = new LANList(getController());
        lanList.load();
    }

    private void enableDisableComponents(boolean lanOnly) {
        relayedConnectionCB.setEnabled(!lanOnly);
        udtConnectionCB.setEnabled(!lanOnly && UDTSocket.isSupported());
        udtConnectionCB.setVisible(UDTSocket.isSupported());
        wanSpeed.setEnabled(!lanOnly);
    }

    /**
     * Creates the JPanel for advanced settings
     *
     * @return the created panel
     */
    public JPanel getUIPanel() {
        if (panel == null) {
            FormLayout layout;
            if (getController().isBackupOnly()) {
                layout = new FormLayout("right:pref, 3dlu, 140dlu, pref:grow",
                        "pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 6dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref");
            } else {
                // Extra pref for useOnlineStorageCB.
                layout = new FormLayout("right:pref, 3dlu, 140dlu, pref:grow",
                        "pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref, 3dlu, pref");
            }
            PanelBuilder builder = new PanelBuilder(layout);
            builder.setBorder(Borders.createEmptyBorder("3dlu, 3dlu, 3dlu, 3dlu"));
            CellConstraints cc = new CellConstraints();

            int row = 1;
            builder.addLabel(Translation.getTranslation("exp.preferences.network_mode_name"), cc.xy(1, row));
            builder.add(networkingModeCombo, cc.xy(3, row));

            row += 2;
            builder.add(relayedConnectionCB, cc.xy(3, row));

            row += 2;
            builder.add(udtConnectionCB, cc.xy(3, row));

            row += 2;
            builder.add(ButtonBarFactory.buildLeftAlignedBar(httpProxyButton), cc.xy(3, row));

            row += 2;
            builder.addLabel(Translation.getTranslation("exp.preferences.network.line_settings"),
                    cc.xywh(1, row, 1, 1, "default, top"));
            builder.add(wanSpeed.getUiComponent(), cc.xyw(3, row, 2));

            row += 2;
            builder.addLabel(Translation.getTranslation("exp.preferences.network.lan_line_settings"),
                    cc.xywh(1, row, 1, 1, "default, top"));
            builder.add(lanSpeed.getUiComponent(), cc.xyw(3, row, 2));

            row += 2;
            builder.addLabel(Translation.getTranslation("exp.preferences.network.adv_port"), cc.xy(1, row))
                    .setToolTipText(Translation.getTranslation("exp.preferences.network.adv_port_tooltip"));
            builder.add(advPortTF, cc.xy(3, row));

            row += 2;
            builder.add(randomPortCB, cc.xy(3, row));

            if (FirewallUtil.isFirewallAccessible()) {
                row += 2;
                builder.add(openPortCB, cc.xy(3, row));
            }

            row += 2;
            builder.addLabel(Translation.getTranslation("exp.preferences.network.bind"), cc.xy(1, row))
                    .setToolTipText(Translation.getTranslation("exp.preferences.network.bind_tooltip"));
            builder.add(bindAddressCombo, cc.xy(3, row));

            row += 2;
            builder.addLabel(Translation.getTranslation("exp.preferences.network.ip_lan_list"),
                    cc.xywh(1, row, 1, 1, "default, top"));
            builder.add(lanList.getUIPanel(), cc.xy(3, row));

            panel = builder.getPanel();
        }
        return panel;
    }

    private static Component pairPanel(JComponent left, JComponent right) {
        FormLayout layout = new FormLayout("pref, 3dlu, pref", "pref");
        PanelBuilder builder = new PanelBuilder(layout);
        CellConstraints cc = new CellConstraints();
        builder.add(left, cc.xy(1, 1));
        builder.add(right, cc.xy(3, 1));
        return builder.getPanel();
    }

    /**
     * Saves the network settings.
     */
    public void save() {

        // Check for correctly entered port values
        try {
            // Check if it's a comma-separated list of parseable numbers
            String port = advPortTF.getText();
            StringTokenizer st = new StringTokenizer(port, ",");
            while (st.hasMoreTokens()) {
                int p = Integer.parseInt(st.nextToken());
                if (p < 0 || p > 65535) {
                    throw new NumberFormatException("Port out of range [0,65535]");
                }
            }

            // Check if only one port was given which is the default port
            if (ConfigurationEntry.NET_BIND_PORT.getValue(getController()) == null) {
                try {
                    int portnum = Integer.parseInt(port);
                    if (portnum != ConnectionListener.DEFAULT_PORT) {
                        needsRestart = true;
                    }
                } catch (NumberFormatException e) {
                }
            }
            // Only compare with old value if the things above don't match
            if (!needsRestart) {
                // Check if the value actually changed
                if (!port.equals(ConfigurationEntry.NET_BIND_PORT.getValue(getController()))) {
                    needsRestart = true;
                }
            }

            ConfigurationEntry.NET_BIND_PORT.setValue(getController(), port);
        } catch (NumberFormatException e) {
            logWarning("Unparsable port number");
        }

        if (FirewallUtil.isFirewallAccessible()) {
            boolean current = ConfigurationEntry.NET_FIREWALL_OPENPORT.getValueBoolean(getController());
            if (current != openPortCB.isSelected()) {
                ConfigurationEntry.NET_FIREWALL_OPENPORT.setValue(getController(),
                        String.valueOf(openPortCB.isSelected()));
                needsRestart = true;
            }
        }

        boolean current = ConfigurationEntry.NET_BIND_RANDOM_PORT.getValueBoolean(getController());
        if (current != randomPortCB.isSelected()) {
            ConfigurationEntry.NET_BIND_RANDOM_PORT.setValue(getController(),
                    String.valueOf(randomPortCB.isSelected()));
            needsRestart = true;
        }

        NetworkingMode netMode = NetworkingMode.values()[networkingModeCombo.getSelectedIndex()];
        getController().setNetworkingMode(netMode);
        TransferManager tm = getController().getTransferManager();
        ConfigurationEntry.TRANSFER_LIMIT_AUTODETECT.setValue(getController(), wanSpeed.isAutomatic());
        if (wanSpeed.isAutomatic()) {
            //Update the automatic rates.
            getController().getThreadPool().execute(tm.getRecalculateAutomaticRate());
        } else {
            tm.setUploadCPSForWAN(wanSpeed.getUploadSpeedKBPS());
            tm.setDownloadCPSForWAN(wanSpeed.getDownloadSpeedKBPS());
        }

        tm.setUploadCPSForLAN(lanSpeed.getUploadSpeedKBPS());
        tm.setDownloadCPSForLAN(lanSpeed.getDownloadSpeedKBPS());

        ConfigurationEntry.RELAYED_CONNECTIONS_ENABLED.setValue(getController(),
                String.valueOf(relayedConnectionCB.isSelected()));
        ConfigurationEntry.UDT_CONNECTIONS_ENABLED.setValue(getController(),
                String.valueOf(udtConnectionCB.isSelected()));

        String cfgBind = ConfigurationEntry.NET_BIND_ADDRESS.getValue(getController());
        Object bindObj = bindAddressCombo.getSelectedItem();
        if (bindObj instanceof String) { // Selected ANY
            if (!StringUtils.isEmpty(cfgBind)) {
                ConfigurationEntry.NET_BIND_ADDRESS.removeValue(getController());
                needsRestart = true;
            }
        } else {
            InetAddress addr = ((InterfaceChoice) bindObj).getAddress();
            if (!addr.getHostAddress().equals(cfgBind)) {
                ConfigurationEntry.NET_BIND_ADDRESS.setValue(getController(), addr.getHostAddress());
                needsRestart = true;
            }
        }

        // LAN list
        needsRestart |= lanList.save();
    }

    private static String getTooltip(NetworkingMode nm) {
        if (nm == NetworkingMode.LANONLYMODE) {
            return Translation.getTranslation("exp.preferences.network.lan_only_tooltip");
        } else if (nm == NetworkingMode.PRIVATEMODE) {
            return Translation.getTranslation("exp.preferences.network.private_tooltip");
        } else if (nm == NetworkingMode.SERVERONLYMODE) {
            return Translation.getTranslation("exp.preferences.network.server_only_tooltip");
        }
        return null;
    }

    private static class HttpProxyAction extends BaseAction {
        private HttpProxyAction(Controller controller) {
            super("action_proxy", controller);

        }

        public void actionPerformed(ActionEvent e) {
            new HTTPProxySettingsDialog(getController()).open();
        }
    }

    /**
     * Accepts oly digits and commas
     *
     * @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc</a>
     */
    private static class NumberAndCommaDocument extends PlainDocument {
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {

            if (str == null) {
                return;
            }
            StringBuilder b = new StringBuilder();
            char[] chars = str.toCharArray();
            for (char aChar : chars) {
                if (Character.isDigit(aChar) || aChar == ',') {
                    b.append(aChar);
                }
            }
            super.insertString(offs, b.toString(), a);
        }
    }

    private static class InterfaceChoice {
        private InetAddress address;
        private String showString;

        private InterfaceChoice(NetworkInterface netInterface, InetAddress address) {
            this.address = address;

            StringBuilder sb = new StringBuilder();
            if (address.getAddress() != null) {
                for (int i = 0; i < address.getAddress().length; i++) {
                    if (i > 0) {
                        sb.append('.');
                    }
                    sb.append(address.getAddress()[i] & 0xff);
                }
            }
            sb.append(" / ");
            if (StringUtils.isNotBlank(netInterface.getDisplayName())) {
                sb.append(netInterface.getDisplayName().trim());
            }
            showString = sb.toString();
        }

        public String toString() {
            return showString;
        }

        public InetAddress getAddress() {
            return address;
        }
    }
}