diff --git a/src/main/java/com/shuzijun/leetcode/plugin/model/Config.java b/src/main/java/com/shuzijun/leetcode/plugin/model/Config.java index 7072e6f1..d44ae567 100644 --- a/src/main/java/com/shuzijun/leetcode/plugin/model/Config.java +++ b/src/main/java/com/shuzijun/leetcode/plugin/model/Config.java @@ -92,6 +92,45 @@ public class Config { private List favoriteList; + /** + * 连接超时时间 + */ + private Integer httpConnectionTimeout; + + /** + * 读取超时时间 + */ + private Integer httpReadTimeout; + + /** + * 重定向个数 + */ + private Integer httpRedirectLimit; + + public Integer getHttpConnectionTimeout() { + return httpConnectionTimeout; + } + + public void setHttpConnectionTimeout(Integer httpConnectionTimeout) { + this.httpConnectionTimeout = httpConnectionTimeout; + } + + public Integer getHttpReadTimeout() { + return httpReadTimeout; + } + + public void setHttpReadTimeout(Integer httpReadTimeout) { + this.httpReadTimeout = httpReadTimeout; + } + + public Integer getHttpRedirectLimit() { + return httpRedirectLimit; + } + + public void setHttpRedirectLimit(Integer httpRedirectLimit) { + this.httpRedirectLimit = httpRedirectLimit; + } + public String getId() { return id; } @@ -238,6 +277,7 @@ public String getCookie(String user) { public String getLevelColour() { return levelColour; } + @Transient public Color[] getFormatLevelColour() { Color[] formatColors = new Color[3]; @@ -267,9 +307,9 @@ public Color[] getFormatLevelColour() { } public void setLevelColour(String levelColour) { - if(levelColour ==null || levelColour.isEmpty()){ + if (levelColour == null || levelColour.isEmpty()) { this.levelColour = Constant.LEVEL_COLOUR; - }else { + } else { this.levelColour = levelColour; } } @@ -308,8 +348,8 @@ public void setJcef(Boolean jcef) { this.jcef = jcef; } - public boolean isModified(Config config){ - if(config ==null){ + public boolean isModified(Config config) { + if (config == null) { return false; } if (version != null ? !version.equals(config.version) : config.version != null) return false; @@ -328,6 +368,12 @@ public boolean isModified(Config config){ return false; if (jcef != null ? !jcef.equals(config.jcef) : config.jcef != null) return false; + if (httpConnectionTimeout != null ? !httpConnectionTimeout.equals(config.httpConnectionTimeout) : config.httpConnectionTimeout != null) + return false; + if (httpReadTimeout != null ? !httpReadTimeout.equals(config.httpReadTimeout) : config.httpReadTimeout != null) + return false; + if (httpRedirectLimit != null ? !httpRedirectLimit.equals(config.httpRedirectLimit) : config.httpRedirectLimit != null) + return false; return levelColour != null ? levelColour.equals(config.levelColour) : config.levelColour == null; } diff --git a/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.form b/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.form index 021575a5..2b5882eb 100644 --- a/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.form +++ b/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.form @@ -1,6 +1,6 @@
- + @@ -20,7 +20,7 @@ - + @@ -337,6 +337,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.java b/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.java index 77f93967..1456e07c 100644 --- a/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.java +++ b/src/main/java/com/shuzijun/leetcode/plugin/setting/SettingUI.java @@ -24,14 +24,18 @@ import com.shuzijun.leetcode.plugin.utils.MTAUtils; import com.shuzijun.leetcode.plugin.utils.PropertiesUtils; import com.shuzijun.leetcode.plugin.utils.URLUtils; +import com.shuzijun.leetcode.plugin.utils.io.HttpRequests; import com.shuzijun.leetcode.plugin.window.HttpLogin; import org.apache.commons.lang.StringUtils; import javax.swing.*; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.NumberFormatter; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; +import java.text.DecimalFormat; /** * @author shuzijun @@ -56,6 +60,9 @@ public class SettingUI { private JPanel codeTemplate; private JPanel templateConstant; private JCheckBox jcefCheckBox; + private JFormattedTextField httpConnectionTimeout; + private JFormattedTextField httpReadTimeout; + private JFormattedTextField httpRedirectLimit; private Editor fileNameEditor = null; @@ -84,10 +91,10 @@ public void initUI() { customCodeBox.addActionListener(new DonateListener(customCodeBox)); proxyCheckBox.setSelected(HttpConfigurable.getInstance().USE_HTTP_PROXY || HttpConfigurable.getInstance().USE_PROXY_PAC); - proxyCheckBox.addMouseListener(new MouseAdapter(){ + proxyCheckBox.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - if(HttpConfigurable.editConfigurable(mainPanel)){ + if (HttpConfigurable.editConfigurable(mainPanel)) { proxyCheckBox.setSelected(HttpConfigurable.getInstance().USE_HTTP_PROXY || HttpConfigurable.getInstance().USE_PROXY_PAC); } } @@ -148,7 +155,11 @@ public void mouseClicked(MouseEvent e) { templateHelpEditorSettings.setLineNumbersShown(false); templateHelpEditorSettings.setVirtualSpace(false); templateConstant.add(templateHelpEditor.getComponent(), BorderLayout.CENTER); - + NumberFormatter numberFormatter = new NumberFormatter(new DecimalFormat("0")); + DefaultFormatterFactory numberFormatterFactory = new DefaultFormatterFactory(numberFormatter); + httpConnectionTimeout.setFormatterFactory(numberFormatterFactory); + httpReadTimeout.setFormatterFactory(numberFormatterFactory); + httpRedirectLimit.setFormatterFactory(numberFormatterFactory); loadSetting(); } @@ -184,6 +195,21 @@ private void loadSetting() { hardLabel.setForeground(colors[2]); jcefCheckBox.setSelected(config.getJcef()); + if (config.getHttpConnectionTimeout() == null) { + httpConnectionTimeout.setText(String.valueOf(HttpRequests.CONNECTION_TIMEOUT)); + } else { + httpConnectionTimeout.setText(String.valueOf(config.getHttpConnectionTimeout())); + } + if (config.getHttpReadTimeout() == null) { + httpReadTimeout.setText(String.valueOf(HttpRequests.READ_TIMEOUT)); + } else { + httpReadTimeout.setText(String.valueOf(config.getHttpReadTimeout())); + } + if (config.getHttpRedirectLimit() == null) { + httpRedirectLimit.setText(String.valueOf(HttpRequests.REDIRECT_LIMIT)); + } else { + httpRedirectLimit.setText(String.valueOf(config.getHttpRedirectLimit())); + } } else { Color[] colors = new Config().getFormatLevelColour(); easyLabel.setForeground(colors[0]); @@ -193,6 +219,9 @@ private void loadSetting() { fileNameEditor.getDocument().setText(Constant.CUSTOM_FILE_NAME); templateEditor.getDocument().setText(Constant.CUSTOM_TEMPLATE); }); + httpConnectionTimeout.setText(String.valueOf(HttpRequests.CONNECTION_TIMEOUT)); + httpReadTimeout.setText(String.valueOf(HttpRequests.READ_TIMEOUT)); + httpRedirectLimit.setText(String.valueOf(HttpRequests.REDIRECT_LIMIT)); } @@ -251,6 +280,12 @@ public void process(Config config) { config.setFormatLevelColour(easyLabel.getForeground(), mediumLabel.getForeground(), hardLabel.getForeground()); config.setEnglishContent(englishContentBox.isSelected()); config.setJcef(jcefCheckBox.isSelected()); + try { + config.setHttpConnectionTimeout(Integer.valueOf(httpConnectionTimeout.getText())); + config.setHttpReadTimeout(Integer.valueOf(httpReadTimeout.getText())); + config.setHttpRedirectLimit(Integer.valueOf(httpRedirectLimit.getText())); + } catch (NumberFormatException ignore) { + } } diff --git a/src/main/java/com/shuzijun/leetcode/plugin/utils/io/HttpRequests.java b/src/main/java/com/shuzijun/leetcode/plugin/utils/io/HttpRequests.java index 9df852a4..57c26f80 100644 --- a/src/main/java/com/shuzijun/leetcode/plugin/utils/io/HttpRequests.java +++ b/src/main/java/com/shuzijun/leetcode/plugin/utils/io/HttpRequests.java @@ -20,6 +20,8 @@ import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.NetUtils; import com.intellij.util.net.ssl.CertificateManager; +import com.shuzijun.leetcode.plugin.model.Config; +import com.shuzijun.leetcode.plugin.setting.PersistentConfig; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -70,7 +72,8 @@ public final class HttpRequests { HttpURLConnection.HTTP_MOVED_PERM, HttpURLConnection.HTTP_SEE_OTHER, 308 /* permanent redirect */ }; - private HttpRequests() { } + private HttpRequests() { + } public interface Request { @NotNull @@ -88,7 +91,9 @@ public interface Request { @NotNull BufferedReader getReader(@Nullable ProgressIndicator indicator) throws IOException; - /** @deprecated Called automatically on open connection. Use {@link RequestBuilder#tryConnect()} to get response code */ + /** + * @deprecated Called automatically on open connection. Use {@link RequestBuilder#tryConnect()} to get response code + */ @Deprecated boolean isSuccessful() throws IOException; @@ -113,7 +118,7 @@ default void write(@NotNull String data) throws IOException { } default void write(byte[] data) throws IOException { - HttpURLConnection connection = (HttpURLConnection)getConnection(); + HttpURLConnection connection = (HttpURLConnection) getConnection(); connection.setFixedLengthStreamingMode(data.length); try (OutputStream stream = connection.getOutputStream()) { stream.write(data); @@ -166,12 +171,12 @@ public static RequestBuilder request(@NotNull String url) { @NotNull public static RequestBuilder head(@NotNull String url) { - return new RequestBuilderImpl(url, connection -> ((HttpURLConnection)connection).setRequestMethod("HEAD")); + return new RequestBuilderImpl(url, connection -> ((HttpURLConnection) connection).setRequestMethod("HEAD")); } @NotNull public static RequestBuilder delete(@NotNull String url) { - return new RequestBuilderImpl(url, connection -> ((HttpURLConnection)connection).setRequestMethod("DELETE")); + return new RequestBuilderImpl(url, connection -> ((HttpURLConnection) connection).setRequestMethod("DELETE")); } @NotNull @@ -207,7 +212,7 @@ private static RequestBuilder requestWithBody(@NotNull String url, @Nullable String contentType, @Nullable ConnectionTuner tuner) { return new RequestBuilderImpl(url, rawConnection -> { - HttpURLConnection connection = (HttpURLConnection)rawConnection; + HttpURLConnection connection = (HttpURLConnection) rawConnection; connection.setRequestMethod(requestMethod); connection.setDoOutput(true); if (contentType != null) { @@ -231,11 +236,11 @@ public static String createErrorMessage(@NotNull IOException e, @NotNull Request builder.append("\n, headers: ").append(connection.getHeaderFields()); } if (connection instanceof HttpURLConnection) { - HttpURLConnection httpConnection = (HttpURLConnection)connection; + HttpURLConnection httpConnection = (HttpURLConnection) connection; builder.append("\n, response: ").append(httpConnection.getResponseCode()).append(' ').append(httpConnection.getResponseMessage()); } + } catch (Throwable ignored) { } - catch (Throwable ignored) { } return builder.toString(); } @@ -259,6 +264,16 @@ private static class RequestBuilderImpl extends RequestBuilder { private RequestBuilderImpl(@NotNull String url, @Nullable ConnectionTuner internalTuner) { myUrl = url; myInternalTuner = internalTuner; + Config config = PersistentConfig.getInstance().getInitConfig(); + if (config != null && config.getHttpConnectionTimeout() != null) { + myConnectTimeout = config.getHttpConnectionTimeout(); + } + if (config != null && config.getHttpReadTimeout() != null) { + myTimeout = config.getHttpReadTimeout(); + } + if (config != null && config.getHttpRedirectLimit() != null) { + myRedirectLimit = config.getHttpRedirectLimit(); + } } @Override @@ -322,8 +337,7 @@ public RequestBuilder productNameAsUserAgent() { String productName = ApplicationNamesInfo.getInstance().getFullProductName(); String version = ApplicationInfo.getInstance().getBuild().asStringWithoutProductCode(); return userAgent(productName + '/' + version); - } - else { + } else { return userAgent("IntelliJ"); } } @@ -384,9 +398,9 @@ public URLConnection getConnection() throws IOException { @Override public InputStream getInputStream() throws IOException { if (myInputStream == null) { - if(((HttpURLConnection)getConnection()).getResponseCode()>=400){ - myInputStream = ((HttpURLConnection)getConnection()).getErrorStream(); - }else { + if (((HttpURLConnection) getConnection()).getResponseCode() >= 400) { + myInputStream = ((HttpURLConnection) getConnection()).getErrorStream(); + } else { myInputStream = getConnection().getInputStream(); } if (myBuilder.myGzip && "gzip".equalsIgnoreCase(getConnection().getContentEncoding())) { @@ -426,7 +440,7 @@ private Charset getCharset() throws IOException { @Override public boolean isSuccessful() throws IOException { URLConnection connection = getConnection(); - return !(connection instanceof HttpURLConnection) || ((HttpURLConnection)connection).getResponseCode() == 200; + return !(connection instanceof HttpURLConnection) || ((HttpURLConnection) connection).getResponseCode() == 200; } @Override @@ -451,8 +465,7 @@ public CharSequence readChars(@Nullable ProgressIndicator indicator) throws IOEx BufferExposingByteArrayOutputStream byteStream = doReadBytes(indicator); if (byteStream.size() == 0) { return ArrayUtil.EMPTY_CHAR_SEQUENCE; - } - else { + } else { return getCharset().decode(ByteBuffer.wrap(byteStream.getInternalBuffer(), 0, byteStream.size())); } } @@ -466,14 +479,11 @@ public File saveToFile(@NotNull File file, @Nullable ProgressIndicator indicator try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) { NetUtils.copyStreamContent(indicator, getInputStream(), out, getConnection().getContentLength()); deleteFile = false; - } - catch (HttpStatusException e) { + } catch (HttpStatusException e) { throw e; - } - catch (IOException e) { + } catch (IOException e) { throw new IOException(createErrorMessage(e, this, false), e); - } - finally { + } finally { if (deleteFile) { FileUtilRt.delete(file); } @@ -487,7 +497,7 @@ public void close() { StreamUtil.closeStream(myInputStream); StreamUtil.closeStream(myReader); if (myConnection instanceof HttpURLConnection) { - ((HttpURLConnection)myConnection).disconnect(); + ((HttpURLConnection) myConnection).disconnect(); } } } @@ -503,12 +513,10 @@ private static T process(RequestBuilderImpl builder, RequestProcessor pro try (URLClassLoader cl = new URLClassLoader(new URL[0], contextLoader)) { Thread.currentThread().setContextClassLoader(cl); return doProcess(builder, processor); - } - finally { + } finally { Thread.currentThread().setContextClassLoader(contextLoader); } - } - else { + } else { return doProcess(builder, processor); } } @@ -526,7 +534,7 @@ private static T doProcess(RequestBuilderImpl builder, RequestProcessor p URLConnection connection = request.myConnection; if (connection != null && connection.getDoOutput()) { // getResponseCode is not checked on connect, because write must be performed before read - HttpURLConnection urlConnection = (HttpURLConnection)connection; + HttpURLConnection urlConnection = (HttpURLConnection) connection; int responseCode = urlConnection.getResponseCode(); if (responseCode >= 400) { throwHttpStatusError(urlConnection, request, builder, responseCode); @@ -549,16 +557,14 @@ private static URLConnection openConnection(RequestBuilderImpl builder, RequestI final URLConnection connection; if (!builder.myUseProxy) { connection = new URL(url).openConnection(Proxy.NO_PROXY); - } - else if (ApplicationManager.getApplication() == null) { + } else if (ApplicationManager.getApplication() == null) { connection = new URL(url).openConnection(); - } - else { + } else { connection = HttpConfigurable.getInstance().openConnection(url); } if (connection instanceof HttpsURLConnection) { - configureSslConnection(url, (HttpsURLConnection)connection); + configureSslConnection(url, (HttpsURLConnection) connection); } connection.setConnectTimeout(builder.myConnectTimeout); @@ -569,7 +575,7 @@ else if (ApplicationManager.getApplication() == null) { } if (builder.myHostnameVerifier != null && connection instanceof HttpsURLConnection) { - ((HttpsURLConnection)connection).setHostnameVerifier(builder.myHostnameVerifier); + ((HttpsURLConnection) connection).setHostnameVerifier(builder.myHostnameVerifier); } if (builder.myGzip) { @@ -600,7 +606,7 @@ else if (ApplicationManager.getApplication() == null) { return connection; } - HttpURLConnection httpURLConnection = (HttpURLConnection)connection; + HttpURLConnection httpURLConnection = (HttpURLConnection) connection; String method = httpURLConnection.getRequestMethod(); LOG.assertTrue(method.equals("GET") || method.equals("HEAD") || method.equals("DELETE"), @@ -612,8 +618,7 @@ else if (ApplicationManager.getApplication() == null) { int responseCode; try { responseCode = httpURLConnection.getResponseCode(); - } - catch (SSLHandshakeException e) { + } catch (SSLHandshakeException e) { throw !NetUtils.isSniEnabled() ? new SSLException("SSL error probably caused by disabled SNI", e) : e; } if (LOG.isDebugEnabled()) { @@ -633,7 +638,7 @@ else if (ApplicationManager.getApplication() == null) { } } - if(builder.myThrowStatusCodeException) { + if (builder.myThrowStatusCodeException) { throwHttpStatusError(httpURLConnection, request, builder, responseCode); } } @@ -666,12 +671,10 @@ private static void configureSslConnection(@NotNull String url, @NotNull HttpsUR SSLSocketFactory factory = CertificateManager.getInstance().getSslContext().getSocketFactory(); if (factory == null) { LOG.info("SSLSocketFactory is not defined by the IDE Certificate Manager; Using default SSL configuration to connect to " + url); - } - else { + } else { connection.setSSLSocketFactory(factory); } - } - catch (Throwable e) { + } catch (Throwable e) { LOG.info("Problems configuring SSL connection to " + url, e); } }