diff --git a/platform-api/che-core-api-builder/pom.xml b/platform-api/che-core-api-builder/pom.xml
index 5220a8233..c9053c04f 100644
--- a/platform-api/che-core-api-builder/pom.xml
+++ b/platform-api/che-core-api-builder/pom.xml
@@ -223,49 +223,4 @@
-
-
- default
-
- true
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- **/*Test.java
-
-
-
-
-
-
-
- unix
-
-
- unix
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- ${project.build.directory}
-
-
- **/*Test.java
-
-
-
-
-
-
-
diff --git a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/BuilderUtils.java b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/BuilderUtils.java
index 89df31264..97c3cb417 100644
--- a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/BuilderUtils.java
+++ b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/BuilderUtils.java
@@ -37,10 +37,10 @@ public static HttpJsonResponse builderRequest(HttpJsonRequest req) throws Builde
try {
return req.request();
} catch (IOException e) {
- throw new BuilderException(e);
+ throw new BuilderException(e.getMessage(), e);
} catch (ServerException | UnauthorizedException | ForbiddenException | NotFoundException | ConflictException
| BadRequestException e) {
- throw new BuilderException(e.getServiceError());
+ throw new BuilderException(e.getMessage(), e);
}
}
diff --git a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/RemoteTask.java b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/RemoteTask.java
index 5463f8aea..81399cc47 100644
--- a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/RemoteTask.java
+++ b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/RemoteTask.java
@@ -17,18 +17,15 @@
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpOutputMessage;
+import org.eclipse.che.api.core.rest.HttpResponse;
import org.eclipse.che.api.core.rest.shared.dto.Link;
-import org.eclipse.che.commons.env.EnvironmentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
import static com.google.common.base.MoreObjects.firstNonNull;
import static org.eclipse.che.api.builder.BuilderUtils.builderRequest;
@@ -217,15 +214,7 @@ public void downloadResultArchive(String archType, HttpOutputMessage output) thr
}
private void readFromUrl(String url, final HttpOutputMessage output) throws IOException {
- final HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
- conn.setConnectTimeout(60 * 1000);
- conn.setReadTimeout(60 * 1000);
- conn.setRequestMethod(HttpMethod.GET);
- final EnvironmentContext context = EnvironmentContext.getCurrent();
- if (context.getUser() != null && context.getUser().getToken() != null) {
- conn.setRequestProperty(HttpHeaders.AUTHORIZATION, context.getUser().getToken());
- }
- try {
+ try (HttpResponse conn = requestFactory.fromUrl(url).setTimeout(60 * 1000).requestGeneral()) {
output.setStatus(conn.getResponseCode());
final String contentType = conn.getContentType();
if (contentType != null) {
@@ -241,9 +230,6 @@ private void readFromUrl(String url, final HttpOutputMessage output) throws IOEx
OutputStream out = output.getOutputStream()) {
ByteStreams.copy(in, out);
}
-
- } finally {
- conn.disconnect();
}
}
}
diff --git a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/internal/SourcesManagerImpl.java b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/internal/SourcesManagerImpl.java
index 9b2a3c342..f1a6d6870 100644
--- a/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/internal/SourcesManagerImpl.java
+++ b/platform-api/che-core-api-builder/src/main/java/org/eclipse/che/api/builder/internal/SourcesManagerImpl.java
@@ -11,8 +11,11 @@
package org.eclipse.che.api.builder.internal;
import org.eclipse.che.api.builder.dto.BaseBuilderRequest;
+import org.eclipse.che.api.core.rest.HttpJsonRequest;
+import org.eclipse.che.api.core.rest.HttpJsonRequest.BodyWriter;
+import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
+import org.eclipse.che.api.core.rest.HttpResponse;
import org.eclipse.che.api.core.util.ValueHolder;
-import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.json.JsonHelper;
import org.eclipse.che.commons.json.JsonParseException;
import org.eclipse.che.commons.lang.IoUtil;
@@ -29,6 +32,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -40,7 +44,9 @@
import java.io.StringReader;
import java.io.Writer;
import java.net.HttpURLConnection;
-import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.ParseException;
import java.util.HashMap;
import java.util.LinkedList;
@@ -82,19 +88,21 @@ public class SourcesManagerImpl implements SourcesManager {
private final AtomicReference projectKeyHolder;
private final Set listeners;
private final ScheduledExecutorService executor;
+ private final HttpJsonRequestFactory provider;
private static final long KEEP_PROJECT_TIME = TimeUnit.MINUTES.toMillis(30);
private static final int CONNECT_TIMEOUT = (int)TimeUnit.MINUTES.toMillis(4);//This time is chosen empirically and
private static final int READ_TIMEOUT = (int)TimeUnit.MINUTES.toMillis(4);//necessary for some large projects. See IDEX-1957.
@Inject
- public SourcesManagerImpl(@Named(Constants.BASE_DIRECTORY) File rootDirectory) {
+ public SourcesManagerImpl(@Named(Constants.BASE_DIRECTORY) File rootDirectory, HttpJsonRequestFactory provider) {
this.rootDirectory = rootDirectory;
tasks = new ConcurrentHashMap<>();
projectKeyHolder = new AtomicReference<>();
executor = Executors.newSingleThreadScheduledExecutor(
new ThreadFactoryBuilder().setNameFormat(getClass().getSimpleName() + "-FileCleaner-%d").setDaemon(true).build());
listeners = new CopyOnWriteArraySet<>();
+ this.provider = provider;
}
@PostConstruct
@@ -202,53 +210,51 @@ public void write(byte[] b) throws IOException {
};
private void download(String downloadUrl, java.io.File downloadTo, File directory) throws IOException {
- HttpURLConnection conn = null;
- try {
- final LinkedList q = new LinkedList<>();
- q.add(downloadTo);
- final long start = System.currentTimeMillis();
- final List> md5sums = new LinkedList<>();
- while (!q.isEmpty()) {
- java.io.File current = q.pop();
- java.io.File[] list = current.listFiles();
- if (list != null) {
- for (java.io.File f : list) {
- if (f.isDirectory()) {
- q.push(f);
- } else {
- md5sums.add(Pair.of(com.google.common.io.Files.hash(f, Hashing.md5()).toString(),
- downloadTo.toPath().relativize(f.toPath()).toString()
- .replace("\\", "/"))); //Replacing of "\" is need for windows support
- }
+ final LinkedList q = new LinkedList<>();
+ q.add(downloadTo);
+ final long start = System.currentTimeMillis();
+ final List> md5sums = new LinkedList<>();
+ while (!q.isEmpty()) {
+ java.io.File current = q.pop();
+ java.io.File[] list = current.listFiles();
+ if (list != null) {
+ for (java.io.File f : list) {
+ if (f.isDirectory()) {
+ q.push(f);
+ } else {
+ md5sums.add(Pair.of(com.google.common.io.Files.hash(f, Hashing.md5()).toString(),
+ downloadTo.toPath().relativize(f.toPath()).toString()
+ .replace("\\", "/"))); //Replacing of "\" is need for windows support
}
}
}
- final long end = System.currentTimeMillis();
- if (md5sums.size() > 0) {
- LOG.debug("count md5sums of {} files, time: {}ms", md5sums.size(), (end - start));
- }
- conn = (HttpURLConnection)new URL(downloadUrl).openConnection();
- conn.setConnectTimeout(CONNECT_TIMEOUT);
- conn.setReadTimeout(READ_TIMEOUT);
- final EnvironmentContext context = EnvironmentContext.getCurrent();
- if (context.getUser() != null && context.getUser().getToken() != null) {
- conn.setRequestProperty(HttpHeaders.AUTHORIZATION, context.getUser().getToken());
- }
- if (!md5sums.isEmpty()) {
- conn.setRequestMethod(HttpMethod.POST);
- conn.setRequestProperty("Content-type", MediaType.TEXT_PLAIN);
- conn.setRequestProperty(HttpHeaders.ACCEPT, MediaType.MULTIPART_FORM_DATA);
- conn.setDoOutput(true);
- try (OutputStream output = conn.getOutputStream();
- Writer writer = new OutputStreamWriter(output)) {
- for (Pair pair : md5sums) {
- writer.write(pair.first);
- writer.write(' ');
- writer.write(pair.second);
- writer.write('\n');
+ }
+ final long end = System.currentTimeMillis();
+ if (md5sums.size() > 0) {
+ LOG.debug("count md5sums of {} files, time: {}ms", md5sums.size(), (end - start));
+ }
+ // Create the main request
+ HttpJsonRequest request = provider.fromUrl(downloadUrl).setTimeout(READ_TIMEOUT);
+ // handle case where checksums are sent
+ if (!md5sums.isEmpty()) {
+ request.usePostMethod();
+ request.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+ request.addHeader(HttpHeaders.ACCEPT, MediaType.MULTIPART_FORM_DATA);
+ request.setBodyWriter(new BodyWriter() {
+ @Override
+ public void writeTo(OutputStream output) throws IOException {
+ try (Writer writer = new OutputStreamWriter(output)) {
+ for (Pair pair : md5sums) {
+ writer.write(pair.first);
+ writer.write(' ');
+ writer.write(pair.second);
+ writer.write('\n');
+ }
}
}
- }
+ });
+ }
+ try (HttpResponse conn = request.requestGeneral()) {
final int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
final String contentType = conn.getHeaderField("content-type");
@@ -314,10 +320,6 @@ private void download(String downloadUrl, java.io.File downloadTo, File director
}
} catch (ParseException | JsonParseException e) {
throw new IOException(e.getMessage(), e);
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
}
}
diff --git a/platform-api/che-core-api-builder/src/test/java/org/eclipse/che/api/builder/BuilderTest.java b/platform-api/che-core-api-builder/src/test/java/org/eclipse/che/api/builder/BuilderTest.java
index f7916c4f4..e223472bd 100644
--- a/platform-api/che-core-api-builder/src/test/java/org/eclipse/che/api/builder/BuilderTest.java
+++ b/platform-api/che-core-api-builder/src/test/java/org/eclipse/che/api/builder/BuilderTest.java
@@ -211,14 +211,12 @@ public void testRemoteBuildSameEnvironment(){
Assert.assertEquals(remoteBuilder.getBuilderEnvironment(), builder.getEnvironments());
}
- private void waitForTask(BuildTask task) throws Exception {
+ private static void waitForTask(BuildTask task) throws Exception {
final long end = System.currentTimeMillis() + 5000;
- synchronized (this) {
- while (!task.isDone()) {
- wait(100);
- if (System.currentTimeMillis() > end) {
- Assert.fail("timeout");
- }
+ while (!task.isDone()) {
+ Thread.sleep(100);
+ if (System.currentTimeMillis() > end) {
+ Assert.fail("timeout");
}
}
}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequest.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequest.java
index e897b6d28..afd1b2567 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequest.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequest.java
@@ -44,8 +44,10 @@
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import static java.util.Objects.requireNonNull;
@@ -63,14 +65,15 @@
public class DefaultHttpJsonRequest implements HttpJsonRequest {
private static final int DEFAULT_QUERY_PARAMS_LIST_SIZE = 5;
- private static final Object[] EMPTY_ARRAY = new Object[0];
private final String url;
private int timeout;
private String method;
private Object body;
+ private BodyWriter bodyWriter;
private List> queryParams;
+ private Map headers;
protected DefaultHttpJsonRequest(String url) {
this.url = requireNonNull(url, "Required non-null url");
@@ -91,18 +94,28 @@ public HttpJsonRequest setMethod(@NotNull String method) {
@Override
public HttpJsonRequest setBody(@NotNull Object body) {
this.body = requireNonNull(body, "Required non-null body");
+ this.bodyWriter = null;
return this;
}
@Override
public HttpJsonRequest setBody(@NotNull Map map) {
this.body = new JsonStringMapImpl<>(requireNonNull(map, "Required non-null body"));
+ this.bodyWriter = null;
return this;
}
@Override
public HttpJsonRequest setBody(@NotNull List> list) {
this.body = new JsonArrayImpl<>(requireNonNull(list, "Required non-null body"));
+ this.bodyWriter = null;
+ return this;
+ }
+
+ @Override
+ public HttpJsonRequest setBodyWriter(BodyWriter bodyWriter) {
+ this.bodyWriter = Objects.requireNonNull(bodyWriter, "Required non-null body writer");
+ this.body = null;
return this;
}
@@ -116,7 +129,17 @@ public HttpJsonRequest addQueryParam(@NotNull String name, @NotNull Object value
queryParams.add(Pair.of(name, value));
return this;
}
-
+
+ @Override
+ public HttpJsonRequest addHeader(String name, String value) {
+ requireNonNull(name, "Required non-null header name");
+ if (headers == null) {
+ headers = new HashMap<>();
+ }
+ headers.put(name, value);
+ return this;
+ }
+
@Override
public HttpJsonRequest setTimeout(int timeout) {
this.timeout = timeout;
@@ -134,9 +157,23 @@ public HttpJsonResponse request() throws IOException,
if (method == null) {
throw new IllegalStateException("Could not perform request, request method wasn't set");
}
+ if (bodyWriter != null) {
+ throw new IllegalStateException("Can not issue a JSON rqeuest in stream mode");
+ }
return doRequest(timeout, url, method, body, queryParams);
}
+ @Override
+ public HttpResponse requestGeneral() throws IOException {
+ if (method == null) {
+ throw new IllegalStateException("Could not perform request, request method wasn't set");
+ }
+ if (body != null) {
+ throw new IllegalStateException("Can not issue a stream rqeuest in JSON mode");
+ }
+ return doRequestGeneral(timeout, url, method, bodyWriter, headers, queryParams);
+ }
+
/**
* Makes this request using {@link HttpURLConnection}.
*
@@ -181,48 +218,22 @@ protected DefaultHttpJsonResponse doRequest(int timeout,
UnauthorizedException,
ConflictException,
BadRequestException {
- final String authToken = getAuthenticationToken();
- final boolean hasQueryParams = parameters != null && !parameters.isEmpty();
- if (hasQueryParams || authToken != null) {
- final UriBuilder ub = UriBuilder.fromUri(url);
- //remove sensitive information from url.
- ub.replaceQueryParam("token", EMPTY_ARRAY);
-
- if (hasQueryParams) {
- for (Pair parameter : parameters) {
- String name = URLEncoder.encode(parameter.first, "UTF-8");
- String value = parameter.second == null ?
- null :
- URLEncoder.encode(String.valueOf(parameter.second), "UTF-8");
- ub.queryParam(name, value);
- }
- }
- url = ub.build().toString();
- }
- final HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
- conn.setConnectTimeout(timeout > 0 ? timeout : 60000);
- conn.setReadTimeout(timeout > 0 ? timeout : 60000);
- try {
- conn.setRequestMethod(method);
- //drop a hint for server side that we want to receive application/json
- conn.addRequestProperty(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
- if (authToken != null) {
- conn.setRequestProperty(HttpHeaders.AUTHORIZATION, authToken);
- }
- if (body != null) {
- conn.addRequestProperty(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
- conn.setDoOutput(true);
- if (HttpMethod.DELETE.equals(method)) { //to avoid jdk bug described here http://bugs.java.com/view_bug.do?bug_id=7157360
- conn.setRequestMethod(HttpMethod.POST);
- conn.setRequestProperty("X-HTTP-Method-Override", HttpMethod.DELETE);
- }
+ Map headers = (this.headers == null ? new HashMap<>() : new HashMap<>(this.headers));
+ headers.put(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
- try (OutputStream output = conn.getOutputStream()) {
- output.write(DtoFactory.getInstance().toJson(body).getBytes());
+ BodyWriter bw = null;
+ if (body != null) {
+ headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+ bw = new BodyWriter() {
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ out.write(DtoFactory.getInstance().toJson(body).getBytes());
}
- }
+ };
+ }
+ try (HttpResponse conn = doRequestGeneral(timeout, url, method, bw, headers, parameters)) {
final int responseCode = conn.getResponseCode();
if ((responseCode / 100) != 2) {
InputStream in = conn.getErrorStream();
@@ -255,22 +266,59 @@ protected DefaultHttpJsonResponse doRequest(int timeout,
}
// Can't parse content as json or content has format other we expect for error.
throw new IOException(String.format("Failed access: %s, method: %s, response code: %d, message: %s",
- UriBuilder.fromUri(url).replaceQuery("token").build(), method, responseCode, str));
+ url, method, responseCode, str));
}
final String contentType = conn.getContentType();
if (contentType != null && !contentType.startsWith(MediaType.APPLICATION_JSON)) {
- throw new IOException(conn.getResponseMessage() + " [ Content-Type: " + contentType + " ]");
+ throw new IOException(Response.Status.Family.familyOf(conn.getResponseCode()) + " [ Content-Type: " + contentType + " ]");
}
try (Reader reader = new InputStreamReader(conn.getInputStream())) {
return new DefaultHttpJsonResponse(CharStreams.toString(reader), responseCode);
}
- } finally {
- conn.disconnect();
}
}
- private String getAuthenticationToken() {
+ protected HttpResponse doRequestGeneral(int timeout, String url, String method, BodyWriter bodyWriter,
+ Map headers, List> queryParams) throws IOException {
+ // Set the query parameters
+ if (queryParams != null && !queryParams.isEmpty()) {
+ final UriBuilder ub = UriBuilder.fromUri(url);
+ for (Pair parameter : queryParams) {
+ String name = URLEncoder.encode(parameter.first, "UTF-8");
+ String value = parameter.second == null ? null
+ : URLEncoder.encode(String.valueOf(parameter.second), "UTF-8");
+ ub.queryParam(name, value);
+ }
+ url = ub.build().toString();
+ }
+ // Initialize the connection
+ URL urlObj = new URL(url);
+ HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
+ conn.setConnectTimeout(timeout > 0 ? timeout : DEFAULT_TIMEOUT);
+ conn.setReadTimeout(timeout > 0 ? timeout : DEFAULT_TIMEOUT);
+ if (method != null) {
+ conn.setRequestMethod(method);
+ }
+ // Set the authorization header if present
+ String authToken = getAuthenticationToken(urlObj);
+ if (authToken != null) {
+ conn.setRequestProperty(HttpHeaders.AUTHORIZATION, authToken);
+ }
+ // Set all the custom headers
+ if (headers != null) {
+ headers.forEach(conn::setRequestProperty);
+ }
+ // Write the body
+ if (bodyWriter != null) {
+ conn.setDoOutput(true);
+ bodyWriter.writeTo(conn.getOutputStream());
+ }
+ // The result
+ return new URLConnectionHttpResponse(conn);
+ }
+
+ protected String getAuthenticationToken(URL urlObj) {
final User user = EnvironmentContext.getCurrent().getUser();
if (user != null) {
return user.getToken();
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequest.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequest.java
index 45b6b62ff..76b81ff57 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequest.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequest.java
@@ -24,6 +24,8 @@
import javax.validation.constraints.NotNull;
import javax.ws.rs.HttpMethod;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -62,6 +64,12 @@
@Beta
public interface HttpJsonRequest {
+ static final int DEFAULT_TIMEOUT = 60 * 1000;
+
+ public interface BodyWriter {
+ public void writeTo(OutputStream out) throws IOException;
+ }
+
/**
* Sets http method to use in this request(e.g. {@link javax.ws.rs.HttpMethod#GET GET}).
*
@@ -108,6 +116,17 @@ public interface HttpJsonRequest {
*/
HttpJsonRequest setBody(@NotNull List> list);
+ /**
+ * Copy the given input stream to the request body.
+ *
+ * @param bodyWriter
+ * write data to the request output stream.
+ * @return this request instance
+ * @throws NullPointerException
+ * when {@code body} is null
+ */
+ HttpJsonRequest setBodyWriter(@NotNull BodyWriter bodyWriter);
+
/**
* Adds query parameter to the request.
*
@@ -121,6 +140,17 @@ public interface HttpJsonRequest {
*/
HttpJsonRequest addQueryParam(@NotNull String name, @NotNull Object value);
+ /**
+ * Adds a header to the request.
+ *
+ * @param name
+ * The name of the header.
+ * @param value
+ * The value of the header.
+ * @return this request instance
+ */
+ HttpJsonRequest addHeader(@NotNull String name, String value);
+
/**
* Sets request timeout.
*
@@ -160,6 +190,8 @@ HttpJsonResponse request() throws IOException,
ConflictException,
BadRequestException;
+ HttpResponse requestGeneral() throws IOException;
+
/**
* Uses {@link HttpMethod#GET} as a request method.
*
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpResponse.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpResponse.java
new file mode 100644
index 000000000..9157bce12
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpResponse.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.rest;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Defines response of {@link HttpRequestFactory}.
+ *
+ * @author Tareq Sharafy
+ */
+@Beta
+public interface HttpResponse extends AutoCloseable {
+
+ /**
+ * Returns a response code.
+ */
+ int getResponseCode() throws IOException;
+
+ /**
+ * The content type of the response data.
+ */
+ String getHeaderField(String name);
+
+ /**
+ * The value of the Content-Type header.
+ */
+ String getContentType();
+
+ /**
+ * Gets a stream of the response body.
+ */
+ InputStream getInputStream() throws IOException;
+
+ InputStream getErrorStream() throws IOException;
+
+ @Override
+ void close() throws IOException;
+
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/URLConnectionHttpResponse.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/URLConnectionHttpResponse.java
new file mode 100644
index 000000000..71c1ea664
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/URLConnectionHttpResponse.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.rest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+import javax.net.ssl.HttpsURLConnection;
+
+/**
+ * An {@link HttpResponse} implementation that is based on {@link HttpURLConnection} and {@link HttpsURLConnection}
+ * connections.
+ *
+ * @author Tareq Sharafy
+ *
+ */
+public class URLConnectionHttpResponse implements HttpResponse {
+
+ private final HttpURLConnection conn;
+
+ public URLConnectionHttpResponse(HttpURLConnection conn) {
+ this.conn = conn;
+ }
+
+ @Override
+ public void close() {
+ conn.disconnect();
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return conn.getInputStream();
+ }
+
+ @Override
+ public int getResponseCode() throws IOException {
+ return conn.getResponseCode();
+ }
+
+ @Override
+ public String getHeaderField(String name) {
+ return conn.getHeaderField(name);
+ }
+
+ @Override
+ public String getContentType() {
+ return conn.getContentType();
+ }
+
+ @Override
+ public InputStream getErrorStream() throws IOException {
+ return conn.getErrorStream();
+ }
+
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPlugin.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPlugin.java
index bdc12895e..f6af0164d 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPlugin.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPlugin.java
@@ -12,11 +12,14 @@
import java.io.IOException;
+import com.google.inject.ImplementedBy;
+
/**
* Downloads remote file.
*
* @author andrew00x
*/
+@ImplementedBy(DownloadPluginImpl.class)
public interface DownloadPlugin {
interface Callback {
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPluginImpl.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPluginImpl.java
new file mode 100644
index 000000000..de46493d2
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPluginImpl.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2012-2016 Codenvy, S.A.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Codenvy, S.A. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.che.api.core.util;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Singleton;
+
+import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
+import org.eclipse.che.api.core.rest.HttpResponse;
+
+/**
+ * DownloadPlugin that downloads single file.
+ *
+ * @author Tareq Sharafy
+ */
+@Singleton
+public class DownloadPluginImpl extends HttpDownloadPlugin {
+
+ private static final int READ_TIMEOUT = (int) TimeUnit.MINUTES.toMillis(3);
+
+ private final HttpJsonRequestFactory provider;
+
+ public DownloadPluginImpl(HttpJsonRequestFactory provider) {
+ this.provider = provider;
+ }
+
+ @Override
+ protected HttpResponse openUrlConnection(String downloadUrl) throws IOException {
+ // Check it
+ HttpResponse conn = provider.fromUrl(downloadUrl).setTimeout(READ_TIMEOUT).requestGeneral();
+ // Connect
+ final int responseCode = conn.getResponseCode();
+ if (responseCode != 200) {
+ conn.close();
+ throw new IOException(String.format("Invalid response status %d from remote server. ", responseCode));
+ }
+ return conn;
+ }
+
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/HttpDownloadPlugin.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/HttpDownloadPlugin.java
index 6cc01604e..116c4a8cb 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/HttpDownloadPlugin.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/HttpDownloadPlugin.java
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.che.api.core.util;
+import org.eclipse.che.api.core.rest.HttpResponse;
+import org.eclipse.che.api.core.rest.URLConnectionHttpResponse;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.NameGenerator;
import org.slf4j.Logger;
@@ -30,17 +32,15 @@
*
* @author andrew00x
*/
-public final class HttpDownloadPlugin implements DownloadPlugin {
+public class HttpDownloadPlugin implements DownloadPlugin {
private static final Logger LOG = LoggerFactory.getLogger(HttpDownloadPlugin.class);
private static final int CONNECT_TIMEOUT = (int)TimeUnit.MINUTES.toMillis(3);
- private static final int READ_TIMEOUT = (int)TimeUnit.MINUTES.toMillis(3);
+ protected static final int READ_TIMEOUT = (int)TimeUnit.MINUTES.toMillis(3);
@Override
public void download(String downloadUrl, java.io.File downloadTo, Callback callback) {
- HttpURLConnection conn = null;
- try {
- conn = openUrlConnection(downloadUrl);
+ try (HttpResponse conn = openUrlConnection(downloadUrl)) {
final String contentDisposition = conn.getHeaderField(HttpHeaders.CONTENT_DISPOSITION);
String fileName = null;
if (contentDisposition != null) {
@@ -65,18 +65,12 @@ public void download(String downloadUrl, java.io.File downloadTo, Callback callb
} catch (IOException e) {
LOG.debug(String.format("Failed access: %s, error: %s", downloadUrl, e.getMessage()), e);
callback.error(e);
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
}
}
@Override
public void download(String downloadUrl, java.io.File downloadTo, String fileName, boolean replaceExisting) throws IOException {
- HttpURLConnection conn = null;
- try {
- conn = openUrlConnection(downloadUrl);
+ try (HttpResponse conn = openUrlConnection(downloadUrl)) {
final java.io.File downloadFile = new java.io.File(downloadTo, fileName);
try (InputStream in = conn.getInputStream()) {
if (replaceExisting) {
@@ -85,14 +79,10 @@ public void download(String downloadUrl, java.io.File downloadTo, String fileNam
Files.copy(in, downloadFile.toPath());
}
}
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
}
}
- private static HttpURLConnection openUrlConnection(String downloadUrl) throws IOException {
+ protected HttpResponse openUrlConnection(String downloadUrl) throws IOException {
HttpURLConnection conn = (HttpURLConnection)new URL(downloadUrl).openConnection();
// Set timeouts
conn.setConnectTimeout(CONNECT_TIMEOUT);
@@ -107,6 +97,6 @@ private static HttpURLConnection openUrlConnection(String downloadUrl) throws IO
if (responseCode != 200) {
throw new IOException(String.format("Invalid response status %d from remote server. ", responseCode));
}
- return conn;
+ return new URLConnectionHttpResponse(conn);
}
}
diff --git a/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/FactoryServiceTest.java b/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/FactoryServiceTest.java
index 4454d10b6..c2135edc5 100644
--- a/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/FactoryServiceTest.java
+++ b/platform-api/che-core-api-factory/src/test/java/org/eclipse/che/api/factory/FactoryServiceTest.java
@@ -123,6 +123,7 @@ public void setUp() throws Exception {
editValidator,
new LinksHelper(),
factoryBuilder,
+ null,
projectManager);
when(accountDao.getByMember(anyString())).thenReturn(Arrays.asList(new Member().withRoles(Arrays.asList("account/owner"))));
diff --git a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RemoteRunnerProcess.java b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RemoteRunnerProcess.java
index dd786322a..1923cad79 100644
--- a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RemoteRunnerProcess.java
+++ b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RemoteRunnerProcess.java
@@ -12,20 +12,14 @@
import com.google.common.io.ByteStreams;
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
-import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.core.UnauthorizedException;
-import org.eclipse.che.api.core.rest.HttpJsonHelper;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.core.rest.HttpOutputMessage;
+import org.eclipse.che.api.core.rest.HttpResponse;
import org.eclipse.che.api.core.rest.OutputProvider;
import org.eclipse.che.api.core.rest.shared.dto.Link;
import org.eclipse.che.api.runner.dto.ApplicationProcessDescriptor;
import org.eclipse.che.api.runner.internal.Constants;
-import org.eclipse.che.commons.env.EnvironmentContext;
-import org.eclipse.che.dto.server.DtoFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,8 +31,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
/**
* Representation of remote application process.
@@ -128,15 +120,7 @@ public void readRecipeFile(OutputProvider output) throws IOException, RunnerExce
}
private void doRequest(String url, String method, final OutputProvider output) throws IOException {
- final HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();
- conn.setConnectTimeout(60 * 1000);
- conn.setReadTimeout(60 * 1000);
- conn.setRequestMethod(method);
- final EnvironmentContext context = EnvironmentContext.getCurrent();
- if (context.getUser() != null && context.getUser().getToken() != null) {
- conn.setRequestProperty(HttpHeaders.AUTHORIZATION, context.getUser().getToken());
- }
- try {
+ try (HttpResponse conn = requestFactory.fromUrl(url).setTimeout(60 * 1000).setMethod(method).requestGeneral()) {
if (output instanceof HttpOutputMessage) {
HttpOutputMessage httpOutput = (HttpOutputMessage)output;
httpOutput.setStatus(conn.getResponseCode());
@@ -155,9 +139,6 @@ private void doRequest(String url, String method, final OutputProvider output) t
OutputStream out = output.getOutputStream()) {
ByteStreams.copy(in, out);
}
-
- } finally {
- conn.disconnect();
}
}
}
diff --git a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunQueue.java b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunQueue.java
index 7f4a3e930..b465997ba 100644
--- a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunQueue.java
+++ b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunQueue.java
@@ -18,15 +18,12 @@
import org.eclipse.che.api.builder.BuilderService;
import org.eclipse.che.api.builder.dto.BuildOptions;
import org.eclipse.che.api.builder.dto.BuildTaskDescriptor;
-import org.eclipse.che.api.core.ConflictException;
-import org.eclipse.che.api.core.ForbiddenException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
-import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.core.notification.EventSubscriber;
-import org.eclipse.che.api.core.rest.HttpJsonHelper;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
+import org.eclipse.che.api.core.rest.HttpResponse;
import org.eclipse.che.api.core.rest.RemoteServiceDescriptor;
import org.eclipse.che.api.core.rest.ServiceContext;
import org.eclipse.che.api.core.rest.shared.dto.Link;
@@ -76,7 +73,6 @@
import static org.eclipse.che.api.runner.RunnerUtils.runnerRequest;
import java.io.IOException;
-import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@@ -1189,7 +1185,7 @@ public String toString() {
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>> application start checker
- private static class ApplicationUrlChecker implements Runnable {
+ private class ApplicationUrlChecker implements Runnable {
final long taskId;
final URL url;
final int healthCheckerTimeout;
@@ -1215,13 +1211,7 @@ public void run() {
} catch (InterruptedException e) {
return;
}
- HttpURLConnection conn = null;
- try {
- conn = (HttpURLConnection)url.openConnection();
- conn.setRequestMethod(requestMethod);
- conn.setConnectTimeout(1000);
- conn.setReadTimeout(1000);
-
+ try (HttpResponse conn = requestFactory.fromUrl(url.toString()).setTimeout(1000).setMethod(requestMethod).requestGeneral()) {
LOG.debug(String.format("Response code: %d.", conn.getResponseCode()));
if (405 == conn.getResponseCode()) {
// In case of Method not allowed, we use get instead of HEAD. X-HTTP-Method-Override would be nice but support is
@@ -1249,10 +1239,6 @@ public void run() {
}
}
} catch (IOException ignored) {
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
}
}
}
diff --git a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunnerUtils.java b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunnerUtils.java
index 60f09461b..a18323512 100644
--- a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunnerUtils.java
+++ b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/RunnerUtils.java
@@ -37,10 +37,10 @@ public static HttpJsonResponse runnerRequest(HttpJsonRequest req) throws RunnerE
try {
return req.request();
} catch (IOException e) {
- throw new RunnerException(e);
+ throw new RunnerException(e.getMessage(), e);
} catch (ServerException | UnauthorizedException | ForbiddenException | NotFoundException | ConflictException
| BadRequestException e) {
- throw new RunnerException(e.getServiceError());
+ throw new RunnerException(e.getMessage(), e);
}
}
diff --git a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/internal/Runner.java b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/internal/Runner.java
index fe3859438..ebc545ed3 100644
--- a/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/internal/Runner.java
+++ b/platform-api/che-core-api-runner/src/main/java/org/eclipse/che/api/runner/internal/Runner.java
@@ -35,6 +35,8 @@
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
@@ -90,6 +92,10 @@ public boolean isValid(DeploymentSources deployment) {
private ScheduledExecutorService cleanScheduler;
private java.io.File deployDirectory;
+ @Inject
+ private DownloadPlugin theDownloadPlugin;
+ /** @deprecated use {@link #downloadFile(String, java.io.File, String, boolean)} */
+ @Deprecated
protected final DownloadPlugin downloadPlugin;
public Runner(java.io.File deployDirectoryRoot, int cleanupDelay, ResourceAllocators allocators, EventService eventService) {
@@ -374,7 +380,7 @@ protected DeploymentSources createDeploymentSources(RunRequest request, java.io.
return NO_SOURCES;
}
final DownloadCallback callback = new DownloadCallback();
- downloadPlugin.download(url, dir, callback);
+ theDownloadPlugin.download(url, dir, callback);
if (callback.getError() != null) {
throw callback.getError();
}
@@ -413,7 +419,7 @@ public IOException getError() {
}
protected java.io.File downloadFile(String url, java.io.File downloadDir, String fileName, boolean replaceExisting) throws IOException {
- downloadPlugin.download(url, downloadDir, fileName, replaceExisting);
+ theDownloadPlugin.download(url, downloadDir, fileName, replaceExisting);
return new java.io.File(downloadDir, fileName);
}
diff --git a/platform-api/che-core-api-runner/src/test/java/org/eclipse/che/api/runner/RunQueueTest.java b/platform-api/che-core-api-runner/src/test/java/org/eclipse/che/api/runner/RunQueueTest.java
index 10c52f1ca..af4a0bd54 100644
--- a/platform-api/che-core-api-runner/src/test/java/org/eclipse/che/api/runner/RunQueueTest.java
+++ b/platform-api/che-core-api-runner/src/test/java/org/eclipse/che/api/runner/RunQueueTest.java
@@ -25,6 +25,7 @@
import org.eclipse.che.api.core.rest.DefaultHttpJsonResponse;
import org.eclipse.che.api.core.rest.HttpJsonRequest;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
+import org.eclipse.che.api.core.rest.HttpResponse;
import org.eclipse.che.api.core.rest.RemoteServiceDescriptor;
import org.eclipse.che.api.core.rest.ServiceContext;
import org.eclipse.che.api.core.rest.shared.dto.Link;