View Javadoc
1   package org.argeo.slc.repo.osgi;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.InputStream;
5   import java.io.OutputStream;
6   import java.util.Properties;
7   import java.util.jar.Manifest;
8   
9   import org.apache.commons.io.IOUtils;
10  import org.apache.commons.logging.Log;
11  import org.apache.commons.logging.LogFactory;
12  import org.argeo.slc.CategorizedNameVersion;
13  import org.argeo.slc.SlcException;
14  import org.argeo.slc.build.Distribution;
15  import org.argeo.slc.build.License;
16  import org.eclipse.aether.artifact.Artifact;
17  import org.eclipse.aether.artifact.DefaultArtifact;
18  import org.osgi.framework.Version;
19  import org.springframework.beans.factory.BeanNameAware;
20  
21  import aQute.bnd.osgi.Builder;
22  import aQute.bnd.osgi.Constants;
23  import aQute.bnd.osgi.Jar;
24  
25  /** Utilities around the BND library, which manipulates OSGi metadata. */
26  public class BndWrapper implements Constants, CategorizedNameVersion,
27  		Distribution, BeanNameAware {
28  	private final static Log log = LogFactory.getLog(BndWrapper.class);
29  
30  	private String groupId;
31  	private String name;
32  	private Properties bndProperties = new Properties();
33  
34  	private String version;
35  	private License license;
36  
37  	private Boolean doNotModify = false;
38  
39  	private Runnable factory = null;
40  
41  	public void wrapJar(InputStream in, OutputStream out) {
42  		Builder b = new Builder();
43  		Jar jar = null;
44  		try {
45  			byte[] jarBytes = IOUtils.toByteArray(in);
46  
47  			jar = new Jar(name, new ByteArrayInputStream(jarBytes));
48  			Manifest sourceManifest = jar.getManifest();
49  
50  			Version versionToUse;
51  			if (sourceManifest != null) {
52  				// Symbolic name
53  				String sourceSymbolicName = sourceManifest.getMainAttributes()
54  						.getValue(BUNDLE_SYMBOLICNAME);
55  				if (sourceSymbolicName != null
56  						&& !sourceSymbolicName.equals(name))
57  					log.info("The new symbolic name ("
58  							+ name
59  							+ ") is not consistant with the wrapped bundle symbolic name ("
60  							+ sourceSymbolicName + ")");
61  
62  				// Version
63  				String sourceVersion = sourceManifest.getMainAttributes()
64  						.getValue(BUNDLE_VERSION);
65  				if (getVersion() == null && sourceVersion == null) {
66  					throw new SlcException("A bundle version must be defined.");
67  				} else if (getVersion() == null && sourceVersion != null) {
68  					versionToUse = new Version(sourceVersion);
69  					version = sourceVersion; // set wrapper version
70  				} else if (getVersion() != null && sourceVersion == null) {
71  					versionToUse = new Version(getVersion());
72  				} else {// both set
73  					versionToUse = new Version(getVersion());
74  					Version sv = new Version(sourceVersion);
75  					if (versionToUse.getMajor() != sv.getMajor()
76  							|| versionToUse.getMinor() != sv.getMinor()
77  							|| versionToUse.getMicro() != sv.getMicro()) {
78  						log.warn("The new version ("
79  								+ versionToUse
80  								+ ") is not consistant with the wrapped bundle version ("
81  								+ sv + ")");
82  					}
83  				}
84  			} else {
85  				versionToUse = new Version(getVersion());
86  			}
87  
88  			if (doNotModify) {
89  				IOUtils.write(jarBytes, out);
90  				// jar.write(out);
91  			} else {
92  
93  				Properties properties = new Properties();
94  				properties.putAll(bndProperties);
95  				properties.setProperty(BUNDLE_SYMBOLICNAME, name);
96  				properties.setProperty(BUNDLE_VERSION, versionToUse.toString());
97  
98  				// License
99  				if (license != null) {
100 					StringBuilder sb = new StringBuilder(license.getUri());
101 					if (license.getName() != null)
102 						sb.append(';').append("description=")
103 								.append(license.getName());
104 					if (license.getLink() != null)
105 						sb.append(';').append("link=")
106 								.append(license.getLink());
107 					properties.setProperty(BUNDLE_LICENSE, sb.toString());
108 					// TODO add LICENSE.TXT
109 				} else {
110 					log.warn("No license set for " + toString());
111 				}
112 
113 				// b.addIncluded(jarFile);
114 				b.addClasspath(jar);
115 
116 				if (log.isDebugEnabled())
117 					log.debug(properties);
118 				b.setProperties(properties);
119 
120 				Jar newJar = b.build();
121 				newJar.write(out);
122 				newJar.close();
123 			}
124 		} catch (Exception e) {
125 			throw new SlcException("Cannot wrap jar", e);
126 		} finally {
127 			try {
128 				b.close();
129 				if (jar != null)
130 					jar.close();
131 			} catch (Exception e) {
132 				// silent
133 			}
134 		}
135 
136 	}
137 
138 	public Runnable getFactory() {
139 		return factory;
140 	}
141 
142 	public void setFactory(Runnable factory) {
143 		if (this.factory != null)
144 			throw new SlcException("Factory already set on " + name);
145 		this.factory = factory;
146 	}
147 
148 	public void setName(String bsn) {
149 		this.name = bsn;
150 	}
151 
152 	public String getName() {
153 		return name;
154 	}
155 
156 	public void setVersion(String version) {
157 		if (this.version != null)
158 			throw new SlcException("Version already set on " + name + " ("
159 					+ this.version + ")");
160 		this.version = version;
161 	}
162 
163 	public String getVersion() {
164 		return version;
165 	}
166 
167 	public License getLicense() {
168 		return license;
169 	}
170 
171 	public void setLicense(License license) {
172 		if (this.license != null)
173 			throw new SlcException("License already set on " + name);
174 		this.license = license;
175 	}
176 
177 	public Properties getBndProperties() {
178 		return bndProperties;
179 	}
180 
181 	public void setBndProperties(Properties bndProperties) {
182 		this.bndProperties = bndProperties;
183 	}
184 
185 	public void setBeanName(String name) {
186 		if (this.name == null) {
187 			this.name = name;
188 		} else {
189 			if (!name.contains("#"))
190 				log.warn("Using explicitely set name " + this.name
191 						+ " and not bean name " + name);
192 		}
193 	}
194 
195 	public String getGroupId() {
196 		return groupId;
197 	}
198 
199 	public String getCategory() {
200 		return getGroupId();
201 	}
202 
203 	public void setGroupId(String groupId) {
204 		this.groupId = groupId;
205 	}
206 
207 	public String getDistributionId() {
208 		return getArtifact().toString();
209 	}
210 
211 	public Artifact getArtifact() {
212 		return new DefaultArtifact(groupId, name, "jar", getVersion());
213 	}
214 
215 	@Override
216 	public String toString() {
217 		return getArtifact().toString();
218 	}
219 
220 	@Override
221 	public int hashCode() {
222 		return getArtifact().hashCode();
223 	}
224 
225 	@Override
226 	public boolean equals(Object obj) {
227 		if (obj instanceof CategorizedNameVersion) {
228 			CategorizedNameVersion cnv = (CategorizedNameVersion) obj;
229 			return getCategory().equals(cnv.getCategory())
230 					&& getName().equals(cnv.getName())
231 					&& getVersion().equals(cnv.getVersion());
232 		} else
233 			return false;
234 	}
235 
236 	public void setDoNotModify(Boolean doNotModify) {
237 		this.doNotModify = doNotModify;
238 	}
239 
240 }