From e4415832777cc62c2d66821559d2729fce298dfb Mon Sep 17 00:00:00 2001 From: Artur Date: Mon, 23 Jun 2025 18:13:30 +0300 Subject: [PATCH 1/2] Start REST server using HttpServer --- META-INF/MANIFEST.MF | 2 + README.md | 7 +++ plugin.xml | 7 ++- src/com/vaadin/plugin/Activator.java | 27 +++++++++ src/com/vaadin/plugin/CopilotRestService.java | 59 +++++++++++++++++++ src/com/vaadin/plugin/EarlyStartup.java | 16 +++++ 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/com/vaadin/plugin/Activator.java create mode 100644 src/com/vaadin/plugin/CopilotRestService.java create mode 100644 src/com/vaadin/plugin/EarlyStartup.java diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index e3b70f5..5e4c744 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -5,5 +5,7 @@ Bundle-SymbolicName: vaadin-eclipse-plugin;singleton:=true Bundle-Version: 1.0.0.qualifier Bundle-Vendor: Vaadin Require-Bundle: org.eclipse.ui +Bundle-Activator: com.vaadin.plugin.Activator +Import-Package: org.osgi.framework,com.sun.net.httpserver Automatic-Module-Name: vaadin.eclipse.plugin Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/README.md b/README.md index 362e39d..b57880e 100644 --- a/README.md +++ b/README.md @@ -1 +1,8 @@ # eclipse-plugin + +This repository contains a minimal Eclipse plug-in example for Vaadin. +At workbench startup the plug-in is activated via an `org.eclipse.ui.startup` extension. The `BundleActivator` starts a small REST service using the JDK `HttpServer`. The server exposes a `/api/copilot` endpoint and its URL is stored in the `vaadin.copilot.endpoint` system property. + +## License + +This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details. diff --git a/plugin.xml b/plugin.xml index d85dcef..d845d6a 100644 --- a/plugin.xml +++ b/plugin.xml @@ -57,6 +57,11 @@ - + + + + + diff --git a/src/com/vaadin/plugin/Activator.java b/src/com/vaadin/plugin/Activator.java new file mode 100644 index 0000000..0257a64 --- /dev/null +++ b/src/com/vaadin/plugin/Activator.java @@ -0,0 +1,27 @@ +package com.vaadin.plugin; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +/** + * Bundle activator that starts the REST service when the plug-in is + * activated and stops it on shutdown. + */ +public class Activator implements BundleActivator { + private CopilotRestService restService; + + @Override + public void start(BundleContext context) throws Exception { + restService = new CopilotRestService(); + restService.start(); + System.setProperty("vaadin.copilot.endpoint", restService.getEndpoint()); + } + + @Override + public void stop(BundleContext context) throws Exception { + if (restService != null) { + restService.stop(); + restService = null; + } + } +} diff --git a/src/com/vaadin/plugin/CopilotRestService.java b/src/com/vaadin/plugin/CopilotRestService.java new file mode 100644 index 0000000..570e03d --- /dev/null +++ b/src/com/vaadin/plugin/CopilotRestService.java @@ -0,0 +1,59 @@ +package com.vaadin.plugin; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +/** + * Starts a small HTTP server for Copilot integration. The server exposes a + * single /api/copilot endpoint that accepts POST requests. + */ +public class CopilotRestService { + private HttpServer server; + private String endpoint; + + /** Start the embedded HTTP server on a random port. */ + public void start() throws IOException { + server = HttpServer.create(new InetSocketAddress(0), 0); + server.createContext("/api/copilot", new Handler()); + server.start(); + endpoint = "http://localhost:" + server.getAddress().getPort() + "/api/copilot"; + System.out.println("Copilot REST service started at " + endpoint); + } + + /** Stop the server if it is running. */ + public void stop() { + if (server != null) { + server.stop(0); + server = null; + } + } + + /** Returns the full endpoint URL. */ + public String getEndpoint() { + return endpoint; + } + + private static class Handler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if (!"POST".equalsIgnoreCase(exchange.getRequestMethod())) { + exchange.sendResponseHeaders(405, -1); + return; + } + InputStream is = exchange.getRequestBody(); + String body = new String(is.readAllBytes(), StandardCharsets.UTF_8); + System.out.println("Received Copilot request: " + body); + byte[] resp = "OK".getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(200, resp.length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(resp); + } + } + } +} diff --git a/src/com/vaadin/plugin/EarlyStartup.java b/src/com/vaadin/plugin/EarlyStartup.java new file mode 100644 index 0000000..286e1db --- /dev/null +++ b/src/com/vaadin/plugin/EarlyStartup.java @@ -0,0 +1,16 @@ +package com.vaadin.plugin; + +import org.eclipse.ui.IStartup; + + +/** + * Ensures the plug-in is activated when the workbench starts so the + * {@link Activator} can launch the embedded REST service. + */ +public class EarlyStartup implements IStartup { + + @Override + public void earlyStartup() { + // Trigger plug-in activation so the BundleActivator runs + } +} From c30eb20d2176fe9056e414e7d5f9677847fafd8b Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 24 Jun 2025 15:53:32 +0300 Subject: [PATCH 2/2] Fix it --- META-INF/MANIFEST.MF | 1 + src/com/vaadin/plugin/Activator.java | 3 +-- src/com/vaadin/plugin/CopilotRestService.java | 12 +++++++----- src/com/vaadin/plugin/EarlyStartup.java | 5 ++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index 5e4c744..fbb46c3 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -6,6 +6,7 @@ Bundle-Version: 1.0.0.qualifier Bundle-Vendor: Vaadin Require-Bundle: org.eclipse.ui Bundle-Activator: com.vaadin.plugin.Activator +Bundle-ActivationPolicy: lazy Import-Package: org.osgi.framework,com.sun.net.httpserver Automatic-Module-Name: vaadin.eclipse.plugin Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/src/com/vaadin/plugin/Activator.java b/src/com/vaadin/plugin/Activator.java index 0257a64..f23d71f 100644 --- a/src/com/vaadin/plugin/Activator.java +++ b/src/com/vaadin/plugin/Activator.java @@ -4,8 +4,7 @@ import org.osgi.framework.BundleContext; /** - * Bundle activator that starts the REST service when the plug-in is - * activated and stops it on shutdown. + * Bundle activator that starts the REST service when the plug-in is activated and stops it on shutdown. */ public class Activator implements BundleActivator { private CopilotRestService restService; diff --git a/src/com/vaadin/plugin/CopilotRestService.java b/src/com/vaadin/plugin/CopilotRestService.java index 570e03d..b663b9a 100644 --- a/src/com/vaadin/plugin/CopilotRestService.java +++ b/src/com/vaadin/plugin/CopilotRestService.java @@ -6,12 +6,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; /** - * Starts a small HTTP server for Copilot integration. The server exposes a - * single /api/copilot endpoint that accepts POST requests. + * Starts a small HTTP server for Copilot integration. */ public class CopilotRestService { private HttpServer server; @@ -19,10 +19,10 @@ public class CopilotRestService { /** Start the embedded HTTP server on a random port. */ public void start() throws IOException { - server = HttpServer.create(new InetSocketAddress(0), 0); - server.createContext("/api/copilot", new Handler()); + server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 0), 0); + server.createContext("/vaadin/copilot", new Handler()); server.start(); - endpoint = "http://localhost:" + server.getAddress().getPort() + "/api/copilot"; + endpoint = "http://localhost:" + server.getAddress().getPort() + "/vaadin/copilot"; System.out.println("Copilot REST service started at " + endpoint); } @@ -48,7 +48,9 @@ public void handle(HttpExchange exchange) throws IOException { } InputStream is = exchange.getRequestBody(); String body = new String(is.readAllBytes(), StandardCharsets.UTF_8); + System.out.println("Received Copilot request: " + body); + byte[] resp = "OK".getBytes(StandardCharsets.UTF_8); exchange.sendResponseHeaders(200, resp.length); try (OutputStream os = exchange.getResponseBody()) { diff --git a/src/com/vaadin/plugin/EarlyStartup.java b/src/com/vaadin/plugin/EarlyStartup.java index 286e1db..651a5b9 100644 --- a/src/com/vaadin/plugin/EarlyStartup.java +++ b/src/com/vaadin/plugin/EarlyStartup.java @@ -2,10 +2,9 @@ import org.eclipse.ui.IStartup; - /** - * Ensures the plug-in is activated when the workbench starts so the - * {@link Activator} can launch the embedded REST service. + * Ensures the plug-in is activated when the workbench starts so the {@link Activator} can launch the embedded REST + * service. */ public class EarlyStartup implements IStartup {