/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.api.workspace.server; import org.eclipse.che.api.core.rest.ServiceContext; import org.eclipse.che.api.core.rest.shared.dto.Link; import org.eclipse.che.api.core.rest.shared.dto.LinkParameter; import org.eclipse.che.api.environment.server.MachineLinksInjector; import org.eclipse.che.api.machine.shared.dto.MachineDto; import org.eclipse.che.api.machine.shared.dto.ServerDto; import org.eclipse.che.api.machine.shared.dto.SnapshotDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceRuntimeDto; import javax.inject.Inject; import javax.inject.Singleton; import javax.ws.rs.core.UriBuilder; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; import static java.lang.String.format; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static javax.ws.rs.core.MediaType.TEXT_HTML; import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING; import static org.eclipse.che.api.core.util.LinksHelper.createLink; import static org.eclipse.che.api.machine.shared.Constants.ENVIRONMENT_OUTPUT_CHANNEL_TEMPLATE; import static org.eclipse.che.api.machine.shared.Constants.ENVIRONMENT_STATUS_CHANNEL_TEMPLATE; import static org.eclipse.che.api.machine.shared.Constants.EXEC_AGENT_REFERENCE; import static org.eclipse.che.api.machine.shared.Constants.LINK_REL_ENVIRONMENT_OUTPUT_CHANNEL; import static org.eclipse.che.api.machine.shared.Constants.LINK_REL_ENVIRONMENT_STATUS_CHANNEL; import static org.eclipse.che.api.machine.shared.Constants.TERMINAL_REFERENCE; import static org.eclipse.che.api.machine.shared.Constants.WSAGENT_REFERENCE; import static org.eclipse.che.api.machine.shared.Constants.WSAGENT_WEBSOCKET_REFERENCE; import static org.eclipse.che.api.workspace.shared.Constants.GET_ALL_USER_WORKSPACES; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_GET_SNAPSHOT; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_GET_WORKSPACE_EVENTS_CHANNEL; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_IDE_URL; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_REMOVE_WORKSPACE; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_SELF; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_START_WORKSPACE; import static org.eclipse.che.api.workspace.shared.Constants.LINK_REL_STOP_WORKSPACE; import static org.eclipse.che.api.workspace.shared.Constants.LIN_REL_GET_WORKSPACE; import static org.eclipse.che.dto.server.DtoFactory.cloneDto; import static org.eclipse.che.dto.server.DtoFactory.newDto; /** * Helps to inject {@link WorkspaceService} related links. * * @author Anton Korneta */ @Singleton public class WorkspaceServiceLinksInjector { private final MachineLinksInjector machineLinksInjector; @Inject public WorkspaceServiceLinksInjector(MachineLinksInjector machineLinksInjector) { this.machineLinksInjector = machineLinksInjector; } public WorkspaceDto injectLinks(WorkspaceDto workspace, ServiceContext serviceContext) { final UriBuilder uriBuilder = serviceContext.getServiceUriBuilder(); final List<Link> links = new ArrayList<>(); // add common workspace links links.add(createLink("GET", uriBuilder.clone() .path(WorkspaceService.class, "getByKey") .build(workspace.getId()) .toString(), LINK_REL_SELF)); links.add(createLink("POST", uriBuilder.clone() .path(WorkspaceService.class, "startById") .build(workspace.getId()) .toString(), APPLICATION_JSON, LINK_REL_START_WORKSPACE)); links.add(createLink("DELETE", uriBuilder.clone() .path(WorkspaceService.class, "delete") .build(workspace.getId()) .toString(), APPLICATION_JSON, LINK_REL_REMOVE_WORKSPACE)); links.add(createLink("GET", uriBuilder.clone() .path(WorkspaceService.class, "getWorkspaces") .build() .toString(), APPLICATION_JSON, GET_ALL_USER_WORKSPACES)); links.add(createLink("GET", uriBuilder.clone() .path(WorkspaceService.class, "getSnapshot") .build(workspace.getId()) .toString(), APPLICATION_JSON, LINK_REL_GET_SNAPSHOT)); //TODO here we add url to IDE with workspace name not good solution do it here but critical for this task https://jira.codenvycorp.com/browse/IDEX-3619 final URI ideUri = uriBuilder.clone() .replacePath("") .path(workspace.getNamespace()) .path(workspace.getConfig().getName()) .build(); links.add(createLink("GET", ideUri.toString(), TEXT_HTML, LINK_REL_IDE_URL)); // add workspace channel links final Link workspaceChannelLink = createLink("GET", serviceContext.getBaseUriBuilder() .path("ws") .scheme("https".equals(ideUri.getScheme()) ? "wss" : "ws") .build() .toString(), null); final LinkParameter channelParameter = newDto(LinkParameter.class).withName("channel") .withRequired(true); links.add(cloneDto(workspaceChannelLink).withRel(LINK_REL_GET_WORKSPACE_EVENTS_CHANNEL) .withParameters(singletonList( cloneDto(channelParameter).withDefaultValue("workspace:" + workspace.getId())))); links.add(cloneDto(workspaceChannelLink).withRel(LINK_REL_ENVIRONMENT_OUTPUT_CHANNEL) .withParameters(singletonList(cloneDto(channelParameter) .withDefaultValue(format(ENVIRONMENT_OUTPUT_CHANNEL_TEMPLATE, workspace.getId()))))); links.add(cloneDto(workspaceChannelLink).withRel(LINK_REL_ENVIRONMENT_STATUS_CHANNEL) .withParameters(singletonList(cloneDto(channelParameter) .withDefaultValue(format(ENVIRONMENT_STATUS_CHANNEL_TEMPLATE, workspace.getId()))))); // add links for running workspace injectRuntimeLinks(workspace, ideUri, uriBuilder, serviceContext); return workspace.withLinks(links); } public SnapshotDto injectLinks(SnapshotDto snapshotDto, ServiceContext serviceContext) { final UriBuilder uriBuilder = serviceContext.getServiceUriBuilder(); final Link machineLink = createLink("GET", serviceContext.getBaseUriBuilder() .path("/machine/{id}") .build(snapshotDto.getId()) .toString(), APPLICATION_JSON, "get machine"); final Link workspaceLink = createLink("GET", uriBuilder.clone() .path(WorkspaceService.class, "getByKey") .build(snapshotDto.getWorkspaceId()) .toString(), APPLICATION_JSON, LIN_REL_GET_WORKSPACE); final Link workspaceSnapshotLink = createLink("GET", uriBuilder.clone() .path(WorkspaceService.class, "getSnapshot") .build(snapshotDto.getWorkspaceId()) .toString(), APPLICATION_JSON, LINK_REL_SELF); return snapshotDto.withLinks(asList(machineLink, workspaceLink, workspaceSnapshotLink)); } protected void injectRuntimeLinks(WorkspaceDto workspace, URI ideUri, UriBuilder uriBuilder, ServiceContext serviceContext) { final WorkspaceRuntimeDto runtime = workspace.getRuntime(); // add links for running workspace if (workspace.getStatus() == RUNNING && runtime != null) { runtime.getLinks() .add(createLink("DELETE", uriBuilder.clone() .path(WorkspaceService.class, "stop") .build(workspace.getId()) .toString(), LINK_REL_STOP_WORKSPACE)); runtime.getMachines().forEach(machine -> injectMachineLinks(machine, serviceContext)); final MachineDto devMachine = runtime.getDevMachine(); if (devMachine != null) { final Collection<ServerDto> servers = devMachine.getRuntime() .getServers() .values(); servers.stream() .filter(server -> WSAGENT_REFERENCE.equals(server.getRef())) .findAny() .ifPresent(wsAgent -> { runtime.getLinks() .add(createLink("GET", wsAgent.getUrl(), WSAGENT_REFERENCE)); runtime.getLinks() .add(createLink("GET", UriBuilder.fromUri(wsAgent.getUrl()) .path("ws") .scheme("https".equals(ideUri.getScheme()) ? "wss" : "ws") .build() .toString(), WSAGENT_WEBSOCKET_REFERENCE)); devMachine.getLinks() .add(createLink("GET", UriBuilder.fromUri(wsAgent.getUrl()) .scheme("https".equals(ideUri.getScheme()) ? "wss" : "ws") .path("/ws") .build() .toString(), WSAGENT_WEBSOCKET_REFERENCE)); }); servers.stream() .filter(server -> TERMINAL_REFERENCE.equals(server.getRef())) .findAny() .ifPresent(terminal -> { devMachine.getLinks() .add(createLink("GET", UriBuilder.fromUri(terminal.getUrl()) .scheme("https".equals(ideUri.getScheme()) ? "wss" : "ws") .path("/pty") .build() .toString(), TERMINAL_REFERENCE)); }); servers.stream() .filter(server -> EXEC_AGENT_REFERENCE.equals(server.getRef())) .findAny() .ifPresent(exec -> { devMachine.getLinks() .add(createLink("GET", UriBuilder.fromUri(exec.getUrl()) .scheme("https".equals(ideUri.getScheme()) ? "wss" : "ws") .path("/connect") .build() .toString(), EXEC_AGENT_REFERENCE)); }); } } } protected MachineDto injectMachineLinks(MachineDto machine, ServiceContext serviceContext) { return machineLinksInjector.injectLinks(machine, serviceContext); } }