--- /dev/null
+package org.argeo.slc.repo.osgi;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+import java.util.jar.Manifest;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.slc.CategoryNameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.build.Distribution;
+import org.argeo.slc.build.License;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.osgi.framework.Version;
+
+import aQute.bnd.osgi.Builder;
+import aQute.bnd.osgi.Constants;
+import aQute.bnd.osgi.Jar;
+
+/** Utilities around the BND library, which manipulates OSGi metadata. */
+public class BndWrapper implements Constants, CategoryNameVersion, Distribution {
+ private final static CmsLog log = CmsLog.getLog(BndWrapper.class);
+
+ private String groupId;
+ private String name;
+ private Properties bndProperties = new Properties();
+
+ private String version;
+ private License license;
+
+ private Boolean doNotModify = false;
+
+ private Runnable factory = null;
+
+ public void wrapJar(InputStream in, OutputStream out) {
+ Builder b = new Builder();
+ Jar jar = null;
+ try {
+ byte[] jarBytes = IOUtils.toByteArray(in);
+
+ jar = new Jar(name, new ByteArrayInputStream(jarBytes));
+ Manifest sourceManifest = jar.getManifest();
+
+ Version versionToUse;
+ if (sourceManifest != null) {
+ // Symbolic name
+ String sourceSymbolicName = sourceManifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ if (sourceSymbolicName != null && !sourceSymbolicName.equals(name))
+ log.info("The new symbolic name (" + name
+ + ") is not consistant with the wrapped bundle symbolic name (" + sourceSymbolicName + ")");
+
+ // Version
+ String sourceVersion = sourceManifest.getMainAttributes().getValue(BUNDLE_VERSION);
+ if (getVersion() == null && sourceVersion == null) {
+ throw new SlcException("A bundle version must be defined.");
+ } else if (getVersion() == null && sourceVersion != null) {
+ versionToUse = new Version(sourceVersion);
+ version = sourceVersion; // set wrapper version
+ } else if (getVersion() != null && sourceVersion == null) {
+ versionToUse = new Version(getVersion());
+ } else {// both set
+ versionToUse = new Version(getVersion());
+ Version sv = new Version(sourceVersion);
+ if (versionToUse.getMajor() != sv.getMajor() || versionToUse.getMinor() != sv.getMinor()
+ || versionToUse.getMicro() != sv.getMicro()) {
+ log.warn("The new version (" + versionToUse
+ + ") is not consistant with the wrapped bundle version (" + sv + ")");
+ }
+ }
+ } else {
+ versionToUse = new Version(getVersion());
+ }
+
+ if (doNotModify) {
+ IOUtils.write(jarBytes, out);
+ // jar.write(out);
+ } else {
+
+ Properties properties = new Properties();
+ properties.putAll(bndProperties);
+ properties.setProperty(BUNDLE_SYMBOLICNAME, name);
+ properties.setProperty(BUNDLE_VERSION, versionToUse.toString());
+
+ // License
+ if (license != null) {
+ properties.setProperty(BUNDLE_LICENSE, license.toString());
+ // TODO add LICENSE.TXT
+ } else {
+ log.warn("No license set for " + toString());
+ }
+
+ // b.addIncluded(jarFile);
+ b.addClasspath(jar);
+
+ if (log.isDebugEnabled())
+ log.debug(properties);
+ b.setProperties(properties);
+
+ Jar newJar = b.build();
+ newJar.write(out);
+ newJar.close();
+ }
+ } catch (Exception e) {
+ throw new SlcException("Cannot wrap jar", e);
+ } finally {
+ try {
+ b.close();
+ if (jar != null)
+ jar.close();
+ } catch (Exception e) {
+ // silent
+ }
+ }
+
+ }
+
+ public Runnable getFactory() {
+ return factory;
+ }
+
+ public void setFactory(Runnable factory) {
+ if (this.factory != null)
+ throw new SlcException("Factory already set on " + name);
+ this.factory = factory;
+ }
+
+ public void setName(String bsn) {
+ this.name = bsn;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setVersion(String version) {
+ if (this.version != null)
+ throw new SlcException("Version already set on " + name + " (" + this.version + ")");
+ this.version = version;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public License getLicense() {
+ return license;
+ }
+
+ public void setLicense(License license) {
+ if (this.license != null)
+ throw new SlcException("License already set on " + name);
+ this.license = license;
+ }
+
+ public Properties getBndProperties() {
+ return bndProperties;
+ }
+
+ public void setBndProperties(Properties bndProperties) {
+ this.bndProperties = bndProperties;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public String getCategory() {
+ return getGroupId();
+ }
+
+ public void setGroupId(String groupId) {
+ this.groupId = groupId;
+ }
+
+ public String getDistributionId() {
+ return getCategory() + ":" + getName() + ":" + getVersion();
+ }
+
+ public Artifact getArtifact() {
+ return new DefaultArtifact(groupId, name, "jar", getVersion());
+ }
+
+ @Override
+ public String toString() {
+ return getDistributionId();
+ }
+
+ @Override
+ public int hashCode() {
+ if (name != null)
+ return name.hashCode();
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof CategoryNameVersion) {
+ CategoryNameVersion cnv = (CategoryNameVersion) obj;
+ return getCategory().equals(cnv.getCategory()) && getName().equals(cnv.getName())
+ && getVersion().equals(cnv.getVersion());
+ } else
+ return false;
+ }
+
+ public void setDoNotModify(Boolean doNotModify) {
+ this.doNotModify = doNotModify;
+ }
+
+ public Boolean getDoNotModify() {
+ return doNotModify;
+ }
+
+}