diff --git a/org.eclipse.m2e.bnd.ui/.classpath b/org.eclipse.m2e.bnd.ui/.classpath new file mode 100644 index 0000000000..375961e4d6 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.eclipse.m2e.bnd.ui/.project b/org.eclipse.m2e.bnd.ui/.project new file mode 100644 index 0000000000..e7bfedc0a1 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/.project @@ -0,0 +1,33 @@ + + + org.eclipse.m2e.bnd.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.core.resources.prefs b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..99f26c0203 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..23fa13b170 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 +org.eclipse.jdt.core.compiler.compliance=21 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=21 diff --git a/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.pde.ds.annotations.prefs b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.pde.ds.annotations.prefs new file mode 100644 index 0000000000..5faf08b7d5 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/.settings/org.eclipse.pde.ds.annotations.prefs @@ -0,0 +1,7 @@ +dsVersion=V1_4 +eclipse.preferences.version=1 +enabled=true +generateBundleActivationPolicyLazy=true +path=OSGI-INF +validationErrorLevel=error +validationErrorLevel.missingImplicitUnbindMethod=error diff --git a/org.eclipse.m2e.bnd.ui/META-INF/MANIFEST.MF b/org.eclipse.m2e.bnd.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..69c958f9ac --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: bnd-maven-plugin integration +Bundle-SymbolicName: org.eclipse.m2e.bnd.ui +Bundle-Version: 1.0.0.qualifier +Import-Package: aQute.bnd.build;version="[4.5.0,5.0.0)", + aQute.bnd.maven.lib.configuration;version="1.2.0", + aQute.bnd.maven.lib.resolve;version="[1.3.0,2.0.0)", + aQute.bnd.osgi;version="[7.0.0,8.0.0)", + aQute.bnd.repository.fileset;version="[1.1.0,2.0.0)" +Require-Bundle: org.eclipse.equinox.common, + org.eclipse.core.resources, + org.eclipse.m2e.core, + org.eclipse.m2e.maven.runtime +Service-Component: OSGI-INF/org.eclipse.m2e.bnd.ui.BndPluginAdapter.xml +Bundle-Vendor: Eclipse +Automatic-Module-Name: org.eclipse.m2e.bnd.ui +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-21 diff --git a/org.eclipse.m2e.bnd.ui/OSGI-INF/.gitignore b/org.eclipse.m2e.bnd.ui/OSGI-INF/.gitignore new file mode 100644 index 0000000000..b878e882ac --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/OSGI-INF/.gitignore @@ -0,0 +1 @@ +/*.xml diff --git a/org.eclipse.m2e.bnd.ui/build.properties b/org.eclipse.m2e.bnd.ui/build.properties new file mode 100644 index 0000000000..d5ed28ecef --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/ +jars.extra.classpath = platform:/plugin/org.eclipse.wildwebdeveloper.xml/language-servers/server/org.eclipse.lemminx-uber.jar diff --git a/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/BndPluginAdapter.java b/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/BndPluginAdapter.java new file mode 100644 index 0000000000..3dee965432 --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/BndPluginAdapter.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2024 Christoph Läubrich + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.m2e.bnd.ui; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.AdapterTypes; +import org.eclipse.core.runtime.Adapters; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.m2e.core.lifecyclemapping.model.IPluginExecutionMetadata; +import org.eclipse.m2e.core.project.IMavenProjectFacade; +import org.eclipse.m2e.core.project.configurator.MojoExecutionKey; +import org.osgi.service.component.annotations.Component; + +import aQute.bnd.build.Project; +import aQute.bnd.build.Workspace; +import aQute.bnd.maven.lib.configuration.BeanProperties; +import aQute.bnd.maven.lib.resolve.ImplicitFileSetRepository; +import aQute.bnd.osgi.Processor; + +/** + * Adapts eclipse projects managed by m2e to bnd projects + */ +@Component +@AdapterTypes(adaptableClass = IProject.class, adapterNames = Project.class) +public class BndPluginAdapter implements IAdapterFactory { + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + try { + if (adaptableObject instanceof IProject eclipseProject) { + if (adapterType == Project.class) { + IMavenProjectFacade mavenProject = Adapters.adapt(eclipseProject, IMavenProjectFacade.class); + if (isRelevantProject(mavenProject)) { + System.out.println(eclipseProject.getName() + " uses bnd plugin!"); + BeanProperties beanProperties = new BeanProperties(); + MavenProject mp = mavenProject.getMavenProject(); + if (mp != null) { + beanProperties.put("project", mp); + } + // TODO beanProperties.put("settings", settings); + Properties processorProperties = new Properties(beanProperties); + if (mp != null) { + Properties projectProperties = mp.getProperties(); + for (String key : projectProperties.stringPropertyNames()) { + processorProperties.setProperty(key, projectProperties.getProperty(key)); + } + } + Processor processor = new Processor(processorProperties, false); + Collection list = new ArrayList(); + if (mp != null) { + for (Artifact artifact : mp.getArtifacts()) { + list.add(artifact.getFile()); + } + } + ImplicitFileSetRepository repository = new ImplicitFileSetRepository("Project Artifacts", list); + // TODO propertiesFile = new BndConfiguration(project, + // mojoExecution).loadProperties(builder); + // TODO + // aQute.bnd.maven.lib.resolve.BndrunContainer.getFileSetRepository(MavenProject) + + Workspace standaloneWorkspace = Workspace.createStandaloneWorkspace(processor, + mavenProject.getPomFile().getParentFile().toURI()); + standaloneWorkspace.addBasicPlugin(repository); + if (mp == null) { + standaloneWorkspace.set("workspaceName", mavenProject.getArtifactKey().toPortableString()); + } else { + // TODO make part of IMavenProjectFacade + standaloneWorkspace.set("workspaceName", mp.getName()); + String description = mp.getDescription(); + if (description != null) { + standaloneWorkspace.set("workspaceDescription", description); + } + } + standaloneWorkspace.refresh(); + Project bndProject = new Project(standaloneWorkspace, null, null); + bndProject.setBase(null); + return adapterType.cast(bndProject); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private boolean isRelevantProject(IMavenProjectFacade mavenProject) { + // TODO cache result inside IProject store + if (mavenProject != null) { + Map> mapping = mavenProject.getMojoExecutionMapping(); + for (MojoExecutionKey key : mapping.keySet()) { + if ("biz.aQute.bnd".equals(key.groupId()) && "bnd-maven-plugin".equals(key.artifactId())) { + return true; + } + } + } + return false; + } + +} diff --git a/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/lemminx/MyExtension.java b/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/lemminx/MyExtension.java new file mode 100644 index 0000000000..659eaddd9a --- /dev/null +++ b/org.eclipse.m2e.bnd.ui/src/org/eclipse/m2e/bnd/ui/lemminx/MyExtension.java @@ -0,0 +1,21 @@ +package org.eclipse.m2e.bnd.ui.lemminx; + +import org.eclipse.lemminx.services.extensions.IXMLExtension; +import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; +import org.eclipse.lsp4j.InitializeParams; + +public class MyExtension implements IXMLExtension { + + @Override + public void start(InitializeParams arg0, XMLExtensionsRegistry arg1) { + // TODO Auto-generated method stub + + } + + @Override + public void stop(XMLExtensionsRegistry arg0) { + // TODO Auto-generated method stub + + } + +} diff --git a/org.eclipse.m2e.core/.settings/org.eclipse.pde.ds.annotations.prefs b/org.eclipse.m2e.core/.settings/org.eclipse.pde.ds.annotations.prefs index 73a356b6d0..19be1e2fb6 100644 --- a/org.eclipse.m2e.core/.settings/org.eclipse.pde.ds.annotations.prefs +++ b/org.eclipse.m2e.core/.settings/org.eclipse.pde.ds.annotations.prefs @@ -1,5 +1,5 @@ classpath=true -dsVersion=V1_3 +dsVersion=V1_5 eclipse.preferences.version=1 enabled=true generateBundleActivationPolicyLazy=true diff --git a/org.eclipse.m2e.lemminx.bnd/.classpath b/org.eclipse.m2e.lemminx.bnd/.classpath new file mode 100644 index 0000000000..5d5961d093 --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/.classpath @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.eclipse.m2e.lemminx.bnd/.project b/org.eclipse.m2e.lemminx.bnd/.project new file mode 100644 index 0000000000..2e7c35044e --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/.project @@ -0,0 +1,23 @@ + + + org.eclipse.m2e.lemminx.bnd + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..68472858a2 --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.m2e.core.prefs b/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000000..f897a7f1cb --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/org.eclipse.m2e.lemminx.bnd/pom.xml b/org.eclipse.m2e.lemminx.bnd/pom.xml new file mode 100644 index 0000000000..837ad3895b --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + + + + + + org.eclipse.m2e.lemminx.bnd + org.eclipse.m2e.lemminx.bnd + 2.1.0-SNAPSHOT + M2E bnd lemminx extension + + + 17 + ${java.version} + + + + + + org.eclipse.lemminx + org.eclipse.lemminx + 0.28.0 + provided + + + biz.aQute.bnd + biz.aQute.bndlib + 7.0.0 + + + + + + lemminx-releases + https://repo.eclipse.org/content/repositories/lemminx-releases/ + + false + + + true + + + + \ No newline at end of file diff --git a/org.eclipse.m2e.lemminx.bnd/src/main/java/org/eclipse/m2e/lemminx/bnd/BndLemminxPlugin.java b/org.eclipse.m2e.lemminx.bnd/src/main/java/org/eclipse/m2e/lemminx/bnd/BndLemminxPlugin.java new file mode 100644 index 0000000000..5aa3aa0cb4 --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/src/main/java/org/eclipse/m2e/lemminx/bnd/BndLemminxPlugin.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2024 Christoph Läubrich + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.m2e.lemminx.bnd; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.eclipse.lemminx.dom.DOMDocument; +import org.eclipse.lemminx.dom.DOMNode; +import org.eclipse.lemminx.services.extensions.IXMLExtension; +import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; +import org.eclipse.lemminx.services.extensions.completion.ICompletionParticipant; +import org.eclipse.lemminx.services.extensions.completion.ICompletionRequest; +import org.eclipse.lemminx.services.extensions.completion.ICompletionResponse; +import org.eclipse.lemminx.services.extensions.save.ISaveContext; +import org.eclipse.lsp4j.CompletionItem; +import org.eclipse.lsp4j.InitializeParams; +import org.eclipse.lsp4j.jsonrpc.CancelChecker; + +import aQute.bnd.help.Syntax; + +public class BndLemminxPlugin implements IXMLExtension { + + // TODO LemminxClasspathExtensionProvider that puts our jar on the classpath + + // bnd dependencies! + + @Override + public void start(InitializeParams params, XMLExtensionsRegistry registry) { + Logger logger = Logger.getLogger("bnd"); + logger.log(Level.INFO, "Hello From BND Extension"); + registry.registerCompletionParticipant(new ICompletionParticipant() { + + @Override + public void onAttributeName(boolean arg0, ICompletionRequest arg1, ICompletionResponse arg2, + CancelChecker arg3) throws Exception { + logger.log(Level.INFO, "onAttributeName"); + } + + @Override + public void onAttributeValue(String arg0, ICompletionRequest arg1, ICompletionResponse arg2, + CancelChecker arg3) throws Exception { + logger.log(Level.INFO, "onAttributeValue"); + } + + @Override + public void onDTDSystemId(String arg0, ICompletionRequest arg1, ICompletionResponse arg2, + CancelChecker arg3) throws Exception { + logger.log(Level.INFO, "onDTDSystemId"); + } + + @Override + public void onTagOpen(ICompletionRequest arg0, ICompletionResponse arg1, CancelChecker arg2) + throws Exception { + logger.log(Level.INFO, "onTagOpen"); + } + + @Override + public void onXMLContent(ICompletionRequest completionRequest, ICompletionResponse response, + CancelChecker checker) throws Exception { + + logger.log(Level.INFO, "onXMLContent"); + try { + // FIXME CDATA do not trigger completion: + // https://github.com/eclipse/lemminx/issues/1694 + DOMDocument xmlDocument = completionRequest.getXMLDocument(); + DOMNode node = xmlDocument.findNodeBefore(completionRequest.getOffset()); + if (isBndNode(node)) { + // FIXME get the text to give better completion proposals, see: + // https://github.com/eclipse/lemminx/issues/1695 +// if (node != null && node.getNodeName().equals("bnd")) { +// logger.log(Level.INFO, "text content=" + node.getTextContent()); +// String substring = xmlDocument.getText().substring(node.getStart(), node.getEnd()); +// logger.log(Level.INFO, "substring=" + substring); +// } else { +// logger.log(Level.INFO, +// "node=" + node + ", start=" + node.getStart() + ", end=" + node.getEnd() +// + " --> text content=" + node.getTextContent()); +// +// // Syntax.HELP.values().stream().map(syntax -> { +// } + Syntax.HELP.values().stream().forEach(syntax -> { + CompletionItem item = new CompletionItem(); + item.setLabel(syntax.getHeader()); + item.setInsertText(syntax.getHeader() + ": "); + response.addCompletionItem(item); + }); + } + } catch (Exception e) { + logger.log(Level.INFO, "err=" + e); + } + } + + private boolean isBndNode(DOMNode node) { + if (node != null) { + if (node.getNodeName().equals("bnd")) { + return true; + } + return isBndNode(node.getParentNode()); + } + return false; + } + + }); + } + + @Override + public void stop(XMLExtensionsRegistry registry) { + // TODO Auto-generated method stub + + } + + @Override + public void doSave(ISaveContext context) { + // TODO Auto-generated method stub + IXMLExtension.super.doSave(context); + } + +} \ No newline at end of file diff --git a/org.eclipse.m2e.lemminx.bnd/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension b/org.eclipse.m2e.lemminx.bnd/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension new file mode 100644 index 0000000000..08c100d454 --- /dev/null +++ b/org.eclipse.m2e.lemminx.bnd/src/main/resources/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension @@ -0,0 +1 @@ +org.eclipse.m2e.lemminx.bnd.BndLemminxPlugin \ No newline at end of file diff --git a/pom.xml b/pom.xml index a4930719f5..3549a3b272 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,8 @@ org.eclipse.m2e.apt.core org.eclipse.m2e.apt.ui org.eclipse.m2e.mavenarchiver + org.eclipse.m2e.bnd.ui + org.eclipse.m2e.lemminx.bnd org.eclipse.m2e.tests.common diff --git a/target-platform/target-platform.target b/target-platform/target-platform.target index 96f134caac..b3b0ff35d5 100644 --- a/target-platform/target-platform.target +++ b/target-platform/target-platform.target @@ -103,6 +103,12 @@ 3.17.0 jar + + biz.aQute.bnd + biz.aQute.bnd.maven + 7.0.0 + jar +