From 8d3c27e5be46967095bce7f2f7d3be59a5e063c2 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Tue, 1 Oct 2019 17:38:15 +0300 Subject: [PATCH 01/13] Devfile validation via message body reader; --- .../che/api/deploy/WsMasterModule.java | 4 + wsmaster/che-core-api-workspace/pom.xml | 9 +- .../server/JavaxExceptionMapper.java | 71 +++++++++++ .../server/WorkspaceEntityProvider.java | 116 ++++++++++++++++++ .../workspace/server/WorkspaceService.java | 22 +--- .../server/devfile/DevfileEntityProvider.java | 114 +++++++++++++++++ .../server/devfile/DevfileModule.java | 1 + .../validator/DevfileSchemaValidator.java | 2 +- 8 files changed, 314 insertions(+), 25 deletions(-) create mode 100644 wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java create mode 100644 wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java create mode 100644 wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index cbe7fa9c3dc..ca4efaee970 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -42,6 +42,8 @@ import org.eclipse.che.api.user.server.jpa.JpaUserDao; import org.eclipse.che.api.user.server.spi.PreferenceDao; import org.eclipse.che.api.user.server.spi.UserDao; +import org.eclipse.che.api.workspace.server.JavaxExceptionMapper; +import org.eclipse.che.api.workspace.server.WorkspaceEntityProvider; import org.eclipse.che.api.workspace.server.WorkspaceLockService; import org.eclipse.che.api.workspace.server.WorkspaceStatusCache; import org.eclipse.che.api.workspace.server.devfile.DevfileModule; @@ -148,6 +150,8 @@ protected void configure() { install(new DevfileModule()); + bind(WorkspaceEntityProvider.class); + bind(JavaxExceptionMapper.class); bind(org.eclipse.che.api.workspace.server.TemporaryWorkspaceRemover.class); bind(org.eclipse.che.api.workspace.server.WorkspaceService.class); install(new FactoryModuleBuilder().build(ServersCheckerFactory.class)); diff --git a/wsmaster/che-core-api-workspace/pom.xml b/wsmaster/che-core-api-workspace/pom.xml index eed5ec06c1e..fa7f07cb75b 100644 --- a/wsmaster/che-core-api-workspace/pom.xml +++ b/wsmaster/che-core-api-workspace/pom.xml @@ -134,6 +134,10 @@ org.eclipse.che.core che-core-commons-tracing + + org.everrest + everrest-core + org.glassfish javax.json @@ -232,11 +236,6 @@ everrest-assured test - - org.everrest - everrest-core - test - org.everrest everrest-test diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java new file mode 100644 index 00000000000..63a3a8d9178 --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server; + +import static org.eclipse.che.dto.server.DtoFactory.newDto; + +import javax.inject.Singleton; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.ForbiddenException; +import javax.ws.rs.NotAcceptableException; +import javax.ws.rs.NotAuthorizedException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.eclipse.che.api.core.rest.shared.dto.ServiceError; +import org.eclipse.che.dto.server.DtoFactory; + +@Provider +@Singleton +public class JavaxExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(WebApplicationException exception) { + + ServiceError error = newDto(ServiceError.class).withMessage(exception.getMessage()); + if (exception instanceof ForbiddenException) { + return Response.status(Response.Status.FORBIDDEN) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotFoundException) { + return Response.status(Response.Status.NOT_FOUND) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotAuthorizedException) { + return Response.status(Response.Status.UNAUTHORIZED) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof BadRequestException) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotAcceptableException) { + return Response.status(Status.NOT_ACCEPTABLE) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else { + return Response.serverError() + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } + } +} diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java new file mode 100644 index 00000000000..bd0853e81f3 --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server; + + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.eclipse.che.api.workspace.server.DtoConverter.asDto; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.Provider; +import org.eclipse.che.api.workspace.server.devfile.DevfileManager; +import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; +import org.eclipse.che.api.workspace.server.dto.DtoServerImpls.WorkspaceDtoImpl; +import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.eclipse.che.dto.server.DtoFactory; +import org.everrest.core.provider.EntityProvider; + +@Singleton +@Provider +@Produces({APPLICATION_JSON}) +@Consumes({APPLICATION_JSON}) +public class WorkspaceEntityProvider implements EntityProvider { + + protected DevfileManager devfileManager; + protected ObjectMapper mapper = new ObjectMapper(); + + @Inject + public WorkspaceEntityProvider(DevfileManager devfileManager) { + this.devfileManager = devfileManager; + SimpleModule module = new SimpleModule(); + module.addDeserializer(DevfileDto.class, new DevfileDtoDeserializer()); + mapper.registerModule(module); + + } + + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return type == WorkspaceDto.class; + } + + @Override + public WorkspaceDto readFrom(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + return mapper.readerFor(WorkspaceDtoImpl.class).without(DeserializationFeature.WRAP_EXCEPTIONS) + .readValue(entityStream); + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return WorkspaceDto.class.isAssignableFrom(type); + } + + @Override + public long getSize(WorkspaceDto workspaceDto, Class type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public void writeTo(WorkspaceDto workspaceDto, Class type, Type genericType, + Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { + httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, "public, no-cache, no-store, no-transform"); + try (Writer w = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) { + w.write(DtoFactory.getInstance().toJson(workspaceDto)); + w.flush(); + } + } + + class DevfileDtoDeserializer extends JsonDeserializer { + @Override + public DevfileDto deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + try { + return asDto(devfileManager.parseJson(p.readValueAsTree().toString())); + } catch (DevfileFormatException e) { + throw new BadRequestException(e.getMessage()); + } + } + } +} diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java index ed19cdc2864..01a97cddfe2 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java @@ -17,7 +17,6 @@ import static java.util.stream.Collectors.toList; import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static javax.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; import static org.eclipse.che.api.workspace.server.DtoConverter.asDto; import static org.eclipse.che.api.workspace.server.WorkspaceKeyValidator.validateKey; import static org.eclipse.che.api.workspace.shared.Constants.CHE_WORKSPACE_AUTO_START; @@ -70,12 +69,10 @@ import org.eclipse.che.api.workspace.server.devfile.FileContentProvider; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; import org.eclipse.che.api.workspace.server.devfile.URLFileContentProvider; -import org.eclipse.che.api.workspace.server.devfile.exception.DevfileException; import org.eclipse.che.api.workspace.server.model.impl.CommandImpl; import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl; import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl; -import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; import org.eclipse.che.api.workspace.server.token.MachineAccessForbidden; import org.eclipse.che.api.workspace.server.token.MachineTokenException; import org.eclipse.che.api.workspace.server.token.MachineTokenProvider; @@ -89,6 +86,7 @@ import org.eclipse.che.api.workspace.shared.dto.ServerDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; import org.eclipse.che.commons.annotation.Nullable; import org.eclipse.che.commons.env.EnvironmentContext; @@ -222,7 +220,7 @@ public Response create( @ApiResponse(code = 500, message = "Internal server error occurred") }) public Response create( - @ApiParam(value = "The devfile of the workspace to create", required = true) String devfile, + @ApiParam(value = "The devfile of the workspace to create", required = true) DevfileDto devfile, @ApiParam( value = "Workspace attribute defined in 'attrName:attrValue' format. " @@ -242,29 +240,15 @@ public Response create( throws ConflictException, BadRequestException, ForbiddenException, NotFoundException, ServerException { requiredNotNull(devfile, "Devfile"); - - DevfileImpl devfileModel; - try { - if (APPLICATION_JSON_TYPE.isCompatible(contentType)) { - devfileModel = devfileManager.parseJson(devfile); - } else { - devfileModel = devfileManager.parseYaml(devfile); - } - } catch (DevfileException e) { - throw new BadRequestException(e.getMessage()); - } - final Map attributes = parseAttrs(attrsList); - if (namespace == null) { namespace = EnvironmentContext.getCurrent().getSubject().getUserName(); } - WorkspaceImpl workspace; try { workspace = workspaceManager.createWorkspace( - devfileModel, + devfile, namespace, attributes, // create a new cache for each request so that we don't have to care about lifetime diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java new file mode 100644 index 00000000000..d848696225d --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server.devfile; + +import static com.google.common.base.Strings.isNullOrEmpty; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.eclipse.che.api.workspace.server.DtoConverter.asDto; + +import com.google.common.io.CharStreams; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.ClientErrorException; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.Provider; +import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.eclipse.che.dto.server.DtoFactory; +import org.everrest.core.provider.EntityProvider; + +@Singleton +@Provider +@Produces({APPLICATION_JSON}) +@Consumes({APPLICATION_JSON, "text/yaml", "text/x-yaml"}) +public class DevfileEntityProvider implements EntityProvider { + + private DevfileManager devfileManager; + + @Inject + public DevfileEntityProvider(DevfileManager devfileManager) { + this.devfileManager = devfileManager; + } + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return type == DevfileDto.class; + } + + @Override + public DevfileDto readFrom(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + + try { + if (mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) { + return asDto(devfileManager.parseJson(CharStreams + .toString(new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); + } else if (mediaType.isCompatible(MediaType.valueOf("text/yaml")) || mediaType + .isCompatible(MediaType.valueOf("text/x-yaml"))) { + return asDto(devfileManager.parseYaml(CharStreams + .toString(new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); + } + } catch (DevfileFormatException e) { + throw new BadRequestException(e.getMessage()); + } + throw new ClientErrorException("Unknown media type " + mediaType.toString(), 400); + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + return DevfileDto.class.isAssignableFrom(type); + } + + @Override + public long getSize(DevfileDto devfileDto, Class type, Type genericType, + Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public void writeTo(DevfileDto devfileDto, Class type, Type genericType, + Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { + httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, "public, no-cache, no-store, no-transform"); + try (Writer w = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) { + w.write(DtoFactory.getInstance().toJson(devfileDto)); + w.flush(); + } + + } + + private String getCharsetOrUtf8(MediaType mediaType) { + String charset = mediaType == null ? null : mediaType.getParameters().get("charset"); + if (isNullOrEmpty(charset)) { + charset = "UTF-8"; + } + return charset; + } +} diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileModule.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileModule.java index 2184f9d5bf7..ab49aff0bc7 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileModule.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileModule.java @@ -25,6 +25,7 @@ public class DevfileModule extends AbstractModule { @Override protected void configure() { bind(DevfileService.class); + bind(DevfileEntityProvider.class); DevfileBindings.onWorkspaceApplierBinder( binder(), diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java index dbea4a20b13..7c91f92a945 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java @@ -71,7 +71,7 @@ private JsonNode validate(String content, ObjectMapper mapper) throws DevfileFor } } - private void validate(JsonNode contentNode) throws DevfileFormatException { + public void validate(JsonNode contentNode) throws DevfileFormatException { try { List validationErrors = new ArrayList<>(); ProblemHandler handler = ProblemHandler.collectingTo(validationErrors); From 86c3e7ecd5f9fcb843e6341305fb47c4ecad8891 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Wed, 2 Oct 2019 16:19:56 +0300 Subject: [PATCH 02/13] Prepare for review fixes --- .../che/api/deploy/WsMasterModule.java | 4 +- .../server/JavaxExceptionMapper.java | 71 ------------------- .../server/WorkspaceEntityProvider.java | 48 ++++++++----- .../workspace/server/WorkspaceService.java | 11 ++- .../server/devfile/DevfileEntityProvider.java | 54 +++++++++----- .../validator/DevfileSchemaValidator.java | 2 +- .../server/WorkspaceServiceTest.java | 53 +------------- 7 files changed, 77 insertions(+), 166 deletions(-) delete mode 100644 wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index ca4efaee970..f39a6701122 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -42,7 +42,7 @@ import org.eclipse.che.api.user.server.jpa.JpaUserDao; import org.eclipse.che.api.user.server.spi.PreferenceDao; import org.eclipse.che.api.user.server.spi.UserDao; -import org.eclipse.che.api.workspace.server.JavaxExceptionMapper; +import org.eclipse.che.api.core.rest.WebApplicationExceptionMapper; import org.eclipse.che.api.workspace.server.WorkspaceEntityProvider; import org.eclipse.che.api.workspace.server.WorkspaceLockService; import org.eclipse.che.api.workspace.server.WorkspaceStatusCache; @@ -151,7 +151,7 @@ protected void configure() { install(new DevfileModule()); bind(WorkspaceEntityProvider.class); - bind(JavaxExceptionMapper.class); + bind(WebApplicationExceptionMapper.class); bind(org.eclipse.che.api.workspace.server.TemporaryWorkspaceRemover.class); bind(org.eclipse.che.api.workspace.server.WorkspaceService.class); install(new FactoryModuleBuilder().build(ServersCheckerFactory.class)); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java deleted file mode 100644 index 63a3a8d9178..00000000000 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/JavaxExceptionMapper.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.api.workspace.server; - -import static org.eclipse.che.dto.server.DtoFactory.newDto; - -import javax.inject.Singleton; -import javax.ws.rs.BadRequestException; -import javax.ws.rs.ForbiddenException; -import javax.ws.rs.NotAcceptableException; -import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; -import org.eclipse.che.api.core.rest.shared.dto.ServiceError; -import org.eclipse.che.dto.server.DtoFactory; - -@Provider -@Singleton -public class JavaxExceptionMapper implements ExceptionMapper { - - @Override - public Response toResponse(WebApplicationException exception) { - - ServiceError error = newDto(ServiceError.class).withMessage(exception.getMessage()); - if (exception instanceof ForbiddenException) { - return Response.status(Response.Status.FORBIDDEN) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else if (exception instanceof NotFoundException) { - return Response.status(Response.Status.NOT_FOUND) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else if (exception instanceof NotAuthorizedException) { - return Response.status(Response.Status.UNAUTHORIZED) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else if (exception instanceof BadRequestException) { - return Response.status(Response.Status.BAD_REQUEST) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else if (exception instanceof NotAcceptableException) { - return Response.status(Status.NOT_ACCEPTABLE) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else { - return Response.serverError() - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } - } -} diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java index bd0853e81f3..38717dbb216 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java @@ -11,7 +11,6 @@ */ package org.eclipse.che.api.workspace.server; - import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.eclipse.che.api.workspace.server.DtoConverter.asDto; @@ -53,8 +52,8 @@ @Consumes({APPLICATION_JSON}) public class WorkspaceEntityProvider implements EntityProvider { - protected DevfileManager devfileManager; - protected ObjectMapper mapper = new ObjectMapper(); + private DevfileManager devfileManager; + private ObjectMapper mapper = new ObjectMapper(); @Inject public WorkspaceEntityProvider(DevfileManager devfileManager) { @@ -62,40 +61,55 @@ public WorkspaceEntityProvider(DevfileManager devfileManager) { SimpleModule module = new SimpleModule(); module.addDeserializer(DevfileDto.class, new DevfileDtoDeserializer()); mapper.registerModule(module); - } - @Override - public boolean isReadable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { + public boolean isReadable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == WorkspaceDto.class; } @Override - public WorkspaceDto readFrom(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) + public WorkspaceDto readFrom( + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + InputStream entityStream) throws IOException, WebApplicationException { - return mapper.readerFor(WorkspaceDtoImpl.class).without(DeserializationFeature.WRAP_EXCEPTIONS) + return mapper + .readerFor(WorkspaceDtoImpl.class) + .without(DeserializationFeature.WRAP_EXCEPTIONS) .readValue(entityStream); } @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { + public boolean isWriteable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return WorkspaceDto.class.isAssignableFrom(type); } @Override - public long getSize(WorkspaceDto workspaceDto, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType) { + public long getSize( + WorkspaceDto workspaceDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType) { return -1; } @Override - public void writeTo(WorkspaceDto workspaceDto, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, WebApplicationException { + public void writeTo( + WorkspaceDto workspaceDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream entityStream) + throws IOException, WebApplicationException { httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, "public, no-cache, no-store, no-transform"); try (Writer w = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) { w.write(DtoFactory.getInstance().toJson(workspaceDto)); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java index 01a97cddfe2..59db773b239 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java @@ -65,7 +65,6 @@ import org.eclipse.che.api.core.model.workspace.Workspace; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.api.core.rest.Service; -import org.eclipse.che.api.workspace.server.devfile.DevfileManager; import org.eclipse.che.api.workspace.server.devfile.FileContentProvider; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; import org.eclipse.che.api.workspace.server.devfile.URLFileContentProvider; @@ -108,7 +107,6 @@ public class WorkspaceService extends Service { private final String apiEndpoint; private final boolean cheWorkspaceAutoStart; private final FileContentProvider devfileContentProvider; - private final DevfileManager devfileManager; @Inject public WorkspaceService( @@ -119,8 +117,7 @@ public WorkspaceService( WorkspaceLinksGenerator linksGenerator, @Named(CHE_WORKSPACE_PLUGIN_REGISTRY_URL_PROPERTY) @Nullable String pluginRegistryUrl, @Named(CHE_WORKSPACE_DEVFILE_REGISTRY_URL_PROPERTY) @Nullable String devfileRegistryUrl, - URLFetcher urlFetcher, - DevfileManager devfileManager) { + URLFetcher urlFetcher) { this.apiEndpoint = apiEndpoint; this.cheWorkspaceAutoStart = cheWorkspaceAutoStart; this.workspaceManager = workspaceManager; @@ -129,7 +126,6 @@ public WorkspaceService( this.pluginRegistryUrl = pluginRegistryUrl; this.devfileRegistryUrl = devfileRegistryUrl; this.devfileContentProvider = new URLFileContentProvider(null, urlFetcher); - this.devfileManager = devfileManager; } @POST @@ -197,7 +193,7 @@ public Response create( @Beta @Path("/devfile") @POST - @Consumes({APPLICATION_JSON, "text/yaml", "text/x-yaml"}) + @Consumes({APPLICATION_JSON}) @Produces(APPLICATION_JSON) @ApiOperation( value = "Creates a new workspace based on the Devfile.", @@ -220,7 +216,8 @@ public Response create( @ApiResponse(code = 500, message = "Internal server error occurred") }) public Response create( - @ApiParam(value = "The devfile of the workspace to create", required = true) DevfileDto devfile, + @ApiParam(value = "The devfile of the workspace to create", required = true) + DevfileDto devfile, @ApiParam( value = "Workspace attribute defined in 'attrName:attrValue' format. " diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java index d848696225d..7e774d60a28 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java @@ -55,24 +55,33 @@ public DevfileEntityProvider(DevfileManager devfileManager) { } @Override - public boolean isReadable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { + public boolean isReadable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return type == DevfileDto.class; } @Override - public DevfileDto readFrom(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) + public DevfileDto readFrom( + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + InputStream entityStream) throws IOException, WebApplicationException { try { if (mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)) { - return asDto(devfileManager.parseJson(CharStreams - .toString(new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); - } else if (mediaType.isCompatible(MediaType.valueOf("text/yaml")) || mediaType - .isCompatible(MediaType.valueOf("text/x-yaml"))) { - return asDto(devfileManager.parseYaml(CharStreams - .toString(new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); + return asDto( + devfileManager.parseJson( + CharStreams.toString( + new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); + } else if (mediaType.isCompatible(MediaType.valueOf("text/yaml")) + || mediaType.isCompatible(MediaType.valueOf("text/x-yaml"))) { + return asDto( + devfileManager.parseYaml( + CharStreams.toString( + new InputStreamReader(entityStream, getCharsetOrUtf8(mediaType))))); } } catch (DevfileFormatException e) { throw new BadRequestException(e.getMessage()); @@ -81,27 +90,36 @@ public DevfileDto readFrom(Class type, Type genericType, Annotation[ } @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, - MediaType mediaType) { + public boolean isWriteable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { return DevfileDto.class.isAssignableFrom(type); } @Override - public long getSize(DevfileDto devfileDto, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType) { + public long getSize( + DevfileDto devfileDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType) { return -1; } @Override - public void writeTo(DevfileDto devfileDto, Class type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - OutputStream entityStream) throws IOException, WebApplicationException { + public void writeTo( + DevfileDto devfileDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream entityStream) + throws IOException, WebApplicationException { httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, "public, no-cache, no-store, no-transform"); try (Writer w = new OutputStreamWriter(entityStream, StandardCharsets.UTF_8)) { w.write(DtoFactory.getInstance().toJson(devfileDto)); w.flush(); } - } private String getCharsetOrUtf8(MediaType mediaType) { diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java index 7c91f92a945..dbea4a20b13 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/validator/DevfileSchemaValidator.java @@ -71,7 +71,7 @@ private JsonNode validate(String content, ObjectMapper mapper) throws DevfileFor } } - public void validate(JsonNode contentNode) throws DevfileFormatException { + private void validate(JsonNode contentNode) throws DevfileFormatException { try { List validationErrors = new ArrayList<>(); ProblemHandler handler = ProblemHandler.collectingTo(validationErrors); diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java index f338176d824..cb73d7197d8 100644 --- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceServiceTest.java @@ -50,6 +50,7 @@ import org.eclipse.che.account.shared.model.Account; import org.eclipse.che.account.spi.AccountImpl; import org.eclipse.che.api.core.Page; +import org.eclipse.che.api.core.ValidationException; import org.eclipse.che.api.core.model.workspace.WorkspaceConfig; import org.eclipse.che.api.core.model.workspace.WorkspaceStatus; import org.eclipse.che.api.core.model.workspace.config.ProjectConfig; @@ -60,9 +61,7 @@ import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus; import org.eclipse.che.api.core.rest.ApiExceptionMapper; import org.eclipse.che.api.core.rest.shared.dto.ServiceError; -import org.eclipse.che.api.workspace.server.devfile.DevfileManager; import org.eclipse.che.api.workspace.server.devfile.URLFetcher; -import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; import org.eclipse.che.api.workspace.server.model.impl.CommandImpl; import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl; import org.eclipse.che.api.workspace.server.model.impl.MachineConfigImpl; @@ -72,7 +71,6 @@ import org.eclipse.che.api.workspace.server.model.impl.ServerImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl; import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl; -import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; import org.eclipse.che.api.workspace.server.token.MachineTokenProvider; import org.eclipse.che.api.workspace.shared.Constants; import org.eclipse.che.api.workspace.shared.dto.CommandDto; @@ -129,7 +127,6 @@ public class WorkspaceServiceTest { @Mock private WorkspaceManager wsManager; @Mock private MachineTokenProvider machineTokenProvider; @Mock private WorkspaceLinksGenerator linksGenerator; - @Mock private DevfileManager devfileManager; @Mock private URLFetcher urlFetcher; private WorkspaceService service; @@ -145,8 +142,7 @@ public void setup() { linksGenerator, CHE_WORKSPACE_PLUGIN_REGISTRY_ULR, CHE_WORKSPACE_DEVFILE_REGISTRY_ULR, - urlFetcher, - devfileManager); + urlFetcher); } @Test @@ -188,8 +184,6 @@ public void shouldCreateWorkspaceFromDevfile() throws Exception { final DevfileDto devfileDto = createDevfileDto(); final WorkspaceImpl workspace = createWorkspace(devfileDto); - when(devfileManager.parseJson(any())).thenReturn(new DevfileImpl()); - when(wsManager.createWorkspace(any(Devfile.class), anyString(), any(), any())) .thenReturn(workspace); @@ -221,52 +215,13 @@ public void shouldCreateWorkspaceFromDevfile() throws Exception { any()); } - @Test - public void shouldAcceptYamlDevfileWhenCreatingWorkspace() throws Exception { - final DevfileDto devfileDto = createDevfileDto(); - final WorkspaceImpl workspace = createWorkspace(devfileDto); - - when(devfileManager.parseYaml(any())).thenReturn(new DevfileImpl()); - - when(wsManager.createWorkspace(any(Devfile.class), anyString(), any(), any())) - .thenReturn(workspace); - - final Response response = - given() - .auth() - .basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD) - .contentType("text/yaml") - .when() - .post( - SECURE_PATH - + "/workspace/devfile" - + "?namespace=test" - + "&attribute=factoryId:factory123" - + "&attribute=custom:custom:value"); - - assertEquals(response.getStatusCode(), 201); - assertEquals( - new WorkspaceImpl(unwrapDto(response, WorkspaceDto.class), TEST_ACCOUNT), workspace); - verify(wsManager) - .createWorkspace( - any(Devfile.class), - eq("test"), - eq( - ImmutableMap.of( - "factoryId", "factory123", - "custom", "custom:value")), - any()); - } - @Test public void shouldReturnBadRequestOnInvalidDevfile() throws Exception { final DevfileDto devfileDto = createDevfileDto(); final WorkspaceImpl workspace = createWorkspace(devfileDto); - when(devfileManager.parseJson(any())).thenThrow(new DevfileFormatException("boom")); - when(wsManager.createWorkspace(any(Devfile.class), anyString(), any(), any())) - .thenReturn(workspace); + .thenThrow(new ValidationException("boom")); final Response response = given() @@ -285,8 +240,6 @@ public void shouldReturnBadRequestOnInvalidDevfile() throws Exception { assertEquals(response.getStatusCode(), 400); String error = unwrapError(response); assertEquals(error, "boom"); - - verify(wsManager, never()).createWorkspace(any(Devfile.class), any(), any(), any()); } @Test From a634bdd1f9c18e930faaffcc84f9845a3a954e50 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Wed, 2 Oct 2019 16:20:31 +0300 Subject: [PATCH 03/13] Prepare for review fixes --- .../rest/WebApplicationExceptionMapper.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java new file mode 100644 index 00000000000..e9ceeb32709 --- /dev/null +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.core.rest; + +import static org.eclipse.che.dto.server.DtoFactory.newDto; + +import javax.inject.Singleton; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.ForbiddenException; +import javax.ws.rs.NotAcceptableException; +import javax.ws.rs.NotAllowedException; +import javax.ws.rs.NotAuthorizedException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.NotSupportedException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.eclipse.che.api.core.rest.shared.dto.ServiceError; +import org.eclipse.che.dto.server.DtoFactory; + +@Provider +@Singleton +public class WebApplicationExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(WebApplicationException exception) { + + ServiceError error = newDto(ServiceError.class).withMessage(exception.getMessage()); + + if (exception instanceof BadRequestException) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof ForbiddenException) { + return Response.status(Response.Status.FORBIDDEN) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotFoundException) { + return Response.status(Response.Status.NOT_FOUND) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotAuthorizedException) { + return Response.status(Response.Status.UNAUTHORIZED) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotAcceptableException) { + return Response.status(Status.NOT_ACCEPTABLE) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotAllowedException) { + return Response.status(Status.METHOD_NOT_ALLOWED) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotSupportedException) { + return Response.status(Status.UNSUPPORTED_MEDIA_TYPE) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else { + return Response.serverError() + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } + } +} From 011ba36c13c671f7e4efc4570192bc9b6c35082e Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Wed, 2 Oct 2019 16:30:13 +0300 Subject: [PATCH 04/13] Fix fmt --- .../rest/WebApplicationExceptionMapper.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java index e9ceeb32709..c2d9994f21f 100644 --- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java @@ -65,16 +65,16 @@ public Response toResponse(WebApplicationException exception) { .type(MediaType.APPLICATION_JSON) .build(); } else if (exception instanceof NotAllowedException) { - return Response.status(Status.METHOD_NOT_ALLOWED) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else if (exception instanceof NotSupportedException) { - return Response.status(Status.UNSUPPORTED_MEDIA_TYPE) - .entity(DtoFactory.getInstance().toJson(error)) - .type(MediaType.APPLICATION_JSON) - .build(); - } else { + return Response.status(Status.METHOD_NOT_ALLOWED) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else if (exception instanceof NotSupportedException) { + return Response.status(Status.UNSUPPORTED_MEDIA_TYPE) + .entity(DtoFactory.getInstance().toJson(error)) + .type(MediaType.APPLICATION_JSON) + .build(); + } else { return Response.serverError() .entity(DtoFactory.getInstance().toJson(error)) .type(MediaType.APPLICATION_JSON) From 4d07aa8615b4e36951e1bd5a25e3b45688be9143 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Wed, 2 Oct 2019 16:59:32 +0300 Subject: [PATCH 05/13] Fix fmt --- .../server/filters/WorkspacePermissionsFilterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/filters/WorkspacePermissionsFilterTest.java b/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/filters/WorkspacePermissionsFilterTest.java index 726a8aa5d81..6d82197ac4b 100644 --- a/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/filters/WorkspacePermissionsFilterTest.java +++ b/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/filters/WorkspacePermissionsFilterTest.java @@ -158,7 +158,7 @@ public void shouldCheckAccountPermissionsAccessOnWorkspaceCreationFromDevfile() .post(SECURE_PATH + "/workspace/devfile?namespace=userok"); assertEquals(response.getStatusCode(), 204); - verify(workspaceService).create(anyString(), any(), any(), eq("userok"), any()); + verify(workspaceService).create(any(DevfileDto.class), any(), any(), eq("userok"), any()); verify(permissionsFilter).checkAccountPermissions("userok", AccountOperation.CREATE_WORKSPACE); verifyZeroInteractions(subject); } From 93e02a2cea2f741c6fdf673c78a56b8576a12413 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Wed, 2 Oct 2019 17:10:14 +0300 Subject: [PATCH 06/13] Fix fmt --- .../main/java/org/eclipse/che/api/deploy/WsMasterModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index f39a6701122..63c4359d784 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -28,6 +28,7 @@ import org.eclipse.che.api.core.rest.CheJsonProvider; import org.eclipse.che.api.core.rest.MessageBodyAdapter; import org.eclipse.che.api.core.rest.MessageBodyAdapterInterceptor; +import org.eclipse.che.api.core.rest.WebApplicationExceptionMapper; import org.eclipse.che.api.deploy.jsonrpc.CheJsonRpcWebSocketConfigurationModule; import org.eclipse.che.api.factory.server.FactoryAcceptValidator; import org.eclipse.che.api.factory.server.FactoryCreateValidator; @@ -42,7 +43,6 @@ import org.eclipse.che.api.user.server.jpa.JpaUserDao; import org.eclipse.che.api.user.server.spi.PreferenceDao; import org.eclipse.che.api.user.server.spi.UserDao; -import org.eclipse.che.api.core.rest.WebApplicationExceptionMapper; import org.eclipse.che.api.workspace.server.WorkspaceEntityProvider; import org.eclipse.che.api.workspace.server.WorkspaceLockService; import org.eclipse.che.api.workspace.server.WorkspaceStatusCache; From 0d1da70bfb8c159350e59828e0ce59d55095551c Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 09:58:54 +0300 Subject: [PATCH 07/13] Add some javadocs --- .../java/org/eclipse/che/api/deploy/WsMasterModule.java | 2 +- .../che/api/core/rest/WebApplicationExceptionMapper.java | 5 +++++ .../che/api/workspace/server/WorkspaceEntityProvider.java | 6 ++++++ .../api/workspace/server/devfile/DevfileEntityProvider.java | 6 ++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index 63c4359d784..544a3e23d5b 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -151,7 +151,6 @@ protected void configure() { install(new DevfileModule()); bind(WorkspaceEntityProvider.class); - bind(WebApplicationExceptionMapper.class); bind(org.eclipse.che.api.workspace.server.TemporaryWorkspaceRemover.class); bind(org.eclipse.che.api.workspace.server.WorkspaceService.class); install(new FactoryModuleBuilder().build(ServersCheckerFactory.class)); @@ -208,6 +207,7 @@ protected void configure() { bind(org.eclipse.che.security.oauth.OAuthAuthenticatorProvider.class) .to(org.eclipse.che.security.oauth.OAuthAuthenticatorProviderImpl.class); + bind(WebApplicationExceptionMapper.class); install(new org.eclipse.che.api.core.rest.CoreRestModule()); install(new org.eclipse.che.api.core.util.FileCleaner.FileCleanerModule()); install(new org.eclipse.che.swagger.deploy.DocsModule()); diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java index c2d9994f21f..5b5756d3b3b 100644 --- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java @@ -30,6 +30,11 @@ import org.eclipse.che.api.core.rest.shared.dto.ServiceError; import org.eclipse.che.dto.server.DtoFactory; +/** + * Mapper for the javax.ws.rs.* exceptions. + * + * @author Max Shaposhnyk + */ @Provider @Singleton public class WebApplicationExceptionMapper implements ExceptionMapper { diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java index 38717dbb216..e4f3e41c4d5 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java @@ -46,6 +46,12 @@ import org.eclipse.che.dto.server.DtoFactory; import org.everrest.core.provider.EntityProvider; +/** + * Entity provider for {@link WorkspaceDto}. Performs schema validation of devfile part of the + * workspace before actual {@link DevfileDto} creation. + * + * @author Max Shaposhnyk + */ @Singleton @Provider @Produces({APPLICATION_JSON}) diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java index 7e774d60a28..b36f2806717 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java @@ -41,6 +41,12 @@ import org.eclipse.che.dto.server.DtoFactory; import org.everrest.core.provider.EntityProvider; +/** + * Parses {@link DevfileDto} either from Json or yaml content, and performs schema validation before + * the actual DTO created. + * + * @author Max Shaposhnyk + */ @Singleton @Provider @Produces({APPLICATION_JSON}) From 6bb454682371476a2446926e600a3f7e4d5fd507 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 10:24:14 +0300 Subject: [PATCH 08/13] Remove beta annotation --- .../eclipse/che/api/workspace/server/WorkspaceService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java index 59db773b239..58c928b1d57 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java @@ -23,7 +23,6 @@ import static org.eclipse.che.api.workspace.shared.Constants.CHE_WORKSPACE_DEVFILE_REGISTRY_URL_PROPERTY; import static org.eclipse.che.api.workspace.shared.Constants.CHE_WORKSPACE_PLUGIN_REGISTRY_URL_PROPERTY; -import com.google.common.annotations.Beta; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; @@ -190,16 +189,12 @@ public Response create( return Response.status(201).entity(asDtoWithLinksAndToken(workspace)).build(); } - @Beta @Path("/devfile") @POST @Consumes({APPLICATION_JSON}) @Produces(APPLICATION_JSON) @ApiOperation( value = "Creates a new workspace based on the Devfile.", - notes = - "This method is in beta phase. It's strongly recommended to use `POST /devfile` instead" - + " to get a workspace from Devfile. Workspaces created with this method are not stable yet.", consumes = "application/json, text/yaml, text/x-yaml", produces = APPLICATION_JSON, nickname = "createFromDevfile", From 2d10ea8bcca0355721190a042acdf064368b4209 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 11:57:46 +0300 Subject: [PATCH 09/13] Add some tests for entity readers --- .../server/devfile/DevfileEntityProvider.java | 4 +- .../server/WorkspaceEntityProviderTest.java | 59 +++++++++++++ .../devfile/DevfileEntityProviderTest.java | 81 ++++++++++++++++++ .../src/test/resources/devfile/devfile.json | 84 +++++++++++++++++++ 4 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProviderTest.java create mode 100644 wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProviderTest.java create mode 100644 wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java index b36f2806717..50d1549ec84 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java @@ -28,8 +28,8 @@ import javax.inject.Inject; import javax.inject.Singleton; import javax.ws.rs.BadRequestException; -import javax.ws.rs.ClientErrorException; import javax.ws.rs.Consumes; +import javax.ws.rs.NotSupportedException; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; @@ -92,7 +92,7 @@ public DevfileDto readFrom( } catch (DevfileFormatException e) { throw new BadRequestException(e.getMessage()); } - throw new ClientErrorException("Unknown media type " + mediaType.toString(), 400); + throw new NotSupportedException("Unknown media type " + mediaType.toString()); } @Override diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProviderTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProviderTest.java new file mode 100644 index 00000000000..66dfdee5846 --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProviderTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server; + +import static org.eclipse.che.dto.server.DtoFactory.newDto; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import org.eclipse.che.api.workspace.server.devfile.DevfileManager; +import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; +import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.eclipse.che.dto.server.DtoFactory; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +@Listeners(MockitoTestNGListener.class) +public class WorkspaceEntityProviderTest { + + @Mock private DevfileManager devfileManager; + + @InjectMocks private WorkspaceEntityProvider workspaceEntityProvider; + + @Test + public void shouldBuildDtoFromValidJson() throws Exception { + + when(devfileManager.parseJson(anyString())).thenReturn(new DevfileImpl()); + + WorkspaceDto actual = newDto(WorkspaceDto.class).withDevfile(newDto(DevfileDto.class)); + + workspaceEntityProvider.readFrom( + WorkspaceDto.class, + WorkspaceDto.class, + null, + MediaType.APPLICATION_JSON_TYPE, + new MultivaluedHashMap<>(), + new ByteArrayInputStream( + DtoFactory.getInstance().toJson(actual).getBytes(StandardCharsets.UTF_8))); + + verify(devfileManager).parseJson(anyString()); + } +} diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProviderTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProviderTest.java new file mode 100644 index 00000000000..d4fde146f34 --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProviderTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.api.workspace.server.devfile; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.ws.rs.NotSupportedException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import org.eclipse.che.api.workspace.server.model.impl.devfile.DevfileImpl; +import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +@Listeners(MockitoTestNGListener.class) +public class DevfileEntityProviderTest { + + @Mock private DevfileManager devfileManager; + + @InjectMocks private DevfileEntityProvider devfileEntityProvider; + + @Test + public void shouldBuildDtoFromValidYaml() throws Exception { + + when(devfileManager.parseYaml(anyString())).thenReturn(new DevfileImpl()); + + devfileEntityProvider.readFrom( + DevfileDto.class, + DevfileDto.class, + null, + MediaType.valueOf("text/x-yaml"), + new MultivaluedHashMap<>(), + getClass().getClassLoader().getResourceAsStream("devfile/devfile.yaml")); + + verify(devfileManager).parseYaml(anyString()); + } + + @Test + public void shouldBuildDtoFromValidJson() throws Exception { + + when(devfileManager.parseJson(anyString())).thenReturn(new DevfileImpl()); + + devfileEntityProvider.readFrom( + DevfileDto.class, + DevfileDto.class, + null, + MediaType.APPLICATION_JSON_TYPE, + new MultivaluedHashMap<>(), + getClass().getClassLoader().getResourceAsStream("devfile/devfile.json")); + + verify(devfileManager).parseJson(anyString()); + } + + @Test( + expectedExceptions = NotSupportedException.class, + expectedExceptionsMessageRegExp = "Unknown media type text/plain") + public void shouldThrowErrorOnInvalidMediaType() throws Exception { + + devfileEntityProvider.readFrom( + DevfileDto.class, + DevfileDto.class, + null, + MediaType.TEXT_PLAIN_TYPE, + new MultivaluedHashMap<>(), + getClass().getClassLoader().getResourceAsStream("devfile/devfile.json")); + } +} diff --git a/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json b/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json new file mode 100644 index 00000000000..a9178bb24b5 --- /dev/null +++ b/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json @@ -0,0 +1,84 @@ +{ + "apiVersion": "1.0.0", + "metadata": { + "name": "petclinic-dev-environment", + "generateName": "petclinic-" + }, + "projects": [ + { + "name": "petclinic", + "source": { + "type": "git", + "location": "git@github.com:spring-projects/spring-petclinic.git" + } + } + ], + "components": [ + { + "alias": "mvn-stack", + "type": "chePlugin", + "id": "eclipse/chemaven-jdk8/1.0.0" + }, + { + "type": "cheEditor", + "id": "eclipse/che-theia/0.0.3" + }, + { + "alias": "jdt.ls", + "type": "chePlugin", + "id": "org.eclipse.chetheia-jdtls:0.0.3", + "preferences": { + "java.home": "/home/user/jdk11", + "java.jdt.ls.vmargs": "-noverify -Xmx1G -XX:+UseG1GC -XX:+UseStringDeduplication", + "java.jtg.memory": 12345, + "java.boolean": true + } + }, + { + "type": "openshift", + "reference": "petclinic.yaml", + "selector": { + "app.kubernetes.io/name": "mysql", + "app.kubernetes.io/component": "database", + "app.kubernetes.io/part-of": "petclinic" + } + } + ], + "commands": [ + { + "name": "build", + "actions": [ + { + "type": "exec", + "component": "mvn-stack", + "command": "mvn package", + "workdir": "/projects/spring-petclinic" + } + ] + }, + { + "name": "run", + "attributes": { + "runType": "sequential" + }, + "actions": [ + { + "type": "exec", + "component": "mvn-stack", + "command": "mvn spring-boot:run", + "workdir": "/projects/spring-petclinic" + } + ] + }, + { + "name": "other", + "actions": [ + { + "type": "exec", + "component": "jdt.ls", + "command": "run.sh" + } + ] + } + ] +} \ No newline at end of file From 19d769b671b6b9ee7b212de39830dc1d911a4bab Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 12:00:53 +0300 Subject: [PATCH 10/13] fixup! Add some tests for entity readers --- .../src/test/resources/devfile/devfile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json b/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json index a9178bb24b5..da300e6a324 100644 --- a/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json +++ b/wsmaster/che-core-api-workspace/src/test/resources/devfile/devfile.json @@ -81,4 +81,4 @@ ] } ] -} \ No newline at end of file +} From 7c2da42c816aa45341590f4f3b82ea44610b3a3e Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 12:54:39 +0300 Subject: [PATCH 11/13] Fix review comments --- .../java/org/eclipse/che/api/deploy/WsMasterModule.java | 2 -- .../java/org/eclipse/che/api/core/rest/CoreRestModule.java | 1 + .../che/api/core/rest/WebApplicationExceptionMapper.java | 2 +- .../che/api/workspace/server/WorkspaceEntityProvider.java | 6 ++++-- .../api/workspace/server/devfile/DevfileEntityProvider.java | 6 ++++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index 544a3e23d5b..515cc29265f 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -28,7 +28,6 @@ import org.eclipse.che.api.core.rest.CheJsonProvider; import org.eclipse.che.api.core.rest.MessageBodyAdapter; import org.eclipse.che.api.core.rest.MessageBodyAdapterInterceptor; -import org.eclipse.che.api.core.rest.WebApplicationExceptionMapper; import org.eclipse.che.api.deploy.jsonrpc.CheJsonRpcWebSocketConfigurationModule; import org.eclipse.che.api.factory.server.FactoryAcceptValidator; import org.eclipse.che.api.factory.server.FactoryCreateValidator; @@ -207,7 +206,6 @@ protected void configure() { bind(org.eclipse.che.security.oauth.OAuthAuthenticatorProvider.class) .to(org.eclipse.che.security.oauth.OAuthAuthenticatorProviderImpl.class); - bind(WebApplicationExceptionMapper.class); install(new org.eclipse.che.api.core.rest.CoreRestModule()); install(new org.eclipse.che.api.core.util.FileCleaner.FileCleanerModule()); install(new org.eclipse.che.swagger.deploy.DocsModule()); diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/CoreRestModule.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/CoreRestModule.java index 134d6c70fe0..9af3634e2de 100644 --- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/CoreRestModule.java +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/CoreRestModule.java @@ -25,5 +25,6 @@ protected void configure() { bind(RuntimeExceptionMapper.class); bind(ApiInfo.class).toProvider(ApiInfoProvider.class); Multibinder.newSetBinder(binder(), Class.class, Names.named("che.json.ignored_classes")); + bind(WebApplicationExceptionMapper.class); } } diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java index 5b5756d3b3b..80b1ab81e4c 100644 --- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/rest/WebApplicationExceptionMapper.java @@ -31,7 +31,7 @@ import org.eclipse.che.dto.server.DtoFactory; /** - * Mapper for the javax.ws.rs.* exceptions. + * Mapper for the {@link WebApplicationException} exceptions. * * @author Max Shaposhnyk */ diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java index e4f3e41c4d5..15480e5462b 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceEntityProvider.java @@ -37,6 +37,8 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import org.eclipse.che.api.workspace.server.devfile.DevfileManager; import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; @@ -44,7 +46,6 @@ import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; import org.eclipse.che.dto.server.DtoFactory; -import org.everrest.core.provider.EntityProvider; /** * Entity provider for {@link WorkspaceDto}. Performs schema validation of devfile part of the @@ -56,7 +57,8 @@ @Provider @Produces({APPLICATION_JSON}) @Consumes({APPLICATION_JSON}) -public class WorkspaceEntityProvider implements EntityProvider { +public class WorkspaceEntityProvider + implements MessageBodyReader, MessageBodyWriter { private DevfileManager devfileManager; private ObjectMapper mapper = new ObjectMapper(); diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java index 50d1549ec84..282c376b8c1 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/devfile/DevfileEntityProvider.java @@ -35,11 +35,12 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; import org.eclipse.che.api.workspace.server.devfile.exception.DevfileFormatException; import org.eclipse.che.api.workspace.shared.dto.devfile.DevfileDto; import org.eclipse.che.dto.server.DtoFactory; -import org.everrest.core.provider.EntityProvider; /** * Parses {@link DevfileDto} either from Json or yaml content, and performs schema validation before @@ -51,7 +52,8 @@ @Provider @Produces({APPLICATION_JSON}) @Consumes({APPLICATION_JSON, "text/yaml", "text/x-yaml"}) -public class DevfileEntityProvider implements EntityProvider { +public class DevfileEntityProvider + implements MessageBodyReader, MessageBodyWriter { private DevfileManager devfileManager; From dd69d9257fff11705a941362aab66e37a96d09db Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Thu, 3 Oct 2019 13:32:40 +0300 Subject: [PATCH 12/13] Fix deps --- wsmaster/che-core-api-workspace/pom.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wsmaster/che-core-api-workspace/pom.xml b/wsmaster/che-core-api-workspace/pom.xml index fa7f07cb75b..eed5ec06c1e 100644 --- a/wsmaster/che-core-api-workspace/pom.xml +++ b/wsmaster/che-core-api-workspace/pom.xml @@ -134,10 +134,6 @@ org.eclipse.che.core che-core-commons-tracing - - org.everrest - everrest-core - org.glassfish javax.json @@ -236,6 +232,11 @@ everrest-assured test + + org.everrest + everrest-core + test + org.everrest everrest-test From 5b19b64881c2c26a622721a6ed91482f2c369258 Mon Sep 17 00:00:00 2001 From: Max Shaposhnik Date: Fri, 4 Oct 2019 04:18:44 +0300 Subject: [PATCH 13/13] Revert header value --- .../org/eclipse/che/api/workspace/server/WorkspaceService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java index 58c928b1d57..7375bafbc56 100644 --- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java +++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceService.java @@ -191,7 +191,7 @@ public Response create( @Path("/devfile") @POST - @Consumes({APPLICATION_JSON}) + @Consumes({APPLICATION_JSON, "text/yaml", "text/x-yaml"}) @Produces(APPLICATION_JSON) @ApiOperation( value = "Creates a new workspace based on the Devfile.",