CHE-10286: Switch import rest methods to Json-rpc (#10440)

6.19.x
Igor Vinokur 2018-07-18 12:01:15 +03:00 committed by GitHub
parent b0eab79dfc
commit 080e17836f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 175 additions and 91 deletions

View File

@ -15,7 +15,11 @@ import static com.google.gwt.http.client.RequestBuilder.DELETE;
import static com.google.gwt.http.client.RequestBuilder.PUT;
import static com.google.gwt.http.client.URL.encodePathSegment;
import static com.google.gwt.http.client.URL.encodeQueryString;
import static org.eclipse.che.api.project.shared.Constants.Services.PROJECTS_BATCH;
import static org.eclipse.che.api.project.shared.Constants.Services.PROJECT_IMPORT;
import static org.eclipse.che.ide.MimeType.APPLICATION_JSON;
import static org.eclipse.che.ide.api.jsonrpc.Constants.WS_AGENT_JSON_RPC_ENDPOINT_ID;
import static org.eclipse.che.ide.jsonrpc.JsonRpcErrorUtils.getPromiseError;
import static org.eclipse.che.ide.rest.HTTPHeader.ACCEPT;
import static org.eclipse.che.ide.rest.HTTPHeader.CONTENT_TYPE;
import static org.eclipse.che.ide.util.PathEncoder.encodePath;
@ -25,6 +29,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.project.shared.dto.CopyOptions;
import org.eclipse.che.api.project.shared.dto.ItemReference;
import org.eclipse.che.api.project.shared.dto.MoveOptions;
@ -33,8 +38,11 @@ import org.eclipse.che.api.project.shared.dto.ProjectSearchResponseDto;
import org.eclipse.che.api.project.shared.dto.SearchResultDto;
import org.eclipse.che.api.project.shared.dto.SourceEstimation;
import org.eclipse.che.api.project.shared.dto.TreeElement;
import org.eclipse.che.api.project.shared.dto.service.CreateBatchProjectsRequestDto;
import org.eclipse.che.api.project.shared.dto.service.ImportRequestDto;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.ide.MimeType;
@ -67,7 +75,6 @@ public class ProjectServiceClient {
private static final String FOLDER = "/folder";
private static final String FILE = "/file";
private static final String SEARCH = "/search";
private static final String IMPORT = "/import";
private static final String RESOLVE = "/resolve";
private static final String ESTIMATE = "/estimate";
@ -75,6 +82,7 @@ public class ProjectServiceClient {
private final AsyncRequestFactory reqFactory;
private final DtoFactory dtoFactory;
private final DtoUnmarshallerFactory unmarshaller;
private final RequestTransmitter requestTransmitter;
private final AppContext appContext;
@Inject
@ -83,11 +91,13 @@ public class ProjectServiceClient {
AsyncRequestFactory reqFactory,
DtoFactory dtoFactory,
DtoUnmarshallerFactory unmarshaller,
RequestTransmitter requestTransmitter,
AppContext appContext) {
this.loaderFactory = loaderFactory;
this.reqFactory = reqFactory;
this.dtoFactory = dtoFactory;
this.unmarshaller = unmarshaller;
this.requestTransmitter = requestTransmitter;
this.appContext = appContext;
}
@ -159,12 +169,20 @@ public class ProjectServiceClient {
* @since 4.4.0
*/
public Promise<Void> importProject(Path path, SourceStorageDto source) {
String url = getBaseUrl() + IMPORT + encodePath(path);
url += url.contains("?") ? "&" : "?";
url += "clientId=" + appContext.getApplicationId().orElse("");
return reqFactory.createPostRequest(url, source).header(CONTENT_TYPE, APPLICATION_JSON).send();
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(PROJECT_IMPORT)
.paramsAsDto(
dtoFactory
.createDto(ImportRequestDto.class)
.withWsPath(path.toString())
.withSourceStorage(source))
.sendAndReceiveResultAsDto(ImportRequestDto.class)
.onSuccess(() -> resolve.apply(null))
.onFailure(error -> reject.apply(getPromiseError(error))));
}
/**
@ -264,18 +282,19 @@ public class ProjectServiceClient {
*/
public Promise<List<ProjectConfigDto>> createBatchProjects(
List<NewProjectConfigDto> configurations) {
String url = getBaseUrl() + BATCH_PROJECTS;
url += url.contains("?") ? "&" : "?";
url += "clientId=" + appContext.getApplicationId().orElse("");
final String loaderMessage =
configurations.size() > 1 ? "Creating the batch of projects..." : "Creating project...";
return reqFactory
.createPostRequest(url, configurations)
.header(ACCEPT, APPLICATION_JSON)
.loader(loaderFactory.newLoader(loaderMessage))
.send(unmarshaller.newListUnmarshaller(ProjectConfigDto.class));
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(PROJECTS_BATCH)
.paramsAsDto(
dtoFactory
.createDto(CreateBatchProjectsRequestDto.class)
.withNewProjectConfigs(configurations))
.sendAndReceiveResultAsListOfDto(ProjectConfigDto.class)
.onSuccess(resolve::apply)
.onFailure(error -> reject.apply(getPromiseError(error))));
}
/**

View File

@ -32,6 +32,7 @@ import com.google.gwt.http.client.RequestBuilder;
import com.google.gwtmockito.GwtMockitoTestRunner;
import java.util.Arrays;
import java.util.List;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.project.shared.dto.CopyOptions;
import org.eclipse.che.api.project.shared.dto.ItemReference;
@ -81,6 +82,7 @@ public class ProjectServiceClientTest {
@Mock private AsyncRequestFactory requestFactory;
@Mock private DtoFactory dtoFactory;
@Mock private DtoUnmarshallerFactory unmarshaller;
@Mock private RequestTransmitter transmitter;
@Mock private AppContext appContext;
@Mock private AsyncRequest asyncRequest;
@ -108,7 +110,7 @@ public class ProjectServiceClientTest {
public void setUp() throws Exception {
client =
new ProjectServiceClient(
loaderFactory, requestFactory, dtoFactory, unmarshaller, appContext);
loaderFactory, requestFactory, dtoFactory, unmarshaller, transmitter, appContext);
when(loaderFactory.newLoader(any(String.class))).thenReturn(messageLoader);
when(asyncRequest.loader(messageLoader)).thenReturn(asyncRequest);

View File

@ -41,6 +41,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-annotations</artifactId>

View File

@ -8,15 +8,17 @@
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.plugin.languageserver.ide.service;
package org.eclipse.che.ide.jsonrpc;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcException;
import org.eclipse.che.api.promises.client.PromiseError;
public class ServiceUtil {
private ServiceUtil() {}
public class JsonRpcErrorUtils {
private JsonRpcErrorUtils() {}
/** Transform {@link JsonRpcError} to {@link PromiseError}. */
public static PromiseError getPromiseError(JsonRpcError jsonRpcError) {
return new PromiseError() {
@Override

View File

@ -11,13 +11,12 @@
package org.eclipse.che.plugin.languageserver.ide.service;
import static org.eclipse.che.ide.api.jsonrpc.Constants.WS_AGENT_JSON_RPC_ENDPOINT_ID;
import static org.eclipse.che.ide.jsonrpc.JsonRpcErrorUtils.getPromiseError;
import java.util.List;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcException;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.languageserver.shared.model.LanguageRegex;
import org.eclipse.che.api.promises.client.Promise;
@ -46,7 +45,7 @@ public class LanguageServerServiceClient {
.sendAndReceiveResultAsDto(ServerCapabilities.class, 30_000)
.onSuccess(resolve::apply)
.onFailure(error -> reject.apply(getPromiseError(error)))
.onTimeout(() -> reject.apply(getPromiseError())));
.onTimeout(() -> reject.apply(getTimeoutPromiseError())));
}
public Promise<List<LanguageRegex>> getLanguageRegexes() {
@ -62,21 +61,7 @@ public class LanguageServerServiceClient {
.onFailure(error -> reject.apply(getPromiseError(error))));
}
private PromiseError getPromiseError(JsonRpcError jsonRpcError) {
return new PromiseError() {
@Override
public String getMessage() {
return jsonRpcError.getMessage();
}
@Override
public Throwable getCause() {
return new JsonRpcException(jsonRpcError.getCode(), jsonRpcError.getMessage());
}
};
}
private PromiseError getPromiseError() {
private PromiseError getTimeoutPromiseError() {
return new PromiseError() {
@Override

View File

@ -11,18 +11,16 @@
package org.eclipse.che.plugin.languageserver.ide.service;
import static org.eclipse.che.ide.api.jsonrpc.Constants.WS_AGENT_JSON_RPC_ENDPOINT_ID;
import static org.eclipse.che.ide.jsonrpc.JsonRpcErrorUtils.getPromiseError;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcError;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcException;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.languageserver.shared.model.ExtendedCompletionItem;
import org.eclipse.che.api.languageserver.shared.model.ExtendedCompletionList;
import org.eclipse.che.api.languageserver.shared.model.RenameResult;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.Command;
@ -263,18 +261,4 @@ public class TextDocumentServiceClient {
.paramsAsDto(jsonSerializable)
.sendAndSkipResult();
}
private PromiseError getPromiseError(JsonRpcError jsonRpcError) {
return new PromiseError() {
@Override
public String getMessage() {
return jsonRpcError.getMessage();
}
@Override
public Throwable getCause() {
return new JsonRpcException(jsonRpcError.getCode(), jsonRpcError.getMessage());
}
};
}
}

View File

@ -11,7 +11,7 @@
package org.eclipse.che.plugin.languageserver.ide.service;
import static org.eclipse.che.ide.api.jsonrpc.Constants.WS_AGENT_JSON_RPC_ENDPOINT_ID;
import static org.eclipse.che.plugin.languageserver.ide.service.ServiceUtil.getPromiseError;
import static org.eclipse.che.ide.jsonrpc.JsonRpcErrorUtils.getPromiseError;
import com.google.inject.Inject;
import com.google.inject.Singleton;

View File

@ -45,6 +45,7 @@ public class Constants {
public static final String PROJECT_GET = "project/get";
public static final String PROJECT_CREATE = "project/create";
public static final String PROJECTS_BATCH = "projects/batch";
public static final String PROJECT_UPDATE = "project/update";
public static final String PROJECT_DELETE = "project/delete";
public static final String PROJECT_RECOGNIZE = "project/recognize";

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2012-2018 Red Hat, Inc.
* 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:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.api.project.shared.dto.service;
import java.util.List;
import org.eclipse.che.api.project.shared.dto.NewProjectConfigDto;
import org.eclipse.che.dto.shared.DTO;
@DTO
public interface CreateBatchProjectsRequestDto {
boolean isRewrite();
void setRewrite(boolean rewrite);
CreateBatchProjectsRequestDto withRewrite(boolean rewrite);
List<NewProjectConfigDto> getNewProjectConfigs();
void setNewProjectConfigs(List<NewProjectConfigDto> newProjectConfigs);
CreateBatchProjectsRequestDto withNewProjectConfigs(List<NewProjectConfigDto> newProjectConfigs);
}

View File

@ -19,7 +19,11 @@ public interface ImportRequestDto {
void setWsPath(String wsPath);
ImportRequestDto withWsPath(String wsPath);
SourceStorageDto getSourceStorage();
void setSourceStorage(SourceStorageDto sourceStorage);
ImportRequestDto withSourceStorage(SourceStorageDto sourceStorage);
}

View File

@ -69,6 +69,8 @@ public class ProjectApiModule extends AbstractModule {
bind(ProjectConfigRegistry.class).to(InmemoryProjectRegistry.class);
bind(ProjectJsonRpcServiceConfigurator.class).asEagerSingleton();
newSetBinder(binder(), ProjectImporter.class).addBinding().to(ZipProjectImporter.class);
newSetBinder(binder(), ProjectTypeDef.class).addBinding().to(BaseProjectType.class);

View File

@ -17,7 +17,22 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
import org.eclipse.che.api.project.server.impl.ProjectJsonRpcServiceBackEnd;
import org.eclipse.che.api.project.shared.dto.service.*;
import org.eclipse.che.api.project.shared.dto.service.CreateBatchProjectsRequestDto;
import org.eclipse.che.api.project.shared.dto.service.CreateRequestDto;
import org.eclipse.che.api.project.shared.dto.service.CreateResponseDto;
import org.eclipse.che.api.project.shared.dto.service.DeleteRequestDto;
import org.eclipse.che.api.project.shared.dto.service.DeleteResponseDto;
import org.eclipse.che.api.project.shared.dto.service.GetRequestDto;
import org.eclipse.che.api.project.shared.dto.service.GetResponseDto;
import org.eclipse.che.api.project.shared.dto.service.ImportRequestDto;
import org.eclipse.che.api.project.shared.dto.service.ImportResponseDto;
import org.eclipse.che.api.project.shared.dto.service.RecognizeRequestDto;
import org.eclipse.che.api.project.shared.dto.service.RecognizeResponseDto;
import org.eclipse.che.api.project.shared.dto.service.UpdateRequestDto;
import org.eclipse.che.api.project.shared.dto.service.UpdateResponseDto;
import org.eclipse.che.api.project.shared.dto.service.VerifyRequestDto;
import org.eclipse.che.api.project.shared.dto.service.VerifyResponseDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
@Singleton
public class ProjectJsonRpcServiceConfigurator {
@ -82,5 +97,12 @@ public class ProjectJsonRpcServiceConfigurator {
.paramsAsDto(ImportRequestDto.class)
.resultAsDto(ImportResponseDto.class)
.withBiFunction(service::doImport);
handlers
.newConfiguration()
.methodName(PROJECTS_BATCH)
.paramsAsDto(CreateBatchProjectsRequestDto.class)
.resultAsListOfDto(ProjectConfigDto.class)
.withBiFunction(service::createBatchProjects);
}
}

View File

@ -23,9 +23,11 @@ import static org.eclipse.che.api.project.shared.Constants.Services.UNAUTHORIZED
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -38,25 +40,15 @@ import org.eclipse.che.api.core.UnauthorizedException;
import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcException;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.project.server.ProjectManager;
import org.eclipse.che.api.project.server.notification.ProjectCreatedEvent;
import org.eclipse.che.api.project.server.type.ProjectTypeResolution;
import org.eclipse.che.api.project.shared.RegisteredProject;
import org.eclipse.che.api.project.shared.dto.ImportProgressRecordDto;
import org.eclipse.che.api.project.shared.dto.NewProjectConfigDto;
import org.eclipse.che.api.project.shared.dto.SourceEstimation;
import org.eclipse.che.api.project.shared.dto.service.CreateRequestDto;
import org.eclipse.che.api.project.shared.dto.service.CreateResponseDto;
import org.eclipse.che.api.project.shared.dto.service.DeleteRequestDto;
import org.eclipse.che.api.project.shared.dto.service.DeleteResponseDto;
import org.eclipse.che.api.project.shared.dto.service.GetRequestDto;
import org.eclipse.che.api.project.shared.dto.service.GetResponseDto;
import org.eclipse.che.api.project.shared.dto.service.ImportRequestDto;
import org.eclipse.che.api.project.shared.dto.service.ImportResponseDto;
import org.eclipse.che.api.project.shared.dto.service.RecognizeRequestDto;
import org.eclipse.che.api.project.shared.dto.service.RecognizeResponseDto;
import org.eclipse.che.api.project.shared.dto.service.UpdateRequestDto;
import org.eclipse.che.api.project.shared.dto.service.UpdateResponseDto;
import org.eclipse.che.api.project.shared.dto.service.VerifyRequestDto;
import org.eclipse.che.api.project.shared.dto.service.VerifyResponseDto;
import org.eclipse.che.api.project.shared.dto.service.*;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
@ -65,12 +57,16 @@ public class ProjectJsonRpcServiceBackEnd {
private final ProjectManager projectManager;
private final RequestTransmitter requestTransmitter;
private final EventService eventService;
@Inject
public ProjectJsonRpcServiceBackEnd(
ProjectManager projectManager, RequestTransmitter requestTransmitter) {
ProjectManager projectManager,
RequestTransmitter requestTransmitter,
EventService eventService) {
this.projectManager = projectManager;
this.requestTransmitter = requestTransmitter;
this.eventService = eventService;
}
public GetResponseDto get(GetRequestDto getRequestDto) {
@ -101,6 +97,11 @@ public class ProjectJsonRpcServiceBackEnd {
return perform(this::doImportInternally, endpointId, importRequestDto);
}
public List<ProjectConfigDto> createBatchProjects(
String endpointId, CreateBatchProjectsRequestDto createProjectsRequest) {
return perform(this::createBatchProjectsInternally, endpointId, createProjectsRequest);
}
private GetResponseDto getInternally(GetRequestDto request)
throws ServerException, ConflictException, ForbiddenException, BadRequestException,
NotFoundException {
@ -229,26 +230,14 @@ public class ProjectJsonRpcServiceBackEnd {
}
private ImportResponseDto doImportInternally(String endpointId, ImportRequestDto request)
throws ServerException, ConflictException, ForbiddenException, BadRequestException,
NotFoundException, UnauthorizedException {
throws ServerException, ConflictException, ForbiddenException, NotFoundException,
UnauthorizedException {
String wsPath = request.getWsPath();
SourceStorageDto sourceStorage = request.getSourceStorage();
BiConsumer<String, String> consumer =
(projectName, message) -> {
ImportProgressRecordDto progressRecord =
newDto(ImportProgressRecordDto.class).withProjectName(projectName).withLine(message);
requestTransmitter
.newRequest()
.endpointId(endpointId)
.methodName(EVENT_IMPORT_OUTPUT_PROGRESS)
.paramsAsDto(progressRecord)
.sendAndSkipResult();
};
RegisteredProject registeredProject =
projectManager.doImport(wsPath, sourceStorage, false, consumer);
projectManager.doImport(wsPath, sourceStorage, false, getImportConsumer(endpointId));
eventService.publish(new ProjectCreatedEvent(wsPath));
ProjectConfigDto projectConfigDto = asDto(registeredProject);
ImportResponseDto response = newDto(ImportResponseDto.class);
response.setConfig(projectConfigDto);
@ -256,6 +245,46 @@ public class ProjectJsonRpcServiceBackEnd {
return response;
}
private List<ProjectConfigDto> createBatchProjectsInternally(
String endpointId, CreateBatchProjectsRequestDto createProjectsRequest)
throws ForbiddenException, BadRequestException, ConflictException, NotFoundException,
ServerException, UnauthorizedException {
List<NewProjectConfigDto> newProjectConfigs = createProjectsRequest.getNewProjectConfigs();
projectManager.doImport(
new HashSet<>(newProjectConfigs),
createProjectsRequest.isRewrite(),
getImportConsumer(endpointId));
Set<RegisteredProject> registeredProjects = new HashSet<>(newProjectConfigs.size());
for (NewProjectConfigDto projectConfig : newProjectConfigs) {
registeredProjects.add(projectManager.update(projectConfig));
}
registeredProjects
.stream()
.map(RegisteredProject::getPath)
.map(ProjectCreatedEvent::new)
.forEach(eventService::publish);
return registeredProjects.stream().map(ProjectDtoConverter::asDto).collect(toList());
}
private BiConsumer<String, String> getImportConsumer(String endpointId) {
return (projectName, message) -> {
ImportProgressRecordDto progressRecord =
newDto(ImportProgressRecordDto.class).withProjectName(projectName).withLine(message);
requestTransmitter
.newRequest()
.endpointId(endpointId)
.methodName(EVENT_IMPORT_OUTPUT_PROGRESS)
.paramsAsDto(progressRecord)
.sendAndSkipResult();
};
}
// TODO temporary solution, further need to make a generalized exception mapper for all json rpc
// service
private <Request, Response> Response perform(