headers = new HashMap<>();
+ headers.put(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
+ 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());
}
- }
- 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);
- }
-
- try (OutputStream output = conn.getOutputStream()) {
- output.write(DtoFactory.getInstance().toJson(body).getBytes());
- }
- }
-
- final int responseCode = conn.getResponseCode();
- if ((responseCode / 100) != 2) {
- InputStream in = conn.getErrorStream();
- if (in == null) {
- in = conn.getInputStream();
- }
- final String str;
- try (Reader reader = new InputStreamReader(in)) {
+ int responseCode;
+ String contentType;
+ String str = null;
+ try (HttpResponse conn = doGeneralRequest(timeout, url, method, bw, headers, parameters)) {
+ responseCode = conn.getResponseCode();
+ contentType = conn.getContentType();
+ if (contentType != null) {
+ try (InputStream in = conn.getInputStream(); Reader reader = new InputStreamReader(in)) {
str = CharStreams.toString(reader);
}
- final String contentType = conn.getContentType();
- if (contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON)) {
- final ServiceError serviceError = DtoFactory.getInstance().createDtoFromJson(str, ServiceError.class);
- if (serviceError.getMessage() != null) {
- if (responseCode == Response.Status.FORBIDDEN.getStatusCode()) {
- throw new ForbiddenException(serviceError);
- } else if (responseCode == Response.Status.NOT_FOUND.getStatusCode()) {
- throw new NotFoundException(serviceError);
- } else if (responseCode == Response.Status.UNAUTHORIZED.getStatusCode()) {
- throw new UnauthorizedException(serviceError);
- } else if (responseCode == Response.Status.CONFLICT.getStatusCode()) {
- throw new ConflictException(serviceError);
- } else if (responseCode == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
- throw new ServerException(serviceError);
- } else if (responseCode == Response.Status.BAD_REQUEST.getStatusCode()) {
- throw new BadRequestException(serviceError);
- }
- throw new ServerException(serviceError);
- }
- }
- // 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));
- }
- final String contentType = conn.getContentType();
- if (contentType != null && !contentType.startsWith(MediaType.APPLICATION_JSON)) {
- throw new IOException(conn.getResponseMessage() + " [ Content-Type: " + contentType + " ]");
}
-
- try (Reader reader = new InputStreamReader(conn.getInputStream())) {
- return new DefaultHttpJsonResponse(CharStreams.toString(reader), responseCode);
+ }
+ if ((responseCode / 100) != 2 && contentType != null && contentType.startsWith(MediaType.APPLICATION_JSON)) {
+ final ServiceError serviceError = DtoFactory.getInstance().createDtoFromJson(str, ServiceError.class);
+ if (serviceError.getMessage() != null) {
+ if (responseCode == Response.Status.FORBIDDEN.getStatusCode()) {
+ throw new ForbiddenException(serviceError);
+ } else if (responseCode == Response.Status.NOT_FOUND.getStatusCode()) {
+ throw new NotFoundException(serviceError);
+ } else if (responseCode == Response.Status.UNAUTHORIZED.getStatusCode()) {
+ throw new UnauthorizedException(serviceError);
+ } else if (responseCode == Response.Status.CONFLICT.getStatusCode()) {
+ throw new ConflictException(serviceError);
+ } else if (responseCode == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
+ throw new ServerException(serviceError);
+ } else if (responseCode == Response.Status.BAD_REQUEST.getStatusCode()) {
+ throw new BadRequestException(serviceError);
+ }
+ throw new ServerException(serviceError);
}
- } finally {
- conn.disconnect();
+ // 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",
+ url, method, responseCode, str));
}
- }
-
- private String getAuthenticationToken() {
- final User user = EnvironmentContext.getCurrent().getUser();
- if (user != null) {
- return user.getToken();
+ if (contentType != null && !contentType.startsWith(MediaType.APPLICATION_JSON)) {
+ throw new IOException(Response.Status.Family.familyOf(responseCode) + " [ Content-Type: " + contentType + " ]");
}
- return null;
+ return new DefaultHttpJsonResponse(str, responseCode);
}
+
}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequestFactory.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequestFactory.java
index 905c67168..5463172a8 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequestFactory.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpJsonRequestFactory.java
@@ -32,4 +32,10 @@ public HttpJsonRequest fromUrl(@NotNull String url) {
public HttpJsonRequest fromLink(@NotNull Link link) {
return new DefaultHttpJsonRequest(link);
}
+
+ @Override
+ public HttpRequest target(String url) {
+ return new DefaultHttpRequest(url);
+ }
+
}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequest.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequest.java
new file mode 100644
index 000000000..6e4dc1ce4
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequest.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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 static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Simple implementation of {@link HttpJsonRequest} based on {@link HttpURLConnection}.
+ *
+ *
+ * The implementation is not thread-safe, instance of this class must be created each time when it's needed.
+ *
+ *
+ * The instance of this request is reusable, which means that it is possible to call {@link #request()} method more than
+ * one time per instance
+ *
+ * @author Yevhenii Voevodin
+ * @see DefaultHttpJsonRequestFactory
+ */
+public class DefaultHttpRequest extends DefaultHttpRequestBase implements HttpRequest {
+
+ private BodyWriter bodyWriter;
+ private Map headers;
+
+ public DefaultHttpRequest(String url) {
+ super(url, null);
+ }
+
+ @Override
+ public HttpRequest setBodyWriter(BodyWriter bodyWriter) {
+ this.bodyWriter = Objects.requireNonNull(bodyWriter, "Required non-null body writer");
+ return this;
+ }
+
+ @Override
+ public HttpRequest 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 HttpResponse request() throws IOException {
+ beforeRequest();
+ return doGeneralRequest(timeout, url, method, bodyWriter, headers, queryParams);
+ }
+
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequestBase.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequestBase.java
new file mode 100644
index 000000000..2dc990b27
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/DefaultHttpRequestBase.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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 static java.util.Objects.requireNonNull;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriBuilder;
+
+import org.eclipse.che.api.core.rest.HttpRequest.BodyWriter;
+import org.eclipse.che.commons.env.EnvironmentContext;
+import org.eclipse.che.commons.lang.Pair;
+import org.eclipse.che.commons.user.User;
+
+/**
+ * A base class for all implementations of {@link HttpRequestBase}.
+ *
+ * @author Tareq Sharafy
+ *
+ * @param
+ */
+public class DefaultHttpRequestBase> implements HttpRequestBase {
+
+ private static final int DEFAULT_QUERY_PARAMS_LIST_SIZE = 5;
+
+ protected final String url;
+ protected int timeout;
+ protected String method;
+ protected List> queryParams;
+
+ protected DefaultHttpRequestBase(String url, String method) {
+ this.url = requireNonNull(url, "Required non-null url");
+ this.method = method;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public RequestT setMethod(@NotNull String method) {
+ this.method = requireNonNull(method, "Required non-null http method");
+ return (RequestT) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public RequestT addQueryParam(@NotNull String name, @NotNull Object value) {
+ requireNonNull(name, "Required non-null query parameter name");
+ requireNonNull(value, "Required non-null query parameter value");
+ if (queryParams == null) {
+ queryParams = new ArrayList<>(DEFAULT_QUERY_PARAMS_LIST_SIZE);
+ }
+ queryParams.add(Pair.of(name, value));
+ return (RequestT) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public RequestT setTimeout(int timeout) {
+ this.timeout = timeout;
+ return (RequestT) this;
+ }
+
+ /**
+ * Do any required validations before th erequest is executed.
+ */
+ protected void beforeRequest() {
+ if (method == null) {
+ throw new IllegalStateException("Could not perform request, request method wasn't set");
+ }
+ }
+
+ protected HttpResponse doGeneralRequest(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();
+ }
+ return null;
+ }
+
+}
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..4c4c26d2d 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
@@ -22,11 +22,9 @@
import org.eclipse.che.dto.server.JsonSerializable;
import javax.validation.constraints.NotNull;
-import javax.ws.rs.HttpMethod;
import java.io.IOException;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
/**
* Defines simple set of methods for requesting json objects.
@@ -60,18 +58,7 @@
* @see HttpJsonRequestFactory
*/
@Beta
-public interface HttpJsonRequest {
-
- /**
- * Sets http method to use in this request(e.g. {@link javax.ws.rs.HttpMethod#GET GET}).
- *
- * @param method
- * http method
- * @return this request instance
- * @throws NullPointerException
- * when {@code method} is null
- */
- HttpJsonRequest setMethod(@NotNull String method);
+public interface HttpJsonRequest extends HttpRequestBase {
/**
* Sets request body.
@@ -108,27 +95,6 @@ public interface HttpJsonRequest {
*/
HttpJsonRequest setBody(@NotNull List> list);
- /**
- * Adds query parameter to the request.
- *
- * @param name
- * query parameter name
- * @param value
- * query parameter value
- * @return this request instance
- * @throws NullPointerException
- * when either name or value is null
- */
- HttpJsonRequest addQueryParam(@NotNull String name, @NotNull Object value);
-
- /**
- * Sets request timeout.
- *
- * @param timeout
- * request timeout
- * @return this request instance
- */
- HttpJsonRequest setTimeout(int timeout);
/**
* Makes http request with content type "application/json" and authorization headers
@@ -160,61 +126,4 @@ HttpJsonResponse request() throws IOException,
ConflictException,
BadRequestException;
- /**
- * Uses {@link HttpMethod#GET} as a request method.
- *
- * @return this request instance
- */
- default HttpJsonRequest useGetMethod() {
- return setMethod(HttpMethod.GET);
- }
-
- /**
- * Uses {@link HttpMethod#OPTIONS} as a request method.
- *
- * @return this request instance
- */
- default HttpJsonRequest useOptionsMethod() {
- return setMethod(HttpMethod.OPTIONS);
- }
-
- /**
- * Uses {@link HttpMethod#POST} as a request method.
- *
- * @return this request instance
- */
- default HttpJsonRequest usePostMethod() {
- return setMethod(HttpMethod.POST);
- }
-
- /**
- * Uses {@link HttpMethod#DELETE} as a request method.
- *
- * @return this request instance
- */
- default HttpJsonRequest useDeleteMethod() {
- return setMethod(HttpMethod.DELETE);
- }
-
- /**
- * Uses {@link HttpMethod#PUT} as a request method.
- *
- * @return this request instance
- */
- default HttpJsonRequest usePutMethod() {
- return setMethod(HttpMethod.PUT);
- }
-
- /**
- * Adds set of query parameters to this request.
- *
- * @param params
- * query parameters map
- * @return this request instance
- */
- default HttpJsonRequest addQueryParams(@NotNull Map params) {
- Objects.requireNonNull(params, "Required non-null query parameters");
- params.forEach(this::addQueryParam);
- return this;
- }
}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequestFactory.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequestFactory.java
index 8ab8c17d2..fabe1b941 100644
--- a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequestFactory.java
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpJsonRequestFactory.java
@@ -24,7 +24,7 @@
*/
@Beta
@ImplementedBy(DefaultHttpJsonRequestFactory.class)
-public interface HttpJsonRequestFactory {
+public interface HttpJsonRequestFactory extends HttpRequestFactory {
/**
* Creates {@link HttpJsonRequest} based on {@code url}, with an initial HTTP method {@code GET}.
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequest.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequest.java
new file mode 100644
index 000000000..da41f3264
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequest.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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.OutputStream;
+
+import javax.validation.constraints.NotNull;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Defines simple set of methods for requesting json objects.
+ *
+ *
+ * Unlike {@link HttpJsonHelper} - provides builder-like style for building requests and getting responses.
+ *
+ *
+ * Simple use-cases:
+ *
+ *
+ * {@code
+ * // starting new workspace
+ * requestFactory.fromUri(apiEndpoint + "/workspace/" + id + "/runtime")
+ * .setMethod("POST")
+ * .addQueryParam("envName", envName)
+ * .addQueryParam("accountId", accountId)
+ * .request();
+ *
+ * // getting user preferences
+ * Map prefs = requestFactory.fromUri(apiEndpoint + "/profile/prefs")
+ * .setMethod("GET")
+ * .request()
+ * .asProperties();
+ *
+ * // getting workspace
+ * UsersWorkspaceDto workspace = requestFactory.fromLink(getWorkspaceLink)
+ * .request()
+ * .asDto(UsersWorkspaceDto.class);
+ * }
+ *
+ *
+ *
+ * Do not use this class for requesting content different from "application/json".
+ *
+ * @author Yevhenii Voevodin
+ * @see HttpJsonRequestFactory
+ */
+@Beta
+public interface HttpRequest extends HttpRequestBase {
+
+ public interface BodyWriter {
+ public void writeTo(OutputStream out) throws IOException;
+ }
+
+ /**
+ * 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
+ */
+ HttpRequest setBodyWriter(@NotNull BodyWriter bodyWriter);
+
+ /**
+ * Adds a header to the request.
+ *
+ * @param name
+ * The name of the header.
+ * @param value
+ * The value of the header.
+ * @return this request instance
+ */
+ HttpRequest addHeader(@NotNull String name, String value);
+
+ /**
+ * Makes http request.
+ *
+ * @return {@link HttpResponse} instance which represents response of this request
+ * @throws IOException
+ * when any io error occurs
+ */
+ HttpResponse request() throws IOException;
+
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestBase.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestBase.java
new file mode 100644
index 000000000..945c772cb
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestBase.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.util.Map;
+import java.util.Objects;
+
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.HttpMethod;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Defines simple set of methods for requesting json objects.
+ *
+ * Unlike {@link HttpJsonHelper} - provides builder-like style for building requests and getting responses.
+ *
+ *
Simple use-cases:
+ *
{@code
+ * // starting new workspace
+ * requestFactory.fromUri(apiEndpoint + "/workspace/" + id + "/runtime")
+ * .setMethod("POST")
+ * .addQueryParam("envName", envName)
+ * .addQueryParam("accountId", accountId)
+ * .request();
+ *
+ * // getting user preferences
+ * Map prefs = requestFactory.fromUri(apiEndpoint + "/profile/prefs")
+ * .setMethod("GET")
+ * .request()
+ * .asProperties();
+ *
+ * // getting workspace
+ * UsersWorkspaceDto workspace = requestFactory.fromLink(getWorkspaceLink)
+ * .request()
+ * .asDto(UsersWorkspaceDto.class);
+ * }
+ *
+ * Do not use this class for requesting content different from "application/json".
+ *
+ * @author Yevhenii Voevodin
+ * @see HttpJsonRequestFactory
+ */
+@Beta
+public interface HttpRequestBase> {
+
+ static final int DEFAULT_TIMEOUT = 60 * 1000;
+
+ /**
+ * Sets http method to use in this request(e.g. {@link javax.ws.rs.HttpMethod#GET GET}).
+ *
+ * @param method
+ * http method
+ * @return this request instance
+ * @throws NullPointerException
+ * when {@code method} is null
+ */
+ RequestT setMethod(@NotNull String method);
+
+ /**
+ * Adds query parameter to the request.
+ *
+ * @param name
+ * query parameter name
+ * @param value
+ * query parameter value
+ * @return this request instance
+ * @throws NullPointerException
+ * when either name or value is null
+ */
+ RequestT addQueryParam(@NotNull String name, @NotNull Object value);
+
+ /**
+ * Sets request timeout.
+ *
+ * @param timeout
+ * request timeout
+ * @return this request instance
+ */
+ RequestT setTimeout(int timeout);
+
+ /**
+ * Uses {@link HttpMethod#GET} as a request method.
+ *
+ * @return this request instance
+ */
+ default RequestT useGetMethod() {
+ return setMethod(HttpMethod.GET);
+ }
+
+ /**
+ * Uses {@link HttpMethod#OPTIONS} as a request method.
+ *
+ * @return this request instance
+ */
+ default RequestT useOptionsMethod() {
+ return setMethod(HttpMethod.OPTIONS);
+ }
+
+ /**
+ * Uses {@link HttpMethod#POST} as a request method.
+ *
+ * @return this request instance
+ */
+ default RequestT usePostMethod() {
+ return setMethod(HttpMethod.POST);
+ }
+
+ /**
+ * Uses {@link HttpMethod#DELETE} as a request method.
+ *
+ * @return this request instance
+ */
+ default RequestT useDeleteMethod() {
+ return setMethod(HttpMethod.DELETE);
+ }
+
+ /**
+ * Uses {@link HttpMethod#PUT} as a request method.
+ *
+ * @return this request instance
+ */
+ default RequestT usePutMethod() {
+ return setMethod(HttpMethod.PUT);
+ }
+
+ /**
+ * Adds set of query parameters to this request.
+ *
+ * @param params
+ * query parameters map
+ * @return this request instance
+ */
+ default RequestT addQueryParams(@NotNull Map params) {
+ Objects.requireNonNull(params, "Required non-null query parameters");
+ params.forEach(this::addQueryParam);
+ @SuppressWarnings("unchecked")
+ RequestT r = (RequestT) this; // to avoid suppressing on the whole method
+ return r;
+ }
+}
diff --git a/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestFactory.java b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestFactory.java
new file mode 100644
index 000000000..772c5de5b
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpRequestFactory.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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 javax.validation.constraints.NotNull;
+
+import com.google.common.annotations.Beta;
+import com.google.inject.ImplementedBy;
+
+/**
+ * Factory for {@link HttpRequest} instances.
+ *
+ * @author Yevhenii Voevodin
+ */
+@Beta
+@ImplementedBy(DefaultHttpJsonRequestFactory.class)
+public interface HttpRequestFactory {
+
+ /**
+ * Creates {@link HttpJsonRequest} based on {@code url}, with an initial HTTP method {@code GET}.
+ *
+ * @param url
+ * request target url
+ * @return new instance of {@link HttpRequest}
+ * @throws NullPointerException
+ * when url is null
+ */
+ HttpRequest target(@NotNull String url);
+
+}
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..8172e5691
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/HttpResponse.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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;
+
+ @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..a6b35c45a
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/URLConnectionHttpResponse.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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 {
+ InputStream errStm = conn.getErrorStream();
+ return errStm != null ? errStm : 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();
+ }
+
+}
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..a7489fdbc
--- /dev/null
+++ b/platform-api/che-core-api-core/src/main/java/org/eclipse/che/api/core/util/DownloadPluginImpl.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.Inject;
+import javax.inject.Singleton;
+
+import org.eclipse.che.api.core.rest.HttpRequestFactory;
+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 HttpRequestFactory provider;
+
+ @Inject
+ public DownloadPluginImpl(HttpRequestFactory provider) {
+ this.provider = provider;
+ }
+
+ @Override
+ protected HttpResponse openUrlConnection(String downloadUrl) throws IOException {
+ // Check it
+ HttpResponse conn = provider.target(downloadUrl).setTimeout(READ_TIMEOUT).request();
+ // 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..35f3a56f2 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.target(url).setTimeout(60 * 1000).setMethod(method).request()) {
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..7f1abbd27 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.target(url.toString()).setTimeout(1000).setMethod(requestMethod).request()) {
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..52a70ba3c 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,8 @@
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.HttpRequest;
+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;
@@ -148,6 +150,11 @@ public HttpJsonRequest fromUrl(String url) {
public HttpJsonRequest fromLink(Link link) {
return new TestJsonRequest(link);
}
+
+ @Override
+ public HttpRequest target(String url) {
+ return null;
+ }
}
@BeforeMethod