1 package com.jetbrains.edu.learning.stepic;
3 import com.google.gson.FieldNamingPolicy;
4 import com.google.gson.Gson;
5 import com.google.gson.GsonBuilder;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.util.net.HttpConfigurable;
8 import com.intellij.util.net.ssl.CertificateManager;
9 import com.jetbrains.edu.learning.StudySerializationUtils;
10 import org.apache.http.HttpEntity;
11 import org.apache.http.HttpHost;
12 import org.apache.http.HttpStatus;
13 import org.apache.http.StatusLine;
14 import org.apache.http.client.methods.CloseableHttpResponse;
15 import org.apache.http.client.methods.HttpGet;
16 import org.apache.http.impl.DefaultConnectionReuseStrategy;
17 import org.apache.http.impl.client.CloseableHttpClient;
18 import org.apache.http.impl.client.HttpClientBuilder;
19 import org.apache.http.impl.client.HttpClients;
20 import org.apache.http.util.EntityUtils;
21 import org.jetbrains.annotations.NotNull;
23 import javax.net.ssl.SSLContext;
24 import javax.net.ssl.TrustManager;
25 import javax.net.ssl.X509TrustManager;
26 import java.io.IOException;
27 import java.net.InetSocketAddress;
28 import java.net.Proxy;
30 import java.security.KeyManagementException;
31 import java.security.NoSuchAlgorithmException;
32 import java.security.SecureRandom;
33 import java.security.cert.X509Certificate;
34 import java.util.List;
36 public class EduStepicClient {
37 private static final Logger LOG = Logger.getInstance(EduStepicClient.class.getName());
38 private static CloseableHttpClient ourClient;
40 private EduStepicClient() {
44 public static CloseableHttpClient getHttpClient() {
45 if (ourClient == null) {
51 public static <T> T getFromStepic(String link, final Class<T> container) throws IOException {
52 return getFromStepic(link, container, getHttpClient());
55 static <T> T getFromStepic(String link, final Class<T> container, @NotNull final CloseableHttpClient client) throws IOException {
56 if (!link.startsWith("/")) link = "/" + link;
57 final HttpGet request = new HttpGet(EduStepicNames.STEPIC_API_URL + link);
58 if (ourClient == null) {
62 final CloseableHttpResponse response = client.execute(request);
63 final StatusLine statusLine = response.getStatusLine();
64 final HttpEntity responseEntity = response.getEntity();
65 final String responseString = responseEntity != null ? EntityUtils.toString(responseEntity) : "";
66 EntityUtils.consume(responseEntity);
67 if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
68 throw new IOException("Stepic returned non 200 status code " + responseString);
70 return deserializeStepicResponse(container, responseString);
73 static <T> T deserializeStepicResponse(Class<T> container, String responseString) {
74 Gson gson = new GsonBuilder().registerTypeAdapter(StepicWrappers.StepOptions.class, new StudySerializationUtils.Json.StepicStepOptionsAdapter()).
75 setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").
76 setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
77 return gson.fromJson(responseString, container);
80 private static void initializeClient() {
81 if (ourClient == null) {
82 final HttpClientBuilder builder = getBuilder();
83 ourClient = builder.build();
88 private static TrustManager[] trustAllCerts() {
89 // Create a trust manager that does not validate certificate for this connection
90 return new TrustManager[]{new X509TrustManager() {
91 public X509Certificate[] getAcceptedIssuers() {
95 public void checkClientTrusted(X509Certificate[] certs, String authType) {
98 public void checkServerTrusted(X509Certificate[] certs, String authType) {
104 private static HttpClientBuilder getBuilder() {
105 final HttpClientBuilder builder = HttpClients.custom().setSslcontext(CertificateManager.getInstance().getSslContext()).
106 setMaxConnPerRoute(100000).setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE);
108 final HttpConfigurable proxyConfigurable = HttpConfigurable.getInstance();
109 final List<Proxy> proxies = proxyConfigurable.getOnlyBySettingsSelector().select(URI.create(EduStepicNames.STEPIC_URL));
110 final InetSocketAddress address = proxies.size() > 0 ? (InetSocketAddress)proxies.get(0).address() : null;
111 if (address != null) {
112 builder.setProxy(new HttpHost(address.getHostName(), address.getPort()));
114 final TrustManager[] trustAllCerts = trustAllCerts();
116 SSLContext sslContext = SSLContext.getInstance("TLS");
117 sslContext.init(null, trustAllCerts, new SecureRandom());
118 builder.setSslcontext(sslContext);
120 catch (NoSuchAlgorithmException | KeyManagementException e) {
121 LOG.error(e.getMessage());