Merge branch 'master' into spi

6.19.x
Artem Zatsarynnyi 2017-10-12 11:54:46 +03:00
commit 5041b59e6e
40 changed files with 2090 additions and 55 deletions

23
agents/ls-yaml/pom.xml Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-agents-parent</artifactId>
<groupId>org.eclipse.che</groupId>
<version>5.19.0-SNAPSHOT</version>
</parent>
<artifactId>ls-yaml-agent</artifactId>
<name>Language Server Yaml Agent</name>
</project>

View File

@ -0,0 +1,8 @@
{
"id": "org.eclipse.che.ls.yaml",
"version": "1.0.0",
"name": "Yaml language server",
"description": "Yaml intellisense",
"dependencies": [],
"properties": {}
}

View File

@ -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}

View File

@ -37,5 +37,6 @@
<module>ls-typescript</module>
<module>ls-csharp</module>
<module>test-ls</module>
<module>ls-yaml</module>
</modules>
</project>

View File

@ -211,6 +211,14 @@
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-web-ext-web</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-ide</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-zend-debugger-ide</artifactId>

View File

@ -139,6 +139,14 @@
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-web-ext-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-zend-debugger-server</artifactId>

View File

@ -104,6 +104,10 @@
<groupId>org.eclipse.che</groupId>
<artifactId>ls-typescript-agent</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che</groupId>
<artifactId>ls-yaml-agent</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che</groupId>
<artifactId>ssh-agent</artifactId>

View File

@ -86,6 +86,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-schedule</artifactId>
</dependency>
<dependency>
<groupId>org.everrest</groupId>
<artifactId>everrest-core</artifactId>

View File

@ -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<String, List<String>> messagesMap = new HashMap<>();
private final Map<String, Queue<DelayedMessage>> 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<String> 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<String> messages = messagesMap.remove(endpointId);
Queue<DelayedMessage> delayedMessages = delayedMessageRegistry.remove(endpointId);
if (messages == null || messages.isEmpty()) {
if (delayedMessages == null || delayedMessages.isEmpty()) {
return;
}
final Optional<Session> sessionOptional = registry.get(endpointId);
Optional<Session> sessionOptional = registry.get(endpointId);
if (!sessionOptional.isPresent()) {
return;
}
final Session session = sessionOptional.get();
final List<String> backing = new ArrayList<>(messages);
messages.clear();
for (String message : backing) {
Queue<DelayedMessage> 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();
}
}
}

View File

@ -52,6 +52,11 @@ export class ProjectSourceSelectorController {
* ID of active button.
*/
private activeButtonId: string;
/**
* <code>true</code> 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;
}
/**

View File

@ -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);
});
};
}

View File

@ -74,6 +74,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-auth</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.multiuser</groupId>
<artifactId>che-multiuser-api-authorization</artifactId>

View File

@ -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);
}
}

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-yaml-parent</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.19.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-yaml-ide</artifactId>
<packaging>jar</packaging>
<name>Che Plugin :: Yaml :: Ide</name>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-gwt</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-ide-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-ide-ui</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-shared</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-elemental</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt.inject</groupId>
<artifactId>gin</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-workspace-shared</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.vectomatic</groupId>
<artifactId>lib-gwt-svg</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.gwt-test-utils</groupId>
<artifactId>gwt-test-utils</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockitong</groupId>
<artifactId>mockitong</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -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() {}
}

View File

@ -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();
}

View File

@ -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<Void> putSchemas(Map<String, String> schemas);
}

View File

@ -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<Void> of the request
*/
@Override
public Promise<Void> putSchemas(Map<String, String> 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.getWsAgentServerApiEndpoint();
}
}

View File

@ -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<PreferencePagePresenter> prefBinder =
GinMultibinder.newSetBinder(binder(), PreferencePagePresenter.class);
prefBinder.addBinding().to(YamlExtensionManagerPresenter.class);
}
}

View File

