From a6faa9a0bd88add9f6aaeed468ad851206d31820 Mon Sep 17 00:00:00 2001 From: Oleksii Kurinnyi Date: Wed, 11 Oct 2017 10:17:20 +0300 Subject: [PATCH 1/4] CHE-5853: add auto scroll feature on workspace creation page. (#6625) Signed-off-by: Oleksii Kurinnyi --- .../project-source-selector.controller.ts | 8 +++++++- .../project-source-selector.directive.ts | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.controller.ts b/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.controller.ts index 9cf027790e..a48e47dd65 100644 --- a/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.controller.ts +++ b/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.controller.ts @@ -52,6 +52,11 @@ export class ProjectSourceSelectorController { * ID of active button. */ private activeButtonId: string; + /** + * true if content has to be scrolled to bottom. + * @type {boolean} + */ + private scrollToBottom: boolean = true; /** * Default constructor that is using resource injection @@ -142,7 +147,8 @@ export class ProjectSourceSelectorController { this.activeActionType = actionType; this.selectedProjectTemplate = angular.copy(template); - this.$scope.updateWidget(this.activeButtonId); + this.$scope.updateWidget(this.activeButtonId, this.scrollToBottom); + this.scrollToBottom = false; } /** diff --git a/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.directive.ts b/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.directive.ts index eb97a7c69e..a14319a748 100644 --- a/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.directive.ts +++ b/dashboard/src/app/workspaces/create-workspace/project-source-selector/project-source-selector.directive.ts @@ -11,7 +11,7 @@ 'use strict'; export interface IProjectSourceSelectorScope extends ng.IScope { - updateWidget(activeButtonId: string): void; + updateWidget: (activeButtonId: string, scrollWidgetInView: boolean) => void; } /** @@ -42,8 +42,8 @@ export class ProjectSourceSelector implements ng.IDirective { this.$timeout = $timeout; } -link($scope: IProjectSourceSelectorScope, $element: ng.IAugmentedJQuery): void { - $scope.updateWidget = (activeButtonId: string) => { + link($scope: IProjectSourceSelectorScope, $element: ng.IAugmentedJQuery): void { + $scope.updateWidget = (activeButtonId: string, scrollToBottom: boolean) => { this.$timeout(() => { const popover = $element.find('.project-source-selector-popover'), arrow = popover.find('.arrow'), @@ -54,7 +54,7 @@ link($scope: IProjectSourceSelectorScope, $element: ng.IAugmentedJQuery): void { return; } const widgetHeight = $element.height(); - let top = selectButton.position().top + (selectButton.height() / 2); + const top = selectButton.position().top + (selectButton.height() / 2); const popoverHeight = popover.height(); if (popoverHeight < top) { @@ -69,6 +69,16 @@ link($scope: IProjectSourceSelectorScope, $element: ng.IAugmentedJQuery): void { popover.attr('style', 'top: 0px;'); arrow.attr('style', `top: ${top}px;`); } + + if (scrollToBottom === false) { + return; + } + + // scroll to bottom of the page + // to make 'Create' button visible + const mdContent = $element.closest('md-content'), + mdContentHeight = mdContent.height(); + mdContent.scrollTop(mdContentHeight); }); }; } From 1bea871d0af5acf31eccdb6ba6fa2878850bbe25 Mon Sep 17 00:00:00 2001 From: Sergii Kabashniuk Date: Wed, 11 Oct 2017 16:21:59 +0300 Subject: [PATCH 2/4] Fixed possible constraint violation with an existed organization. (#6674) * Fixed possible constraint violation with an existed organization. Usecase is following: If we have already an organization with name, let's say "org" and the new user also has name "org" then we will have constraint violation. In this case, we will try to create the user with name "org"+random string. --- .../che-multiuser-keycloak-server/pom.xml | 4 ++ ...eycloakEnvironmentInitalizationFilter.java | 44 +++++++++++-------- .../che/account/spi/jpa/JpaAccountDao.java | 15 ++++--- .../che/account/spi/tck/AccountDaoTest.java | 8 ++++ 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/pom.xml b/multiuser/keycloak/che-multiuser-keycloak-server/pom.xml index daeddacec1..29310c20e3 100644 --- a/multiuser/keycloak/che-multiuser-keycloak-server/pom.xml +++ b/multiuser/keycloak/che-multiuser-keycloak-server/pom.xml @@ -74,6 +74,10 @@ org.eclipse.che.core che-core-commons-auth + + org.eclipse.che.core + che-core-commons-lang + org.eclipse.che.multiuser che-multiuser-api-authorization diff --git a/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilter.java b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilter.java index 2f548b2986..81f5fbfe1c 100644 --- a/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilter.java +++ b/multiuser/keycloak/che-multiuser-keycloak-server/src/main/java/org/eclipse/che/multiuser/keycloak/server/KeycloakEnvironmentInitalizationFilter.java @@ -11,6 +11,7 @@ package org.eclipse.che.multiuser.keycloak.server; import static java.util.Collections.emptyList; +import static org.eclipse.che.commons.lang.NameGenerator.generate; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwt; @@ -79,15 +80,21 @@ public class KeycloakEnvironmentInitalizationFilter extends AbstractKeycloakFilt throw new ServletException("Cannot detect or instantiate user."); } Claims claims = (Claims) jwtToken.getBody(); - User user = - getOrCreateUser( - claims.getSubject(), - claims.get("email", String.class), - claims.get("preferred_username", String.class)); - subject = - new AuthorizedSubject( - new SubjectImpl(user.getName(), user.getId(), token, false), permissionChecker); - session.setAttribute("che_subject", subject); + + try { + User user = + getOrCreateUser( + claims.getSubject(), + claims.get("email", String.class), + claims.get("preferred_username", String.class)); + subject = + new AuthorizedSubject( + new SubjectImpl(user.getName(), user.getId(), token, false), permissionChecker); + session.setAttribute("che_subject", subject); + } catch (ServerException | ConflictException e) { + throw new ServletException( + "Unable to identify user " + claims.getSubject() + " in Che database", e); + } } try { @@ -98,19 +105,20 @@ public class KeycloakEnvironmentInitalizationFilter extends AbstractKeycloakFilt } } - private synchronized User getOrCreateUser(String id, String email, String username) - throws ServletException { + private User getOrCreateUser(String id, String email, String username) + throws ServerException, ConflictException { try { return userManager.getById(id); } catch (NotFoundException e) { - try { - final UserImpl cheUser = new UserImpl(id, email, username, "secret", emptyList()); - return userManager.create(cheUser, false); - } catch (ServerException | ConflictException ex) { - throw new ServletException("Unable to create new user", ex); + synchronized (this) { + final UserImpl cheUser = new UserImpl(id, email, username, generate("", 12), emptyList()); + try { + return userManager.create(cheUser, false); + } catch (ConflictException ex) { + cheUser.setName(generate(cheUser.getName(), 4)); + return userManager.create(cheUser, false); + } } - } catch (ServerException e) { - throw new ServletException("Unable to get user", e); } } diff --git a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java index 3e68d63f53..6817b29f0c 100644 --- a/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java +++ b/wsmaster/che-core-api-account/src/main/java/org/eclipse/che/account/spi/jpa/JpaAccountDao.java @@ -14,7 +14,6 @@ import static java.lang.String.format; import static java.util.Objects.requireNonNull; import com.google.inject.persist.Transactional; -import java.util.Optional; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; @@ -111,7 +110,9 @@ public class JpaAccountDao implements AccountDao { @Transactional protected void doCreate(AccountImpl account) { - managerProvider.get().persist(account); + final EntityManager manager = managerProvider.get(); + manager.persist(account); + manager.flush(); } @Transactional @@ -127,10 +128,12 @@ public class JpaAccountDao implements AccountDao { } @Transactional - protected Optional doRemove(String id) { + protected void doRemove(String id) { final EntityManager manager = managerProvider.get(); - final Optional account = Optional.ofNullable(manager.find(AccountImpl.class, id)); - account.ifPresent(manager::remove); - return account; + AccountImpl account = manager.find(AccountImpl.class, id); + if (account != null) { + manager.remove(account); + manager.flush(); + } } } diff --git a/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java index ff7eb603c1..48a2e8ff3b 100644 --- a/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java +++ b/wsmaster/che-core-api-account/src/test/java/org/eclipse/che/account/spi/tck/AccountDaoTest.java @@ -96,6 +96,14 @@ public class AccountDaoTest { accountDao.update(account); } + @Test(expectedExceptions = ConflictException.class) + public void shouldThrowConflictExceptionWhenCreatingAccountWithExistingName() throws Exception { + AccountImpl account = + new AccountImpl(NameGenerator.generate("account", 5), accounts[0].getName(), "test"); + + accountDao.create(account); + } + @Test(expectedExceptions = NotFoundException.class) public void shouldThrowNotFoundExceptionWhenUpdatingNonExistingAccount() throws Exception { AccountImpl account = accounts[0]; From 6d71a32449108e62be371ccd2a98bde155f8c846 Mon Sep 17 00:00:00 2001 From: Dmytro Kulieshov Date: Wed, 11 Oct 2017 16:31:25 +0300 Subject: [PATCH 3/4] Heap on master filled with JSON-RPC message Strings (#6676) --- core/che-core-api-core/pom.xml | 4 ++ .../core/websocket/impl/MessagesReSender.java | 72 ++++++++++++------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/core/che-core-api-core/pom.xml b/core/che-core-api-core/pom.xml index fad26fc8b6..58e6603d59 100644 --- a/core/che-core-api-core/pom.xml +++ b/core/che-core-api-core/pom.xml @@ -86,6 +86,10 @@ org.eclipse.che.core che-core-commons-lang + + org.eclipse.che.core + che-core-commons-schedule + org.everrest everrest-core diff --git a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/websocket/impl/MessagesReSender.java b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/websocket/impl/MessagesReSender.java index 358ddae899..f10190f48a 100644 --- a/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/websocket/impl/MessagesReSender.java +++ b/core/che-core-api-core/src/main/java/org/eclipse/che/api/core/websocket/impl/MessagesReSender.java @@ -10,15 +10,15 @@ */ package org.eclipse.che.api.core.websocket.impl; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import com.google.common.collect.EvictingQueue; import java.util.Map; import java.util.Optional; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; import javax.inject.Singleton; import javax.websocket.Session; +import org.eclipse.che.commons.schedule.ScheduleDelay; /** * Instance is responsible for re-sending messages that were not sent during the period when WEB @@ -29,57 +29,77 @@ import javax.websocket.Session; */ @Singleton public class MessagesReSender { + private static final int MAX_MESSAGES = 100; private final WebSocketSessionRegistry registry; - private final Map> messagesMap = new HashMap<>(); + private final Map> delayedMessageRegistry = + new ConcurrentHashMap<>(); @Inject public MessagesReSender(WebSocketSessionRegistry registry) { this.registry = registry; } + @ScheduleDelay(initialDelay = 60, delay = 60) + void cleanStaleMessages() { + long currentTimeMillis = System.currentTimeMillis(); + + delayedMessageRegistry + .values() + .forEach(it -> it.removeIf(m -> currentTimeMillis - m.timeMillis > 60_000)); + + delayedMessageRegistry.values().removeIf(Queue::isEmpty); + } + public void add(String endpointId, String message) { - List messages = messagesMap.get(endpointId); - if (messages == null) { - messages = new LinkedList<>(); - messagesMap.put(endpointId, messages); - } - - if (messages.size() <= MAX_MESSAGES) { - messages.add(message); - } + delayedMessageRegistry + .computeIfAbsent(endpointId, k -> EvictingQueue.create(MAX_MESSAGES)) + .offer(new DelayedMessage(message)); } public void resend(String endpointId) { - final List messages = messagesMap.remove(endpointId); + Queue delayedMessages = delayedMessageRegistry.remove(endpointId); - if (messages == null || messages.isEmpty()) { + if (delayedMessages == null || delayedMessages.isEmpty()) { return; } - final Optional sessionOptional = registry.get(endpointId); + Optional sessionOptional = registry.get(endpointId); if (!sessionOptional.isPresent()) { return; } - final Session session = sessionOptional.get(); - - final List backing = new ArrayList<>(messages); - messages.clear(); - - for (String message : backing) { + Queue backingQueue = EvictingQueue.create(delayedMessages.size()); + while (!delayedMessages.isEmpty()) { + backingQueue.offer(delayedMessages.poll()); + } + Session session = sessionOptional.get(); + for (DelayedMessage delayedMessage : backingQueue) { if (session.isOpen()) { - session.getAsyncRemote().sendText(message); + session.getAsyncRemote().sendText(delayedMessage.message); } else { - messages.add(message); + delayedMessages.add(delayedMessage); } } - messagesMap.put(endpointId, messages); + if (!delayedMessages.isEmpty()) { + delayedMessageRegistry.put(endpointId, delayedMessages); + } + } + + private static class DelayedMessage { + + private final long timeMillis; + private final String message; + + private DelayedMessage(String message) { + this.message = message; + this.timeMillis = System.currentTimeMillis(); + } } } From 1870d7dd838cf1454784c21f5eaa5a4467394b37 Mon Sep 17 00:00:00 2001 From: Josh Pinkney Date: Wed, 11 Oct 2017 11:05:16 -0400 Subject: [PATCH 4/4] Integrated yaml language server (#6371) Signed-off-by: jpinkney --- agents/ls-yaml/pom.xml | 33 +++ .../eclipse/che/api/agent/LSYamlAgent.java | 34 +++ .../resources/org.eclipse.che.ls.yaml.json | 7 + .../org.eclipse.che.ls.yaml.script.sh | 168 +++++++++++ agents/pom.xml | 1 + assembly/assembly-ide-war/pom.xml | 8 + assembly/assembly-wsagent-war/pom.xml | 8 + assembly/assembly-wsmaster-war/pom.xml | 4 + .../che/api/deploy/WsMasterModule.java | 2 + .../plugin-yaml/che-plugin-yaml-ide/pom.xml | 125 +++++++++ .../che/plugin/yaml/ide/YamlExtension.java | 27 ++ .../yaml/ide/YamlLocalizationConstant.java | 48 ++++ .../plugin/yaml/ide/YamlServiceClient.java | 23 ++ .../yaml/ide/YamlServiceClientImpl.java | 70 +++++ .../plugin/yaml/ide/inject/YamlGinModule.java | 42 +++ .../YamlExtensionManagerPresenter.java | 260 ++++++++++++++++++ .../preferences/YamlExtensionManagerView.java | 48 ++++ .../YamlExtensionManagerViewImpl.java | 188 +++++++++++++ .../YamlExtensionManagerViewImpl.ui.xml | 77 ++++++ .../org/eclipse/che/plugin/yaml/Yaml.gwt.xml | 27 ++ .../ide/YamlLocalizationConstant.properties | 20 ++ .../che-plugin-yaml-server/pom.xml | 90 ++++++ .../plugin/yaml/server/inject/YamlModule.java | 49 ++++ .../YamlLanguageServerLauncher.java | 192 +++++++++++++ .../YamlSchemaAssociations.java | 25 ++ .../server/languageserver/YamlService.java | 61 ++++ .../che-plugin-yaml-shared/pom.xml | 155 +++++++++++ .../plugin/yaml/shared/PreferenceHelper.java | 49 ++++ .../che/plugin/yaml/shared/YamlDTO.java | 38 +++ .../che/plugin/yaml/shared/YamlDTOImpl.java | 41 +++ .../plugin/yaml/shared/YamlPreference.java | 43 +++ plugins/plugin-yaml/pom.xml | 30 ++ plugins/pom.xml | 1 + pom.xml | 20 ++ 34 files changed, 2014 insertions(+) create mode 100644 agents/ls-yaml/pom.xml create mode 100644 agents/ls-yaml/src/main/java/org/eclipse/che/api/agent/LSYamlAgent.java create mode 100644 agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.json create mode 100644 agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.script.sh create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/pom.xml create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlExtension.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClient.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClientImpl.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/inject/YamlGinModule.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerPresenter.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerView.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.ui.xml create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/Yaml.gwt.xml create mode 100644 plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.properties create mode 100644 plugins/plugin-yaml/che-plugin-yaml-server/pom.xml create mode 100644 plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/inject/YamlModule.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlLanguageServerLauncher.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlSchemaAssociations.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlService.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-shared/pom.xml create mode 100644 plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/PreferenceHelper.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTO.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTOImpl.java create mode 100644 plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlPreference.java create mode 100644 plugins/plugin-yaml/pom.xml diff --git a/agents/ls-yaml/pom.xml b/agents/ls-yaml/pom.xml new file mode 100644 index 0000000000..c47e346622 --- /dev/null +++ b/agents/ls-yaml/pom.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + che-agents-parent + org.eclipse.che + 5.19.0-SNAPSHOT + + ls-yaml-agent + Language Server Yaml Agent + + + com.google.inject + guice + + + org.eclipse.che.core + che-core-api-agent-shared + + + diff --git a/agents/ls-yaml/src/main/java/org/eclipse/che/api/agent/LSYamlAgent.java b/agents/ls-yaml/src/main/java/org/eclipse/che/api/agent/LSYamlAgent.java new file mode 100644 index 0000000000..bcbb55683a --- /dev/null +++ b/agents/ls-yaml/src/main/java/org/eclipse/che/api/agent/LSYamlAgent.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012-2017 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.agent; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.io.IOException; +import org.eclipse.che.api.agent.shared.model.Agent; +import org.eclipse.che.api.agent.shared.model.impl.BasicAgent; + +/** + * Language server yaml agent. + * + * @see Agent + * @author Joshua Pinkney + */ +@Singleton +public class LSYamlAgent extends BasicAgent { + private static final String AGENT_DESCRIPTOR = "org.eclipse.che.ls.yaml.json"; + private static final String AGENT_SCRIPT = "org.eclipse.che.ls.yaml.script.sh"; + + @Inject + public LSYamlAgent() throws IOException { + super(AGENT_DESCRIPTOR, AGENT_SCRIPT); + } +} diff --git a/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.json b/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.json new file mode 100644 index 0000000000..06012757b3 --- /dev/null +++ b/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.json @@ -0,0 +1,7 @@ +{ + "id": "org.eclipse.che.ls.yaml", + "name": "Yaml language server", + "description": "Yaml intellisense", + "dependencies": [], + "properties": {} +} diff --git a/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.script.sh b/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.script.sh new file mode 100644 index 0000000000..0062373493 --- /dev/null +++ b/agents/ls-yaml/src/main/resources/org.eclipse.che.ls.yaml.script.sh @@ -0,0 +1,168 @@ +# +# Copyright (c) 2012-2017 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 +# + +is_current_user_root() { + test "$(id -u)" = 0 +} + +is_current_user_sudoer() { + sudo -n true > /dev/null 2>&1 +} + +set_sudo_command() { + if is_current_user_sudoer && ! is_current_user_root; then SUDO="sudo -E"; else unset SUDO; fi +} + +set_sudo_command +unset PACKAGES +command -v tar >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" tar"; } +command -v curl >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" curl"; } + +AGENT_BINARIES_URI=http://download.jboss.org/jbosstools/oxygen/stable/builds/yaml-language-server/yaml-language-server-latest.tar.gz +CHE_DIR=$HOME/che +LS_DIR=${CHE_DIR}/ls-yaml +LS_LAUNCHER=${LS_DIR}/launch.sh + +if [ -f /etc/centos-release ]; then + FILE="/etc/centos-release" + LINUX_TYPE=$(cat $FILE | awk '{print $1}') + elif [ -f /etc/redhat-release ]; then + FILE="/etc/redhat-release" + LINUX_TYPE=$(cat $FILE | cut -c 1-8) + else + FILE="/etc/os-release" + LINUX_TYPE=$(cat $FILE | grep ^ID= | tr '[:upper:]' '[:lower:]') + LINUX_VERSION=$(cat $FILE | grep ^VERSION_ID=) +fi + +MACHINE_TYPE=$(uname -m) + +mkdir -p ${CHE_DIR} +mkdir -p ${LS_DIR} + +######################## +### Install packages ### +######################## + +# Red Hat Enterprise Linux 7 +############################ +if echo ${LINUX_TYPE} | grep -qi "rhel"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + curl --silent --location https://rpm.nodesource.com/setup_6.x | ${SUDO} bash -; + ${SUDO} yum -y install nodejs; + } + +# Red Hat Enterprise Linux 6 +############################ +elif echo ${LINUX_TYPE} | grep -qi "Red Hat"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + curl --silent --location https://rpm.nodesource.com/setup_6.x | ${SUDO} bash -; + ${SUDO} yum -y install nodejs; + } + + +# Ubuntu 14.04 16.04 / Linux Mint 17 +#################################### +elif echo ${LINUX_TYPE} | grep -qi "ubuntu"; then + test "${PACKAGES}" = "" || { + ${SUDO} apt-get update; + ${SUDO} apt-get -y install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + { + curl -sL https://deb.nodesource.com/setup_6.x | ${SUDO} bash -; + }; + + ${SUDO} apt-get update; + ${SUDO} apt-get install -y nodejs; + } + + +# Debian 8 +########## +elif echo ${LINUX_TYPE} | grep -qi "debian"; then + test "${PACKAGES}" = "" || { + ${SUDO} apt-get update; + ${SUDO} apt-get -y install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + { + curl -sL https://deb.nodesource.com/setup_6.x | ${SUDO} bash -; + }; + + ${SUDO} apt-get update; + ${SUDO} apt-get install -y nodejs; + } + +# Fedora 23 +########### +elif echo ${LINUX_TYPE} | grep -qi "fedora"; then + command -v ps >/dev/null 2>&1 || { PACKAGES=${PACKAGES}" procps-ng"; } + test "${PACKAGES}" = "" || { + ${SUDO} dnf -y install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + curl --silent --location https://rpm.nodesource.com/setup_6.x | ${SUDO} bash -; + ${SUDO} dnf -y install nodejs; + } + + +# CentOS 7.1 & Oracle Linux 7.1 +############################### +elif echo ${LINUX_TYPE} | grep -qi "centos"; then + test "${PACKAGES}" = "" || { + ${SUDO} yum -y install ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + curl --silent --location https://rpm.nodesource.com/setup_6.x | ${SUDO} bash -; + ${SUDO} yum -y install nodejs; + } + +# openSUSE 13.2 +############### +elif echo ${LINUX_TYPE} | grep -qi "opensuse"; then + test "${PACKAGES}" = "" || { + ${SUDO} zypper install -y ${PACKAGES}; + } + + command -v nodejs >/dev/null 2>&1 || { + ${SUDO} zypper ar http://download.opensuse.org/repositories/devel:/languages:/nodejs/openSUSE_13.1/ Node.js + ${SUDO} zypper in nodejs + } + +else + >&2 echo "Unrecognized Linux Type" + >&2 cat $FILE + exit 1 +fi + + +######################## +### Install Yaml LS ### +######################## + +curl -s ${AGENT_BINARIES_URI} | tar xzf - -C ${LS_DIR} + +touch ${LS_LAUNCHER} +chmod +x ${LS_LAUNCHER} +echo "nodejs ${LS_DIR}/out/server/src/server.js --stdio" > ${LS_LAUNCHER} diff --git a/agents/pom.xml b/agents/pom.xml index 60872d1ab8..40d2e1d721 100644 --- a/agents/pom.xml +++ b/agents/pom.xml @@ -38,5 +38,6 @@ ls-typescript ls-csharp test-ls + ls-yaml diff --git a/assembly/assembly-ide-war/pom.xml b/assembly/assembly-ide-war/pom.xml index f9ee7da7bb..2b4adb2f34 100644 --- a/assembly/assembly-ide-war/pom.xml +++ b/assembly/assembly-ide-war/pom.xml @@ -215,6 +215,14 @@ org.eclipse.che.plugin che-plugin-web-ext-web + + org.eclipse.che.plugin + che-plugin-yaml-ide + + + org.eclipse.che.plugin + che-plugin-yaml-shared + org.eclipse.che.plugin che-plugin-zend-debugger-ide diff --git a/assembly/assembly-wsagent-war/pom.xml b/assembly/assembly-wsagent-war/pom.xml index 7a7f72b8c5..0c8383ff3e 100644 --- a/assembly/assembly-wsagent-war/pom.xml +++ b/assembly/assembly-wsagent-war/pom.xml @@ -139,6 +139,14 @@ org.eclipse.che.plugin che-plugin-web-ext-server + + org.eclipse.che.plugin + che-plugin-yaml-server + + + org.eclipse.che.plugin + che-plugin-yaml-shared + org.eclipse.che.plugin che-plugin-zend-debugger-server diff --git a/assembly/assembly-wsmaster-war/pom.xml b/assembly/assembly-wsmaster-war/pom.xml index b9b869f5a7..fe479ecd03 100644 --- a/assembly/assembly-wsmaster-war/pom.xml +++ b/assembly/assembly-wsmaster-war/pom.xml @@ -90,6 +90,10 @@ org.eclipse.che ls-typescript-agent + + org.eclipse.che + ls-yaml-agent + org.eclipse.che ssh-agent 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 68481faba2..522271ea03 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 @@ -23,6 +23,7 @@ import org.eclipse.che.api.agent.LSJsonAgent; import org.eclipse.che.api.agent.LSPhpAgent; import org.eclipse.che.api.agent.LSPythonAgent; import org.eclipse.che.api.agent.LSTypeScriptAgent; +import org.eclipse.che.api.agent.LSYamlAgent; import org.eclipse.che.api.agent.SshAgent; import org.eclipse.che.api.agent.SshAgentLauncher; import org.eclipse.che.api.agent.UnisonAgent; @@ -156,6 +157,7 @@ public class WsMasterModule extends AbstractModule { agents.addBinding().to(LSPhpAgent.class); agents.addBinding().to(LSPythonAgent.class); agents.addBinding().to(LSJsonAgent.class); + agents.addBinding().to(LSYamlAgent.class); agents.addBinding().to(LSCSharpAgent.class); agents.addBinding().to(LSTypeScriptAgent.class); agents.addBinding().to(GitCredentialsAgent.class); diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/pom.xml b/plugins/plugin-yaml/che-plugin-yaml-ide/pom.xml new file mode 100644 index 0000000000..58bbe3d031 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/pom.xml @@ -0,0 +1,125 @@ + + + + 4.0.0 + + che-plugin-yaml-parent + org.eclipse.che.plugin + 5.19.0-SNAPSHOT + + che-plugin-yaml-ide + jar + Che Plugin :: Yaml :: Ide + + + javax.validation + validation-api + + + org.eclipse.che.core + che-core-commons-gwt + + + org.eclipse.che.core + che-core-ide-api + + + org.eclipse.che.core + che-core-ide-ui + + + org.eclipse.che.plugin + che-plugin-yaml-shared + + + org.slf4j + slf4j-api + + + com.google.gwt + gwt-elemental + provided + + + com.google.gwt + gwt-user + provided + + + com.google.gwt.inject + gin + provided + + + com.google.inject + guice + provided + + + org.eclipse.che.core + che-core-api-workspace-shared + provided + + + org.vectomatic + lib-gwt-svg + provided + + + ch.qos.logback + logback-classic + test + + + com.google.gwt + gwt-dev + test + + + com.googlecode.gwt-test-utils + gwt-test-utils + test + + + junit + junit + test + + + org.mockito + mockito-core + test + + + org.mockitong + mockitong + test + + + org.testng + testng + test + + + + + + src/main/java + + + src/main/resources + + + + diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlExtension.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlExtension.java new file mode 100644 index 0000000000..70d430a371 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlExtension.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.eclipse.che.ide.api.extension.Extension; + +/** + * Extension for Yaml support. + * + * @author Joshua Pinkney + */ +@Singleton +@Extension(title = "Yaml", version = "3.0.0") +public class YamlExtension { + @Inject + public YamlExtension() {} +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.java new file mode 100644 index 0000000000..9867787beb --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide; + +import com.google.gwt.i18n.client.Messages; + +/** + * Localization for Yaml Language Server. + * + * @author Joshua Pinkney + */ +public interface YamlLocalizationConstant extends Messages { + + @Key("addUrlText") + String addUrlText(); + + @Key("deleteUrlText") + String deleteUrlText(); + + @Key("headerUiMessage") + String headerUiMessage(); + + @Key("addUrlLabel") + String addUrlLabel(); + + @Key("deleteUrlLabel") + String deleteUrlLabel(); + + @Key("urlColumnHeader") + String urlColumnHeader(); + + @Key("globColumnHeader") + String globColumnHeader(); + + @Key("deleteColumnHeader") + String deleteColumnHeader(); + + @Key("addSchemaButtonText") + String addSchemaButtonText(); +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClient.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClient.java new file mode 100644 index 0000000000..8839d856cd --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClient.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide; + +import java.util.Map; +import org.eclipse.che.api.promises.client.Promise; + +/** + * Interface for sending schemas to server. + * + * @author Joshua Pinkney + */ +public interface YamlServiceClient { + Promise putSchemas(Map schemas); +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClientImpl.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClientImpl.java new file mode 100644 index 0000000000..ba0ee29add --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/YamlServiceClientImpl.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.Map; +import org.eclipse.che.api.promises.client.Promise; +import org.eclipse.che.ide.api.app.AppContext; +import org.eclipse.che.ide.dto.DtoFactory; +import org.eclipse.che.ide.rest.AsyncRequestFactory; +import org.eclipse.che.ide.rest.AsyncRequestLoader; +import org.eclipse.che.ide.ui.loaders.request.LoaderFactory; +import org.eclipse.che.plugin.yaml.shared.YamlDTO; + +/** + * The yaml client service for injecting the schemas into yaml language server + * + * @author Joshua Pinkney + */ +@Singleton +public class YamlServiceClientImpl implements YamlServiceClient { + + private final LoaderFactory loaderFactory; + private final AsyncRequestFactory asyncRequestFactory; + private final AsyncRequestLoader loader; + private final AppContext appContext; + private final DtoFactory dtoFactory; + + @Inject + public YamlServiceClientImpl( + LoaderFactory loaderFactory, + AsyncRequestFactory asyncRequestFactory, + AppContext appContext, + DtoFactory dtoFactory) { + this.loaderFactory = loaderFactory; + this.asyncRequestFactory = asyncRequestFactory; + this.loader = loaderFactory.newLoader(); + this.appContext = appContext; + this.dtoFactory = dtoFactory; + } + + /** + * Service for sending the schemas to the yaml language server + * + * @param schemas The schemas you want to send to the yaml language server + * @return Promise of the request + */ + @Override + public Promise putSchemas(Map schemas) { + YamlDTO schemaAddition = dtoFactory.createDto(YamlDTO.class).withSchemas(schemas); + String schemasLocation = getWsAgentBaseUrl() + "/yaml/schemas"; + return asyncRequestFactory + .createPostRequest(schemasLocation, schemaAddition) + .loader(loader) + .send(); + } + + private String getWsAgentBaseUrl() { + return appContext.getDevMachine().getWsAgentBaseUrl(); + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/inject/YamlGinModule.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/inject/YamlGinModule.java new file mode 100644 index 0000000000..3172832426 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/inject/YamlGinModule.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide.inject; + +import com.google.gwt.inject.client.AbstractGinModule; +import com.google.gwt.inject.client.multibindings.GinMultibinder; +import com.google.inject.Singleton; +import org.eclipse.che.ide.api.extension.ExtensionGinModule; +import org.eclipse.che.ide.api.preferences.PreferencePagePresenter; +import org.eclipse.che.plugin.yaml.ide.YamlServiceClient; +import org.eclipse.che.plugin.yaml.ide.YamlServiceClientImpl; +import org.eclipse.che.plugin.yaml.ide.preferences.YamlExtensionManagerPresenter; +import org.eclipse.che.plugin.yaml.ide.preferences.YamlExtensionManagerView; +import org.eclipse.che.plugin.yaml.ide.preferences.YamlExtensionManagerViewImpl; + +/** + * Gin module for Yaml support. + * + * @author Joshua Pinkney + */ +@ExtensionGinModule +public class YamlGinModule extends AbstractGinModule { + + /** {@inheritDoc} */ + @Override + protected void configure() { + bind(YamlServiceClient.class).to(YamlServiceClientImpl.class).in(Singleton.class); + + bind(YamlExtensionManagerView.class).to(YamlExtensionManagerViewImpl.class).in(Singleton.class); + GinMultibinder prefBinder = + GinMultibinder.newSetBinder(binder(), PreferencePagePresenter.class); + prefBinder.addBinding().to(YamlExtensionManagerPresenter.class); + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerPresenter.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerPresenter.java new file mode 100644 index 0000000000..8263312e0d --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerPresenter.java @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide.preferences; + +import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONObject; +import com.google.gwt.json.client.JSONString; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonObject; +import java.util.*; +import javax.validation.constraints.NotNull; +import org.eclipse.che.ide.api.dialogs.CancelCallback; +import org.eclipse.che.ide.api.dialogs.ConfirmCallback; +import org.eclipse.che.ide.api.dialogs.DialogFactory; +import org.eclipse.che.ide.api.dialogs.InputCallback; +import org.eclipse.che.ide.api.preferences.AbstractPreferencePagePresenter; +import org.eclipse.che.ide.api.preferences.PreferencesManager; +import org.eclipse.che.plugin.yaml.ide.YamlLocalizationConstant; +import org.eclipse.che.plugin.yaml.ide.YamlServiceClient; +import org.eclipse.che.plugin.yaml.shared.PreferenceHelper; +import org.eclipse.che.plugin.yaml.shared.YamlPreference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The presenter for managing the YamlPreferenceCellTable in YamlExtensionManagerView. + * + * @author Joshua Pinkney + */ +@Singleton +public class YamlExtensionManagerPresenter extends AbstractPreferencePagePresenter + implements YamlExtensionManagerView.ActionDelegate { + + private static final Logger LOG = LoggerFactory.getLogger(YamlExtensionManagerPresenter.class); + private final String preferenceName = "yaml.preferences"; + private DialogFactory dialogFactory; + private YamlExtensionManagerView view; + private PreferencesManager preferencesManager; + private List yamlPreferences; + private YamlLocalizationConstant local; + private YamlServiceClient service; + private boolean dirty = false; + + @Inject + public YamlExtensionManagerPresenter( + YamlExtensionManagerView view, + DialogFactory dialogFactory, + PreferencesManager preferencesManager, + YamlLocalizationConstant local, + YamlServiceClient service) { + super("Yaml", "Language Server Settings"); + this.view = view; + this.dialogFactory = dialogFactory; + this.local = local; + this.service = service; + this.preferencesManager = preferencesManager; + if (preferencesManager.getValue(preferenceName) == null + || "".equals(preferencesManager.getValue(preferenceName)) + || "{}".equals(preferencesManager.getValue(preferenceName))) { + this.yamlPreferences = new ArrayList(); + } else { + this.yamlPreferences = + jsonToYamlPreference(this.preferencesManager.getValue(this.preferenceName)); + } + this.view.setDelegate(this); + refreshTable(); + } + + /** {@inheritDoc} */ + @Override + public void onDeleteClicked(@NotNull final YamlPreference pairKey) { + dialogFactory + .createConfirmDialog( + local.deleteUrlText(), + local.deleteUrlLabel(), + new ConfirmCallback() { + @Override + public void accepted() { + deleteKeyFromPreferences(pairKey); + refreshTable(); + nowDirty(); + } + }, + getCancelCallback()) + .show(); + } + + private CancelCallback getCancelCallback() { + return new CancelCallback() { + @Override + public void cancelled() { + //for now do nothing but it need for tests + } + }; + } + + /** + * Delete a preference from Yaml Preferences + * + * @param pref The preference you would like to delete + */ + private void deleteKeyFromPreferences(final YamlPreference pref) { + this.yamlPreferences.remove(pref); + } + + /** + * Add a url to Yaml Preferences + * + * @param url The url you would like to add to yaml preferences + */ + private void addUrlToPreferences(String url) { + YamlPreference pref = new YamlPreference(url, "/*"); + this.yamlPreferences.add(pref); + } + + /** + * Converts json string to list of Yaml Preferences + * + * @param jsonStr The json string to turn into the list of Yaml Preferences + * @return List of Yaml Preferences + */ + private List jsonToYamlPreference(String jsonStr) { + ArrayList yamlPreferences = new ArrayList(); + JsonObject parsedJson = Json.parse(jsonStr); + for (String glob : parsedJson.keys()) { + try { + JsonArray jsonArray = parsedJson.getArray(glob); + for (int arrNum = 0; arrNum < jsonArray.length(); arrNum++) { + YamlPreference newYamlPref = new YamlPreference(jsonArray.getString(arrNum), glob); + yamlPreferences.add(newYamlPref); + } + } catch (Exception e) { + LOG.debug(e.getMessage(), e); + } + } + + return yamlPreferences; + } + + /** {@inheritDoc} */ + @Override + public void onAddUrlClicked() { + dialogFactory + .createInputDialog( + local.addUrlText(), + local.addUrlLabel(), + "", + 0, + 0, + local.addSchemaButtonText(), + new InputCallback() { + @Override + public void accepted(String url) { + addUrlToPreferences(url); + refreshTable(); + nowDirty(); + } + }, + getCancelCallback()) + .show(); + } + + /** Send the schemas to the Language Server */ + private void setSchemas() { + Map> schemaMap = + PreferenceHelper.yamlPreferenceToMap(this.yamlPreferences); + + Map jsonSchemaMap = new HashMap(); + for (Map.Entry> entry : schemaMap.entrySet()) { + jsonSchemaMap.put(entry.getKey(), prefListToJsonArray(entry.getValue()).toString()); + } + + if (schemaMap != null) { + service.putSchemas(jsonSchemaMap); + } + } + + /** {@inheritDoc} */ + @Override + public boolean isDirty() { + return dirty; + } + + /** {@inheritDoc} */ + public void nowDirty() { + dirty = true; + delegate.onDirtyChanged(); + } + + /** {@inheritDoc} */ + @Override + public void go(AcceptsOneWidget container) { + container.setWidget(view); + refreshTable(); + setSchemas(); + } + + /** Refresh YamlPreferenceCellTable */ + private void refreshTable() { + view.setPairs(this.yamlPreferences); + } + + /** + * Convert a list of strings to JSON + * + * @param yamlStringList the List of Strings you want to convert to JSON + * @return JSONArray of yamlPreferences + */ + private JSONArray prefListToJsonArray(List yamlStringList) { + JSONArray yamlPreferenceJsonArr = new JSONArray(); + for (int arrNum = 0; arrNum < yamlStringList.size(); arrNum++) { + yamlPreferenceJsonArr.set(arrNum, new JSONString(yamlStringList.get(arrNum))); + } + + return yamlPreferenceJsonArr; + } + + /** + * Convert YamlPreference's to JSON + * + * @param yamlPreferencesList + * @return String of yamlPreferences + */ + private String yamlPreferencesToJson(List yamlPreferencesList) { + Map> schemaMap = PreferenceHelper.yamlPreferenceToMap(yamlPreferencesList); + + JSONObject jsonObj = new JSONObject(); + for (String glob : schemaMap.keySet()) { + jsonObj.put(glob, prefListToJsonArray(schemaMap.get(glob))); + } + + return jsonObj.toString(); + } + + @Override + public void storeChanges() { + setSchemas(); + + this.preferencesManager.setValue( + this.preferenceName, yamlPreferencesToJson(this.yamlPreferences)); + this.preferencesManager.flushPreferences(); + dirty = false; + delegate.onDirtyChanged(); + } + + @Override + public void revertChanges() {} +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerView.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerView.java new file mode 100644 index 0000000000..18472f17f1 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerView.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide.preferences; + +import java.util.List; +import javax.validation.constraints.NotNull; +import org.eclipse.che.ide.api.mvp.View; +import org.eclipse.che.plugin.yaml.shared.YamlPreference; + +/** + * The view of {@link YamlExtensionManagerPresenter}. + * + * @author Joshua Pinkney + */ +public interface YamlExtensionManagerView extends View { + /** Needs for delegate some function into YamlExtensionManagerPresenter. */ + interface ActionDelegate { + /** + * Performs any actions appropriate in response to the user having pressed the Delete button. + * + * @param prefKey prefKey what needs to be deleted + */ + void onDeleteClicked(@NotNull YamlPreference prefKey); + + /** + * Performs any actions appropriate in response to the user having pressed the Add url button. + */ + void onAddUrlClicked(); + + /** Sets the current state to dirty. */ + void nowDirty(); + } + + /** + * Set pairs into view. + * + * @param pairs available pairs + */ + void setPairs(@NotNull List pairs); +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.java b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.java new file mode 100644 index 0000000000..0021be9aa8 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.ide.preferences; + +import com.google.gwt.cell.client.ButtonCell; +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.cell.client.EditTextCell; +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.client.ui.*; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.List; +import javax.validation.constraints.NotNull; +import org.eclipse.che.ide.ui.cellview.CellTableResources; +import org.eclipse.che.plugin.yaml.ide.YamlLocalizationConstant; +import org.eclipse.che.plugin.yaml.shared.YamlPreference; + +/** + * The implementation of {@link YamlExtensionManagerView}. + * + * @author Joshua Pinkney + */ +@Singleton +public class YamlExtensionManagerViewImpl extends Composite implements YamlExtensionManagerView { + interface YamlExtensionManagerViewImplUiBinder + extends UiBinder {} + + private static YamlExtensionManagerViewImplUiBinder uiBinder = + GWT.create(YamlExtensionManagerViewImplUiBinder.class); + + @UiField Button addUrl; + + @UiField(provided = true) + CellTable YamlPreferenceCellTable; + + @UiField Label headerUiMsg; + + private ActionDelegate delegate; + + private YamlLocalizationConstant local; + + @Inject + protected YamlExtensionManagerViewImpl(CellTableResources res, YamlLocalizationConstant local) { + initYamlExtensionTable(res); + initWidget(uiBinder.createAndBindUi(this)); + this.local = local; + } + + /** + * Creates table which contains list of available preferences + * + * @param res Celltable resources + */ + private void initYamlExtensionTable(final CellTable.Resources res) { + + YamlPreferenceCellTable = new CellTable(20, res); + Column urlColumn = + new Column(new EditTextCell()) { + @Override + public String getValue(YamlPreference object) { + return object.getUrl(); + } + + @Override + public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) { + sb.appendHtmlConstant( + "
"); + super.render(context, object, sb); + } + }; + + urlColumn.setFieldUpdater( + new FieldUpdater() { + @Override + public void update(int index, YamlPreference object, String value) { + object.setUrl(value); + delegate.nowDirty(); + } + }); + + Column globColumn = + new Column(new EditTextCell()) { + @Override + public String getValue(YamlPreference object) { + return object.getGlob(); + } + + @Override + public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) { + sb.appendHtmlConstant( + "
"); + if (object != null) { + super.render(context, object, sb); + } + } + }; + + globColumn.setFieldUpdater( + new FieldUpdater() { + @Override + public void update(int index, YamlPreference object, String value) { + object.setGlob(value); + delegate.nowDirty(); + } + }); + + Column deletePreferenceColumn = + new Column(new ButtonCell()) { + @Override + public String getValue(YamlPreference object) { + return "Delete"; + } + + @Override + public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) { + sb.appendHtmlConstant( + "
"); + super.render(context, object, sb); + } + }; + + // Creates handler on button clicked + deletePreferenceColumn.setFieldUpdater( + new FieldUpdater() { + @Override + public void update(int index, YamlPreference object, String value) { + delegate.onDeleteClicked(object); + } + }); + + YamlPreferenceCellTable.addColumn(urlColumn, local.urlColumnHeader()); + YamlPreferenceCellTable.addColumn(globColumn, local.globColumnHeader()); + YamlPreferenceCellTable.addColumn(deletePreferenceColumn, local.deleteColumnHeader()); + YamlPreferenceCellTable.setWidth("100%", true); + YamlPreferenceCellTable.setColumnWidth(urlColumn, 45, Style.Unit.PCT); + YamlPreferenceCellTable.setColumnWidth(globColumn, 30, Style.Unit.PCT); + YamlPreferenceCellTable.setColumnWidth(deletePreferenceColumn, 25, Style.Unit.PCT); + + // don't show loading indicator + YamlPreferenceCellTable.setLoadingIndicator(null); + } + + /** {@inheritDoc} */ + @Override + public void setPairs(@NotNull List pairs) { + this.YamlPreferenceCellTable.setRowData(pairs); + } + + /** {@inheritDoc} */ + @Override + public void setDelegate(ActionDelegate delegate) { + this.delegate = delegate; + } + + @UiHandler("addUrl") + public void onAddUrlClicked(ClickEvent event) { + delegate.onAddUrlClicked(); + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.ui.xml b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.ui.xml new file mode 100644 index 0000000000..096c698fff --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/java/org/eclipse/che/plugin/yaml/ide/preferences/YamlExtensionManagerViewImpl.ui.xml @@ -0,0 +1,77 @@ + + + + + + + .alignRight { + float: right; + } + + .alignLeft { + float: left; + } + + .emptyBorder { + margin: 6px; + } + + .space { + margin-left: 5px; + } + + .button-layout { + min-width: 20px; + height: 20px; + padding: 0 3px; + } + + .button-layout svg { + width: 14px; + height: 20px; + text-align: center; + padding-left: 3px; + fill: buttonFontColor; + } + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/Yaml.gwt.xml b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/Yaml.gwt.xml new file mode 100644 index 0000000000..aad7573529 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/Yaml.gwt.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.properties b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.properties new file mode 100644 index 0000000000..215bc31386 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-ide/src/main/resources/org/eclipse/che/plugin/yaml/ide/YamlLocalizationConstant.properties @@ -0,0 +1,20 @@ +# +# Copyright (c) 2012-2017 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 +# + +addUrlText=Add Schema Url +deleteUrlText=Delete Url +headerUiMessage=Enter a schema which can be either the url, kedge, or kubernetes. If you specify kedge or kubernetes the languageserver will specify the schema url for you. +addUrlLabel=Add Schema url +addSchemaButtonText=Add +deleteUrlLabel=Delete url +urlColumnHeader=Schema Url +globColumnHeader=Apply To +deleteColumnHeader=Delete diff --git a/plugins/plugin-yaml/che-plugin-yaml-server/pom.xml b/plugins/plugin-yaml/che-plugin-yaml-server/pom.xml new file mode 100644 index 0000000000..663df27903 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-server/pom.xml @@ -0,0 +1,90 @@ + + + + 4.0.0 + + che-plugin-yaml-parent + org.eclipse.che.plugin + 5.19.0-SNAPSHOT + + che-plugin-yaml-server + Che Plugin :: Yaml :: Server + + false + + + + com.google.code.gson + gson + + + com.google.inject + guice + + + com.google.inject.extensions + guice-multibindings + + + javax.inject + javax.inject + + + javax.ws.rs + javax.ws.rs-api + + + org.eclipse.che.core + che-core-api-core + + + org.eclipse.che.core + che-core-api-languageserver + + + org.eclipse.che.core + che-core-api-languageserver-shared + + + org.eclipse.che.core + che-core-commons-inject + + + org.eclipse.che.plugin + che-plugin-yaml-shared + + + org.eclipse.lsp4j + org.eclipse.lsp4j + + + org.eclipse.lsp4j + org.eclipse.lsp4j.jsonrpc + + + org.slf4j + slf4j-api + + + + + + src/main/java + + + src/main/resources + + + + diff --git a/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/inject/YamlModule.java b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/inject/YamlModule.java new file mode 100644 index 0000000000..5e28adf894 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/inject/YamlModule.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.server.inject; + +import static java.util.Arrays.asList; + +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncher; +import org.eclipse.che.api.languageserver.shared.model.LanguageDescription; +import org.eclipse.che.inject.DynaModule; +import org.eclipse.che.plugin.yaml.server.languageserver.YamlLanguageServerLauncher; +import org.eclipse.che.plugin.yaml.server.languageserver.YamlService; + +/** + * Yaml module for server side of Yaml Language Server + * + * @author Joshua Pinkney + */ +@DynaModule +public class YamlModule extends AbstractModule { + public static final String LANGUAGE_ID = "yaml"; + private static final String[] EXTENSIONS = new String[] {"yaml", "yml"}; + private static final String MIME_TYPE = "text/yaml"; + + @Override + protected void configure() { + Multibinder.newSetBinder(binder(), LanguageServerLauncher.class) + .addBinding() + .to(YamlLanguageServerLauncher.class); + LanguageDescription description = new LanguageDescription(); + description.setFileExtensions(asList(EXTENSIONS)); + description.setLanguageId(LANGUAGE_ID); + description.setMimeType(MIME_TYPE); + Multibinder.newSetBinder(binder(), LanguageDescription.class) + .addBinding() + .toInstance(description); + + bind(YamlService.class); + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlLanguageServerLauncher.java b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlLanguageServerLauncher.java new file mode 100644 index 0000000000..cdbaf8499a --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlLanguageServerLauncher.java @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.server.languageserver; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.io.IOException; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import javax.inject.Named; +import org.eclipse.che.api.core.ApiException; +import org.eclipse.che.api.core.rest.HttpJsonRequestFactory; +import org.eclipse.che.api.languageserver.exception.LanguageServerException; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncher; +import org.eclipse.che.api.languageserver.launcher.LanguageServerLauncherTemplate; +import org.eclipse.che.api.languageserver.registry.DocumentFilter; +import org.eclipse.che.api.languageserver.registry.LanguageServerDescription; +import org.eclipse.che.api.languageserver.registry.ServerInitializerObserver; +import org.eclipse.che.plugin.yaml.server.inject.YamlModule; +import org.eclipse.che.plugin.yaml.shared.PreferenceHelper; +import org.eclipse.che.plugin.yaml.shared.YamlPreference; +import org.eclipse.lsp4j.ServerCapabilities; +import org.eclipse.lsp4j.jsonrpc.Endpoint; +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints; +import org.eclipse.lsp4j.services.LanguageClient; +import org.eclipse.lsp4j.services.LanguageServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Launcher for Yaml Language Server + * + * @author Joshua Pinkney + */ +@Singleton +public class YamlLanguageServerLauncher extends LanguageServerLauncherTemplate + implements ServerInitializerObserver { + + private static final Logger LOG = LoggerFactory.getLogger(YamlLanguageServerLauncher.class); + + private static final String REGEX = ".*\\.(yaml|yml)"; + private static final LanguageServerDescription DESCRIPTION = createServerDescription(); + private static LanguageServer yamlLanguageServer; + private final Path launchScript; + private HttpJsonRequestFactory requestFactory; + private String apiUrl; + + @Inject + public YamlLanguageServerLauncher( + @Named("che.api") String apiUrl, HttpJsonRequestFactory requestFactory) { + this.apiUrl = apiUrl; + this.requestFactory = requestFactory; + launchScript = Paths.get(System.getenv("HOME"), "che/ls-yaml/launch.sh"); + } + + @Override + public boolean isAbleToLaunch() { + return Files.exists(launchScript); + } + + protected LanguageServer connectToLanguageServer( + final Process languageServerProcess, LanguageClient client) { + Launcher launcher = + Launcher.createLauncher( + client, + LanguageServer.class, + languageServerProcess.getInputStream(), + languageServerProcess.getOutputStream()); + launcher.startListening(); + setYamlLanguageServer(launcher.getRemoteProxy()); + return launcher.getRemoteProxy(); + } + + protected Process startLanguageServerProcess(String projectPath) throws LanguageServerException { + ProcessBuilder processBuilder = new ProcessBuilder(launchScript.toString()); + processBuilder.redirectInput(ProcessBuilder.Redirect.PIPE); + processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE); + try { + return processBuilder.start(); + } catch (IOException e) { + throw new LanguageServerException("Can't start YAML language server", e); + } + } + + protected static LanguageServer getYamlLanguageServer() { + return yamlLanguageServer; + } + + protected static void setYamlLanguageServer(LanguageServer yamlLanguageServer) { + YamlLanguageServerLauncher.yamlLanguageServer = yamlLanguageServer; + } + + @Override + public void onServerInitialized( + LanguageServerLauncher launcher, + LanguageServer server, + ServerCapabilities capabilities, + String projectPath) { + + try { + Map preferences = + requestFactory.fromUrl(apiUrl + "/preferences").useGetMethod().request().asProperties(); + + Endpoint endpoint = ServiceEndpoints.toEndpoint(server); + YamlSchemaAssociations serviceObject = + ServiceEndpoints.toServiceObject(endpoint, YamlSchemaAssociations.class); + Map associations = + jsonToSchemaAssociations(preferences.get("yaml.preferences")); + serviceObject.yamlSchemaAssociation(associations); + + } catch (ApiException | IOException e) { + LOG.error(e.getLocalizedMessage(), e); + } + } + + /** + * Converts json string to map of schema associations + * + * @param jsonStr The json string you would like to change to schema association + * @return Map of schema associations + */ + private Map jsonToSchemaAssociations(String jsonStr) { + List preferenceList = jsonToYamlPreference(jsonStr); + + if (preferenceList == null) { + return null; + } + + Map> preferenceSchemaMap = + PreferenceHelper.yamlPreferenceToMap(preferenceList); + Map jsonSchemaMap = new HashMap(); + for (Map.Entry> preferenceEntry : preferenceSchemaMap.entrySet()) { + jsonSchemaMap.put( + preferenceEntry.getKey(), preferenceEntry.getValue().toArray(new String[0])); + } + return jsonSchemaMap; + } + + /** + * Converts json string to yaml preference + * + * @param jsonStr The json string you would like to change into Yaml Preferences + * @return List of Yaml Preferences + */ + private List jsonToYamlPreference(String jsonStr) { + + List preferences = new ArrayList(); + + Type type = new TypeToken>() {}.getType(); + Map yamlPreferenceMap = new Gson().fromJson(jsonStr, type); + + if (yamlPreferenceMap == null || jsonStr == "") { + return new ArrayList(); + } + + for (Map.Entry yamlPreferenceMapItem : yamlPreferenceMap.entrySet()) { + for (String url : yamlPreferenceMapItem.getValue()) { + YamlPreference newYamlPref = new YamlPreference(url, yamlPreferenceMapItem.getKey()); + preferences.add(newYamlPref); + } + } + + return preferences; + } + + public LanguageServerDescription getDescription() { + return DESCRIPTION; + } + + private static LanguageServerDescription createServerDescription() { + LanguageServerDescription description = + new LanguageServerDescription( + "org.eclipse.che.plugin.yaml.server.languageserver", + null, + Arrays.asList(new DocumentFilter(YamlModule.LANGUAGE_ID, REGEX, null))); + return description; + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlSchemaAssociations.java b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlSchemaAssociations.java new file mode 100644 index 0000000000..a0e52e9565 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlSchemaAssociations.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.server.languageserver; + +import java.util.Map; +import org.eclipse.lsp4j.jsonrpc.services.JsonNotification; + +/** + * Interface for schema associations. + * + * @author Joshua Pinkney + */ +public interface YamlSchemaAssociations { + + @JsonNotification(value = "json/schemaAssociations", useSegment = false) + void yamlSchemaAssociation(Map associations); +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlService.java b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlService.java new file mode 100644 index 0000000000..4843626154 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-server/src/main/java/org/eclipse/che/plugin/yaml/server/languageserver/YamlService.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.server.languageserver; + +import com.google.gson.Gson; +import java.util.HashMap; +import java.util.Map; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import org.eclipse.che.api.core.ApiException; +import org.eclipse.che.plugin.yaml.shared.YamlDTO; +import org.eclipse.lsp4j.jsonrpc.Endpoint; +import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints; +import org.eclipse.lsp4j.services.LanguageServer; + +/** + * The yaml server side endpoint for injecting the schema into yaml language server + * + * @author Joshua Pinkney + */ +@Path("yaml") +public class YamlService { + + /** + * Route for getting getting schemas from client side and injecting them into yaml language server + * + * @param yamlDto A yamlDTO containing the list of schemas you would like to add + */ + @POST + @Path("schemas") + @Consumes(MediaType.APPLICATION_JSON) + public void putSchemas(YamlDTO yamlDto) throws ApiException { + + LanguageServer yamlLS = YamlLanguageServerLauncher.getYamlLanguageServer(); + + if (yamlDto != null && yamlLS != null) { + + Endpoint endpoint = ServiceEndpoints.toEndpoint(yamlLS); + YamlSchemaAssociations serviceObject = + ServiceEndpoints.toServiceObject(endpoint, YamlSchemaAssociations.class); + + Map schemaAssociations = new HashMap<>(); + Map yamlDtoSchemas = yamlDto.getSchemas(); + + for (Map.Entry schema : yamlDtoSchemas.entrySet()) { + schemaAssociations.put( + schema.getKey(), new Gson().fromJson(schema.getValue(), String[].class)); + } + + serviceObject.yamlSchemaAssociation(schemaAssociations); + } + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-shared/pom.xml b/plugins/plugin-yaml/che-plugin-yaml-shared/pom.xml new file mode 100644 index 0000000000..f900bf6601 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-shared/pom.xml @@ -0,0 +1,155 @@ + + + + 4.0.0 + + che-plugin-yaml-parent + org.eclipse.che.plugin + 5.19.0-SNAPSHOT + + che-plugin-yaml-shared + jar + Che Plugin :: Yaml :: Shared + + ${project.build.directory}/generated-sources/dto/ + false + + + + com.google.code.gson + gson + + + com.google.inject + guice + + + org.eclipse.che.core + che-core-api-dto + + + org.eclipse.che.core + che-core-commons-gwt + + + com.google.gwt + gwt-user + provided + + + + + + src/main/java + + + src/main/resources + + + ${dto-generator-out-directory} + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-resource + process-sources + + add-resource + + + + + ${dto-generator-out-directory}/META-INF + META-INF + + + + + + add-source + process-sources + + add-source + + + + ${dto-generator-out-directory} + + + + + + + maven-compiler-plugin + + + pre-compile + generate-sources + + compile + + + + + + org.eclipse.che.core + che-core-api-dto-maven-plugin + ${project.version} + + + generate-client-dto + process-sources + + generate + + + + org.eclipse.che.plugin.yaml.shared + + ${dto-generator-out-directory} + org.eclipse.che.plugin.yaml.ide.dto.DtoClientImpls + client + + + + generate-server-dto + process-sources + + generate + + + + org.eclipse.che.plugin.yaml.shared + + ${dto-generator-out-directory} + org.eclipse.che.plugin.yaml.server.dto.DtoServerImpls + server + + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + + + + diff --git a/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/PreferenceHelper.java b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/PreferenceHelper.java new file mode 100644 index 0000000000..308a6f797b --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/PreferenceHelper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.shared; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Shared class between yaml client and server + * + * @author Joshua Pinkney + */ +public class PreferenceHelper { + + /** + * Converts List of Yaml Preferences to Map of Globs to List of urls + * + * @param pref The list of Yaml Preferences you want to convert + * @return Map of Globs to List of urls of the Yaml Preferences + */ + public static Map> yamlPreferenceToMap(List pref) { + Map> preferenceMap = new HashMap>(); + + for (YamlPreference prefItr : pref) { + + if (preferenceMap.containsKey(prefItr.getGlob())) { + ArrayList prefList = new ArrayList(preferenceMap.get(prefItr.getGlob())); + prefList.add(prefItr.getUrl()); + preferenceMap.put(prefItr.getGlob(), prefList); + } else { + ArrayList prefList = new ArrayList(); + prefList.add(prefItr.getUrl()); + preferenceMap.put(prefItr.getGlob(), prefList); + } + } + + return preferenceMap; + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTO.java b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTO.java new file mode 100644 index 0000000000..a8a1946a86 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTO.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.shared; + +import java.util.Map; +import org.eclipse.che.dto.shared.DTO; + +/** + * Interface of DTO for sending schemas + * + * @author Joshua Pinkney + */ +@DTO +public interface YamlDTO { + /** + * Get the schemas in the DTO + * + * @return Map of Schemas in the DTO + */ + Map getSchemas(); + + /** + * Set the schemas in the DTO + * + * @param schemas The schemas to set in the DTO + */ + void setSchemas(Map schemas); + + YamlDTO withSchemas(Map schemas); +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTOImpl.java b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTOImpl.java new file mode 100644 index 0000000000..77f29fe6e8 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlDTOImpl.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.shared; + +import java.util.Map; + +/** + * Implementation of {@link YamlDTO} + * + * @author Joshua Pinkney + */ +public class YamlDTOImpl implements YamlDTO { + + private Map schemas; + + /** {@inheritDoc} */ + @Override + public Map getSchemas() { + return this.schemas; + } + + /** {@inheritDoc} */ + @Override + public void setSchemas(Map schemas) { + this.schemas = schemas; + } + + @Override + public YamlDTO withSchemas(Map schemas) { + this.schemas = schemas; + return this; + } +} diff --git a/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlPreference.java b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlPreference.java new file mode 100644 index 0000000000..1aa974f273 --- /dev/null +++ b/plugins/plugin-yaml/che-plugin-yaml-shared/src/main/java/org/eclipse/che/plugin/yaml/shared/YamlPreference.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012-2017 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.plugin.yaml.shared; + +/** + * Establishes the format for Yaml Preferences + * + * @author Joshua Pinkney + */ +public class YamlPreference { + + private String url; + private String glob; + + public YamlPreference(String url, String glob) { + this.url = url; + this.glob = glob; + } + + public String getUrl() { + return this.url; + } + + public String getGlob() { + return this.glob; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setGlob(String glob) { + this.glob = glob; + } +} diff --git a/plugins/plugin-yaml/pom.xml b/plugins/plugin-yaml/pom.xml new file mode 100644 index 0000000000..43a65ebc72 --- /dev/null +++ b/plugins/plugin-yaml/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + che-plugin-parent + org.eclipse.che.plugin + 5.19.0-SNAPSHOT + ../pom.xml + + che-plugin-yaml-parent + pom + Che Plugin :: YAML :: Parent + + che-plugin-yaml-shared + che-plugin-yaml-ide + che-plugin-yaml-server + + diff --git a/plugins/pom.xml b/plugins/pom.xml index 92e7c89f3b..862060c099 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -61,5 +61,6 @@ plugin-testing-php plugin-pullrequest-parent plugin-traefik + plugin-yaml diff --git a/pom.xml b/pom.xml index efebb39ad8..eabc3bc07d 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,11 @@ ls-typescript-agent ${che.version} + + org.eclipse.che + ls-yaml-agent + ${che.version} + org.eclipse.che ssh-agent @@ -1262,6 +1267,21 @@ che-plugin-web-ext-web ${che.version} + + org.eclipse.che.plugin + che-plugin-yaml-ide + ${che.version} + + + org.eclipse.che.plugin + che-plugin-yaml-server + ${che.version} + + + org.eclipse.che.plugin + che-plugin-yaml-shared + ${che.version} + org.eclipse.che.plugin che-plugin-zend-debugger-ide