aboutsummaryrefslogtreecommitdiffstats
path: root/bundle-plugin
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@verizonmedia.com>2020-06-24 13:48:47 +0200
committerBjørn Christian Seime <bjorncs@verizonmedia.com>2020-06-24 13:48:47 +0200
commit1f1876624de0ca909a366fa16db97a34a686ae42 (patch)
treece136cb3df899dfafd118335bb51db51fb2c3c34 /bundle-plugin
parent2635e09140e047b9b7b078d844082f3444d76f78 (diff)
Implement goal for generating OSGi manifest for test bundles
Introduce an abstract class containing behaviour that is shared with existing manifest goal.
Diffstat (limited to 'bundle-plugin')
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AbstractGenerateOsgiManifestMojo.java210
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java222
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java80
3 files changed, 305 insertions, 207 deletions
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AbstractGenerateOsgiManifestMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AbstractGenerateOsgiManifestMojo.java
new file mode 100644
index 00000000000..d648d9ca258
--- /dev/null
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AbstractGenerateOsgiManifestMojo.java
@@ -0,0 +1,210 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.plugin.mojo;
+
+import com.yahoo.container.plugin.classanalysis.Analyze;
+import com.yahoo.container.plugin.classanalysis.ClassFileMetaData;
+import com.yahoo.container.plugin.classanalysis.ExportPackageAnnotation;
+import com.yahoo.container.plugin.classanalysis.PackageTally;
+import com.yahoo.container.plugin.osgi.ExportPackageParser;
+import com.yahoo.container.plugin.osgi.ExportPackages;
+import com.yahoo.container.plugin.osgi.ImportPackages;
+import com.yahoo.container.plugin.util.Strings;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.yahoo.container.plugin.util.IO.withFileOutputStream;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author bjorncs
+ */
+abstract class AbstractGenerateOsgiManifestMojo extends AbstractMojo {
+
+ @Parameter(defaultValue = "${project}")
+ MavenProject project;
+
+ /**
+ * If set to true, the artifact's version is used as default package version for ExportPackages.
+ * Packages from included (compile scoped) artifacts will use the version for their own artifact.
+ * If the package is exported with an explicit version in package-info.java, that version will be
+ * used regardless of this parameter.
+ */
+ @Parameter(alias = "UseArtifactVersionForExportPackages", defaultValue = "false")
+ boolean useArtifactVersionForExportPackages;
+
+ @Parameter(alias = "Bundle-Version", defaultValue = "${project.version}")
+ String bundleVersion;
+
+ // TODO: default should include groupId, but that will require a lot of changes both by us and users.
+ @Parameter(alias = "Bundle-SymbolicName", defaultValue = "${project.artifactId}")
+ String bundleSymbolicName;
+
+ @Parameter(alias = "Import-Package")
+ String importPackage;
+
+ Map<String, String> generateManifestContent(
+ Collection<Artifact> jarArtifactsToInclude,
+ Map<String, ImportPackages.Import> calculatedImports,
+ PackageTally pluginPackageTally) {
+
+ Map<String, Optional<String>> manualImports = getManualImports();
+ for (String packageName : manualImports.keySet()) {
+ calculatedImports.remove(packageName);
+ }
+ Collection<ImportPackages.Import> imports = calculatedImports.values();
+
+ Map<String, String> ret = new HashMap<>();
+ String importPackage = Stream.concat(manualImports.entrySet().stream().map(e -> asOsgiImport(e.getKey(), e.getValue())),
+ imports.stream().map(ImportPackages.Import::asOsgiImport)).sorted()
+ .collect(Collectors.joining(","));
+
+ String exportPackage = osgiExportPackages(pluginPackageTally.exportedPackages()).stream().sorted()
+ .collect(Collectors.joining(","));
+
+ ret.put("Created-By", "vespa container maven plugin");
+ ret.put("Bundle-ManifestVersion", "2");
+ ret.put("Bundle-Name", project.getName());
+ ret.put("Bundle-SymbolicName", bundleSymbolicName);
+ ret.put("Bundle-Version", asBundleVersion(bundleVersion));
+ ret.put("Bundle-Vendor", "Yahoo!");
+ addIfNotEmpty(ret, "Bundle-ClassPath", bundleClassPath(jarArtifactsToInclude));
+ addIfNotEmpty(ret, "Import-Package", importPackage);
+ addIfNotEmpty(ret, "Export-Package", exportPackage);
+
+ return ret;
+ }
+
+ PackageTally definedPackages(Collection<Artifact> jarArtifacts) {
+ List<PackageTally> tallies = new ArrayList<>();
+ for (var artifact : jarArtifacts) {
+ try {
+ tallies.add(definedPackages(new JarFile(artifact.getFile()), artifactVersionOrNull(artifact.getVersion())));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return PackageTally.combine(tallies);
+ }
+
+ ArtifactVersion artifactVersionOrNull(String version) {
+ return useArtifactVersionForExportPackages ? new DefaultArtifactVersion(version) : null;
+ }
+
+ static void createManifestFile(Path outputDirectory, Map<String, String> manifestContent) {
+ Manifest manifest = new Manifest();
+ Attributes mainAttributes = manifest.getMainAttributes();
+
+ mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+ manifestContent.forEach(mainAttributes::putValue);
+
+ withFileOutputStream(outputDirectory.resolve(JarFile.MANIFEST_NAME).toFile(), out -> {
+ manifest.write(out);
+ return null;
+ });
+ }
+
+ static void addIfNotEmpty(Map<String, String> map, String key, String value) {
+ if (value != null && ! value.isEmpty()) {
+ map.put(key, value);
+ }
+ }
+
+ private Collection<String> osgiExportPackages(Map<String, ExportPackageAnnotation> exportedPackages) {
+ return exportedPackages.entrySet().stream().map(entry -> entry.getKey() + ";version=" + entry.getValue().osgiVersion())
+ .collect(Collectors.toList());
+ }
+
+ private static String asOsgiImport(String packageName, Optional<String> version) {
+ return version
+ .map(s -> packageName + ";version=" + ("\"" + s + "\""))
+ .orElse(packageName);
+ }
+
+ private static String bundleClassPath(Collection<Artifact> artifactsToInclude) {
+ return Stream.concat(Stream.of("."), artifactsToInclude.stream()
+ .map(artifact -> "dependencies/" + artifact.getFile().getName()))
+ .collect(Collectors.joining(","));
+ }
+
+ private Map<String, Optional<String>> getManualImports() {
+ try {
+ if (importPackage == null || importPackage.isBlank()) return Map.of();
+ Map<String, Optional<String>> ret = new HashMap<>();
+ List<ExportPackages.Export> imports = ExportPackageParser.parseExports(importPackage);
+ for (ExportPackages.Export imp : imports) {
+ Optional<String> version = getVersionThrowOthers(imp.getParameters());
+ imp.getPackageNames().forEach(pn -> ret.put(pn, version));
+ }
+ return ret;
+ } catch (Exception e) {
+ throw new RuntimeException("Error in Import-Package:" + importPackage, e);
+ }
+ }
+
+ private static String asBundleVersion(String projectVersion) {
+ if (projectVersion == null) {
+ throw new IllegalArgumentException("Missing project version.");
+ }
+
+ String[] parts = projectVersion.split("-", 2);
+ List<String> numericPart = Stream.of(parts[0].split("\\.")).map(s -> Strings.replaceEmptyString(s, "0")).limit(3)
+ .collect(toList());
+ while (numericPart.size() < 3) {
+ numericPart.add("0");
+ }
+
+ return String.join(".", numericPart);
+ }
+
+ private static Optional<String> getVersionThrowOthers(List<ExportPackages.Parameter> parameters) {
+ if (parameters.size() == 1 && "version".equals(parameters.get(0).getName())) {
+ return Optional.of(parameters.get(0).getValue());
+ } else if (parameters.size() == 0) {
+ return Optional.empty();
+ } else {
+ List<String> paramNames = parameters.stream().map(ExportPackages.Parameter::getName).collect(Collectors.toList());
+ throw new RuntimeException("A single, optional version parameter expected, but got " + paramNames);
+ }
+ }
+
+ private static PackageTally definedPackages(JarFile jarFile, ArtifactVersion version) throws MojoExecutionException {
+ List<ClassFileMetaData> analyzedClasses = new ArrayList<>();
+ for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
+ JarEntry entry = entries.nextElement();
+ if (! entry.isDirectory() && entry.getName().endsWith(".class")) {
+ analyzedClasses.add(analyzeClass(jarFile, entry, version));
+ }
+ }
+ return PackageTally.fromAnalyzedClassFiles(analyzedClasses);
+ }
+
+ private static ClassFileMetaData analyzeClass(JarFile jarFile, JarEntry entry, ArtifactVersion version) throws MojoExecutionException {
+ try {
+ return Analyze.analyzeClass(jarFile.getInputStream(entry), version);
+ } catch (Exception e) {
+ throw new MojoExecutionException(
+ String.format("While analyzing the class '%s' in jar file '%s'", entry.getName(), jarFile.getName()), e);
+ }
+ }
+
+}
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
index 41420b38360..3020184fd35 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateOsgiManifestMojo.java
@@ -4,36 +4,23 @@ package com.yahoo.container.plugin.mojo;
import com.google.common.collect.Sets;
import com.yahoo.container.plugin.classanalysis.Analyze;
import com.yahoo.container.plugin.classanalysis.ClassFileMetaData;
-import com.yahoo.container.plugin.classanalysis.ExportPackageAnnotation;
import com.yahoo.container.plugin.classanalysis.PackageTally;
-import com.yahoo.container.plugin.osgi.ExportPackageParser;
import com.yahoo.container.plugin.osgi.ExportPackages;
import com.yahoo.container.plugin.osgi.ExportPackages.Export;
import com.yahoo.container.plugin.osgi.ImportPackages.Import;
-import com.yahoo.container.plugin.util.Strings;
import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.versioning.ArtifactVersion;
-import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
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 java.io.File;
-import java.util.ArrayList;
+import java.nio.file.Paths;
import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -41,7 +28,6 @@ import static com.yahoo.container.plugin.bundle.AnalyzeBundle.exportedPackagesAg
import static com.yahoo.container.plugin.osgi.ExportPackages.exportsByPackageName;
import static com.yahoo.container.plugin.osgi.ImportPackages.calculateImports;
import static com.yahoo.container.plugin.util.Files.allDescendantFiles;
-import static com.yahoo.container.plugin.util.IO.withFileOutputStream;
/**
@@ -49,19 +35,7 @@ import static com.yahoo.container.plugin.util.IO.withFileOutputStream;
* @author ollivir
*/
@Mojo(name = "generate-osgi-manifest", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
-public class GenerateOsgiManifestMojo extends AbstractMojo {
-
- @Parameter(defaultValue = "${project}")
- private MavenProject project = null;
-
- /**
- * If set to true, the artifact's version is used as default package version for ExportPackages.
- * Packages from included (compile scoped) artifacts will use the version for their own artifact.
- * If the package is exported with an explicit version in package-info.java, that version will be
- * used regardless of this parameter.
- */
- @Parameter(alias = "UseArtifactVersionForExportPackages", defaultValue = "false")
- private boolean useArtifactVersionForExportPackages;
+public class GenerateOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
@Parameter
private String discApplicationClass = null;
@@ -69,22 +43,12 @@ public class GenerateOsgiManifestMojo extends AbstractMojo {
@Parameter
private String discPreInstallBundle = null;
- @Parameter(alias = "Bundle-Version", defaultValue = "${project.version}")
- private String bundleVersion = null;
-
- // TODO: default should include groupId, but that will require a lot of changes both by us and users.
- @Parameter(alias = "Bundle-SymbolicName", defaultValue = "${project.artifactId}")
- private String bundleSymbolicName = null;
-
@Parameter(alias = "Bundle-Activator")
private String bundleActivator = null;
@Parameter(alias = "X-JDisc-Privileged-Activator")
private String jdiscPrivilegedActivator = null;
- @Parameter(alias = "Import-Package")
- private String importPackage = null;
-
@Parameter(alias = "WebInfUrl")
private String webInfUrl = null;
@@ -127,19 +91,25 @@ public class GenerateOsgiManifestMojo extends AbstractMojo {
includedPackages.definedPackages(),
exportsByPackageName(exportedPackagesFromProvidedJars));
- Map<String, Optional<String>> manualImports = emptyToNone(importPackage).map(GenerateOsgiManifestMojo::getManualImports)
- .orElseGet(HashMap::new);
- for (String packageName : manualImports.keySet()) {
- calculatedImports.remove(packageName);
- }
- createManifestFile(new File(project.getBuild().getOutputDirectory()), manifestContent(project,
- artifactSet.getJarArtifactsToInclude(), manualImports, calculatedImports.values(), includedPackages));
+
+ Map<String, String> manifestContent = generateManifestContent(artifactSet.getJarArtifactsToInclude(), calculatedImports, includedPackages);
+ addAdditionalManifestProperties(manifestContent);
+ createManifestFile(Paths.get(project.getBuild().getOutputDirectory()), manifestContent);
} catch (Exception e) {
throw new MojoExecutionException("Failed generating osgi manifest", e);
}
}
+ private void addAdditionalManifestProperties(Map<String, String> manifestContent) {
+ addIfNotEmpty(manifestContent, "Bundle-Activator", bundleActivator);
+ addIfNotEmpty(manifestContent, "X-JDisc-Privileged-Activator", jdiscPrivilegedActivator);
+ addIfNotEmpty(manifestContent, "Main-Class", mainClass);
+ addIfNotEmpty(manifestContent, "X-JDisc-Application", discApplicationClass);
+ addIfNotEmpty(manifestContent, "X-JDisc-Preinstall-Bundle", trimWhitespace(Optional.ofNullable(discPreInstallBundle)));
+ addIfNotEmpty(manifestContent, "WebInfUrl", webInfUrl);
+ }
+
private void logDebugPackageSets(List<Export> exportedPackagesFromProvidedJars, PackageTally includedPackages) {
if (getLog().isDebugEnabled()) {
getLog().debug("Referenced packages = " + includedPackages.referencedPackages());
@@ -197,101 +167,10 @@ public class GenerateOsgiManifestMojo extends AbstractMojo {
}
}
- private Collection<String> osgiExportPackages(Map<String, ExportPackageAnnotation> exportedPackages) {
- return exportedPackages.entrySet().stream().map(entry -> entry.getKey() + ";version=" + entry.getValue().osgiVersion())
- .collect(Collectors.toList());
- }
-
private static String trimWhitespace(Optional<String> lines) {
return Stream.of(lines.orElse("").split(",")).map(String::trim).collect(Collectors.joining(","));
}
- private Map<String, String> manifestContent(MavenProject project, Collection<Artifact> jarArtifactsToInclude,
- Map<String, Optional<String>> manualImports, Collection<Import> imports, PackageTally pluginPackageTally) {
- Map<String, String> ret = new HashMap<>();
- String importPackage = Stream.concat(manualImports.entrySet().stream().map(e -> asOsgiImport(e.getKey(), e.getValue())),
- imports.stream().map(Import::asOsgiImport)).sorted()
- .collect(Collectors.joining(","));
-
- String exportPackage = osgiExportPackages(pluginPackageTally.exportedPackages()).stream().sorted()
- .collect(Collectors.joining(","));
-
- ret.put("Created-By", "vespa container maven plugin");
- ret.put("Bundle-ManifestVersion", "2");
- addIfNotEmpty(ret, "Bundle-Name", project.getName());
- addIfNotEmpty(ret, "Bundle-SymbolicName", bundleSymbolicName);
- addIfNotEmpty(ret, "Bundle-Version", asBundleVersion(bundleVersion));
- ret.put("Bundle-Vendor", "Yahoo!");
- addIfNotEmpty(ret, "Bundle-ClassPath", bundleClassPath(jarArtifactsToInclude));
- addIfNotEmpty(ret, "Bundle-Activator", bundleActivator);
- addIfNotEmpty(ret, "X-JDisc-Privileged-Activator", jdiscPrivilegedActivator);
- addIfNotEmpty(ret, "Main-Class", mainClass);
- addIfNotEmpty(ret, "X-JDisc-Application", discApplicationClass);
- addIfNotEmpty(ret, "X-JDisc-Preinstall-Bundle", trimWhitespace(Optional.ofNullable(discPreInstallBundle)));
- addIfNotEmpty(ret, "WebInfUrl", webInfUrl);
- addIfNotEmpty(ret, "Import-Package", importPackage);
- addIfNotEmpty(ret, "Export-Package", exportPackage);
-
- return ret;
- }
-
- private static void addIfNotEmpty(Map<String, String> map, String key, String value) {
- if (value != null && ! value.isEmpty()) {
- map.put(key, value);
- }
- }
-
- private static String asOsgiImport(String packageName, Optional<String> version) {
- return version.map(s -> packageName + ";version=" + quote(s)).orElse(packageName);
- }
-
- private static String quote(String s) {
- return "\"" + s + "\"";
- }
-
- private static void createManifestFile(File outputDirectory, Map<String, String> manifestContent) {
- Manifest manifest = toManifest(manifestContent);
-
- withFileOutputStream(new File(outputDirectory, JarFile.MANIFEST_NAME), outputStream -> {
- manifest.write(outputStream);
- return null;
- });
- }
-
- private static Manifest toManifest(Map<String, String> manifestContent) {
- Manifest manifest = new Manifest();
- Attributes mainAttributes = manifest.getMainAttributes();
-
- mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
- manifestContent.forEach(mainAttributes::putValue);
-
- return manifest;
- }
-
- private static String bundleClassPath(Collection<Artifact> artifactsToInclude) {
- return Stream.concat(Stream.of("."), artifactsToInclude.stream().map(GenerateOsgiManifestMojo::dependencyPath))
- .collect(Collectors.joining(","));
- }
-
- private static String dependencyPath(Artifact artifact) {
- return "dependencies/" + artifact.getFile().getName();
- }
-
- private static String asBundleVersion(String projectVersion) {
- if (projectVersion == null) {
- throw new IllegalArgumentException("Missing project version.");
- }
-
- String[] parts = projectVersion.split("-", 2);
- List<String> numericPart = Stream.of(parts[0].split("\\.")).map(s -> Strings.replaceEmptyString(s, "0")).limit(3)
- .collect(Collectors.toList());
- while (numericPart.size() < 3) {
- numericPart.add("0");
- }
-
- return String.join(".", numericPart);
- }
-
private void warnOnUnsupportedArtifacts(Collection<Artifact> nonJarArtifacts) {
List<Artifact> unsupportedArtifacts = nonJarArtifacts.stream().filter(a -> ! a.getType().equals("pom"))
.collect(Collectors.toList());
@@ -301,10 +180,6 @@ public class GenerateOsgiManifestMojo extends AbstractMojo {
artifact.getId(), artifact.getType())));
}
- private ArtifactVersion artifactVersionOrNull(String version) {
- return useArtifactVersionForExportPackages ? new DefaultArtifactVersion(version) : null;
- }
-
private PackageTally getProjectClassesTally() {
File outputDirectory = new File(project.getBuild().getOutputDirectory());
@@ -315,71 +190,4 @@ public class GenerateOsgiManifestMojo extends AbstractMojo {
return PackageTally.fromAnalyzedClassFiles(analyzedClasses);
}
-
- private PackageTally definedPackages(Collection<Artifact> jarArtifacts) {
- List<PackageTally> tallies = new ArrayList<>();
- for (var artifact : jarArtifacts) {
- try {
- tallies.add(definedPackages(new JarFile(artifact.getFile()), artifactVersionOrNull(artifact.getVersion())));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- return PackageTally.combine(tallies);
- }
-
- private static PackageTally definedPackages(JarFile jarFile, ArtifactVersion version) throws MojoExecutionException {
- List<ClassFileMetaData> analyzedClasses = new ArrayList<>();
- for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
- JarEntry entry = entries.nextElement();
- if (! entry.isDirectory() && entry.getName().endsWith(".class")) {
- analyzedClasses.add(analyzeClass(jarFile, entry, version));
- }
- }
- return PackageTally.fromAnalyzedClassFiles(analyzedClasses);
- }
-
- private static ClassFileMetaData analyzeClass(JarFile jarFile, JarEntry entry, ArtifactVersion version) throws MojoExecutionException {
- try {
- return Analyze.analyzeClass(jarFile.getInputStream(entry), version);
- } catch (Exception e) {
- throw new MojoExecutionException(
- String.format("While analyzing the class '%s' in jar file '%s'", entry.getName(), jarFile.getName()), e);
- }
- }
-
- private static Map<String, Optional<String>> getManualImports(String importPackage) {
- try {
- Map<String, Optional<String>> ret = new HashMap<>();
- List<Export> imports = parseImportPackages(importPackage);
- for (Export imp : imports) {
- Optional<String> version = getVersionThrowOthers(imp.getParameters());
- imp.getPackageNames().forEach(pn -> ret.put(pn, version));
- }
-
- return ret;
- } catch (Exception e) {
- throw new RuntimeException("Error in Import-Package:" + importPackage, e);
- }
- }
-
- private static Optional<String> getVersionThrowOthers(List<ExportPackages.Parameter> parameters) {
- if (parameters.size() == 1 && "version".equals(parameters.get(0).getName())) {
- return Optional.of(parameters.get(0).getValue());
- } else if (parameters.size() == 0) {
- return Optional.empty();
- } else {
- List<String> paramNames = parameters.stream().map(ExportPackages.Parameter::getName).collect(Collectors.toList());
- throw new RuntimeException("A single, optional version parameter expected, but got " + paramNames);
- }
- }
-
- private static List<Export> parseImportPackages(String importPackages) {
- return ExportPackageParser.parseExports(importPackages);
- }
-
- private static Optional<String> emptyToNone(String str) {
- return Optional.ofNullable(str).map(String::trim).filter(s -> ! s.isEmpty());
- }
-
}
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java
new file mode 100644
index 00000000000..811aff87b7e
--- /dev/null
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java
@@ -0,0 +1,80 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.plugin.mojo;
+
+import com.yahoo.container.plugin.classanalysis.Analyze;
+import com.yahoo.container.plugin.classanalysis.ClassFileMetaData;
+import com.yahoo.container.plugin.classanalysis.PackageTally;
+import com.yahoo.container.plugin.osgi.ExportPackages.Export;
+import com.yahoo.container.plugin.osgi.ImportPackages;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static com.yahoo.container.plugin.bundle.AnalyzeBundle.exportedPackagesAggregated;
+import static com.yahoo.container.plugin.mojo.TestBundleUtils.outputDirectory;
+import static com.yahoo.container.plugin.osgi.ExportPackages.exportsByPackageName;
+import static com.yahoo.container.plugin.osgi.ImportPackages.calculateImports;
+import static com.yahoo.container.plugin.util.Files.allDescendantFiles;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * @author bjorncs
+ */
+@Mojo(name = "generate-test-bundle-osgi-manifest", requiresDependencyResolution = ResolutionScope.TEST, threadSafe = true)
+public class GenerateTestBundleOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
+
+ @Parameter
+ private String testProvidedArtifacts;
+
+ public void execute() throws MojoExecutionException {
+ try {
+ Artifacts.ArtifactSet artifactSet = Artifacts.getArtifacts(project, true, testProvidedArtifacts);
+
+ List<File> providedJars = artifactSet.getJarArtifactsProvided().stream()
+ .map(Artifact::getFile)
+ .collect(toList());
+
+ List<Export> exportedPackagesFromProvidedJars = exportedPackagesAggregated(providedJars);
+
+ PackageTally projectPackages = getProjectMainAndTestClassesTally();
+
+ PackageTally jarArtifactsToInclude = definedPackages(artifactSet.getJarArtifactsToInclude());
+
+ PackageTally includedPackages = projectPackages.combine(jarArtifactsToInclude);
+
+ Map<String, ImportPackages.Import> calculatedImports = calculateImports(includedPackages.referencedPackages(),
+ includedPackages.definedPackages(),
+ exportsByPackageName(exportedPackagesFromProvidedJars));
+
+ Map<String, String> manifestContent = generateManifestContent(artifactSet.getJarArtifactsToInclude(), calculatedImports, includedPackages);
+ addAdditionalManifestProperties(manifestContent);
+ createManifestFile(outputDirectory(project), manifestContent);
+
+ } catch (Exception e) {
+ throw new MojoExecutionException("Failed generating osgi manifest", e);
+ }
+ }
+
+ private void addAdditionalManifestProperties(Map<String, String> manifestContent) {
+ manifestContent.put("X-JDisc-Test-Bundle-Version", "1.0");
+ }
+
+ private PackageTally getProjectMainAndTestClassesTally() {
+ List<ClassFileMetaData> analyzedClasses =
+ Stream.concat(
+ allDescendantFiles(new File(project.getBuild().getOutputDirectory())),
+ allDescendantFiles(new File(project.getBuild().getTestOutputDirectory())))
+ .filter(file -> file.getName().endsWith(".class"))
+ .map(classFile -> Analyze.analyzeClass(classFile, null))
+ .collect(toList());
+ return PackageTally.fromAnalyzedClassFiles(analyzedClasses);
+ }
+
+}