@ -0,0 +1,263 @@
/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.NotNull;
import org.eclipse.che.ide.api.preferences.AbstractPreferencePagePresenter;
import org.eclipse.che.ide.api.preferences.PreferencesManager;
import org.eclipse.che.ide.ui.dialogs.CancelCallback;
import org.eclipse.che.ide.ui.dialogs.DialogFactory;
import org.eclipse.che.ide.ui.dialogs.confirm.ConfirmCallback;
import org.eclipse.che.ide.ui.dialogs.input.InputCallback;
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<YamlPreference> 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<YamlPreference>();
} 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<YamlPreference> jsonToYamlPreference(String jsonStr) {
ArrayList yamlPreferences = new ArrayList<YamlPreference>();
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<String, List<String>> schemaMap =
PreferenceHelper.yamlPreferenceToMap(this.yamlPreferences);
Map<String, String> jsonSchemaMap = new HashMap<String, String>();
for (Map.Entry<String, List<String>> 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<String> 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<YamlPreference> yamlPreferencesList) {
Map<String, List<String>> 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() {}
}

View File

@ -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<YamlExtensionManagerView.ActionDelegate> {
/** 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<YamlPreference> pairs);
}

View File

@ -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<Widget, YamlExtensionManagerViewImpl> {}
private static YamlExtensionManagerViewImplUiBinder uiBinder =
GWT.create(YamlExtensionManagerViewImplUiBinder.class);
@UiField Button addUrl;
@UiField(provided = true)
CellTable<YamlPreference> 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<YamlPreference>(20, res);
Column<YamlPreference, String> urlColumn =
new Column<YamlPreference, String>(new EditTextCell()) {
@Override
public String getValue(YamlPreference object) {
return object.getUrl();
}
@Override
public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) {
sb.appendHtmlConstant(
"<div id=\""
+ UIObject.DEBUG_ID_PREFIX
+ "-preferences-cellTable-url-"
+ context.getIndex()
+ "\">");
super.render(context, object, sb);
}
};
urlColumn.setFieldUpdater(
new FieldUpdater<YamlPreference, String>() {
@Override
public void update(int index, YamlPreference object, String value) {
object.setUrl(value);
delegate.nowDirty();
}
});
Column<YamlPreference, String> globColumn =
new Column<YamlPreference, String>(new EditTextCell()) {
@Override
public String getValue(YamlPreference object) {
return object.getGlob();
}
@Override
public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) {
sb.appendHtmlConstant(
"<div id=\""
+ UIObject.DEBUG_ID_PREFIX
+ "-preferences-cellTable-glob-"
+ context.getIndex()
+ "\">");
if (object != null) {
super.render(context, object, sb);
}
}
};
globColumn.setFieldUpdater(
new FieldUpdater<YamlPreference, String>() {
@Override
public void update(int index, YamlPreference object, String value) {
object.setGlob(value);
delegate.nowDirty();
}
});
Column<YamlPreference, String> deletePreferenceColumn =
new Column<YamlPreference, String>(new ButtonCell()) {
@Override
public String getValue(YamlPreference object) {
return "Delete";
}
@Override
public void render(Context context, YamlPreference object, SafeHtmlBuilder sb) {
sb.appendHtmlConstant(
"<div id=\""
+ UIObject.DEBUG_ID_PREFIX
+ "-preferences-cellTable-delete-"
+ context.getIndex()
+ "\">");
super.render(context, object, sb);
}
};
// Creates handler on button clicked
deletePreferenceColumn.setFieldUpdater(
new FieldUpdater<YamlPreference, String>() {
@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<YamlPreference> pairs) {
this.YamlPreferenceCellTable.setRowData(pairs);
}
/** {@inheritDoc} */
@Override
public void setDelegate(ActionDelegate delegate) {
this.delegate = delegate;
}
@UiHandler("addUrl")
public void onAddUrlClicked(ClickEvent event) {
delegate.onAddUrlClicked();
}
}

View File

@ -0,0 +1,77 @@
<!--
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
-->
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:svgui='urn:import:org.vectomatic.dom.svg.ui'
xmlns:p1='urn:import:com.google.gwt.user.cellview.client'>
<ui:with field='locale'
type='org.eclipse.che.plugin.yaml.ide.YamlLocalizationConstant'/>
<ui:style>
.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;
}
</ui:style>
<g:DockLayoutPanel unit="PX" width="100%" height="100%">
<g:south size="36.0">
<g:FlowPanel width="100%">
<g:FlowPanel addStyleNames="{style.emptyBorder}">
<g:Button addStyleNames="{style.alignLeft}" height="22px"
ui:field="addUrl" debugId="preferences-addUrl">
<ui:text from="{locale.addUrlText}"/>
</g:Button>
</g:FlowPanel>
</g:FlowPanel>
</g:south>
<g:north size="50">
<g:FlowPanel>
<g:Label ui:field="headerUiMsg" text="{locale.headerUiMessage}" width="100%" />
</g:FlowPanel>
</g:north>
<g:center>
<g:ScrollPanel addStyleNames="{style.emptyBorder}">
<g:SimplePanel>
<p1:CellTable width="100%" ui:field="YamlPreferenceCellTable" focus="false"
debugId="preferences-cellTable-keys"/>
</g:SimplePanel>
</g:ScrollPanel>
</g:center>
</g:DockLayoutPanel>
</ui:UiBinder>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN" "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module>
<inherits name="com.google.gwt.user.User"/>
<inherits name="com.google.gwt.http.HTTP"/>
<inherits name="com.google.gwt.i18n.I18N"/>
<inherits name="com.google.gwt.json.JSON"/>
<inherits name='org.eclipse.che.ide.Api'/>
<inherits name='org.eclipse.che.ide.ui.CodenvyUI'/>
<inherits name="com.google.gwt.inject.Inject"/>
<inherits name="org.eclipse.che.api.project.Project"/>
<source path="ide"/>
<source path="shared"/>
</module>

