View Javadoc
1   /*-
2    * #%L
3    * io.earcam.instrumental.module.osgi
4    * %%
5    * Copyright (C) 2018 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */
19  package io.earcam.instrumental.module.osgi;
20  
21  import static io.earcam.instrumental.module.manifest.ManifestInfoBuilder.attribute;
22  import static io.earcam.instrumental.module.osgi.BundleManifestHeaders.BUNDLE_MANIFESTVERSION;
23  import static io.earcam.instrumental.module.osgi.ClauseParameters.EMPTY_PARAMETERS;
24  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.BUNDLE_ACTIVATOR;
25  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.BUNDLE_SYMBOLICNAME;
26  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.DYNAMICIMPORT_PACKAGE;
27  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.EXPORT_PACKAGE;
28  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.FRAGMENT_HOST;
29  import static io.earcam.instrumental.module.osgi.OsgiManifestHeaderConstants.IMPORT_PACKAGE;
30  
31  import java.io.ByteArrayInputStream;
32  import java.io.ByteArrayOutputStream;
33  import java.io.InputStream;
34  import java.util.SortedSet;
35  import java.util.function.Predicate;
36  import java.util.jar.Attributes.Name;
37  import java.util.jar.Manifest;
38  
39  import io.earcam.instrumental.fluent.Fluent;
40  import io.earcam.instrumental.module.manifest.ManifestInfoBuilder;
41  import io.earcam.instrumental.module.osgi.parser.BundleInfoParser;
42  import io.earcam.instrumental.reflect.Types;
43  import io.earcam.unexceptional.Exceptional;
44  
45  /**
46   * <p>
47   * BundleInfoBuilder interface.
48   * </p>
49   *
50   */
51  public interface BundleInfoBuilder extends ManifestInfoBuilder<BundleInfoBuilder> {
52  
53  	/**
54  	 * <p>
55  	 * bundle.
56  	 * </p>
57  	 *
58  	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
59  	 */
60  	@Fluent
61  	public static BundleInfoBuilder bundle()
62  	{
63  		return new DefaultBundleInfo();
64  	}
65  
66  
67  	/**
68  	 * <p>
69  	 * bundleFrom.
70  	 * </p>
71  	 *
72  	 * @param input a {@link java.lang.String} object.
73  	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
74  	 */
75  	@Fluent
76  	public static BundleInfoBuilder bundleFrom(String input)
77  	{
78  		return BundleInfoParser.parse(input);
79  	}
80  
81  
82  	/**
83  	 * <p>
84  	 * bundleFrom.
85  	 * </p>
86  	 *
87  	 * @param input a {@link java.io.InputStream} object.
88  	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
89  	 */
90  	@Fluent
91  	public static BundleInfoBuilder bundleFrom(InputStream input)
92  	{
93  		return BundleInfoParser.parse(input);
94  	}
95  
96  
97  	/**
98  	 * <p>
99  	 * bundleManifestVersion.
100 	 * </p>
101 	 *
102 	 * @param version a {@link java.lang.String} object.
103 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
104 	 */
105 	public default BundleInfoBuilder bundleManifestVersion(String version)
106 	{
107 		return manifestMain(attribute(BUNDLE_MANIFESTVERSION.header(), version));
108 	}
109 
110 
111 	/**
112 	 * <p>
113 	 * symbolicName.
114 	 * </p>
115 	 *
116 	 * @param name a {@link java.lang.CharSequence} object.
117 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
118 	 */
119 	public default BundleInfoBuilder symbolicName(CharSequence name)
120 	{
121 		return symbolicName(name, EMPTY_PARAMETERS);
122 	}
123 
124 
125 	/**
126 	 * <p>
127 	 * symbolicName.
128 	 * </p>
129 	 *
130 	 * @param name a {@link java.lang.CharSequence} object.
131 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
132 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
133 	 */
134 	public default BundleInfoBuilder symbolicName(CharSequence name, ClauseParameters parameters)
135 	{
136 		return headerClause(BUNDLE_SYMBOLICNAME.value, new Clause(Clause.sortedSet(name.toString()), parameters));
137 	}
138 
139 
140 	/**
141 	 * <p>
142 	 * symbolicName.
143 	 * </p>
144 	 *
145 	 * @param name a {@link java.lang.CharSequence} object.
146 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
147 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
148 	 */
149 	public default BundleInfoBuilder fragmentHost(CharSequence name, ClauseParameters parameters)
150 	{
151 		return headerClause(FRAGMENT_HOST.value, new Clause(Clause.sortedSet(name.toString()), parameters));
152 	}
153 
154 
155 	/**
156 	 * <p>
157 	 * exportPackages.
158 	 * </p>
159 	 *
160 	 * @param packages a {@link java.lang.String} object.
161 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
162 	 */
163 	public default BundleInfoBuilder exportPackages(String... packages)
164 	{
165 		return exportPackages(packages, EMPTY_PARAMETERS);
166 	}
167 
168 
169 	/**
170 	 * <p>
171 	 * exportPackages.
172 	 * </p>
173 	 *
174 	 * @param paquet a {@link java.lang.String} object.
175 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
176 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
177 	 */
178 	public default BundleInfoBuilder exportPackages(String paquet, ClauseParameters parameters)
179 	{
180 		return exportPackages(new String[] { paquet }, parameters);
181 	}
182 
183 
184 	/**
185 	 * <p>
186 	 * exportPackages.
187 	 * </p>
188 	 *
189 	 * @param packages an array of {@link java.lang.String} objects.
190 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
191 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
192 	 */
193 	public default BundleInfoBuilder exportPackages(String[] packages, ClauseParameters parameters)
194 	{
195 		return exportPackages(Clause.sortedSet(packages), parameters);
196 	}
197 
198 
199 	/**
200 	 * <p>
201 	 * exportPackages.
202 	 * </p>
203 	 *
204 	 * @param packages a {@link java.util.SortedSet} object.
205 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
206 	 */
207 	public default BundleInfoBuilder exportPackages(SortedSet<String> packages)
208 	{
209 		return exportPackages(packages, EMPTY_PARAMETERS);
210 	}
211 
212 
213 	/**
214 	 * <p>
215 	 * exportPackages.
216 	 * </p>
217 	 *
218 	 * @param packages a {@link java.util.SortedSet} object.
219 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
220 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
221 	 */
222 	public default BundleInfoBuilder exportPackages(SortedSet<String> packages, ClauseParameters parameters)
223 	{
224 		return headerClause(EXPORT_PACKAGE.value, new Clause(packages, parameters));
225 	}
226 
227 
228 	/**
229 	 * <p>
230 	 * importPackages.
231 	 * </p>
232 	 *
233 	 * @param packages a {@link java.lang.String} object.
234 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
235 	 */
236 	public default BundleInfoBuilder importPackages(String... packages)
237 	{
238 		return importPackages(packages, EMPTY_PARAMETERS);
239 	}
240 
241 
242 	/**
243 	 * <p>
244 	 * importPackages.
245 	 * </p>
246 	 *
247 	 * @param paquet a {@link java.lang.String} object.
248 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
249 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
250 	 */
251 	public default BundleInfoBuilder importPackages(String paquet, ClauseParameters parameters)
252 	{
253 		return importPackages(Clause.sortedSet(paquet), parameters);
254 	}
255 
256 
257 	/**
258 	 * <p>
259 	 * importPackages.
260 	 * </p>
261 	 *
262 	 * @param packages an array of {@link java.lang.String} objects.
263 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
264 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
265 	 */
266 	public default BundleInfoBuilder importPackages(String[] packages, ClauseParameters parameters)
267 	{
268 		return importPackages(Clause.sortedSet(packages), parameters);
269 	}
270 
271 
272 	/**
273 	 * <p>
274 	 * importPackages.
275 	 * </p>
276 	 *
277 	 * @param packages a {@link java.util.SortedSet} object.
278 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
279 	 */
280 	public default BundleInfoBuilder importPackages(SortedSet<String> packages)
281 	{
282 		return importPackages(packages, EMPTY_PARAMETERS);
283 	}
284 
285 
286 	/**
287 	 * <p>
288 	 * importPackages.
289 	 * </p>
290 	 *
291 	 * @param packages a {@link java.util.SortedSet} object.
292 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
293 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
294 	 */
295 	public default BundleInfoBuilder importPackages(SortedSet<String> packages, ClauseParameters parameters)
296 	{
297 		return importPackages(new Clause(packages, parameters));
298 	}
299 
300 
301 	/**
302 	 * <p>
303 	 * importPackages.
304 	 * </p>
305 	 *
306 	 * @param clause a {@link io.earcam.instrumental.module.osgi.Clause} object.
307 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
308 	 */
309 	public default BundleInfoBuilder importPackages(Clause clause)
310 	{
311 		return headerClause(IMPORT_PACKAGE.value, clause);
312 	}
313 
314 
315 	/**
316 	 * <p>
317 	 * dynamic importPackages.
318 	 * </p>
319 	 *
320 	 * @param packages a {@link java.util.SortedSet} object.
321 	 * @param parameters a {@link io.earcam.instrumental.module.osgi.ClauseParameters} object.
322 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
323 	 */
324 	public default BundleInfoBuilder dynamicImportPackages(SortedSet<String> packages, ClauseParameters parameters)
325 	{
326 		return dynamicImportPackages(new Clause(packages, parameters));
327 	}
328 
329 
330 	/**
331 	 * <p>
332 	 * dynamic importPackages.
333 	 * </p>
334 	 *
335 	 * @param clause a {@link io.earcam.instrumental.module.osgi.Clause} object.
336 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
337 	 */
338 	public default BundleInfoBuilder dynamicImportPackages(Clause clause)
339 	{
340 		return headerClause(DYNAMICIMPORT_PACKAGE.value, clause);
341 	}
342 
343 
344 	/**
345 	 * <p>
346 	 * headerClause.
347 	 * </p>
348 	 *
349 	 * @param header a {@link java.lang.String} object.
350 	 * @param clause a {@link io.earcam.instrumental.module.osgi.Clause} object.
351 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
352 	 */
353 	public default BundleInfoBuilder headerClause(String header, Clause clause)
354 	{
355 		return headerClause(new Name(header), clause);
356 	}
357 
358 
359 	/**
360 	 * <p>
361 	 * headerClause.
362 	 * </p>
363 	 *
364 	 * @param header a {@link java.util.jar.Attributes.Name} object.
365 	 * @param clause a {@link io.earcam.instrumental.module.osgi.Clause} object.
366 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
367 	 */
368 	public abstract BundleInfoBuilder headerClause(Name header, Clause clause);
369 
370 
371 	/**
372 	 * <p>
373 	 * activator.
374 	 * </p>
375 	 *
376 	 * @param className a {@link java.lang.String} object.
377 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
378 	 */
379 	public default BundleInfoBuilder activator(Class<?> activator)
380 	{
381 		final String iface = "org.osgi.framework.BundleActivator";
382 		boolean implementsActivator = Types.allInterfacesOf(activator)
383 				.map(Class::getCanonicalName)
384 				.anyMatch(Predicate.isEqual(iface));
385 		if(!implementsActivator) {
386 			throw new IllegalArgumentException(activator.getCanonicalName() + " does not implement " + iface);
387 		}
388 		return activator(activator.getCanonicalName());
389 	}
390 
391 
392 	/**
393 	 * <p>
394 	 * activator.
395 	 * </p>
396 	 *
397 	 * @param className a {@link java.lang.String} object.
398 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfoBuilder} object.
399 	 */
400 	public default BundleInfoBuilder activator(String className)
401 	{
402 		return headerClause(BUNDLE_ACTIVATOR.value, new Clause(className, EMPTY_PARAMETERS));
403 	}
404 
405 
406 	/**
407 	 * <p>
408 	 * construct.
409 	 * </p>
410 	 *
411 	 * @return a {@link io.earcam.instrumental.module.osgi.BundleInfo} object.
412 	 */
413 	public abstract BundleInfo construct();
414 
415 
416 	@Fluent
417 	public static BundleInfoBuilder bundleFrom(Manifest manifest)
418 	{
419 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
420 		Exceptional.accept(manifest::write, baos);
421 		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
422 		return BundleInfoBuilder.bundleFrom(bais);
423 	}
424 }