diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java index 6684090a218d..48d3364c0813 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -21,31 +21,19 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.fileTypes.FileTypes; -import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsBundle; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PathUtilRt; import com.intellij.util.Url; -import com.intellij.util.io.UrlConnectionUtil; -import com.intellij.util.net.ssl.CertificateManager; +import com.intellij.util.io.HttpRequests; import org.jetbrains.annotations.NotNull; -import org.jetbrains.io.Responses; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; import java.io.*; import java.net.HttpURLConnection; -import java.net.URL; -/** - * @author nik - */ public class DefaultRemoteContentProvider extends RemoteContentProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.http.DefaultRemoteContentProvider"); - private static final int CONNECT_TIMEOUT = 60 * 1000; - private static final int READ_TIMEOUT = 60 * 1000; + private static final Logger LOG = Logger.getInstance(DefaultRemoteContentProvider.class); @Override public boolean canProvideContent(@NotNull Url url) { @@ -64,93 +52,66 @@ public class DefaultRemoteContentProvider extends RemoteContentProvider { private static void downloadContent(@NotNull final Url url, final File file, final DownloadingCallback callback) { LOG.debug("Downloading started: " + url); - InputStream input = null; - OutputStream output = null; + final String presentableUrl = StringUtil.trimMiddle(url.trimParameters().toDecodedForm(), 40); + callback.setProgressText(VfsBundle.message("download.progress.connecting", presentableUrl), true); try { - String presentableUrl = StringUtil.trimMiddle(url.trimParameters().toDecodedForm(), 40); - callback.setProgressText(VfsBundle.message("download.progress.connecting", presentableUrl), true); - HttpURLConnection connection = (HttpURLConnection)new URL(url.toExternalForm()).openConnection(); - connection.setRequestProperty("User-Agent", Responses.getServerHeaderValue()); - connection.setConnectTimeout(CONNECT_TIMEOUT); - connection.setReadTimeout(READ_TIMEOUT); - if (connection instanceof HttpsURLConnection) { - try { - HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; - httpsConnection.setHostnameVerifier(new HostnameVerifier() { - @Override - public boolean verify(String hostname, SSLSession session) { - return true; + HttpRequests.request(url.toExternalForm()) + .connectTimeout(60 * 1000) + .readTimeout(60 * 1000) + .disableHostVerification() + .connect(new HttpRequests.RequestProcessor() { + @Override + public Object process(@NotNull HttpRequests.Request request) throws IOException { + HttpURLConnection connection = (HttpURLConnection)request.getConnection(); + int responseCode = connection.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); } - }); - httpsConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory()); - } - catch (Exception e) { - LOG.warn(e); - } - } - input = UrlConnectionUtil.getConnectionInputStreamWithException(connection, new EmptyProgressIndicator()); - final int responseCode = connection.getResponseCode(); - if (responseCode != HttpURLConnection.HTTP_OK) { - throw new IOException(IdeBundle.message("error.connection.failed.with.http.code.N", responseCode)); - } + int size = connection.getContentLength(); + OutputStream output = new BufferedOutputStream(new FileOutputStream(file)); + try { + callback.setProgressText(VfsBundle.message("download.progress.downloading", presentableUrl), size == -1); + if (size != -1) { + callback.setProgressFraction(0); + } - final int size = connection.getContentLength(); - //noinspection IOResourceOpenedButNotSafelyClosed - output = new BufferedOutputStream(new FileOutputStream(file)); - callback.setProgressText(VfsBundle.message("download.progress.downloading", presentableUrl), size == -1); - if (size != -1) { - callback.setProgressFraction(0); - } + int count; + byte[] buf = new byte[4096]; + int total = 0; + while ((count = request.getInputStream().read(buf)) > 0) { + if (callback.isCancelled()) { + return null; + } + total += count; + if (size > 0) { + callback.setProgressFraction((double)total / size); + } + output.write(buf, 0, count); + } + } + finally { + output.close(); + } - FileType fileType = RemoteFileUtil.getFileType(connection.getContentType()); - if (fileType == FileTypes.PLAIN_TEXT) { - FileType fileTypeByFileName = FileTypeRegistry.getInstance().getFileTypeByFileName(PathUtilRt.getFileName(url.getPath())); - if (fileTypeByFileName != FileTypes.UNKNOWN) { - fileType = fileTypeByFileName; - } - } + FileType fileType = RemoteFileUtil.getFileType(connection.getContentType()); + if (fileType == FileTypes.PLAIN_TEXT) { + FileType fileTypeByFileName = FileTypeRegistry.getInstance().getFileTypeByFileName(PathUtilRt.getFileName(url.getPath())); + if (fileTypeByFileName != FileTypes.UNKNOWN) { + fileType = fileTypeByFileName; + } + } - int len; - final byte[] buf = new byte[1024]; - int count = 0; - while ((len = input.read(buf)) > 0) { - if (callback.isCancelled()) { - return; - } - count += len; - if (size > 0) { - callback.setProgressFraction((double)count / size); - } - output.write(buf, 0, len); - } - output.close(); - output = null; - LOG.debug("Downloading finished, " + size + " bytes downloaded"); - callback.finished(fileType); + LOG.debug("Downloading finished, " + size + " bytes downloaded"); + callback.finished(fileType); + return null; + } + }); } catch (IOException e) { LOG.info(e); callback.errorOccurred(VfsBundle.message("cannot.load.remote.file", url, e.getMessage()), false); } - finally { - if (input != null) { - try { - input.close(); - } - catch (IOException e) { - LOG.info(e); - } - } - if (output != null) { - try { - output.close(); - } - catch (IOException e) { - LOG.info(e); - } - } - } } @Override diff --git a/platform/platform-impl/src/com/intellij/util/io/HttpRequests.java b/platform/platform-impl/src/com/intellij/util/io/HttpRequests.java index 4c2be947681d..bd6b7b7ca3fb 100644 --- a/platform/platform-impl/src/com/intellij/util/io/HttpRequests.java +++ b/platform/platform-impl/src/com/intellij/util/io/HttpRequests.java @@ -17,11 +17,17 @@ package com.intellij.util.io; import com.intellij.ide.IdeBundle; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.SystemProperties; import com.intellij.util.net.HttpConfigurable; +import com.intellij.util.net.ssl.CertificateManager; import org.jetbrains.annotations.NotNull; +import org.jetbrains.io.Responses; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; @@ -41,6 +47,8 @@ import java.util.zip.GZIPInputStream; * } */ public final class HttpRequests { + private static final Logger LOG = Logger.getInstance(HttpRequests.class); + private static final boolean ourParallelLoader = SystemProperties.getBooleanProperty("idea.parallel.class.loader", true); public interface Request { @@ -58,7 +66,8 @@ public final class HttpRequests { private int myTimeout = HttpConfigurable.READ_TIMEOUT; private int myRedirectLimit = HttpConfigurable.REDIRECT_LIMIT; private boolean myGzip = true; - private boolean myForceHttps = false; + private boolean myForceHttps; + private boolean myDisableHostVerification; private RequestBuilder(@NotNull String url) { myUrl = url; @@ -94,6 +103,12 @@ public final class HttpRequests { return this; } + @NotNull + public RequestBuilder disableHostVerification() { + myDisableHostVerification = true; + return this; + } + public T connect(@NotNull RequestProcessor processor) throws IOException { // todo[r.sh] drop condition in IDEA 15 if (ourParallelLoader) { @@ -186,6 +201,30 @@ public final class HttpRequests { connection.setConnectTimeout(builder.myConnectTimeout); connection.setReadTimeout(builder.myTimeout); + + String userAgent = Responses.getServerHeaderValue(); + if (userAgent != null) { + connection.setRequestProperty("User-Agent", userAgent); + } + + if (connection instanceof HttpsURLConnection) { + try { + HttpsURLConnection httpsConnection = (HttpsURLConnection)connection; + if (builder.myDisableHostVerification) { + httpsConnection.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + } + httpsConnection.setSSLSocketFactory(CertificateManager.getInstance().getSslContext().getSocketFactory()); + } + catch (Exception e) { + LOG.warn(e); + } + } + if (builder.myGzip) { connection.setRequestProperty("Accept-Encoding", "gzip"); }