View File

@ -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

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-yaml-parent</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.19.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-yaml-server</artifactId>
<name>Che Plugin :: Yaml :: Server</name>
<properties>
<findbugs.failonerror>false</findbugs.failonerror>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-multibindings</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-languageserver</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-languageserver-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.lsp4j</groupId>
<artifactId>org.eclipse.lsp4j</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.lsp4j</groupId>
<artifactId>org.eclipse.lsp4j.jsonrpc</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -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);
}
}

View File

@ -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<LanguageServer> 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<String, String> preferences =
requestFactory.fromUrl(apiUrl + "/preferences").useGetMethod().request().asProperties();
Endpoint endpoint = ServiceEndpoints.toEndpoint(server);
YamlSchemaAssociations serviceObject =
ServiceEndpoints.toServiceObject(endpoint, YamlSchemaAssociations.class);
Map<String, String[]> 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<String, String[]> jsonToSchemaAssociations(String jsonStr) {
List<YamlPreference> preferenceList = jsonToYamlPreference(jsonStr);
if (preferenceList == null) {
return null;
}
Map<String, List<String>> preferenceSchemaMap =
PreferenceHelper.yamlPreferenceToMap(preferenceList);
Map<String, String[]> jsonSchemaMap = new HashMap<String, String[]>();
for (Map.Entry<String, List<String>> 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<YamlPreference> jsonToYamlPreference(String jsonStr) {
List<YamlPreference> preferences = new ArrayList<YamlPreference>();
Type type = new TypeToken<Map<String, String[]>>() {}.getType();
Map<String, String[]> yamlPreferenceMap = new Gson().fromJson(jsonStr, type);
if (yamlPreferenceMap == null || jsonStr == "") {
return new ArrayList<YamlPreference>();
}
for (Map.Entry<String, String[]> 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;
}
}

View File

@ -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<String, String[]> associations);
}

View File

