diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
index e3b70f5..928f7e9 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: javax.servlet,javax.servlet.http,org.osgi.service.http,org.osgi.framework
Automatic-Module-Name: vaadin.eclipse.plugin
Bundle-RequiredExecutionEnvironment: JavaSE-21
diff --git a/README.md b/README.md
index 362e39d..a4a7b48 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` registers a servlet using the OSGi `HttpService`. The servlet exposes a unique `/api/{serviceName}` endpoint on the container's HTTP server, and the full endpoint 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..f5165ad
--- /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(context);
+ System.setProperty("vaadin.copilot.endpoint", restService.getEndpoint());
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ if (restService != null) {
+ restService.stop(context);
+ restService = null;
+ }
+ }
+}
diff --git a/src/com/vaadin/plugin/CopilotRestService.java b/src/com/vaadin/plugin/CopilotRestService.java
new file mode 100644
index 0000000..14ea271
--- /dev/null
+++ b/src/com/vaadin/plugin/CopilotRestService.java
@@ -0,0 +1,53 @@
+package com.vaadin.plugin;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Registers a simple servlet for Vaadin Copilot integration using the OSGi
+ * {@link HttpService}. The servlet is bound to a unique "/api/{serviceName}"
+ * alias and the full endpoint URL can be retrieved via {@link #getEndpoint()}.
+ */
+public class CopilotRestService {
+ private HttpService httpService;
+ private ServiceReference serviceRef;
+ private String serviceName;
+ private String endpoint;
+
+ public void start(BundleContext context) throws ServletException, NamespaceException {
+ serviceName = "copilot-" + UUID.randomUUID();
+ serviceRef = context.getServiceReference(HttpService.class);
+ if (serviceRef == null) {
+ throw new IllegalStateException("HttpService not available");
+ }
+ httpService = context.getService(serviceRef);
+ String alias = "/api/" + serviceName;
+ httpService.registerServlet(alias, new CopilotServlet(), null, null);
+ String port = context.getProperty("org.osgi.service.http.port");
+ if (port == null) {
+ port = "8080";
+ }
+ endpoint = "http://localhost:" + port + alias;
+ System.out.println("Copilot REST service registered at " + endpoint);
+ }
+
+ public void stop(BundleContext context) {
+ if (httpService != null) {
+ String alias = "/api/" + serviceName;
+ httpService.unregister(alias);
+ context.ungetService(serviceRef);
+ httpService = null;
+ serviceRef = null;
+ }
+ }
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+}
diff --git a/src/com/vaadin/plugin/CopilotServlet.java b/src/com/vaadin/plugin/CopilotServlet.java
new file mode 100644
index 0000000..126b8c7
--- /dev/null
+++ b/src/com/vaadin/plugin/CopilotServlet.java
@@ -0,0 +1,21 @@
+package com.vaadin.plugin;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.stream.Collectors;
+
+/**
+ * Simple servlet used by {@link CopilotRestService} to receive Copilot requests.
+ */
+public class CopilotServlet extends HttpServlet {
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ String body = req.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
+ System.out.println("Received Copilot request: " + body);
+ resp.setStatus(HttpServletResponse.SC_OK);
+ resp.getWriter().write("OK");
+ }
+}
diff --git a/src/com/vaadin/plugin/EarlyStartup.java b/src/com/vaadin/plugin/EarlyStartup.java
new file mode 100644
index 0000000..cab972f
--- /dev/null
+++ b/src/com/vaadin/plugin/EarlyStartup.java
@@ -0,0 +1,16 @@
+package com.vaadin.plugin;
+
+import org.eclipse.ui.IStartup;
+
+
+/**
+ * Starts the REST service when the workbench starts. The service is registered
+ * using the OSGi {@code HttpService} and stopped when the bundle shuts down.
+ */
+public class EarlyStartup implements IStartup {
+
+ @Override
+ public void earlyStartup() {
+ // Trigger plug-in activation so the BundleActivator runs
+ }
+}