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

Extract some generic bndlib code into a common module #4714

Merged
merged 1 commit into from
Feb 12, 2025
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
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@
<module>tycho-eclipse-plugin</module>
<module>tycho-wrap-plugin</module>
<module>tycho-cleancode-plugin</module>
<module>tycho-bndlib</module>
</modules>
<profiles>
<profile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.eclipse.tycho.bndlib.PathResource;

import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.ManifestResource;
Expand All @@ -54,7 +55,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
String path = StreamSupport.stream(relativePath.spliterator(), false).map(Path::toString)
.collect(Collectors.joining("/"));
log.debug("Adding " + path + " to project jar...");
putResource(path, new MavenProjectResource(file));
putResource(path, new PathResource(file));
} else {
log.debug("Ignore " + relativePath + " because it is filtered");
}
Expand All @@ -81,7 +82,7 @@ public void setManifest(Manifest manifest) {

@Override
public boolean putResource(String path, Resource resource, boolean overwrite) {
if (resource instanceof MavenProjectResource) {
if (resource instanceof PathResource) {
return super.putResource(path, resource, overwrite);
}
Path file = outputFolder.resolve(path);
Expand All @@ -98,6 +99,6 @@ public boolean putResource(String path, Resource resource, boolean overwrite) {
} catch (Exception e) {
throw new RuntimeException(e);
}
return super.putResource(path, new MavenProjectResource(file), overwrite);
return super.putResource(path, new PathResource(file), overwrite);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.tycho.TychoConstants;
import org.eclipse.tycho.bnd.BndRunFile;
import org.eclipse.tycho.bnd.mojos.BndRunMojo;
import org.eclipse.tycho.bndlib.BndRunFile;
import org.eclipse.tycho.core.bnd.BndPluginManager;

import aQute.bnd.build.Project;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProjectHelper;
import org.eclipse.tycho.bnd.BndRunFile;
import org.eclipse.tycho.bndlib.BndRunFile;
import org.osgi.service.resolver.ResolutionException;

import aQute.bnd.build.Container;
Expand Down
8 changes: 8 additions & 0 deletions tycho-bndlib/.settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -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=ignore
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=17
23 changes: 23 additions & 0 deletions tycho-bndlib/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho</artifactId>
<version>5.0.0-SNAPSHOT</version>
</parent>
<artifactId>tycho-bndlib</artifactId>
<name>Tycho BNDlib Extensions</name>
<description>Provides extensions to BNDlib used by Tycho</description>
<dependencies>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.bnd;
package org.eclipse.tycho.bndlib;

import java.nio.file.Path;

Expand Down
50 changes: 50 additions & 0 deletions tycho-bndlib/src/main/java/org/eclipse/tycho/bndlib/JDTClazz.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*******************************************************************************
* 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 java.util.HashSet;
import java.util.Set;

import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Clazz;
import aQute.bnd.osgi.Descriptors.TypeRef;
import aQute.bnd.osgi.Resource;

/**
* An extension to the (bndlib) {@link Clazz} that is capable to return
* discovered information form the java sources.
*/
final class JDTClazz extends Clazz {
private Set<TypeRef> annotations = new HashSet<>();
private TypeRef className;

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

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

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

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.bnd;
package org.eclipse.tycho.bndlib;

import java.io.IOException;
import java.io.InputStream;
Expand All @@ -21,12 +21,12 @@

import aQute.bnd.osgi.Resource;

class MavenProjectResource implements Resource {
public class PathResource implements Resource {

private String extra;
private Path path;

public MavenProjectResource(Path path) {
public PathResource(Path path) {
this.path = path;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*******************************************************************************
* 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
* 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 java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
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;
import org.eclipse.jdt.core.dom.ASTNode;
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.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;

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

/**
* Enhances the analyzed classes by information obtained from the source code
*/
public 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_CLASS = PACKAGE_INFO + ".class";
private List<Path> sourcePaths;
private Map<PackageRef, Clazz> packageInfoMap = new HashMap<>();
private boolean alreadyRun;

public SourceCodeAnalyzerPlugin() {
this(null);
}

public SourceCodeAnalyzerPlugin(List<Path> sourcePaths) {
this.sourcePaths = sourcePaths;
}

@Override
public boolean analyzeJar(Analyzer analyzer) throws Exception {
if (alreadyRun) {
return false;
}
alreadyRun = true;
ASTParser parser = ASTParser.newParser(AST.getJLSLatest());
Set<String> seenPackages = new HashSet<>();
Set<Path> analyzedPath = new HashSet<>();
for (Path sourcePath : getSourcePath(analyzer)) {
Files.walkFileTree(sourcePath, new FileVisitor<Path>() {

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
String fileName = file.getFileName().toString().toLowerCase();
if (fileName.endsWith(".java")) {
boolean packageInfo = fileName.equals(PACKAGE_INFO_JAVA);
if (packageInfo || analyzedPath.add(file.getParent())) {
String source = Files.readString(file);
parser.setSource(source.toCharArray());
ASTNode ast = parser.createAST(null);
if (ast instanceof CompilationUnit cu) {
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
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;
for (Object raw : packageDecl.annotations()) {
if (raw instanceof Annotation annot) {
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()) {
MemberValuePair pair = (MemberValuePair) vp;
if ("value"
.equals(pair.getName().getFullyQualifiedName())) {
StringLiteral value = (StringLiteral) pair.getValue();
version = value.getLiteralValue();
}
}
} else if (annot instanceof SingleMemberAnnotation single) {
StringLiteral value = (StringLiteral) single.getValue();
version = value.getLiteralValue();
}
}
}
}
if (export) {
packageInfoMap.put(packageRef, clazz);
if (version == null) {
analyzer.getContained().put(packageRef);
} else {
analyzer.getContained().put(packageRef,
Attrs.create("version", version));
}
}
}
}
}
}
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
return FileVisitResult.CONTINUE;
}
});
}
return false;
}

private List<Path> getSourcePath(Analyzer analyzer) {
if (sourcePaths != null) {
return sourcePaths;
}
if (analyzer instanceof Builder builder) {
return builder.getSourcePath().stream().map(File::toPath).toList();
}
return List.of();
}

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

}
5 changes: 5 additions & 0 deletions tycho-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-bndlib</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.tycho.TychoConstants;
import org.eclipse.tycho.bndlib.SourceCodeAnalyzerPlugin;
import org.eclipse.tycho.core.TychoProjectManager;
import org.eclipse.tycho.core.maven.MavenDependenciesResolver;
import org.eclipse.tycho.p2maven.InstallableUnitGenerator;
Expand Down
Loading
Loading