From 4227b8e8f284efbc3f5f2f2a565a223c0ba978d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 28 Jan 2024 19:55:28 +0100 Subject: [PATCH] Add an organize-manifest mojo --- .../eclipse/tycho}/ArtifactTypeHelper.java | 19 ++- .../org/eclipse/tycho/TargetPlatform.java | 17 +++ .../core/osgitools/TargetPlatformProject.java | 2 +- .../resolver/DefaultP2ResolutionResult.java | 2 +- .../core/resolver/target/ArtifactMatcher.java | 1 + .../publisher/PublishProductToolImpl.java | 2 +- .../tycho/p2resolver/P2ResolverImpl.java | 2 +- .../PomDependencyCollectorImpl.java | 2 +- .../p2resolver/TargetPlatformBaseImpl.java | 2 +- .../p2resolver/TargetPlatformFactoryImpl.java | 2 +- .../tycho-dependency-tools-plugin/pom.xml | 4 + .../tycho/extras/pde/ExportedPackages.java | 18 +++ .../tycho/extras/pde/ImportedPackage.java | 49 +++++++ .../tycho/extras/pde/ImportedPackages.java | 40 ++++++ .../extras/pde/OrganizeManifestMojo.java | 132 ++++++++++++++++++ .../tycho/extras/pde/RequiredBundle.java | 34 +++++ .../tycho/extras/pde/RequiredBundles.java | 66 +++++++++ 17 files changed, 376 insertions(+), 18 deletions(-) rename {tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target => tycho-api/src/main/java/org/eclipse/tycho}/ArtifactTypeHelper.java (92%) create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ExportedPackages.java create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackage.java create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackages.java create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/OrganizeManifestMojo.java create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundle.java create mode 100644 tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundles.java diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactTypeHelper.java b/tycho-api/src/main/java/org/eclipse/tycho/ArtifactTypeHelper.java similarity index 92% rename from tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactTypeHelper.java rename to tycho-api/src/main/java/org/eclipse/tycho/ArtifactTypeHelper.java index 5742b32f6e..b9327e5c10 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactTypeHelper.java +++ b/tycho-api/src/main/java/org/eclipse/tycho/ArtifactTypeHelper.java @@ -10,7 +10,7 @@ * Contributors: * SAP SE - initial API and implementation *******************************************************************************/ -package org.eclipse.tycho.core.resolver.target; +package org.eclipse.tycho; import static org.eclipse.tycho.ArtifactType.TYPE_BUNDLE_FRAGMENT; import static org.eclipse.tycho.ArtifactType.TYPE_ECLIPSE_FEATURE; @@ -24,20 +24,14 @@ import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.metadata.VersionRange; -import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction; import org.eclipse.equinox.p2.query.IQuery; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; -import org.eclipse.tycho.ArtifactKey; -import org.eclipse.tycho.ArtifactType; -import org.eclipse.tycho.DefaultArtifactKey; -import org.eclipse.tycho.IArtifactFacade; -import org.eclipse.tycho.IllegalArtifactReferenceException; -import org.eclipse.tycho.PackagingType; public class ArtifactTypeHelper { - // p2 installable units + public static final String CAPABILITY_NS_OSGI_BUNDLE = "osgi.bundle"; //see org.eclipse.equinox.p2.publisher.eclipse.BundlesAction.CAPABILITY_NS_OSGI_BUNDLE + public static final String OSGI_BUNDLE_CLASSIFIER = "osgi.bundle"; //see org.eclipse.equinox.p2.publisher.eclipse.BundlesAction.OSGI_BUNDLE_CLASSIFIER /** * Returns a query matching the installable units representing the specified Eclipse @@ -90,8 +84,7 @@ public static IRequirement createRequirementFor(String type, String id, VersionR } private static IRequirement createBundleRequirement(String id, VersionRange versionRange) { - return MetadataFactory.createRequirement(BundlesAction.CAPABILITY_NS_OSGI_BUNDLE, id, versionRange, null, false, - true); // optional=false, multiple=true + return MetadataFactory.createRequirement(CAPABILITY_NS_OSGI_BUNDLE, id, versionRange, null, false, true); // optional=false, multiple=true } private static IRequirement createFeatureRequirement(String id, VersionRange versionRange) { @@ -187,4 +180,8 @@ public static String getType(IArtifactFacade artifactFacade) { return ArtifactType.TYPE_INSTALLABLE_UNIT; } + public static boolean isBundle(IArtifactKey key) { + return key != null && OSGI_BUNDLE_CLASSIFIER.equals(key.getClassifier()); + } + } diff --git a/tycho-api/src/main/java/org/eclipse/tycho/TargetPlatform.java b/tycho-api/src/main/java/org/eclipse/tycho/TargetPlatform.java index ffbb72eb09..2340a74099 100644 --- a/tycho-api/src/main/java/org/eclipse/tycho/TargetPlatform.java +++ b/tycho-api/src/main/java/org/eclipse/tycho/TargetPlatform.java @@ -13,7 +13,12 @@ package org.eclipse.tycho; import java.io.File; +import java.util.stream.Stream; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.VersionRange; +import org.eclipse.equinox.p2.query.IQuery; +import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; @@ -89,6 +94,18 @@ default ResolvedArtifactKey resolvePackage(String packageName, String versionRef location); } + default Stream resolvePackages(String packageName, VersionRange versionRange) { + IQuery query = ArtifactTypeHelper.createQueryFor(PublisherHelper.CAPABILITY_NS_JAVA_PACKAGE, + packageName, versionRange); + IQueryResult result = getMetadataRepository().query(query, null); + return result.stream().flatMap(iu -> { + return iu.getArtifacts().stream().filter(key -> ArtifactTypeHelper.isBundle(key)).map(key -> { + return new DefaultArtifactKey(ArtifactType.TYPE_ECLIPSE_PLUGIN, key.getId(), + key.getVersion().toString()); + }); + }); + } + /** * @return the target platform content as a {@link IMetadataRepository}. */ diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java index 1dc6feae4c..1ca7ea6995 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java @@ -22,6 +22,7 @@ import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.tycho.ArtifactKey; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.DependencyArtifacts; import org.eclipse.tycho.PackagingType; @@ -32,7 +33,6 @@ import org.eclipse.tycho.core.ArtifactDependencyWalker; import org.eclipse.tycho.core.TychoProject; import org.eclipse.tycho.core.osgitools.targetplatform.DefaultDependencyArtifacts; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.model.Feature; import org.eclipse.tycho.targetplatform.P2TargetPlatform; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultP2ResolutionResult.java b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultP2ResolutionResult.java index 1c0145c602..21499147c3 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultP2ResolutionResult.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultP2ResolutionResult.java @@ -27,8 +27,8 @@ import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.DefaultArtifactKey; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.p2.resolver.ClassifiedArtifactKey; import org.eclipse.tycho.p2.resolver.ClassifiedLocation; import org.eclipse.tycho.targetplatform.P2TargetPlatform; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactMatcher.java b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactMatcher.java index b138e48891..3026d24e33 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactMatcher.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/target/ArtifactMatcher.java @@ -31,6 +31,7 @@ import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.IllegalArtifactReferenceException; public class ArtifactMatcher { diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java index 4d73213b55..e338c5bc6e 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java @@ -33,10 +33,10 @@ import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.BuildFailureException; import org.eclipse.tycho.DependencySeed; import org.eclipse.tycho.Interpolator; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.core.shared.MavenLogger; import org.eclipse.tycho.p2.repository.PublishingRepository; import org.eclipse.tycho.p2.tools.publisher.facade.PublishProductTool; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2ResolverImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2ResolverImpl.java index 21db213c82..68c1a0943b 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2ResolverImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2ResolverImpl.java @@ -48,6 +48,7 @@ import org.eclipse.equinox.p2.query.QueryUtil; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.DependencyResolutionException; import org.eclipse.tycho.ExecutionEnvironmentConfiguration; @@ -66,7 +67,6 @@ import org.eclipse.tycho.core.resolver.P2ResolutionResult; import org.eclipse.tycho.core.resolver.P2Resolver; import org.eclipse.tycho.core.resolver.shared.PomDependencies; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.core.shared.LoggingProgressMonitor; import org.eclipse.tycho.core.shared.MavenLogger; import org.eclipse.tycho.core.shared.MultiLineLogger; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PomDependencyCollectorImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PomDependencyCollectorImpl.java index d77a7e6b63..d6c0fa00bd 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PomDependencyCollectorImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/PomDependencyCollectorImpl.java @@ -37,12 +37,12 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.IArtifactFacade; import org.eclipse.tycho.IRawArtifactFileProvider; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.TychoConstants; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.core.resolver.target.FileArtifactRepository; import org.eclipse.tycho.p2.repository.ArtifactTransferPolicies; import org.eclipse.tycho.p2.repository.FileRepositoryArtifactProvider; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformBaseImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformBaseImpl.java index bf7865521c..e6c20ed191 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformBaseImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformBaseImpl.java @@ -26,6 +26,7 @@ import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.metadata.VersionRange; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.DependencyResolutionException; import org.eclipse.tycho.ExecutionEnvironmentResolutionHints; @@ -34,7 +35,6 @@ import org.eclipse.tycho.IllegalArtifactReferenceException; import org.eclipse.tycho.ReactorProjectIdentities; import org.eclipse.tycho.core.resolver.target.ArtifactMatcher; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.p2.repository.LocalArtifactRepository; import org.eclipse.tycho.targetplatform.P2TargetPlatform; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java index e31cfbb8e8..e5693c3a5f 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java @@ -64,6 +64,7 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.tycho.ArtifactTypeHelper; import org.eclipse.tycho.ExecutionEnvironmentConfiguration; import org.eclipse.tycho.ExecutionEnvironmentResolutionHints; import org.eclipse.tycho.IArtifactFacade; @@ -84,7 +85,6 @@ import org.eclipse.tycho.core.osgitools.MavenBundleResolver; import org.eclipse.tycho.core.osgitools.OsgiBundleProject; import org.eclipse.tycho.core.resolver.shared.ReferencedRepositoryMode; -import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; import org.eclipse.tycho.core.resolver.target.DuplicateReactorIUsException; import org.eclipse.tycho.core.resolver.target.FileArtifactRepository; import org.eclipse.tycho.core.resolver.target.TargetPlatformFilterEvaluator; diff --git a/tycho-extras/tycho-dependency-tools-plugin/pom.xml b/tycho-extras/tycho-dependency-tools-plugin/pom.xml index 849866c9b8..82504a1aaa 100644 --- a/tycho-extras/tycho-dependency-tools-plugin/pom.xml +++ b/tycho-extras/tycho-dependency-tools-plugin/pom.xml @@ -39,6 +39,10 @@ org.eclipse.tycho tycho-core + + biz.aQute.bnd + biz.aQute.bndlib + diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ExportedPackages.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ExportedPackages.java new file mode 100644 index 0000000000..01e4743ba9 --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ExportedPackages.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +public class ExportedPackages { + + public ExportedPackages(String manifestValue) { + // TODO Auto-generated constructor stub + } + +} diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackage.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackage.java new file mode 100644 index 0000000000..1201f4d553 --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackage.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +import org.osgi.framework.Constants; + +import aQute.bnd.header.Attrs; + +public class ImportedPackage { + + private ImportedPackages packages; + private String packageName; + private Attrs attrs; + + public ImportedPackage(ImportedPackages packages, String packageName, Attrs attrs) { + this.packages = packages; + this.packageName = packageName; + this.attrs = attrs; + } + + public String getPackageName() { + return packageName; + } + + public String getVersion() { + return attrs.get(Constants.VERSION_ATTRIBUTE); + } + + public boolean isJava() { + return packageName.startsWith("java."); + } + + @Override + public String toString() { + String version = getVersion(); + if (version != null) { + return getPackageName() + " " + version; + } + return getPackageName(); + } + +} diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackages.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackages.java new file mode 100644 index 0000000000..ba939d09df --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/ImportedPackages.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.stream.Stream; + +import aQute.bnd.header.Attrs; +import aQute.bnd.header.OSGiHeader; +import aQute.bnd.header.Parameters; + +public class ImportedPackages { + + //import package order is not important so we can sort here by name + private Map packages = new TreeMap<>(); + + public ImportedPackages(String manifestValue) { + if (manifestValue != null) { + Parameters header = OSGiHeader.parseHeader(manifestValue); + for (Entry entry : header.entrySet()) { + packages.put(entry.getKey(), new ImportedPackage(this, entry.getKey(), entry.getValue())); + } + } + } + + public Stream packages() { + return packages.values().stream(); + + } + +} diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/OrganizeManifestMojo.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/OrganizeManifestMojo.java new file mode 100644 index 0000000000..4dafabc0fa --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/OrganizeManifestMojo.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +import java.io.File; +import java.util.List; +import java.util.jar.Manifest; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; +import org.eclipse.equinox.p2.metadata.VersionRange; +import org.eclipse.tycho.ArtifactDescriptor; +import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.DependencyArtifacts; +import org.eclipse.tycho.PackagingType; +import org.eclipse.tycho.TargetPlatform; +import org.eclipse.tycho.core.TychoProject; +import org.eclipse.tycho.core.TychoProjectManager; +import org.eclipse.tycho.core.osgitools.DefaultReactorProject; +import org.eclipse.tycho.core.osgitools.OsgiBundleProject; +import org.osgi.framework.Constants; + +import aQute.bnd.osgi.Analyzer; +import aQute.bnd.osgi.Jar; + +@Mojo(name = "organize-manifest", requiresProject = true, threadSafe = true, requiresDependencyCollection = ResolutionScope.TEST) +public class OrganizeManifestMojo extends AbstractMojo { + + @Parameter(defaultValue = "true") + private boolean addMissingVersions; + + @Parameter + private boolean skip; + + @Component + private MavenProject mavenProject; + + @Component + private TychoProjectManager projectManager; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + if (PackagingType.TYPE_ECLIPSE_PLUGIN.equals(mavenProject.getPackaging())) { + TychoProject tychoProject = projectManager.getTychoProject(mavenProject).get(); + if (tychoProject instanceof OsgiBundleProject osgi) { + DependencyArtifacts artifacts = tychoProject + .getDependencyArtifacts(DefaultReactorProject.adapt(mavenProject)); + TargetPlatform tp = projectManager.getTargetPlatform(mavenProject).get(); + File file = mavenProject.getArtifact().getFile(); + if (!file.isFile()) { + file = new File(mavenProject.getBuild().getOutputDirectory()); + if (!file.isDirectory()) { + throw new MojoFailureException( + "Artifact is not packed and output directory is not present, do you executed the compile/package phase for this project?"); + } + } + RequiredBundles requiredBundles = new RequiredBundles( + osgi.getManifestValue(Constants.REQUIRE_BUNDLE, mavenProject)); + expandReexports(requiredBundles); + ExportedPackages exportedPackages = new ExportedPackages( + osgi.getManifestValue(Constants.EXPORT_PACKAGE, mavenProject)); + ImportedPackages importedPackages = new ImportedPackages( + osgi.getManifestValue(Constants.IMPORT_PACKAGE, mavenProject)); + ImportedPackages calculatePackages = calculatePackages(artifacts, tp, file, requiredBundles); + System.out.println("=== Required Bundles ==="); + requiredBundles.bundles().forEach(rb -> { + System.out.println(rb.getBundleSymbolicName()); + requiredBundles.contributedPackages(rb).forEach(pkg -> System.out.println("\t <-- " + pkg)); + }); + System.out.println("=== Imported Packages ==="); + importedPackages.packages().forEach(pkg -> System.out.println(pkg.getPackageName())); + } + } + } + + private ImportedPackages calculatePackages(DependencyArtifacts artifacts, TargetPlatform tp, File file, + RequiredBundles requiredBundles) throws MojoExecutionException { + try (Jar jar = new Jar(file)) { + jar.setManifest((Manifest) null); + try (Analyzer analyzer = new Analyzer(jar)) { + analyzer.setImportPackage("*"); + List list = artifacts.getArtifacts(ArtifactType.TYPE_ECLIPSE_PLUGIN); + for (ArtifactDescriptor artifactDescriptor : list) { + File cp = artifactDescriptor.fetchArtifact().join(); + if (!cp.exists() || cp.length() == 0) { + continue; + } + analyzer.addClasspath(cp); + } + Manifest manifest = analyzer.calcManifest(); + Log log = getLog(); + analyzer.getWarnings().forEach(log::warn); + analyzer.getErrors().forEach(log::error); + String value = manifest.getMainAttributes().getValue(Constants.IMPORT_PACKAGE); + ImportedPackages calculatedPackages = new ImportedPackages(value); + calculatedPackages.packages().forEach(pkg -> { + if (!pkg.isJava()) { + String version = pkg.getVersion(); + tp.resolvePackages(pkg.getPackageName(), + version == null ? VersionRange.emptyRange : VersionRange.create(version)) + .forEach(key -> { + requiredBundles.addPackageMapping(pkg, key); + }); + } + }); + return calculatedPackages; + } + } catch (Exception e) { + throw new MojoExecutionException("Organize manifest failed", e); + } + } + + private void expandReexports(RequiredBundles requiredBundles) { + //here we need to add childs to the RequiredBundle if that bundle has reexported required bundles... + //as these packages are visible we need to consider if we can remove the parent + } + +} diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundle.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundle.java new file mode 100644 index 0000000000..15357f4749 --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundle.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +import org.osgi.framework.Constants; + +import aQute.bnd.header.Attrs; + +public class RequiredBundle { + + private String bundleSymbolicName; + private Attrs attrs; + + public RequiredBundle(String bundleSymbolicName, Attrs attrs) { + this.bundleSymbolicName = bundleSymbolicName; + this.attrs = attrs; + } + + public String getBundleSymbolicName() { + return bundleSymbolicName; + } + + public boolean isReexport() { + return Constants.VISIBILITY_REEXPORT.equals(attrs.get(Constants.VISIBILITY_DIRECTIVE + ":")); + } + +} diff --git a/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundles.java b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundles.java new file mode 100644 index 0000000000..a1b6b3035a --- /dev/null +++ b/tycho-extras/tycho-dependency-tools-plugin/src/main/java/org/eclipse/tycho/extras/pde/RequiredBundles.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * 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 + *******************************************************************************/ +package org.eclipse.tycho.extras.pde; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import org.eclipse.tycho.ArtifactKey; + +import aQute.bnd.header.Attrs; +import aQute.bnd.header.OSGiHeader; +import aQute.bnd.header.Parameters; + +public class RequiredBundles { + + //The order of require bundle is important so we need to retain it + private Map bundles = new LinkedHashMap<>(); + + private Map> contributedPackages = new HashMap<>(); + + private Map> contributingBundles = new HashMap<>(); + + public Stream contributedPackages(RequiredBundle bundle) { + return contributedPackages.getOrDefault(bundle, List.of()).stream() + .sorted(Comparator.comparing(ImportedPackage::getPackageName)); + } + + public RequiredBundles(String manifestValue) { + if (manifestValue != null) { + Parameters header = OSGiHeader.parseHeader(manifestValue); + for (Entry entry : header.entrySet()) { + String bsn = entry.getKey(); + Attrs attrs = entry.getValue(); + bundles.put(bsn, new RequiredBundle(bsn, attrs)); + } + } + } + + public Stream bundles() { + return bundles.values().stream(); + + } + + public void addPackageMapping(ImportedPackage pkg, ArtifactKey key) { + RequiredBundle requiredBundle = bundles.get(key.getId()); + if (requiredBundle != null) { + contributedPackages.computeIfAbsent(requiredBundle, x -> new HashSet<>()).add(pkg); + contributingBundles.computeIfAbsent(pkg, x -> new HashSet<>()).add(requiredBundle); + } + } + +}