diff options
Diffstat (limited to 'platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java')
-rw-r--r-- | platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java | 296 |
1 files changed, 159 insertions, 137 deletions
diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java index d51891a8ffe4..0f9855001b63 100644 --- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java +++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java @@ -21,22 +21,28 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; +import com.intellij.util.Base64; import com.intellij.util.SystemProperties; import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.proxy.CommonProxy; import com.intellij.util.proxy.JavaProxyProperty; import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.XmlSerializerUtil; import com.intellij.util.xmlb.annotations.Transient; -import org.apache.commons.codec.binary.Base64; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import gnu.trove.TObjectObjectProcedure; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,75 +54,74 @@ import java.lang.reflect.InvocationTargetException; import java.net.*; import java.util.*; -/** - * Created by IntelliJ IDEA. - * User: stathik - * Date: Oct 7, 2003 - * Time: 3:58:23 PM - * To change this template use Options | File Templates. - */ @State( name = "HttpConfigurable", storages = { - @Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml" ), - @Storage( file = StoragePathMacros.APP_CONFIG + "/proxy.settings.xml" ) + // we use two storages due to backward compatibility, see http://crucible.labs.intellij.net/cru/CR-IC-5142 + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml"), + @Storage(file = StoragePathMacros.APP_CONFIG + "/proxy.settings.xml") }, storageChooser = HttpConfigurable.StorageChooser.class ) -public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent, - ExportableApplicationComponent { +public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ExportableApplicationComponent { public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("idea.connection.timeout", 10000); - private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable"); - public boolean PROXY_TYPE_IS_SOCKS = false; - public boolean USE_HTTP_PROXY = false; - public boolean USE_PROXY_PAC = false; - public volatile transient boolean AUTHENTICATION_CANCELLED = false; - public String PROXY_HOST = ""; + private static final Logger LOG = Logger.getInstance(HttpConfigurable.class); + + public boolean PROXY_TYPE_IS_SOCKS; + public boolean USE_HTTP_PROXY; + public boolean USE_PROXY_PAC; + public volatile transient boolean AUTHENTICATION_CANCELLED; + public String PROXY_HOST; public int PROXY_PORT = 80; - public volatile boolean PROXY_AUTHENTICATION = false; - public volatile String PROXY_LOGIN = ""; - public volatile String PROXY_PASSWORD_CRYPT = ""; - public boolean KEEP_PROXY_PASSWORD = false; + public volatile boolean PROXY_AUTHENTICATION; + public volatile String PROXY_LOGIN; + public volatile String PROXY_PASSWORD_CRYPT; + public boolean KEEP_PROXY_PASSWORD; public transient String LAST_ERROR; - public Map<CommonProxy.HostInfo, ProxyInfo> myGenericPasswords = new HashMap<CommonProxy.HostInfo, ProxyInfo>(); - public Set<CommonProxy.HostInfo> myGenericCancelled = new HashSet<CommonProxy.HostInfo>(); + + private final THashMap<CommonProxy.HostInfo, ProxyInfo> myGenericPasswords = new THashMap<CommonProxy.HostInfo, ProxyInfo>(); + private final Set<CommonProxy.HostInfo> myGenericCancelled = new THashSet<CommonProxy.HostInfo>(); + + public String PROXY_EXCEPTIONS; + public boolean USE_PAC_URL; + public String PAC_URL; + + private transient IdeaWideProxySelector mySelector; + private transient final Object myLock = new Object(); - private IdeaWideProxySelector mySelector; - private IdeaWideAuthenticator myAuthenticator; + + @SuppressWarnings("UnusedDeclaration") public transient Getter<PasswordAuthentication> myTestAuthRunnable = new StaticGetter<PasswordAuthentication>(null); public transient Getter<PasswordAuthentication> myTestGenericAuthRunnable = new StaticGetter<PasswordAuthentication>(null); - public String PROXY_EXCEPTIONS = ""; - public boolean USE_PAC_URL = false; - public String PAC_URL = ""; public static HttpConfigurable getInstance() { return ServiceManager.getService(HttpConfigurable.class); } - public static boolean editConfigurable(final JComponent parent) { - return ShowSettingsUtil.getInstance().editConfigurable(parent, new HTTPProxySettingsPanel(getInstance())); + public static boolean editConfigurable(@Nullable JComponent parent) { + return ShowSettingsUtil.getInstance().editConfigurable(parent, new HttpProxyConfigurable()); } @Override public HttpConfigurable getState() { CommonProxy.isInstalledAssertion(); - final HttpConfigurable state = new HttpConfigurable(); + + HttpConfigurable state = new HttpConfigurable(); XmlSerializerUtil.copyBean(this, state); if (!KEEP_PROXY_PASSWORD) { - state.PROXY_PASSWORD_CRYPT = ""; + state.PROXY_PASSWORD_CRYPT = null; } - correctPasswords(this, state); + correctPasswords(state); return state; } @Override public void initComponent() { mySelector = new IdeaWideProxySelector(this); - myAuthenticator = new IdeaWideAuthenticator(this); - final String name = getClass().getName(); + String name = getClass().getName(); CommonProxy.getInstance().setCustom(name, mySelector); - CommonProxy.getInstance().setCustomAuth(name, myAuthenticator); + CommonProxy.getInstance().setCustomAuth(name, new IdeaWideAuthenticator(this)); } @NotNull @@ -137,62 +142,64 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return getClass().getName(); } - private void correctPasswords(HttpConfigurable from, HttpConfigurable to) { + private void correctPasswords(@NotNull HttpConfigurable to) { synchronized (myLock) { - to.myGenericPasswords = new HashMap<CommonProxy.HostInfo, ProxyInfo>(); - for (Map.Entry<CommonProxy.HostInfo, ProxyInfo> entry : from.myGenericPasswords.entrySet()) { - if (Boolean.TRUE.equals(entry.getValue().isStore())) { - to.myGenericPasswords.put(entry.getKey(), entry.getValue()); + to.myGenericPasswords.retainEntries(new TObjectObjectProcedure<CommonProxy.HostInfo, ProxyInfo>() { + @Override + public boolean execute(CommonProxy.HostInfo hostInfo, ProxyInfo proxyInfo) { + return proxyInfo.isStore(); } - } + }); } } @Override - public void loadState(HttpConfigurable state) { + public void loadState(@NotNull HttpConfigurable state) { XmlSerializerUtil.copyBean(state, this); if (!KEEP_PROXY_PASSWORD) { - PROXY_PASSWORD_CRYPT = ""; + PROXY_PASSWORD_CRYPT = null; } - correctPasswords(state, this); + correctPasswords(this); } - public boolean isGenericPasswordCanceled(final String host, final int port) { + public boolean isGenericPasswordCanceled(@NotNull String host, int port) { synchronized (myLock) { - return myGenericCancelled.contains(Pair.create(host, port)); + return myGenericCancelled.contains(new CommonProxy.HostInfo(null, host, port)); } } public void setGenericPasswordCanceled(final String host, final int port) { synchronized (myLock) { - myGenericCancelled.add(new CommonProxy.HostInfo("", host, port)); + myGenericCancelled.add(new CommonProxy.HostInfo(null, host, port)); } } - public PasswordAuthentication getGenericPassword(final String host, final int port) { + public PasswordAuthentication getGenericPassword(@NotNull String host, int port) { final ProxyInfo proxyInfo; synchronized (myLock) { - proxyInfo = myGenericPasswords.get(new CommonProxy.HostInfo("", host, port)); + proxyInfo = myGenericPasswords.get(new CommonProxy.HostInfo(null, host, port)); + } + if (proxyInfo == null) { + return null; } - if (proxyInfo == null) return null; return new PasswordAuthentication(proxyInfo.getUsername(), decode(String.valueOf(proxyInfo.getPasswordCrypt())).toCharArray()); } - public void putGenericPassword(final String host, final int port, final PasswordAuthentication authentication, final boolean remember) { - final PasswordAuthentication coded = new PasswordAuthentication(authentication.getUserName(), encode(String.valueOf(authentication.getPassword())).toCharArray()); + public void putGenericPassword(final String host, final int port, @NotNull PasswordAuthentication authentication, boolean remember) { + PasswordAuthentication coded = new PasswordAuthentication(authentication.getUserName(), encode(String.valueOf(authentication.getPassword())).toCharArray()); synchronized (myLock) { - myGenericPasswords.put(new CommonProxy.HostInfo("", host, port), new ProxyInfo(remember, coded.getUserName(), String.valueOf( - coded.getPassword()))); + myGenericPasswords.put(new CommonProxy.HostInfo(null, host, port), new ProxyInfo(remember, coded.getUserName(), String.valueOf(coded.getPassword()))); } } @Transient + @Nullable public String getPlainProxyPassword() { - return decode(PROXY_PASSWORD_CRYPT); + return PROXY_PASSWORD_CRYPT == null ? null : decode(PROXY_PASSWORD_CRYPT); } - private String decode(String value) { - return new String(new Base64().decode(value.getBytes())); + private static String decode(String value) { + return new String(Base64.decode(value)); } @Transient @@ -200,42 +207,50 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab PROXY_PASSWORD_CRYPT = encode(password); } - private String encode(String password) { - return new String(new Base64().encode(password.getBytes())); + private static String encode(String password) { + return new String(Base64.encode(password.getBytes(CharsetToolkit.UTF8_CHARSET))); } public PasswordAuthentication getGenericPromptedAuthentication(final String prefix, final String host, final String prompt, final int port, final boolean remember) { if (ApplicationManager.getApplication().isUnitTestMode()) { return myTestGenericAuthRunnable.get(); } - final PasswordAuthentication[] value = new PasswordAuthentication[1]; - final Runnable runnable = new Runnable() { + + final Ref<PasswordAuthentication> value = Ref.create(); + runAboveAll(new Runnable() { + @Override public void run() { - if (isGenericPasswordCanceled(host, port)) return; - final PasswordAuthentication password = getGenericPassword(host, port); + if (isGenericPasswordCanceled(host, port)) { + return; + } + + PasswordAuthentication password = getGenericPassword(host, port); if (password != null) { - value[0] = password; + value.set(password); return; } - final AuthenticationDialog dlg = new AuthenticationDialog(PopupUtil.getActiveComponent(), prefix + host, - "Please enter credentials for: " + prompt, "", "", remember); - dlg.show(); - if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) { - final AuthenticationPanel panel = dlg.getPanel(); - final boolean remember1 = remember && panel.isRememberPassword(); - value[0] = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); - putGenericPassword(host, port, value[0], remember1); - } else { + + AuthenticationDialog dialog = new AuthenticationDialog(PopupUtil.getActiveComponent(), prefix + host, + "Please enter credentials for: " + prompt, "", "", remember); + dialog.show(); + if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + AuthenticationPanel panel = dialog.getPanel(); + PasswordAuthentication passwordAuthentication = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); + putGenericPassword(host, port, passwordAuthentication, remember && panel.isRememberPassword()); + value.set(passwordAuthentication); + } + else { setGenericPasswordCanceled(host, port); } } - }; - runAboveAll(runnable); - return value[0]; + }); + return value.get(); } public PasswordAuthentication getPromptedAuthentication(final String host, final String prompt) { - if (AUTHENTICATION_CANCELLED) return null; + if (AUTHENTICATION_CANCELLED) { + return null; + } final String password = getPlainProxyPassword(); if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password)) { return new PasswordAuthentication(PROXY_LOGIN, password.toCharArray()); @@ -248,63 +263,63 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab if (ApplicationManager.getApplication().isUnitTestMode()) { return myTestGenericAuthRunnable.get(); } - final String login = PROXY_LOGIN == null ? "" : PROXY_LOGIN; final PasswordAuthentication[] value = new PasswordAuthentication[1]; - final Runnable runnable = new Runnable() { + runAboveAll(new Runnable() { + @Override public void run() { - if (AUTHENTICATION_CANCELLED) return; + if (AUTHENTICATION_CANCELLED) { + return; + } + // password might have changed, and the check below is for that - final String password = getPlainProxyPassword(); + String password = getPlainProxyPassword(); if (PROXY_AUTHENTICATION && ! StringUtil.isEmptyOrSpaces(PROXY_LOGIN) && ! StringUtil.isEmptyOrSpaces(password)) { value[0] = new PasswordAuthentication(PROXY_LOGIN, password.toCharArray()); return; } - final AuthenticationDialog dlg = new AuthenticationDialog(PopupUtil.getActiveComponent(), "Proxy authentication: " + host, - "Please enter credentials for: " + prompt, login, "", KEEP_PROXY_PASSWORD); - dlg.show(); - if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) { + AuthenticationDialog dialog = new AuthenticationDialog(PopupUtil.getActiveComponent(), "Proxy authentication: " + host, + "Please enter credentials for: " + prompt, PROXY_LOGIN, "", KEEP_PROXY_PASSWORD); + dialog.show(); + if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) { PROXY_AUTHENTICATION = true; - final AuthenticationPanel panel = dlg.getPanel(); + AuthenticationPanel panel = dialog.getPanel(); KEEP_PROXY_PASSWORD = panel.isRememberPassword(); - PROXY_LOGIN = panel.getLogin(); + PROXY_LOGIN = StringUtil.nullize(panel.getLogin()); setPlainProxyPassword(String.valueOf(panel.getPassword())); value[0] = new PasswordAuthentication(panel.getLogin(), panel.getPassword()); } else { AUTHENTICATION_CANCELLED = true; } } - }; - runAboveAll(runnable); + }); return value[0]; } - @SuppressWarnings("MethodMayBeStatic") - private void runAboveAll(final Runnable runnable) { + private static void runAboveAll(@NotNull final Runnable runnable) { final Runnable throughSwing = new Runnable() { @Override public void run() { if (SwingUtilities.isEventDispatchThread()) { runnable.run(); - return; } - try { - SwingUtilities.invokeAndWait(runnable); - } - catch (InterruptedException e) { - LOG.info(e); - } - catch (InvocationTargetException e) { - LOG.info(e); + else { + try { + SwingUtilities.invokeAndWait(runnable); + } + catch (InterruptedException e) { + LOG.info(e); + } + catch (InvocationTargetException e) { + LOG.info(e); + } } } }; - if (ProgressManager.getInstance().getProgressIndicator() != null) { - if (ProgressManager.getInstance().getProgressIndicator().isModal()) { - WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(runnable); - } else { - throughSwing.run(); - } - } else { + ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + if (progressIndicator != null && progressIndicator.isModal()) { + WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(runnable); + } + else { throughSwing.run(); } } @@ -312,22 +327,23 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab //these methods are preserved for compatibility with com.intellij.openapi.project.impl.IdeaServerSettings @Deprecated public void readExternal(Element element) throws InvalidDataException { + //noinspection ConstantConditions loadState(XmlSerializer.deserialize(element, HttpConfigurable.class)); } @Deprecated public void writeExternal(Element element) throws WriteExternalException { XmlSerializer.serializeInto(getState(), element); - if (USE_PROXY_PAC && USE_HTTP_PROXY && ! ApplicationManager.getApplication().isDisposed()) { + if (USE_PROXY_PAC && USE_HTTP_PROXY && !ApplicationManager.getApplication().isDisposed()) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { - final IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); + IdeFrame frame = IdeFocusManager.findInstance().getLastFocusedFrame(); if (frame != null) { USE_PROXY_PAC = false; Messages.showMessageDialog(frame.getComponent(), "Proxy: both 'use proxy' and 'autodetect proxy' settings were set." + "\nOnly one of these options should be selected.\nPlease re-configure.", - "Proxy setup", Messages.getWarningIcon()); + "Proxy Setup", Messages.getWarningIcon()); editConfigurable(frame.getComponent()); } } @@ -344,51 +360,52 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab * @param url URL for HTTP connection * @throws IOException */ - public void prepareURL (String url) throws IOException { - //setAuthenticator(); - CommonProxy.isInstalledAssertion(); - - final URLConnection connection = openConnection(url); + public void prepareURL(@NotNull String url) throws IOException { + URLConnection connection = openConnection(url); try { connection.connect(); connection.getInputStream(); } - catch (Throwable e) { - if (e instanceof IOException) { - throw (IOException)e; - } - } finally { + catch (IOException e) { + throw e; + } + catch (Throwable ignored) { + } + finally { if (connection instanceof HttpURLConnection) { ((HttpURLConnection)connection).disconnect(); } } } + @NotNull public URLConnection openConnection(@NotNull String location) throws IOException { CommonProxy.isInstalledAssertion(); final URL url = new URL(location); URLConnection urlConnection = null; final List<Proxy> proxies = CommonProxy.getInstance().select(url); - if (proxies == null || proxies.isEmpty()) { + if (ContainerUtil.isEmpty(proxies)) { urlConnection = url.openConnection(); - } else { - IOException ioe = null; + } + else { + IOException exception = null; for (Proxy proxy : proxies) { try { urlConnection = url.openConnection(proxy); - } catch (IOException e) { + } + catch (IOException e) { // continue iteration - ioe = e; + exception = e; } } - if (urlConnection == null && ioe != null) { - throw ioe; + if (urlConnection == null && exception != null) { + throw exception; } } - if (urlConnection != null) { - urlConnection.setReadTimeout(CONNECTION_TIMEOUT); - urlConnection.setConnectTimeout(CONNECTION_TIMEOUT); - } + + assert urlConnection != null; + urlConnection.setReadTimeout(CONNECTION_TIMEOUT); + urlConnection.setConnectTimeout(CONNECTION_TIMEOUT); return urlConnection; } @@ -461,12 +478,15 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return result; } - public static boolean isRealProxy(Proxy proxy) { - return ! Proxy.NO_PROXY.equals(proxy) && ! Proxy.Type.DIRECT.equals(proxy.type()); + public static boolean isRealProxy(@NotNull Proxy proxy) { + return !Proxy.NO_PROXY.equals(proxy) && !Proxy.Type.DIRECT.equals(proxy.type()); } + @NotNull public static List<String> convertArguments(@NotNull final List<KeyValue<String, String>> list) { - if (list.isEmpty()) return Collections.emptyList(); + if (list.isEmpty()) { + return Collections.emptyList(); + } final List<String> result = new ArrayList<String>(list.size()); for (KeyValue<String, String> value : list) { result.add("-D" + value.getKey() + "=" + value.getValue()); @@ -481,7 +501,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab } } - public void removeGeneric(CommonProxy.HostInfo info) { + public void removeGeneric(@NotNull CommonProxy.HostInfo info) { synchronized (myLock) { myGenericPasswords.remove(info); } @@ -518,6 +538,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab public String myUsername; public String myPasswordCrypt; + @SuppressWarnings("UnusedDeclaration") public ProxyInfo() { } @@ -547,6 +568,7 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab return myPasswordCrypt; } + @SuppressWarnings("UnusedDeclaration") public void setPasswordCrypt(String passwordCrypt) { myPasswordCrypt = passwordCrypt; } |