blob: e71d8e5af4ec0fff9776c93833929156c324c013 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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 com.intellij.util.net;
import com.google.common.net.HostAndPort;
import com.google.common.net.InetAddresses;
import com.google.common.net.InternetDomainName;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.ui.PortField;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.util.proxy.CommonProxy;
import com.intellij.util.proxy.JavaProxyProperty;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.concurrent.atomic.AtomicReference;
class HttpProxySettingsUi implements ConfigurableUi<HttpConfigurable> {
private JPanel myMainPanel;
private JTextField myProxyLoginTextField;
private JPasswordField myProxyPasswordTextField;
private JCheckBox myProxyAuthCheckBox;
private PortField myProxyPortTextField;
private JTextField myProxyHostTextField;
private JCheckBox myRememberProxyPasswordCheckBox;
private JLabel myProxyLoginLabel;
private JLabel myProxyPasswordLabel;
private JLabel myHostNameLabel;
private JLabel myPortNumberLabel;
private JBRadioButton myAutoDetectProxyRb;
private JBRadioButton myUseHTTPProxyRb;
private JBLabel mySystemProxyDefined;
private JBRadioButton myNoProxyRb;
private JBRadioButton myHTTP;
private JBRadioButton mySocks;
private JButton myClearPasswordsButton;
private JLabel myErrorLabel;
private JButton myCheckButton;
private JBLabel myOtherWarning;
private JLabel myProxyExceptionsLabel;
private JTextArea myProxyExceptions;
private JLabel myNoProxyForLabel;
private JCheckBox myPacUrlCheckBox;
private JTextField myPacUrlTextField;
private volatile boolean myConnectionCheckInProgress;
@Override
public boolean isModified(@NotNull HttpConfigurable settings) {
if (!isValid()) {
return false;
}
return !Comparing.strEqual(myProxyExceptions.getText().trim(), settings.PROXY_EXCEPTIONS) ||
settings.USE_PROXY_PAC != myAutoDetectProxyRb.isSelected() ||
settings.USE_PAC_URL != myPacUrlCheckBox.isSelected() ||
!Comparing.strEqual(settings.PAC_URL, myPacUrlTextField.getText()) ||
settings.USE_HTTP_PROXY != myUseHTTPProxyRb.isSelected() ||
settings.PROXY_AUTHENTICATION != myProxyAuthCheckBox.isSelected() ||
settings.KEEP_PROXY_PASSWORD != myRememberProxyPasswordCheckBox.isSelected() ||
settings.PROXY_TYPE_IS_SOCKS != mySocks.isSelected() ||
!Comparing.strEqual(settings.PROXY_LOGIN, myProxyLoginTextField.getText()) ||
!Comparing.strEqual(settings.getPlainProxyPassword(), new String(myProxyPasswordTextField.getPassword())) ||
settings.PROXY_PORT != myProxyPortTextField.getNumber() ||
!Comparing.strEqual(settings.PROXY_HOST, myProxyHostTextField.getText());
}
public HttpProxySettingsUi(@NotNull final HttpConfigurable settings) {
ButtonGroup group = new ButtonGroup();
group.add(myUseHTTPProxyRb);
group.add(myAutoDetectProxyRb);
group.add(myNoProxyRb);
myNoProxyRb.setSelected(true);
ButtonGroup proxyTypeGroup = new ButtonGroup();
proxyTypeGroup.add(myHTTP);
proxyTypeGroup.add(mySocks);
myHTTP.setSelected(true);
myProxyExceptions.setBorder(UIUtil.getTextFieldBorder());
Boolean property = Boolean.getBoolean(JavaProxyProperty.USE_SYSTEM_PROXY);
mySystemProxyDefined.setVisible(Boolean.TRUE.equals(property));
if (Boolean.TRUE.equals(property)) {
mySystemProxyDefined.setIcon(Messages.getWarningIcon());
mySystemProxyDefined.setFont(mySystemProxyDefined.getFont().deriveFont(Font.BOLD));
mySystemProxyDefined.setUI(new MultiLineLabelUI());
}
myProxyAuthCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
enableProxyAuthentication(myProxyAuthCheckBox.isSelected());
}
});
myPacUrlCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
myPacUrlTextField.setEnabled(myPacUrlCheckBox.isSelected());
}
});
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
enableProxy(myUseHTTPProxyRb.isSelected());
}
};
myUseHTTPProxyRb.addActionListener(listener);
myAutoDetectProxyRb.addActionListener(listener);
myNoProxyRb.addActionListener(listener);
myClearPasswordsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
settings.clearGenericPasswords();
//noinspection DialogTitleCapitalization
Messages.showMessageDialog(myMainPanel, "Proxy passwords were cleared.", "Auto-detected Proxy", Messages.getInformationIcon());
}
});
configureCheckButton();
}
private void configureCheckButton() {
if (HttpConfigurable.getInstance() == null) {
myCheckButton.setVisible(false);
return;
}
myCheckButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
final String title = "Check Proxy Settings";
final String answer = Messages.showInputDialog(myMainPanel, "Warning: your settings will be saved.\n\nEnter any URL to check connection to:",
title, Messages.getQuestionIcon(), "http://", null);
if (StringUtil.isEmptyOrSpaces(answer)) {
return;
}
final HttpConfigurable settings = HttpConfigurable.getInstance();
apply(settings);
final AtomicReference<IOException> exceptionReference = new AtomicReference<IOException>();
myCheckButton.setEnabled(false);
myCheckButton.setText("Check connection (in progress...)");
myConnectionCheckInProgress = true;
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
//already checked for null above
//noinspection ConstantConditions
connection = settings.openHttpConnection(answer);
connection.setReadTimeout(3 * 1000);
connection.setConnectTimeout(3 * 1000);
connection.connect();
final int code = connection.getResponseCode();
if (HttpURLConnection.HTTP_OK != code) {
exceptionReference.set(new IOException("Error code: " + code));
}
}
catch (IOException e) {
exceptionReference.set(e);
}
finally {
if (connection != null) {
connection.disconnect();
}
}
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
myConnectionCheckInProgress = false;
reset(settings); // since password might have been set
Component parent;
if (myMainPanel.isShowing()) {
parent = myMainPanel;
myCheckButton.setText("Check connection");
myCheckButton.setEnabled(canEnableConnectionCheck());
}
else {
IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame();
if (frame == null) {
return;
}
parent = frame.getComponent();
}
//noinspection ThrowableResultOfMethodCallIgnored
final IOException exception = exceptionReference.get();
if (exception == null) {
Messages.showMessageDialog(parent, "Connection successful", title, Messages.getInformationIcon());
}
else {
final String message = exception.getMessage();
if (settings.USE_HTTP_PROXY) {
settings.LAST_ERROR = message;
}
Messages.showErrorDialog(parent, errorText(message));
}
}
});
}
});
}
});
}
private boolean canEnableConnectionCheck() {
return !myNoProxyRb.isSelected() && !myConnectionCheckInProgress;
}
@Override
public void reset(@NotNull HttpConfigurable settings) {
myNoProxyRb.setSelected(true); // default
myAutoDetectProxyRb.setSelected(settings.USE_PROXY_PAC);
myPacUrlCheckBox.setSelected(settings.USE_PAC_URL);
myPacUrlTextField.setText(settings.PAC_URL);
myUseHTTPProxyRb.setSelected(settings.USE_HTTP_PROXY);
myProxyAuthCheckBox.setSelected(settings.PROXY_AUTHENTICATION);
enableProxy(settings.USE_HTTP_PROXY);
myProxyLoginTextField.setText(settings.PROXY_LOGIN);
myProxyPasswordTextField.setText(settings.getPlainProxyPassword());
myProxyPortTextField.setNumber(settings.PROXY_PORT);
myProxyHostTextField.setText(settings.PROXY_HOST);
myProxyExceptions.setText(StringUtil.notNullize(settings.PROXY_EXCEPTIONS));
myRememberProxyPasswordCheckBox.setSelected(settings.KEEP_PROXY_PASSWORD);
mySocks.setSelected(settings.PROXY_TYPE_IS_SOCKS);
myHTTP.setSelected(!settings.PROXY_TYPE_IS_SOCKS);
boolean showError = !StringUtil.isEmptyOrSpaces(settings.LAST_ERROR);
myErrorLabel.setVisible(showError);
myErrorLabel.setText(showError ? errorText(settings.LAST_ERROR) : null);
final String oldStyleText = CommonProxy.getMessageFromProps(CommonProxy.getOldStyleProperties());
myOtherWarning.setVisible(oldStyleText != null);
if (oldStyleText != null) {
myOtherWarning.setText(oldStyleText);
myOtherWarning.setUI(new MultiLineLabelUI());
myOtherWarning.setIcon(Messages.getWarningIcon());
}
}
@NotNull
private static String errorText(@NotNull String s) {
return "Problem with connection: " + s;
}
private boolean isValid() {
if (myUseHTTPProxyRb.isSelected()) {
String host = getText(myProxyHostTextField);
if (host == null) {
return false;
}
try {
HostAndPort parsedHost = HostAndPort.fromString(host);
if (parsedHost.hasPort()) {
return false;
}
host = parsedHost.getHostText();
try {
InetAddresses.forString(host);
return true;
}
catch (IllegalArgumentException e) {
// it is not an IPv4 or IPv6 literal
}
InternetDomainName.from(host);
}
catch (IllegalArgumentException e) {
return false;
}
if (myProxyAuthCheckBox.isSelected()) {
return !StringUtil.isEmptyOrSpaces(myProxyLoginTextField.getText()) && myProxyPasswordTextField.getPassword().length > 0;
}
}
return true;
}
@Override
public void apply(@NotNull HttpConfigurable settings) {
if (!isValid()) {
return;
}
if (isModified(settings)) {
settings.AUTHENTICATION_CANCELLED = false;
}
settings.USE_PROXY_PAC = myAutoDetectProxyRb.isSelected();
settings.USE_PAC_URL = myPacUrlCheckBox.isSelected();
settings.PAC_URL = getText(myPacUrlTextField);
settings.USE_HTTP_PROXY = myUseHTTPProxyRb.isSelected();
settings.PROXY_TYPE_IS_SOCKS = mySocks.isSelected();
settings.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected();
settings.KEEP_PROXY_PASSWORD = myRememberProxyPasswordCheckBox.isSelected();
settings.PROXY_LOGIN = getText(myProxyLoginTextField);
settings.setPlainProxyPassword(new String(myProxyPasswordTextField.getPassword()));
settings.PROXY_EXCEPTIONS = StringUtil.nullize(myProxyExceptions.getText(), true);
settings.PROXY_PORT = myProxyPortTextField.getNumber();
settings.PROXY_HOST = getText(myProxyHostTextField);
}
@Nullable
private static String getText(@NotNull JTextField field) {
return StringUtil.nullize(field.getText(), true);
}
private void enableProxy(boolean enabled) {
myHostNameLabel.setEnabled(enabled);
myPortNumberLabel.setEnabled(enabled);
myProxyHostTextField.setEnabled(enabled);
myProxyPortTextField.setEnabled(enabled);
mySocks.setEnabled(enabled);
myHTTP.setEnabled(enabled);
myProxyExceptions.setEnabled(enabled);
myProxyExceptions.setBackground(myProxyPortTextField.getBackground());
myProxyExceptionsLabel.setEnabled(enabled);
myNoProxyForLabel.setEnabled(enabled);
myProxyAuthCheckBox.setEnabled(enabled);
enableProxyAuthentication(enabled && myProxyAuthCheckBox.isSelected());
myCheckButton.setEnabled(canEnableConnectionCheck());
final boolean autoDetectProxy = myAutoDetectProxyRb.isSelected();
myPacUrlCheckBox.setEnabled(autoDetectProxy);
myClearPasswordsButton.setEnabled(autoDetectProxy);
myPacUrlTextField.setEnabled(autoDetectProxy && myPacUrlCheckBox.isSelected());
}
private void enableProxyAuthentication(boolean enabled) {
myProxyPasswordLabel.setEnabled(enabled);
myProxyLoginLabel.setEnabled(enabled);
myProxyLoginTextField.setEnabled(enabled);
myProxyPasswordTextField.setEnabled(enabled);
myRememberProxyPasswordCheckBox.setEnabled(enabled);
}
@Override
@NotNull
public JComponent getComponent() {
return myMainPanel;
}
}