diff --git a/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/JdtProjectBuilder.java b/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/JdtProjectBuilder.java new file mode 100644 index 0000000000..94d6088c59 --- /dev/null +++ b/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/JdtProjectBuilder.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2025 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 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.bndlib; + +import aQute.bnd.build.Project; +import aQute.bnd.build.ProjectBuilder; + +/** + * A project builder that injects information from the sources into the builder + */ +public class JdtProjectBuilder extends ProjectBuilder { + + public JdtProjectBuilder(Project project) { + super(project); + addBasicPlugin(new SourceCodeAnalyzerPlugin()); + } + + @Override + public String _packageattribute(String[] args) { + SourceCodeAnalyzerPlugin analyzerPlugin = getPlugin(SourceCodeAnalyzerPlugin.class); + try { + analyzerPlugin.analyzeJar(this); + } catch (Exception e) { + } + return super._packageattribute(args); + } +} diff --git a/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/SourceCodeAnalyzerPlugin.java b/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/SourceCodeAnalyzerPlugin.java index 14099c9673..a6cde1a2b4 100644 --- a/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/SourceCodeAnalyzerPlugin.java +++ b/tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/SourceCodeAnalyzerPlugin.java @@ -30,7 +30,9 @@ import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.MemberValuePair; +import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.PackageDeclaration; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; @@ -49,10 +51,11 @@ */ public class SourceCodeAnalyzerPlugin implements AnalyzerPlugin { + private static final String JAVA_EXTENSION = ".java"; private static final String PACKAGE_INFO = "package-info"; private static final String ANNOTATION_VERSION = "org.osgi.annotation.versioning.Version"; private static final String ANNOTATION_EXPORT = "org.osgi.annotation.bundle.Export"; - private static final String PACKAGE_INFO_JAVA = PACKAGE_INFO + ".java"; + private static final String PACKAGE_INFO_JAVA = PACKAGE_INFO + JAVA_EXTENSION; private static final String PACKAGE_INFO_CLASS = PACKAGE_INFO + ".class"; private List sourcePaths; private Map packageInfoMap = new HashMap<>(); @@ -86,7 +89,7 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { String fileName = file.getFileName().toString().toLowerCase(); - if (fileName.endsWith(".java")) { + if (fileName.endsWith(JAVA_EXTENSION)) { boolean packageInfo = fileName.equals(PACKAGE_INFO_JAVA); if (packageInfo || analyzedPath.add(file.getParent())) { String source = Files.readString(file); @@ -95,6 +98,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO if (ast instanceof CompilationUnit cu) { PackageDeclaration packageDecl = cu.getPackage(); if (packageDecl != null) { + List imports = cu.imports(); String packageFqdn = packageDecl.getName().getFullyQualifiedName(); PackageRef packageRef = analyzer.getPackageRef(packageFqdn); if (seenPackages.add(packageFqdn)) { @@ -111,12 +115,13 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO String version = null; for (Object raw : packageDecl.annotations()) { if (raw instanceof Annotation annot) { - String annotationFqdn = annot.getTypeName().getFullyQualifiedName(); - if (ANNOTATION_EXPORT.equals(annotationFqdn)) { + Name typeName = annot.getTypeName(); + String annotationFqdn = typeName.getFullyQualifiedName(); + if (isType(annotationFqdn, ANNOTATION_EXPORT, imports)) { export = true; clazz.addAnnotation( analyzer.getTypeRef(ANNOTATION_EXPORT.replace('.', '/'))); - } else if (ANNOTATION_VERSION.equals(annotationFqdn)) { + } else if (isType(annotationFqdn, ANNOTATION_VERSION, imports)) { if (annot instanceof NormalAnnotation normal) { for (Object vp : normal.values()) { MemberValuePair pair = (MemberValuePair) vp; @@ -133,14 +138,12 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO } } } + if (version != null) { + // if the package is exported or not, the version info must be propagated + analyzer.getContained().put(packageRef, Attrs.create("version", version)); + } if (export) { packageInfoMap.put(packageRef, clazz); - if (version == null) { - analyzer.getContained().put(packageRef); - } else { - analyzer.getContained().put(packageRef, - Attrs.create("version", version)); - } } } } @@ -174,8 +177,24 @@ private List getSourcePath(Analyzer analyzer) { return List.of(); } - public Clazz getPackageInfo(PackageRef packageRef) { + public Clazz getPackageInfoClass(PackageRef packageRef) { return packageInfoMap.get(packageRef); } + private static boolean isType(String simpleOrFqdn, String type, List imports) { + if (type.equals(simpleOrFqdn)) { + return true; + } + if (type.endsWith("." + simpleOrFqdn)) { + for (Object object : imports) { + if (object instanceof ImportDeclaration importDecl) { + if (type.equals(importDecl.getName().getFullyQualifiedName())) { + return true; + } + } + } + } + return false; + } + } diff --git a/tycho-build/pom.xml b/tycho-build/pom.xml index 23c8ed9c53..4704286889 100644 --- a/tycho-build/pom.xml +++ b/tycho-build/pom.xml @@ -150,5 +150,10 @@ org.osgi.util.promise 1.3.0 + + org.eclipse.tycho + tycho-bndlib + ${project.version} + \ No newline at end of file diff --git a/tycho-build/src/main/java/org/eclipse/tycho/build/bnd/BndProjectMapping.java b/tycho-build/src/main/java/org/eclipse/tycho/build/bnd/BndProjectMapping.java index a3449fe1cb..55a902e8b0 100644 --- a/tycho-build/src/main/java/org/eclipse/tycho/build/bnd/BndProjectMapping.java +++ b/tycho-build/src/main/java/org/eclipse/tycho/build/bnd/BndProjectMapping.java @@ -28,6 +28,7 @@ import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.eclipse.tycho.TychoConstants; +import org.eclipse.tycho.bndlib.JdtProjectBuilder; import org.eclipse.tycho.pomless.AbstractTychoMapping; import org.eclipse.tycho.pomless.NoParentPomFound; import org.eclipse.tycho.pomless.ParentModel; @@ -168,7 +169,7 @@ protected void initModel(Model model, Reader artifactReader, Path artifactFile) } private static ProjectBuilder createBuilder(Project project) throws Exception { - ProjectBuilder builder = new ProjectBuilder(project); + ProjectBuilder builder = new JdtProjectBuilder(project); builder.setBase(project.getBase()); builder.use(project); builder.setFailOk(true); diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/PdeInstallableUnitProvider.java b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/PdeInstallableUnitProvider.java index c762c24d18..285f526ce0 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/PdeInstallableUnitProvider.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/PdeInstallableUnitProvider.java @@ -194,7 +194,7 @@ private Collection generateWithProcessor(MavenProject project, public Clazz getPackageInfo(PackageRef packageRef) { Clazz info = super.getPackageInfo(packageRef); if (info == null) { - return plugin.getPackageInfo(packageRef); + return plugin.getPackageInfoClass(packageRef); } return info; }