Use HttpRequests to fix IDEA-131621

checkPluginsHost — don't load twice versions info (we still parse it twice)
ensure that we download plugin under determinate progress
This commit is contained in:
Vladimir Krivosheev
2014-11-12 16:56:47 +01:00
parent 73c2ce167e
commit e402e8a574
7 changed files with 168 additions and 224 deletions
@@ -16,6 +16,7 @@
package com.intellij.ide.plugins;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.xml.sax.Attributes;
@@ -24,9 +25,8 @@ import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
class RepositoryContentHandler extends DefaultHandler {
public class RepositoryContentHandler extends DefaultHandler {
@NonNls public static final String CATEGORY = "category";
@NonNls public static final String IDEA_PLUGIN = "idea-plugin";
@NonNls public static final String NAME = "name";
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -39,7 +39,6 @@ import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.List;
import java.util.zip.GZIPInputStream;
/**
* @author stathik
@@ -52,24 +51,6 @@ public class RepositoryHelper {
return loadPluginsFromRepository(indicator, null);
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@NotNull
public static InputStream getConnectionInputStream(@NotNull URLConnection connection) throws IOException {
InputStream inputStream = connection.getInputStream();
if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
try {
return new GZIPInputStream(inputStream);
}
catch (IOException e) {
inputStream.close();
throw e;
}
}
else {
return inputStream;
}
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable final ProgressIndicator indicator, @Nullable BuildNumber buildnumber) throws Exception {
final ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
@@ -83,6 +64,7 @@ public class RepositoryHelper {
final File pluginListFile = new File(PathManager.getPluginsPath(), PLUGIN_LIST_FILE);
if (pluginListFile.length() > 0) {
try {
//noinspection SpellCheckingInspection
url = url + "&crc32=" + Files.hash(pluginListFile, Hashing.crc32()).toString();
}
catch (NoSuchMethodError e) {
@@ -91,15 +73,12 @@ public class RepositoryHelper {
}
}
return HttpRequests.request(url).supportGzip(true).get(new ThrowableConvertor<URLConnection, List<IdeaPluginDescriptor>, Exception>() {
return HttpRequests.request(url).get(new ThrowableConvertor<URLConnection, List<IdeaPluginDescriptor>, Exception>() {
@Override
public List<IdeaPluginDescriptor> convert(URLConnection connection) throws Exception {
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
}
connection.connect();
if (indicator != null) {
indicator.checkCanceled();
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
}
if (connection instanceof HttpURLConnection && ((HttpURLConnection)connection).getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
@@ -107,6 +86,7 @@ public class RepositoryHelper {
}
if (indicator != null) {
indicator.checkCanceled();
indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins"));
}
return readPluginsStream(connection, indicator, PLUGIN_LIST_FILE);
@@ -114,11 +94,11 @@ public class RepositoryHelper {
});
}
private synchronized static List<IdeaPluginDescriptor> readPluginsStream(@NotNull URLConnection connection,
@Nullable ProgressIndicator indicator,
@NotNull String file) throws Exception {
public synchronized static List<IdeaPluginDescriptor> readPluginsStream(@NotNull URLConnection connection,
@Nullable ProgressIndicator indicator,
@NotNull String file) throws Exception {
File localFile;
InputStream input = getConnectionInputStream(connection);
InputStream input = HttpRequests.getInputStream(connection);
try {
localFile = createLocalPluginsDescriptions(file);
OutputStream output = new FileOutputStream(localFile);
@@ -159,10 +139,6 @@ public class RepositoryHelper {
return temp;
}
public static List<IdeaPluginDescriptor> loadPluginsFromDescription(@NotNull URLConnection connection, @Nullable ProgressIndicator indicator) throws Exception {
return readPluginsStream(connection, indicator, "host.xml");
}
public static String getDownloadUrl() {
return ApplicationInfoImpl.getShadowInstance().getPluginsDownloadUrl() + "?action=download&id=";
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2009 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.ide.reporter;
public class ConnectionException extends Exception {
public ConnectionException(String message) {
super(message);
}
public ConnectionException(Throwable cause) {
super(cause);
}
public ConnectionException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -25,15 +25,15 @@ import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.util.Consumer;
import com.intellij.util.HttpRequests;
import com.intellij.util.PathUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.ThrowableConvertor;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NonNls;
@@ -41,7 +41,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.List;
@@ -92,7 +91,7 @@ public class PluginDownloader {
return prepareToInstall(progressIndicator, myBuildNumber);
}
public boolean prepareToInstall(@Nullable ProgressIndicator progressIndicator, @Nullable BuildNumber forBuildNumber) throws IOException {
public boolean prepareToInstall(@NotNull ProgressIndicator progressIndicator, @Nullable BuildNumber forBuildNumber) throws IOException {
if (myFile != null) {
return true;
}
@@ -226,65 +225,54 @@ public class PluginDownloader {
}
}
private File downloadPlugin(@Nullable final ProgressIndicator progressIndicator) throws IOException {
final File pluginsTemp = new File(PathManager.getPluginTempPath());
@NotNull
private File downloadPlugin(@NotNull final ProgressIndicator progressIndicator) throws IOException {
File pluginsTemp = new File(PathManager.getPluginTempPath());
if (!pluginsTemp.exists() && !pluginsTemp.mkdirs()) {
throw new IOException(IdeBundle.message("error.cannot.create.temp.dir", pluginsTemp));
}
final File file = FileUtil.createTempFile(pluginsTemp, "plugin_", "_download", true, false);
if (progressIndicator != null) {
progressIndicator.setText(IdeBundle.message("progress.connecting"));
}
progressIndicator.checkCanceled();
progressIndicator.setText(IdeBundle.message("progress.downloading.plugin", getPluginName()));
URLConnection connection = null;
try {
Pair<URLConnection, String> result = HttpRequests.openConnection(myPluginUrl, false);
if (result.second != null) {
myPluginUrl = result.second;
return HttpRequests.request(myPluginUrl).supportGzip(false).effectiveUrlConsumer(new Consumer<String>() {
@Override
public void consume(String url) {
myPluginUrl = url;
}
connection = result.first;
}).get(new ThrowableConvertor<URLConnection, File, IOException>() {
@Override
public File convert(URLConnection connection) throws IOException {
progressIndicator.checkCanceled();
final InputStream is = (ApplicationManager.getApplication() != null)
? UrlConnectionUtil.getConnectionInputStream(connection, progressIndicator)
: connection.getInputStream();
if (is == null) {
throw new IOException("Failed to open connection");
}
if (progressIndicator != null && ApplicationManager.getApplication() != null) {
progressIndicator.setText(IdeBundle.message("progress.downloading.plugin", getPluginName()));
}
try {
final OutputStream fos = new BufferedOutputStream(new FileOutputStream(file, false));
InputStream input = HttpRequests.getInputStream(connection);
try {
NetUtils.copyStreamContent(progressIndicator, is, fos, connection.getContentLength());
OutputStream fileOut = new FileOutputStream(file);
try {
NetUtils.copyStreamContent(progressIndicator, input, fileOut, connection.getContentLength());
}
finally {
fileOut.close();
}
}
finally {
fos.close();
input.close();
}
}
finally {
is.close();
}
if (myFileName == null) {
myFileName = guessFileName(connection, file);
}
if (myFileName == null) {
myFileName = guessFileName(connection, file);
}
final File newFile = new File(file.getParentFile(), myFileName);
FileUtil.rename(file, newFile);
return newFile;
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
File newFile = new File(file.getParentFile(), myFileName);
FileUtil.rename(file, newFile);
return newFile;
}
}
});
}
@NotNull
private String guessFileName(final URLConnection connection, final File file) throws IOException {
private String guessFileName(@NotNull URLConnection connection, @NotNull File file) throws IOException {
String fileName = null;
final String contentDisposition = connection.getHeaderField("Content-Disposition");
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -18,7 +18,6 @@ package com.intellij.openapi.updateSettings.impl;
import com.intellij.diagnostic.IdeErrorsDialog;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.*;
import com.intellij.ide.reporter.ConnectionException;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.*;
import com.intellij.openapi.application.ApplicationInfo;
@@ -30,24 +29,20 @@ import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.HttpRequests;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ThrowableConvertor;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.net.NetUtils;
import com.intellij.util.ui.UIUtil;
import org.jdom.Document;
import org.jdom.Element;
@@ -58,15 +53,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* See XML file by {@link com.intellij.openapi.application.ex.ApplicationInfoEx#getUpdateUrls()} for reference.
@@ -133,7 +127,6 @@ public final class UpdateChecker {
ProgressManager.getInstance().run(new Task.Backgroundable(project, IdeBundle.message("updates.checking.progress"), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
indicator.setIndeterminate(true);
doUpdateAndShowResult(project, !fromSettings, true, settings, indicator, null);
}
@@ -163,7 +156,9 @@ public final class UpdateChecker {
settings.setKnownChannelIds(result.getAllChannelsIds());
}
else if (result.getState() == UpdateStrategy.State.CONNECTION_ERROR) {
showErrorMessage(manualCheck, IdeBundle.message("updates.error.connection.failed"));
//noinspection ThrowableResultOfMethodCallIgnored
showErrorMessage(manualCheck,
result.getError() instanceof InterruptedIOException ? IdeBundle.message("updates.timeout.error") : IdeBundle.message("updates.error.connection.failed"));
return;
}
@@ -287,7 +282,7 @@ public final class UpdateChecker {
if (isReadyToUpdate(pluginId, pluginVersion)) {
descriptor = downloader.getDescriptor();
if (descriptor == null) {
if (downloader.prepareToInstall(indicator, buildNumber)) {
if (downloader.prepareToInstall(indicator == null ? new EmptyProgressIndicator() : indicator, buildNumber)) {
descriptor = downloader.getDescriptor();
}
ourUpdatedPlugins.put(pluginId, downloader);
@@ -351,45 +346,74 @@ public final class UpdateChecker {
return checkPluginsHost(host, downloaded, null, collectToUpdate, indicator, null);
}
private static boolean checkPluginsHost(String host,
private static boolean checkPluginsHost(@NotNull String host,
final Map<PluginId, PluginDownloader> downloaded,
final @Nullable Collection<IdeaPluginDescriptor> incompatiblePlugins,
final boolean collectToUpdate,
@Nullable ProgressIndicator indicator,
boolean collectToUpdate,
@Nullable final ProgressIndicator indicator,
final BuildNumber buildNumber) throws Exception {
String url;
if (StandardFileSystems.FILE_PROTOCOL.equals(new URL(host).getProtocol())) {
url = host;
}
else {
url = host + (host.contains("?") ? '&' : '?') + "build=" + ApplicationInfo.getInstance().getBuild().asString();
}
BufferExposingByteArrayOutputStream bytes = HttpRequests.request(url)
.get(new ThrowableConvertor<URLConnection, BufferExposingByteArrayOutputStream, Exception>() {
@Override
public BufferExposingByteArrayOutputStream convert(URLConnection connection) throws Exception {
InputStream input = HttpRequests.getInputStream(connection);
try {
BufferExposingByteArrayOutputStream output = new BufferExposingByteArrayOutputStream();
try {
NetUtils.copyStreamContent(indicator, input, output, connection.getContentLength());
}
finally {
output.close();
}
return output;
}
finally {
input.close();
}
}
});
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes.getInternalBuffer(), 0, bytes.size());
final Document document;
try {
document = JDOMUtil.loadDocument(RepositoryHelper.getConnectionInputStream(loadVersionInfo(host)));
document = JDOMUtil.loadDocument(inputStream);
}
catch (JDOMException e) {
return false;
}
finally {
inputStream.reset();
}
final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(loadVersionInfo(host), indicator);
for (IdeaPluginDescriptor descriptor : descriptors) {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
RepositoryContentHandler handler = new RepositoryContentHandler();
parser.parse(inputStream, handler);
for (IdeaPluginDescriptor descriptor : handler.getPluginsList()) {
((PluginNode)descriptor).setRepositoryName(host);
prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate,
indicator);
}
boolean success = true;
for (Object plugin : document.getRootElement().getChildren("plugin")) {
final Element pluginElement = (Element)plugin;
for (Element pluginElement : document.getRootElement().getChildren("plugin")) {
final String pluginId = pluginElement.getAttributeValue("id");
final String pluginUrl = pluginElement.getAttributeValue("url");
String pluginUrl = pluginElement.getAttributeValue("url");
final String pluginVersion = pluginElement.getAttributeValue("version");
final Element descriptionElement = pluginElement.getChild("description");
final String description;
if (descriptionElement != null) {
description = descriptionElement.getText();
} else {
description = null;
}
Element descriptionElement = pluginElement.getChild("description");
String description = descriptionElement != null ? descriptionElement.getText() : null;
final List<PluginId> dependsPlugins = new ArrayList<PluginId>();
final List depends = pluginElement.getChildren("depends");
for (Object depend : depends) {
dependsPlugins.add(PluginId.getId(((Element)depend).getText()));
List<PluginId> dependsPlugins = new SmartList<PluginId>();
for (Element depend : pluginElement.getChildren("depends")) {
dependsPlugins.add(PluginId.getId(depend.getText()));
}
if (pluginId == null) {
@@ -404,8 +428,10 @@ public final class UpdateChecker {
continue;
}
final VirtualFile pluginFile = PluginDownloader.findPluginFile(pluginUrl, host);
if (pluginFile == null) continue;
VirtualFile pluginFile = PluginDownloader.findPluginFile(pluginUrl, host);
if (pluginFile == null) {
continue;
}
if (collectToUpdate) {
final String finalPluginUrl = getPluginUrl(pluginFile);
@@ -436,7 +462,8 @@ public final class UpdateChecker {
String pluginVersion,
BuildNumber buildNumber,
Map<PluginId, PluginDownloader> downloaded,
Collection<IdeaPluginDescriptor> incompatiblePlugins, boolean collectToUpdate, ProgressIndicator indicator) {
Collection<IdeaPluginDescriptor> incompatiblePlugins, boolean collectToUpdate,
ProgressIndicator indicator) {
try {
if (indicator != null) {
indicator.setText2(finalPluginUrl);
@@ -463,7 +490,7 @@ public final class UpdateChecker {
}
@Nullable
private static UpdatesInfo loadUpdatesInfo(@Nullable final String updateUrl) throws Exception {
private static UpdatesInfo loadUpdatesInfo(@Nullable String updateUrl) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
}
@@ -477,7 +504,7 @@ public final class UpdateChecker {
.get(new ThrowableConvertor<URLConnection, UpdatesInfo, Exception>() {
@Override
public UpdatesInfo convert(URLConnection connection) throws Exception {
InputStream inputStream = connection.getInputStream();
InputStream inputStream = HttpRequests.getInputStream(connection);
try {
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
}
@@ -502,9 +529,6 @@ public final class UpdateChecker {
return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED);
}
}
catch (InterruptedIOException e) {
return new CheckForUpdateResult(UpdateStrategy.State.CONNECTION_ERROR, new ConnectionException(IdeBundle.message("updates.timeout.error")));
}
catch (Exception e) {
return new CheckForUpdateResult(UpdateStrategy.State.CONNECTION_ERROR, e);
}
@@ -645,49 +669,6 @@ public final class UpdateChecker {
}
}
@NotNull
private static URLConnection loadVersionInfo(@NotNull final String url) throws Exception {
final Ref<URLConnection> connectionRef = Ref.create();
final Ref<Exception> exception = Ref.create();
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
String urlToCheck;
if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
}
else {
urlToCheck = url;
}
URLConnection connection = HttpRequests.openConnection(urlToCheck, true).first;
connection.connect();
connectionRef.set(connection);
}
catch (IOException e) {
exception.set(e);
}
}
});
try {
downloadThreadFuture.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException ignored) {
}
if (!downloadThreadFuture.isDone()) {
downloadThreadFuture.cancel(true);
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
}
if (!exception.isNull()) {
throw exception.get();
}
return connectionRef.get();
}
public static String getInstallationUID(final PropertiesComponent propertiesComponent) {
if (SystemInfo.isWindows) {
String uid = getInstallationUIDOnWindows(propertiesComponent);
@@ -17,25 +17,29 @@ package com.intellij.util;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ClassLoaderUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.zip.GZIPInputStream;
/**
* GZip supported by default, so, you must use {@link #getInputStream(java.net.URLConnection)} to get connection input stream.
*/
public final class HttpRequests {
public static class HttpRequestBuilder {
private final String url;
private int connectTimeout = HttpConfigurable.CONNECTION_TIMEOUT;
private int readTimeout = HttpConfigurable.CONNECTION_TIMEOUT;
private boolean supportGzip;
private Consumer<String> effectiveUrlConsumer;
private boolean supportGzip = true;
private HttpRequestBuilder(@NotNull String url) {
this.url = url;
@@ -47,6 +51,7 @@ public final class HttpRequests {
return this;
}
@SuppressWarnings("unused")
@NotNull
public HttpRequestBuilder readTimeout(int value) {
readTimeout = value;
@@ -59,7 +64,13 @@ public final class HttpRequests {
return this;
}
public <T> T get(@NotNull final ThrowableConvertor<URLConnection, T, Exception> handler) throws Exception {
@NotNull
public HttpRequestBuilder effectiveUrlConsumer(Consumer<String> value) {
effectiveUrlConsumer = value;
return this;
}
public <T, E extends Throwable> T get(@NotNull final ThrowableConvertor<URLConnection, T, E> handler) throws E, IOException {
return loadData(this, handler);
}
}
@@ -69,30 +80,46 @@ public final class HttpRequests {
return new HttpRequestBuilder(url);
}
private static <T> T loadData(@NotNull final HttpRequestBuilder requestBuilder, @NotNull final ThrowableConvertor<URLConnection, T, Exception> handler) throws Exception {
return ClassLoaderUtil.runWithClassLoader(new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()), new ThrowableComputable<T, Exception>() {
@Override
public T compute() throws Exception {
URLConnection connection = openConnection(requestBuilder.url, requestBuilder.supportGzip).first;
try {
return handler.convert(connection);
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@NotNull
public static InputStream getInputStream(@NotNull URLConnection connection) throws IOException {
InputStream inputStream = connection.getInputStream();
if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
try {
return new GZIPInputStream(inputStream);
}
catch (IOException e) {
inputStream.close();
throw e;
}
}
else {
return inputStream;
}
}
private static <T, E extends Throwable> T loadData(@NotNull HttpRequestBuilder requestBuilder, @NotNull ThrowableConvertor<URLConnection, T, E> handler)
throws E, IOException {
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], oldClassLoader));
try {
URLConnection connection = openConnection(requestBuilder);
try {
return handler.convert(connection);
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
}
}
});
}
finally {
Thread.currentThread().setContextClassLoader(oldClassLoader);
}
}
@NotNull
public static Pair<URLConnection, String> openConnection(@NotNull String initialUrl, boolean supportGzip) throws IOException {
return openConnection(request(initialUrl).supportGzip(supportGzip));
}
@NotNull
private static Pair<URLConnection, String> openConnection(@NotNull HttpRequestBuilder requestBuilder) throws IOException {
private static URLConnection openConnection(@NotNull HttpRequestBuilder requestBuilder) throws IOException {
int i = 0;
String url = requestBuilder.url;
while (i++ < 99) {
@@ -132,7 +159,11 @@ public final class HttpRequests {
}
}
}
return Pair.create(connection, url == requestBuilder.url ? null : url);
if (url != requestBuilder.url && requestBuilder.effectiveUrlConsumer != null) {
requestBuilder.effectiveUrlConsumer.consume(url);
}
return connection;
}
throw new IOException("Infinite redirection");
}
@@ -531,7 +531,6 @@ button.http.proxy.settings=&HTTP Proxy Settings...
group.vendor=Vendor
plugin.status.installed=Installed
progress.waiting.for.reply.from.plugin.manager=Waiting for reply from {0}
progress.connecting=Connecting...
progress.downloading.plugin=Downloading plugin ''{0}''
error.cannot.create.temp.dir=Unable to create temp directory ''{0}''
error.connection.failed.with.http.code.N=Connection failed with HTTP code {0}