@ -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<String, String[]> schemaAssociations = new HashMap<>();
Map<String, String> yamlDtoSchemas = yamlDto.getSchemas();
for (Map.Entry<String, String> schema : yamlDtoSchemas.entrySet()) {
schemaAssociations.put(
schema.getKey(), new Gson().fromJson(schema.getValue(), String[].class));
}
serviceObject.yamlSchemaAssociation(schemaAssociations);
}
}
}

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-yaml-parent</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.19.0-SNAPSHOT</version>
</parent>
<artifactId>che-plugin-yaml-shared</artifactId>
<packaging>jar</packaging>
<name>Che Plugin :: Yaml :: Shared</name>
<properties>
<dto-generator-out-directory>${project.build.directory}/generated-sources/dto/</dto-generator-out-directory>
<findbugs.failonerror>false</findbugs.failonerror>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-dto</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-gwt</artifactId>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>${dto-generator-out-directory}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-resource</id>
<phase>process-sources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${dto-generator-out-directory}/META-INF</directory>
<targetPath>META-INF</targetPath>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>add-source</id>
<phase>process-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${dto-generator-out-directory}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>pre-compile</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-dto-maven-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>generate-client-dto</id>
<phase>process-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<dtoPackages>
<package>org.eclipse.che.plugin.yaml.shared</package>
</dtoPackages>
<outputDirectory>${dto-generator-out-directory}</outputDirectory>
<genClassName>org.eclipse.che.plugin.yaml.ide.dto.DtoClientImpls</genClassName>
<impl>client</impl>
</configuration>
</execution>
<execution>
<id>generate-server-dto</id>
<phase>process-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<dtoPackages>
<package>org.eclipse.che.plugin.yaml.shared</package>
</dtoPackages>
<outputDirectory>${dto-generator-out-directory}</outputDirectory>
<genClassName>org.eclipse.che.plugin.yaml.server.dto.DtoServerImpls</genClassName>
<impl>server</impl>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -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<String, List<String>> yamlPreferenceToMap(List<YamlPreference> pref) {
Map<String, List<String>> preferenceMap = new HashMap<String, List<String>>();
for (YamlPreference prefItr : pref) {
if (preferenceMap.containsKey(prefItr.getGlob())) {
ArrayList<String> prefList = new ArrayList<String>(preferenceMap.get(prefItr.getGlob()));
prefList.add(prefItr.getUrl());
preferenceMap.put(prefItr.getGlob(), prefList);
} else {
ArrayList<String> prefList = new ArrayList<String>();
prefList.add(prefItr.getUrl());
preferenceMap.put(prefItr.getGlob(), prefList);
}
}
return preferenceMap;
}
}

View File

@ -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<String, String> getSchemas();
/**
* Set the schemas in the DTO
*
* @param schemas The schemas to set in the DTO
*/
void setSchemas(Map<String, String> schemas);
YamlDTO withSchemas(Map<String, String> schemas);
}

View File

@ -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<String, String> schemas;
/** {@inheritDoc} */
@Override
public Map<String, String> getSchemas() {
return this.schemas;
}
/** {@inheritDoc} */
@Override
public void setSchemas(Map<String, String> schemas) {
this.schemas = schemas;
}
@Override
public YamlDTO withSchemas(Map<String, String> schemas) {
this.schemas = schemas;
return this;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-plugin-parent</artifactId>
<groupId>org.eclipse.che.plugin</groupId>
<version>5.19.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>che-plugin-yaml-parent</artifactId>
<packaging>pom</packaging>
<name>Che Plugin :: YAML :: Parent</name>
<modules>
<module>che-plugin-yaml-shared</module>
<module>che-plugin-yaml-ide</module>
<module>che-plugin-yaml-server</module>
</modules>
</project>

View File

@ -60,5 +60,6 @@
<module>plugin-testing-php</module>
<module>plugin-pullrequest-parent</module>
<module>plugin-traefik</module>
<module>plugin-yaml</module>
</modules>
</project>

20
pom.xml
View File

@ -201,6 +201,11 @@
<artifactId>ls-typescript-agent</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che</groupId>
<artifactId>ls-yaml-agent</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che</groupId>
<artifactId>ssh-agent</artifactId>
@ -1292,6 +1297,21 @@
<artifactId>che-plugin-web-ext-web</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-ide</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-server</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-yaml-shared</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-zend-debugger-ide</artifactId>

View File

@ -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<AccountImpl> doRemove(String id) {
protected void doRemove(String id) {
final EntityManager manager = managerProvider.get();
final Optional<AccountImpl> 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();
}
}
}

View File

@ -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];