diff --git a/.gitpod.yml b/.gitpod.yml
index 933056a4cb217c..de947ec21474c2 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -33,6 +33,7 @@ tasks:
init: |
leeway exec --package components/supervisor-api/java:lib --package components/gitpod-protocol/java:lib -- ./gradlew build
leeway exec --package components/ide/jetbrains/backend-plugin:plugin -- ./gradlew buildPlugin
+ leeway exec --package components/ide/jetbrains/gateway-plugin:plugin -- ./gradlew buildPlugin
- name: TypeScript
before: scripts/branch-namespace.sh
init: yarn --network-timeout 100000 && yarn build
diff --git a/.werft/build.ts b/.werft/build.ts
index 25ef01878e4bc0..420f9216281fb5 100644
--- a/.werft/build.ts
+++ b/.werft/build.ts
@@ -149,6 +149,7 @@ export async function build(context, version) {
const storage = buildConfig["storage"] || "";
const withIntegrationTests = "with-integration-tests" in buildConfig;
const publishToNpm = "publish-to-npm" in buildConfig || mainBuild;
+ const publishToJBMarketplace = "publish-to-jb-marketplace" in buildConfig || mainBuild;
const analytics = buildConfig["analytics"];
const localAppVersion = mainBuild || ("with-localapp-version" in buildConfig) ? version : "unknown";
const retag = ("with-retag" in buildConfig) ? "" : "--dont-retag";
@@ -171,6 +172,7 @@ export async function build(context, version) {
storage: storage,
withIntegrationTests,
publishToNpm,
+ publishToJBMarketplace,
analytics,
localAppVersion,
retag,
@@ -205,7 +207,7 @@ export async function build(context, version) {
if (withContrib || publishRelease) {
exec(`leeway build --docker-build-options network=host --werft=true -c remote ${dontTest ? '--dont-test' : ''} -Dversion=${version} -DimageRepoBase=${imageRepo} contrib:all`);
}
- exec(`leeway build --docker-build-options network=host --werft=true -c remote ${dontTest ? '--dont-test' : ''} ${retag} --coverage-output-path=${coverageOutput} -Dversion=${version} -DremoveSources=false -DimageRepoBase=${imageRepo} -DlocalAppVersion=${localAppVersion} -DSEGMENT_IO_TOKEN=${process.env.SEGMENT_IO_TOKEN} -DnpmPublishTrigger=${publishToNpm ? Date.now() : 'false'}`);
+ exec(`leeway build --docker-build-options network=host --werft=true -c remote ${dontTest ? '--dont-test' : ''} ${retag} --coverage-output-path=${coverageOutput} -Dversion=${version} -DremoveSources=false -DimageRepoBase=${imageRepo} -DlocalAppVersion=${localAppVersion} -DSEGMENT_IO_TOKEN=${process.env.SEGMENT_IO_TOKEN} -DnpmPublishTrigger=${publishToNpm ? Date.now() : 'false'} -DjbMarketplacePublishTrigger=${publishToJBMarketplace ? Date.now() : 'false'}`);
if (publishRelease) {
try {
werft.phase("publish", "checking version semver compliance...");
diff --git a/.werft/build.yaml b/.werft/build.yaml
index 14834be69f24c3..5594a8f6e6ad0b 100644
--- a/.werft/build.yaml
+++ b/.werft/build.yaml
@@ -123,6 +123,11 @@ pod:
secretKeyRef:
name: npm-auth-token
key: npm-auth-token.json
+ - name: JB_MARKETPLACE_PUBLISH_TOKEN
+ valueFrom:
+ secretKeyRef:
+ name: jb-marketplace-publish-token
+ key: token
- name: SLACK_NOTIFICATION_PATH
valueFrom:
secretKeyRef:
diff --git a/.werft/debug.yaml b/.werft/debug.yaml
index 5c9127c5cc4ed8..56cf457e2f8129 100644
--- a/.werft/debug.yaml
+++ b/.werft/debug.yaml
@@ -107,6 +107,11 @@ pod:
secretKeyRef:
name: npm-auth-token
key: npm-auth-token.json
+ - name: JB_MARKETPLACE_PUBLISH_TOKEN
+ valueFrom:
+ secretKeyRef:
+ name: jb_marketplace_publish_token
+ key: token
- name: SLACK_NOTIFICATION_PATH
valueFrom:
secretKeyRef:
diff --git a/WORKSPACE.yaml b/WORKSPACE.yaml
index a2903cf4d064f8..5e38df1b151f92 100644
--- a/WORKSPACE.yaml
+++ b/WORKSPACE.yaml
@@ -4,6 +4,8 @@ defaultArgs:
coreYarnLockBase: ../..
npmPublishTrigger: "false"
publishToNPM: true
+ jbMarketplacePublishTrigger: "false"
+ publishToJBMarketplace: true
localAppVersion: unknown
codeCommit: 40c9a1fb052740734bf465b98032f1a50404c042
intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2021.3.1.tar.gz"
diff --git a/chart/templates/server-ide-configmap.yaml b/chart/templates/server-ide-configmap.yaml
index 3ec8a51dc431ee..831ee3728df866 100644
--- a/chart/templates/server-ide-configmap.yaml
+++ b/chart/templates/server-ide-configmap.yaml
@@ -78,28 +78,24 @@ options:
title: "IntelliJ IDEA"
type: "desktop"
logo: "https://ide.{{ $.Values.hostname }}/image/ide-logo/intellijIdeaLogo.svg"
- notes: ["While in beta, when you open a workspace with IntelliJ IDEA you will need to use the password “gitpod”."]
image: {{ (include "gitpod.comp.imageFull" (dict "root" $ "gp" $gp "comp" $gp.components.workspace.desktopIdeImages.intellij)) }}
goland:
orderKey: "05"
title: "GoLand"
type: "desktop"
logo: "https://ide.{{ $.Values.hostname }}/image/ide-logo/golandLogo.svg"
- notes: ["While in beta, when you open a workspace with GoLand you will need to use the password “gitpod”."]
image: {{ (include "gitpod.comp.imageFull" (dict "root" $ "gp" $gp "comp" $gp.components.workspace.desktopIdeImages.goland)) }}
pycharm:
orderKey: "06"
title: "PyCharm"
type: "desktop"
logo: "https://ide.{{ $.Values.hostname }}/image/ide-logo/pycharmLogo.svg"
- notes: ["While in beta, when you open a workspace with PyCharm you will need to use the password “gitpod”."]
image: {{ (include "gitpod.comp.imageFull" (dict "root" $ "gp" $gp "comp" $gp.components.workspace.desktopIdeImages.pycharm)) }}
phpstorm:
orderKey: "07"
title: "PhpStorm"
type: "desktop"
logo: "https://ide.{{ $.Values.hostname }}/image/ide-logo/phpstormLogo.svg"
- notes: ["While in beta, when you open a workspace with PhpStorm you will need to use the password “gitpod”."]
image: {{ (include "gitpod.comp.imageFull" (dict "root" $ "gp" $gp "comp" $gp.components.workspace.desktopIdeImages.phpstorm)) }}
defaultIde: "code"
@@ -122,7 +118,7 @@ clients:
defaultDesktopIDE: "intellij"
desktopIDEs: ["intellij", "goland", "pycharm", "phpstorm"]
installationSteps: [
- "If you don't see an open dialog by the browser, make sure you have JetBrains Gateway with Gitpod Plugin installed on your machine, and then click ${OPEN_LINK_LABEL} below.",
+ "If you don't see an open dialog by the browser, make sure you have JetBrains Gateway with Gitpod Plugin installed on your machine, and then click ${OPEN_LINK_LABEL} below.",
]
{{ end }}
diff --git a/components/BUILD.yaml b/components/BUILD.yaml
index 192874e5b69335..a35555a321bb5c 100644
--- a/components/BUILD.yaml
+++ b/components/BUILD.yaml
@@ -79,6 +79,7 @@ packages:
- components/local-app-api/typescript-grpcweb:publish
- components/supervisor-api/typescript-grpc:publish
- components/supervisor-api/typescript-grpcweb:publish
+ - components/ide/jetbrains/gateway-plugin:publish
- name: all-apps
type: generic
deps:
diff --git a/components/gitpod-protocol/java/build.gradle b/components/gitpod-protocol/java/build.gradle
index 910c46222ed9b7..99f324696b7c73 100644
--- a/components/gitpod-protocol/java/build.gradle
+++ b/components/gitpod-protocol/java/build.gradle
@@ -15,7 +15,7 @@ dependencies {
implementation group: 'org.eclipse.lsp4j', name: 'org.eclipse.lsp4j.jsonrpc', version: '0.12.0'
implementation group: 'org.eclipse.lsp4j', name: 'org.eclipse.lsp4j.websocket', version: '0.12.0'
compileOnly group: 'javax.websocket', name: 'javax.websocket-api', version: '1.1'
- implementation group: 'org.glassfish.tyrus.bundles', name: 'tyrus-standalone-client', version: '1.18'
+ implementation("org.eclipse.jetty.websocket:javax-websocket-client-impl:9.4.44.v20210927")
}
application {
@@ -27,6 +27,10 @@ java {
withJavadocJar()
}
+compileJava {
+ sourceCompatibility = "11"
+ targetCompatibility = "11"
+}
publishing {
publications {
diff --git a/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/BufferingWebSocketMessageWriter.java b/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/BufferingWebSocketMessageWriter.java
new file mode 100644
index 00000000000000..e3d0b481d799ef
--- /dev/null
+++ b/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/BufferingWebSocketMessageWriter.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
+// Licensed under the GNU Affero General Public License (AGPL).
+// See License-AGPL.txt in the project root for license information.
+
+package io.gitpod.gitpodprotocol.api;
+
+import org.eclipse.lsp4j.jsonrpc.JsonRpcException;
+import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
+import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
+import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler;
+import org.eclipse.lsp4j.jsonrpc.messages.Message;
+
+import javax.websocket.Session;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class BufferingWebSocketMessageWriter implements MessageConsumer {
+
+ private static final Logger LOG = Logger.getLogger(BufferingWebSocketMessageWriter.class.getName());
+
+ private Session session;
+
+ private final MessageJsonHandler jsonHandler;
+ private List buffer = new ArrayList<>();
+
+ public BufferingWebSocketMessageWriter(MessageJsonHandler jsonHandler) {
+ this.jsonHandler = jsonHandler;
+ }
+
+ public synchronized void setSession(Session session) {
+ this.session = session;
+ if (this.buffer.isEmpty()) {
+ return;
+ }
+ List buffer = this.buffer;
+ this.buffer = new ArrayList<>();
+ for (String msg : buffer) {
+ this.send(msg);
+ }
+ }
+
+ @Override
+ public synchronized void consume(Message message) throws MessageIssueException, JsonRpcException {
+ this.send(jsonHandler.serialize(message));
+ }
+
+ private void send(String msg) {
+ if (this.session == null || !this.session.isOpen()) {
+ this.buffer.add(msg);
+ return;
+ }
+ try {
+ int length = msg.length();
+ if (length <= session.getMaxTextMessageBufferSize()) {
+ session.getBasicRemote().sendText(msg);
+ } else {
+ int currentOffset = 0;
+ while (currentOffset < length) {
+ int currentEnd = Math.min(currentOffset + session.getMaxTextMessageBufferSize(), length);
+ session.getBasicRemote().sendText(msg.substring(currentOffset, currentEnd), currentEnd == length);
+ currentOffset = currentEnd;
+ }
+ }
+ } catch (IOException e) {
+ LOG.log(Level.WARNING, "failed to send message", e);
+ this.buffer.add(msg);
+ }
+ }
+
+}
diff --git a/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/ConnectionHelper.java b/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/ConnectionHelper.java
deleted file mode 100644
index 66bd70e9bcfeee..00000000000000
--- a/components/gitpod-protocol/java/src/main/java/io/gitpod/gitpodprotocol/api/ConnectionHelper.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
-// Licensed under the GNU Affero General Public License (AGPL).
-// See License-AGPL.txt in the project root for license information.
-
-package io.gitpod.gitpodprotocol.api;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import javax.websocket.ClientEndpointConfig;
-import javax.websocket.ContainerProvider;
-import javax.websocket.DeploymentException;
-import javax.websocket.Session;
-import javax.websocket.WebSocketContainer;
-
-import org.eclipse.lsp4j.jsonrpc.Launcher;
-import org.eclipse.lsp4j.websocket.WebSocketEndpoint;
-
-public class ConnectionHelper {
-
- private Session session;
-
- public GitpodClient connect(final String uri, final String origin, final String token)
- throws DeploymentException, IOException {
- final GitpodClientImpl gitpodClient = new GitpodClientImpl();
-
- final WebSocketEndpoint webSocketEndpoint = new WebSocketEndpoint() {
- @Override
- protected void configure(final Launcher.Builder builder) {
- builder.setLocalService(gitpodClient).setRemoteInterface(GitpodServer.class);
- }
-
- @Override
- protected void connect(final Collection