Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tycho-4.0.x] Synthesize a (bnd) clazz from the JDT model to support export annotation #3853

Merged
merged 1 commit into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Christoph Läubrich and others.
* Copyright (c) 2023, 2024 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
Expand Down Expand Up @@ -49,7 +49,10 @@
import org.eclipse.tycho.resolver.InstallableUnitProvider;

import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Clazz;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.Descriptors.TypeRef;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Processor;
import aQute.bnd.version.MavenVersion;
Expand Down Expand Up @@ -183,7 +186,25 @@ private static Map<String, Dependency> collectInitial(MavenProject project, Map<

private Collection<IInstallableUnit> generateWithProcessor(MavenProject project, Processor processor,
Collection<Artifact> artifacts) throws Exception {
try (Builder analyzer = new Builder(processor)) {
SourceCodeAnalyzerPlugin plugin = new SourceCodeAnalyzerPlugin(
project.getCompileSourceRoots().stream().map(Path::of).toList());
try (Builder analyzer = new Builder(processor) {
@Override
public Clazz getPackageInfo(PackageRef packageRef) {
Clazz info = super.getPackageInfo(packageRef);
if (info == null) {
return plugin.getPackageInfo(packageRef);
}
return info;
}

@Override
public Clazz findClass(TypeRef typeRef) throws Exception {
//TODO instead of override the getPackageInfo(...) we can also use this but
//in that case we probably need to implement more in the JDTClazz as it is called from different places
return super.findClass(typeRef);
};
}) {
analyzer.setBase(project.getBasedir());
Jar jar = new Jar(project.getArtifactId());
analyzer.setJar(jar);
Expand All @@ -197,8 +218,7 @@ private Collection<IInstallableUnit> generateWithProcessor(MavenProject project,
}
}
}
analyzer.addBasicPlugin(
new SourceCodeAnalyzerPlugin(project.getCompileSourceRoots().stream().map(Path::of).toList()));
analyzer.addBasicPlugin(plugin);
analyzer.setProperty(Constants.NOEXTRAHEADERS, "true");
analyzer.build();
Manifest manifest = jar.getManifest();
Expand All @@ -210,6 +230,12 @@ private Collection<IInstallableUnit> generateWithProcessor(MavenProject project,
ManifestUtil.write(manifest, outputStream);
String str = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
logger.debug("Generated preliminary manifest for " + project.getId() + ":\r\n" + str);
for (String error : analyzer.getErrors()) {
logger.debug("ERROR: " + error);
}
for (String warn : analyzer.getWarnings()) {
logger.debug("WARN: " + warn);
}
}
return installableUnitGenerator.getInstallableUnits(manifest);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Christoph Läubrich and others.
* Copyright (c) 2023, 2024 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
Expand All @@ -18,8 +18,10 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.dom.AST;
Expand All @@ -35,19 +37,25 @@

import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Descriptors;
import aQute.bnd.osgi.Clazz;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.Descriptors.TypeRef;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Resource;
import aQute.bnd.service.AnalyzerPlugin;

/**
* Enhances the analyzed classes by information obtained from the source code
*/
class SourceCodeAnalyzerPlugin implements AnalyzerPlugin {

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";
private static final String PACKAGE_INFO_CLASS = PACKAGE_INFO + ".class";
private List<Path> sourcePaths;
private Map<PackageRef, Clazz> packageInfoMap = new HashMap<>();

public SourceCodeAnalyzerPlugin(List<Path> sourcePaths) {
this.sourcePaths = sourcePaths;
Expand All @@ -56,7 +64,6 @@ public SourceCodeAnalyzerPlugin(List<Path> sourcePaths) {
@Override
public boolean analyzeJar(Analyzer analyzer) throws Exception {
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
Descriptors descriptors = new Descriptors();
Set<String> seenPackages = new HashSet<>();
Set<Path> analyzedPath = new HashSet<>();
for (Path sourcePath : sourcePaths) {
Expand All @@ -80,12 +87,16 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
PackageDeclaration packageDecl = cu.getPackage();
if (packageDecl != null) {
String packageFqdn = packageDecl.getName().getFullyQualifiedName();
PackageRef packageRef = analyzer.getPackageRef(packageFqdn);
if (seenPackages.add(packageFqdn)) {
//make the package available to bnd analyzer
PackageRef packageRef = descriptors.getPackageRef(packageFqdn);
analyzer.getContained().put(packageRef);
}
if (packageInfo) {
JDTClazz clazz = new JDTClazz(analyzer,
packageRef.getBinary() + "/" + PACKAGE_INFO_CLASS,
new FileResource(file),
analyzer.getTypeRef(packageRef.getBinary() + "/" + PACKAGE_INFO));
//check for export annotations
boolean export = false;
String version = null;
Expand All @@ -94,6 +105,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
String annotationFqdn = annot.getTypeName().getFullyQualifiedName();
if (ANNOTATION_EXPORT.equals(annotationFqdn)) {
export = true;
clazz.addAnnotation(
analyzer.getTypeRef(ANNOTATION_EXPORT.replace('.', '/')));
} else if (ANNOTATION_VERSION.equals(annotationFqdn)) {
if (annot instanceof NormalAnnotation normal) {
for (Object vp : normal.values()) {
Expand All @@ -112,7 +125,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
}
}
if (export) {
PackageRef packageRef = descriptors.getPackageRef(packageFqdn);
packageInfoMap.put(packageRef, clazz);
if (version == null) {
analyzer.getContained().put(packageRef);
} else {
Expand Down Expand Up @@ -142,4 +155,33 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
return false;
}

Clazz getPackageInfo(PackageRef packageRef) {
return packageInfoMap.get(packageRef);
}

private static final class JDTClazz extends Clazz {
private Set<TypeRef> annotations = new HashSet<>();
private TypeRef className;

public JDTClazz(Analyzer analyzer, String path, Resource resource, TypeRef className) {
super(analyzer, path, resource);
this.className = className;
}

@Override
public TypeRef getClassName() {
return className;
}

public void addAnnotation(TypeRef typeRef) {
annotations.add(typeRef);
}

@Override
public Set<TypeRef> annotations() {
return annotations;
}

}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Christoph Läubrich and others.
* Copyright (c) 2023, 2024 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
Expand Down Expand Up @@ -31,6 +31,7 @@
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.tycho.ClasspathEntry;
import org.eclipse.tycho.TychoConstants;
import org.eclipse.tycho.classpath.ClasspathContributor;
import org.eclipse.tycho.helper.PluginConfigurationHelper;
import org.eclipse.tycho.helper.PluginRealmHelper;
Expand Down Expand Up @@ -74,7 +75,10 @@ public BndManifestProcessor(MavenSession mavenSession) {

@Override
public void processManifest(MavenProject mavenProject, Manifest manifest) {

if (new File(mavenProject.getBasedir(), TychoConstants.PDE_BND).exists()) {
// we don't want to process manifests already generated by BND!
return;
}
if (configurationHelper.getConfiguration().getBoolean("deriveHeaderFromSource")
// don't be confused here, we use FALSE as default because it means no such
// configuration option defined in the mojo (probably called from different
Expand Down
Loading