package org.argeo.slc.repo.osgi; import static org.argeo.slc.ManifestConstants.SLC_ORIGIN_M2; import static org.argeo.slc.ManifestConstants.SLC_ORIGIN_URI; import java.io.IOException; import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.argeo.api.cms.CmsLog; import org.argeo.slc.CategoryNameVersion; import org.argeo.slc.ManifestConstants; import org.argeo.slc.ModuleSet; import org.argeo.slc.NameVersion; import org.argeo.slc.build.Distribution; import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.repo.ArgeoOsgiDistribution; import org.argeo.slc.repo.ArtifactDistribution; import org.argeo.slc.repo.FreeLicense; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.osgi.framework.Constants; /** * A consistent and versioned OSGi distribution, which can be built and tested. */ public class ArgeoOsgiDistributionImpl extends ArtifactDistribution implements ArgeoOsgiDistribution { private final static CmsLog log = CmsLog.getLog(ArgeoOsgiDistributionImpl.class); private List modules = new ArrayList(); public ArgeoOsgiDistributionImpl(String coords) { super(coords); } public void init() { if (log.isDebugEnabled()) log.debug(describe()); migrateTov2(Paths.get(System.getProperty("user.home"), "dev/git/unstable/argeo-tp/migration")); } public void destroy() { } public String describe() { SortedSet sort = new TreeSet(); Iterator nvIt = nameVersions(); while (nvIt.hasNext()) { NameVersion nv = nvIt.next(); String str = nv.toString(); if (nv instanceof MavenWrapper) str = str + "\t(Maven)"; else if (nv instanceof UriWrapper) str = str + "\t(URI)"; else if (nv instanceof ArchiveWrapperCNV) str = str + "\t(OSGi from archive)"; else if (nv instanceof BndWrapper) str = str + "\t(Plain BND from archive)"; else str = str + "\t(UNKNOWN??)"; sort.add(str); } StringBuffer buf = new StringBuffer("## DISTRIBUTION " + toString() + " ##\n"); for (String str : sort) { buf.append(str).append('\n'); } return buf.toString(); } public void migrateTov2(Path baseDir) { Set archiveWrappers = new HashSet<>(); Iterator nvIt = nameVersions(); while (nvIt.hasNext()) { NameVersion nv = nvIt.next(); try { if (nv instanceof CategoryNameVersion) { CategoryNameVersion cnv = (CategoryNameVersion) nv; // TODO add branch? Path categoryBase = baseDir.resolve(cnv.getCategory()); Files.createDirectories(categoryBase); if (cnv instanceof BndWrapper) { BndWrapper bw = (BndWrapper) cnv; Path bndPath = categoryBase.resolve(cnv.getName() + ".bnd"); Map props = new TreeMap<>(); for (Map.Entry entry : ((BndWrapper) cnv).getBndProperties().entrySet()) { props.put(entry.getKey().toString(), entry.getValue().toString()); } props.put(Constants.BUNDLE_SYMBOLICNAME, cnv.getName()); props.put(Constants.BUNDLE_VERSION, cnv.getVersion()); if (bw.getLicense() != null) props.put(Constants.BUNDLE_LICENSE, bw.getLicense().toString()); else log.warn("No license for " + cnv); if (bw.getDoNotModify()) { props.put(ManifestConstants.SLC_ORIGIN_MANIFEST_NOT_MODIFIED.toString(), "true"); } // props.put("SLC-Category", cnv.getCategory()); if (cnv instanceof MavenWrapper) { MavenWrapper mw = (MavenWrapper) cnv; String sourceCoords = mw.getSourceCoords(); props.put(SLC_ORIGIN_M2.toString(), sourceCoords); Artifact mavenCnv = new DefaultArtifact(sourceCoords); if (mavenCnv.getArtifactId().equals(cnv.getName())) props.remove(Constants.BUNDLE_SYMBOLICNAME); if (mavenCnv.getVersion().equals(cnv.getVersion())) props.remove(Constants.BUNDLE_VERSION); } else if (cnv instanceof UriWrapper) { UriWrapper mw = (UriWrapper) cnv; props.put(SLC_ORIGIN_URI.toString(), mw.getEffectiveUri()); if (mw.getUri() == null && mw.getBaseUri() != null) { log.warn("Base URI for " + cnv); props.put("SLC-Origin-BaseURI", mw.getBaseUri()); props.put("SLC-Origin-VersionSeparator", mw.getVersionSeparator()); } } else { log.warn("Unidentified BND wrapper " + cnv); } // write BND file try (Writer writer = Files.newBufferedWriter(bndPath)) { // writer.write("# " + cnv + "\n"); props: for (String key : props.keySet()) { String value = props.get(key); if (Constants.EXPORT_PACKAGE.equals(key) && "*".equals(value.trim())) continue props; writer.write(key + ": " + value + '\n'); } if (log.isTraceEnabled()) log.trace("Wrote " + bndPath); } } else if (cnv instanceof ArchiveWrapperCNV) { ArchiveWrapperCNV onv = (ArchiveWrapperCNV) cnv; ArchiveWrapper aw = onv.getBuild(); archiveWrappers.add(aw); // TODO specify and implement archive wrapper support } else { log.warn("Unsupported wrapper " + cnv.getClass() + " for " + cnv); } } else { log.error("Category required for " + nv + ", skipping..."); } } catch (IOException e) { log.error("Could not process " + nv, e); } } if (log.isDebugEnabled()) { for (ArchiveWrapper aw : archiveWrappers) { log.debug("Archive wrapper " + aw.getUri() + ":"); log.debug(" includes: " + aw.getIncludes()); log.debug(" excludes: " + aw.getExcludes()); log.debug(" beans : " + aw.getWrappers()); String uri = aw.getUri(); String duName = null; String category = null; String oldCategory = null; if (uri.startsWith("http://www.eclipse.org/downloads/rt/rap/3.10/e4/rap-e4")) { duName = "eclipse-rap"; category = "org.argeo.tp.eclipse.rap"; oldCategory = "org.argeo.tp.rap.e4"; } else if (uri.startsWith("http://www.eclipse.org/downloads/equinox/")) { duName = "eclipse-equinox"; category = "org.argeo.tp.eclipse.equinox"; oldCategory = "org.argeo.tp.equinox"; } else if (uri.startsWith("http://www.eclipse.org/downloads/eclipse/downloads/drops4")) { duName = "eclipse-rcp"; category = "org.argeo.tp.eclipse.rcp"; oldCategory = "org.argeo.tp.rcp.e4"; } if (duName != null) { try { Path duDir = baseDir.resolve(category).resolve(duName); Files.createDirectories(duDir); Path bndPath = duDir.resolve("common.bnd"); Path includesPath = duDir.resolve("includes.properties"); Map props = new TreeMap<>(); props.put(ManifestConstants.SLC_ORIGIN_URI.toString(), aw.getUri()); props.put(ManifestConstants.SLC_ORIGIN_MANIFEST_NOT_MODIFIED.toString(), "true"); props.put(Constants.BUNDLE_LICENSE, FreeLicense.EPL.toString()); // write BND file try (Writer bndWriter = Files.newBufferedWriter(bndPath); Writer includesWriter = Files.newBufferedWriter(includesPath);) { // writer.write("# " + cnv + "\n"); props: for (String key : props.keySet()) { String value = props.get(key); if (Constants.EXPORT_PACKAGE.equals(key) && "*".equals(value.trim())) continue props; bndWriter.write(key + ": " + value + '\n'); } for (String key : aw.getIncludes().keySet()) { String value = aw.getIncludes().get(key); if (value.equals(oldCategory)) value = category; includesWriter.write(key + "=" + value + '\n'); } if (log.isTraceEnabled()) log.trace("Wrote " + bndPath); } } catch (IOException e) { log.error("Could not process " + aw, e); } } } } } public Iterator nameVersions() { List nameVersions = new ArrayList(); for (Object module : modules) { // extract runnable from execution flow if (module instanceof ExecutionFlow) { for (Iterator it = ((ExecutionFlow) module).runnables(); it.hasNext();) { processModule(nameVersions, it.next()); } } else { processModule(nameVersions, module); } } return nameVersions.iterator(); } private void processModule(List nameVersions, Object module) { if (module instanceof ModuleSet) addNameVersions(nameVersions, (ModuleSet) module); else if (module instanceof NameVersion) { NameVersion nv = (NameVersion) module; addNameVersion(nameVersions, nv); } else log.warn("Ignored " + module); } private void addNameVersions(List nameVersions, ModuleSet moduleSet) { Iterator it = moduleSet.nameVersions(); while (it.hasNext()) { NameVersion nv = it.next(); addNameVersion(nameVersions, nv); } } protected void addNameVersion(List nameVersions, NameVersion nv) { if (!nameVersions.contains(nv)) { nameVersions.add(nv); } } // Modular distribution interface methods. Not yet used. public Distribution getModuleDistribution(String moduleName, String moduleVersion) { throw new UnsupportedOperationException(); } public Object getModulesDescriptor(String descriptorType) { throw new UnsupportedOperationException(); } /* DEPENDENCY INJECTION */ public void setModules(List modules) { this.modules = modules; } }