import static java.nio.file.StandardOpenOption.APPEND;
import static java.nio.file.StandardOpenOption.CREATE;
import static java.util.jar.Attributes.Name.MANIFEST_VERSION;
+import static org.argeo.build.Repackage.ManifestHeader.ARGEO_DO_NOT_MODIFY;
import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_M2;
import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_M2_MERGE;
import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_M2_REPO;
import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_NO_METADATA_GENERATION;
+import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_SOURCES_URI;
import static org.argeo.build.Repackage.ManifestHeader.ARGEO_ORIGIN_URI;
import static org.argeo.build.Repackage.ManifestHeader.AUTOMATIC_MODULE_NAME;
import static org.argeo.build.Repackage.ManifestHeader.BUNDLE_LICENSE;
* etc.).
*/
ARGEO_ORIGIN_URI("Argeo-Origin-URI"), //
+ /**
+ * Origin (non-Maven) URI of the source of the component. It may be anything
+ * (jar, archive, code repository, etc.).
+ */
+ ARGEO_ORIGIN_SOURCES_URI("Argeo-Origin-Sources-URI"), //
;
final String value;
final Map<String, List<String>> mirrors = new HashMap<String, List<String>>();
/** Whether sources should be packaged separately */
- final boolean sourceBundles;
+ final boolean separateSources;
/** Constructor initialises the various variables */
public Repackage(Path a2Base, Path descriptorsBase) {
- sourceBundles = Boolean.parseBoolean(System.getenv(ENV_SOURCE_BUNDLES));
- if (sourceBundles)
+ separateSources = Boolean.parseBoolean(System.getenv(ENV_SOURCE_BUNDLES));
+ if (separateSources)
logger.log(INFO, "Sources will be packaged separately");
Objects.requireNonNull(a2Base);
// TODO define and use a build base
this.a2Base = a2Base;
- this.a2SrcBase = a2Base.getParent().resolve(a2Base.getFileName() + ".src");
+ this.a2SrcBase = separateSources ? a2Base.getParent().resolve(a2Base.getFileName() + ".src") : a2Base;
this.a2LibBase = a2Base.resolve("lib");
this.descriptorsBase = descriptorsBase;
if (!Files.exists(this.descriptorsBase))
try (InputStream in = Files.newInputStream(bndFile)) {
fileProps.load(in);
}
- String repoStr = fileProps.containsKey(ARGEO_ORIGIN_M2_REPO.toString())
- ? fileProps.getProperty(ARGEO_ORIGIN_M2_REPO.toString())
- : null;
-
// use file name as symbolic name
if (!fileProps.containsKey(BUNDLE_SYMBOLICNAME.toString())) {
String symbolicName = bndFile.getFileName().toString();
if (m2Coordinates == null)
throw new IllegalArgumentException("No M2 coordinates available for " + bndFile);
M2Artifact artifact = new M2Artifact(m2Coordinates);
- URL url = M2ConventionsUtils.mavenRepoUrl(repoStr, artifact);
- Path downloaded = downloadMaven(url, artifact);
-
- // some proprietary artifacts do not allow any modification
- // when releasing (with separate sources) we just copy it
- boolean doNotModify = Boolean.parseBoolean(
- fileProps.getOrDefault(ManifestHeader.ARGEO_DO_NOT_MODIFY.toString(), "false").toString());
- if (doNotModify && sourceBundles) {
- Path unmodifiedTarget = targetCategoryBase.resolve(
- fileProps.getProperty(BUNDLE_SYMBOLICNAME.toString()) + "." + artifact.getBranch() + ".jar");
- Files.copy(downloaded, unmodifiedTarget, StandardCopyOption.REPLACE_EXISTING);
- Path bundleDir = targetCategoryBase
- .resolve(fileProps.getProperty(BUNDLE_SYMBOLICNAME.toString()) + "." + artifact.getBranch());
- downloadAndProcessM2Sources(repoStr, artifact, bundleDir, false);
- Manifest manifest;
- try (JarInputStream jarIn = new JarInputStream(Files.newInputStream(unmodifiedTarget))) {
- manifest = jarIn.getManifest();
- }
- createSourceJar(bundleDir, manifest);
+
+ Path downloaded = downloadMaven(fileProps, artifact);
+
+ boolean doNotModify = Boolean
+ .parseBoolean(fileProps.getOrDefault(ARGEO_DO_NOT_MODIFY.toString(), "false").toString());
+ if (doNotModify) {
+ processNotModified(targetCategoryBase, downloaded, fileProps, artifact);
return;
}
// regular processing
A2Origin origin = new A2Origin();
Path bundleDir = processBndJar(downloaded, targetCategoryBase, fileProps, artifact, origin);
- downloadAndProcessM2Sources(repoStr, artifact, bundleDir, false);
+ downloadAndProcessM2Sources(fileProps, artifact, bundleDir, false);
createJar(bundleDir, origin);
} catch (Exception e) {
throw new RuntimeException("Cannot process " + bndFile, e);
}
// prepare manifest entries
- Properties mergeProps = new Properties();
- mergeProps.putAll(commonProps);
+ Properties mergedProps = new Properties();
+ mergedProps.putAll(commonProps);
fileEntries: for (Object key : fileProps.keySet()) {
if (ARGEO_ORIGIN_M2.toString().equals(key))
continue fileEntries;
String value = fileProps.getProperty(key.toString());
- Object previousValue = mergeProps.put(key.toString(), value);
+ Object previousValue = mergedProps.put(key.toString(), value);
if (previousValue != null) {
logger.log(WARNING,
commonBnd + ": " + key + " was " + previousValue + ", overridden with " + value);
}
}
- mergeProps.put(ARGEO_ORIGIN_M2.toString(), artifact.toM2Coordinates());
- if (!mergeProps.containsKey(BUNDLE_SYMBOLICNAME.toString())) {
+ mergedProps.put(ARGEO_ORIGIN_M2.toString(), artifact.toM2Coordinates());
+ if (!mergedProps.containsKey(BUNDLE_SYMBOLICNAME.toString())) {
// use file name as symbolic name
String symbolicName = p.getFileName().toString();
symbolicName = symbolicName.substring(0, symbolicName.length() - ".bnd".length());
- mergeProps.put(BUNDLE_SYMBOLICNAME.toString(), symbolicName);
+ mergedProps.put(BUNDLE_SYMBOLICNAME.toString(), symbolicName);
}
- String repoStr = mergeProps.containsKey(ARGEO_ORIGIN_M2_REPO.toString())
- ? mergeProps.getProperty(ARGEO_ORIGIN_M2_REPO.toString())
- : null;
-
// download
- URL url = M2ConventionsUtils.mavenRepoUrl(repoStr, artifact);
- Path downloaded = downloadMaven(url, artifact);
+ Path downloaded = downloadMaven(mergedProps, artifact);
- A2Origin origin = new A2Origin();
- Path targetBundleDir = processBndJar(downloaded, targetCategoryBase, mergeProps, artifact, origin);
- downloadAndProcessM2Sources(repoStr, artifact, targetBundleDir, false);
- createJar(targetBundleDir, origin);
+ boolean doNotModify = Boolean
+ .parseBoolean(mergedProps.getOrDefault(ARGEO_DO_NOT_MODIFY.toString(), "false").toString());
+ if (doNotModify) {
+ processNotModified(targetCategoryBase, downloaded, mergedProps, artifact);
+ } else {
+ A2Origin origin = new A2Origin();
+ Path targetBundleDir = processBndJar(downloaded, targetCategoryBase, mergedProps, artifact, origin);
+ downloadAndProcessM2Sources(mergedProps, artifact, targetBundleDir, false);
+ createJar(targetBundleDir, origin);
+ }
}
} catch (IOException e) {
throw new RuntimeException("Cannot process " + duDir, e);
if (artifactsStr == null)
throw new IllegalArgumentException(mergeBnd + ": " + ARGEO_ORIGIN_M2_MERGE + " must be set");
- String repoStr = mergeProps.containsKey(ARGEO_ORIGIN_M2_REPO.toString())
- ? mergeProps.getProperty(ARGEO_ORIGIN_M2_REPO.toString())
- : null;
-
String bundleSymbolicName = mergeProps.getProperty(BUNDLE_SYMBOLICNAME.toString());
if (bundleSymbolicName == null)
throw new IllegalArgumentException("Bundle-SymbolicName must be set in " + mergeBnd);
if (artifact.getVersion() == null)
artifact.setVersion(m2Version);
originDesc.add(artifact.toString());
- URL url = M2ConventionsUtils.mavenRepoUrl(repoStr, artifact);
- Path downloaded = downloadMaven(url, artifact);
+ Path downloaded = downloadMaven(mergeProps, artifact);
JarEntry entry;
try (JarInputStream jarIn = new JarInputStream(Files.newInputStream(downloaded), false)) {
entries: while ((entry = jarIn.getNextJarEntry()) != null) {
origin.added.add("binary content of " + artifact);
// process sources
- downloadAndProcessM2Sources(repoStr, artifact, bundleDir, true);
+ downloadAndProcessM2Sources(mergeProps, artifact, bundleDir, true);
}
// additional service files
}
+ /** Process an artifact that should not be modified. */
+ void processNotModified(Path targetCategoryBase, Path downloaded, Properties fileProps, M2Artifact artifact)
+ throws IOException {
+ // Some proprietary or signed artifacts do not allow any modification
+ // When releasing (with separate sources), we just copy it
+ Path unmodifiedTarget = targetCategoryBase
+ .resolve(fileProps.getProperty(BUNDLE_SYMBOLICNAME.toString()) + "." + artifact.getBranch() + ".jar");
+ Files.createDirectories(unmodifiedTarget.getParent());
+ Files.copy(downloaded, unmodifiedTarget, StandardCopyOption.REPLACE_EXISTING);
+ Path bundleDir = targetCategoryBase
+ .resolve(fileProps.getProperty(BUNDLE_SYMBOLICNAME.toString()) + "." + artifact.getBranch());
+ downloadAndProcessM2Sources(fileProps, artifact, bundleDir, false);
+ Manifest manifest;
+ try (JarInputStream jarIn = new JarInputStream(Files.newInputStream(unmodifiedTarget))) {
+ manifest = jarIn.getManifest();
+ }
+ createSourceJar(bundleDir, manifest, true);
+ }
+
/** Download and integrates sources for a single Maven artifact. */
- void downloadAndProcessM2Sources(String repoStr, M2Artifact artifact, Path targetBundleDir, boolean merging)
+ void downloadAndProcessM2Sources(Properties props, M2Artifact artifact, Path targetBundleDir, boolean merging)
throws IOException {
try {
+ String repoStr = props.containsKey(ARGEO_ORIGIN_M2_REPO.toString())
+ ? props.getProperty(ARGEO_ORIGIN_M2_REPO.toString())
+ : null;
+ String alternateUri = props.getProperty(ARGEO_ORIGIN_SOURCES_URI.toString());
M2Artifact sourcesArtifact = new M2Artifact(artifact.toM2Coordinates(), "sources");
- URL sourcesUrl = M2ConventionsUtils.mavenRepoUrl(repoStr, sourcesArtifact);
- Path sourcesDownloaded = downloadMaven(sourcesUrl, artifact, true);
+ URL sourcesUrl = alternateUri != null ? new URL(alternateUri)
+ : M2ConventionsUtils.mavenRepoUrl(repoStr, sourcesArtifact);
+ Path sourcesDownloaded = downloadMaven(sourcesUrl, sourcesArtifact);
processM2SourceJar(sourcesDownloaded, targetBundleDir, merging ? artifact : null);
logger.log(TRACE, () -> "Processed source " + sourcesDownloaded);
} catch (Exception e) {
/** Integrate sources from a downloaded jar file. */
void processM2SourceJar(Path file, Path bundleDir, M2Artifact mergingFrom) throws IOException {
A2Origin origin = new A2Origin();
- Path sourceDir = sourceBundles ? bundleDir.getParent().resolve(bundleDir.toString() + ".src")
+ Path sourceDir = separateSources ? bundleDir.getParent().resolve(bundleDir.toString() + ".src")
: bundleDir.resolve("OSGI-OPT/src");
try (JarInputStream jarIn = new JarInputStream(Files.newInputStream(file), false)) {
}
}
// write the changes
- if (sourceBundles) {
+ if (separateSources) {
origin.appendChanges(sourceDir);
} else {
origin.added.add("source code under OSGI-OPT/src");
}
/** Download a Maven artifact. */
- Path downloadMaven(URL url, M2Artifact artifact) throws IOException {
- return downloadMaven(url, artifact, false);
+ Path downloadMaven(Properties props, M2Artifact artifact) throws IOException {
+ String repoStr = props.containsKey(ARGEO_ORIGIN_M2_REPO.toString())
+ ? props.getProperty(ARGEO_ORIGIN_M2_REPO.toString())
+ : null;
+ String alternateUri = props.getProperty(ARGEO_ORIGIN_URI.toString());
+ URL url = alternateUri != null ? new URL(alternateUri) : M2ConventionsUtils.mavenRepoUrl(repoStr, artifact);
+ return downloadMaven(url, artifact);
}
/** Download a Maven artifact. */
- Path downloadMaven(URL url, M2Artifact artifact, boolean sources) throws IOException {
- return download(url, mavenBase, artifact.getGroupId().replace(".", "/") //
- + '/' + artifact.getArtifactId() + '/' + artifact.getVersion() //
- + '/' + artifact.getArtifactId() + "-" + artifact.getVersion() + (sources ? "-sources" : "") + ".jar");
+ Path downloadMaven(URL url, M2Artifact artifact) throws IOException {
+ return download(url, mavenBase, M2ConventionsUtils.artifactPath("", artifact));
}
/*
NameVersion nameVersion = new NameVersion(relatedBundle[0], version);
bundleDir = targetBase.resolve(nameVersion.getName() + "." + nameVersion.getBranch());
- Path sourceDir = sourceBundles ? bundleDir.getParent().resolve(bundleDir.toString() + ".src")
+ Path sourceDir = separateSources ? bundleDir.getParent().resolve(bundleDir.toString() + ".src")
: bundleDir.resolve("OSGI-OPT/src");
Files.createDirectories(sourceDir);
}
// write the changes
- if (sourceBundles) {
+ if (separateSources) {
origin.appendChanges(sourceDir);
} else {
origin.added.add("source code under OSGI-OPT/src");
}
deleteDirectory(bundleDir);
- if (sourceBundles)
- createSourceJar(bundleDir, manifest);
+ if (separateSources)
+ createSourceJar(bundleDir, manifest, false);
return jarPath;
}
/** Package sources separately, in the Eclipse-SourceBundle format. */
- void createSourceJar(Path bundleDir, Manifest manifest) throws IOException {
+ void createSourceJar(Path bundleDir, Manifest manifest, boolean notModified) throws IOException {
Path bundleCategoryDir = bundleDir.getParent();
Path sourceDir = bundleCategoryDir.resolve(bundleDir.toString() + ".src");
if (!Files.exists(sourceDir)) {
logger.log(WARNING, sourceDir + " does not exist, skipping...");
return;
}
- createReadMe(sourceDir, manifest);
+
+ if (!notModified)
+ createReadMe(sourceDir, manifest);
Path relPath = a2Base.relativize(bundleCategoryDir);
Path srcCategoryDir = a2SrcBase.resolve(relPath);
writer.append("\nA detailed list of changes is available under " + CHANGES + ".\n");
if (!jarDir.getFileName().endsWith(".src")) {// binary archive
- if (sourceBundles)
+ if (separateSources)
writer.append("Corresponding sources are available in the related archive named "
+ jarDir.toString() + ".src.jar.\n");
else
/** Absolute path to the directories where the files will be stored */
static String artifactParentPath(String artifactBasePath, M2Artifact artifact) {
- return artifactBasePath + (artifactBasePath.endsWith("/") ? "" : "/") + artifactParentPath(artifact);
+ return artifactBasePath + (artifactBasePath.endsWith("/") || artifactBasePath.equals("") ? "" : "/")
+ + artifactParentPath(artifact);
}
/** Relative path to the directories where the files will be stored */