1 package com.atlassian.activeobjects.osgi;
2
3 import com.google.common.base.Function;
4 import com.google.common.base.Predicate;
5 import com.google.common.collect.ImmutableList;
6 import org.osgi.framework.BundleContext;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9
10 import java.net.URL;
11 import java.util.Enumeration;
12
13 import static com.google.common.base.Preconditions.checkNotNull;
14 import static com.google.common.collect.Iterables.filter;
15
16 final class BundleContextScanner {
17 private final Logger log = LoggerFactory.getLogger(this.getClass());
18
19 <T> Iterable<T> findClasses(BundleContext bundleContext, String packageName, Function<String, T> f, Predicate<T> p) {
20 checkNotNull(bundleContext);
21 checkNotNull(packageName);
22 checkNotNull(f);
23 checkNotNull(p);
24
25 return filter(toIterable(getBundleEntries(bundleContext, packageName), f), p);
26 }
27
28 private Enumeration getBundleEntries(BundleContext bundleContext, String packageName) {
29 log.debug("Scanning package '{}' of bundle {}", packageName, bundleContext.getBundle());
30 return bundleContext.getBundle().findEntries(toFolder(packageName), "*.class", true);
31 }
32
33 private <T> Iterable<T> toIterable(Enumeration entries, Function<String, T> f) {
34 final ImmutableList.Builder<T> classes = ImmutableList.builder();
35 if (entries != null) {
36 while (entries.hasMoreElements()) {
37 final String className = getClassName((URL) entries.nextElement());
38 log.debug("Found class '{}'", className);
39
40 classes.add(f.apply(className));
41 }
42 }
43 return classes.build();
44 }
45
46 private String getClassName(URL url) {
47 return getClassName(url.getFile());
48 }
49
50 private String getClassName(String file) {
51 String className = file.substring(1);
52 className = className.substring(0, className.lastIndexOf('.'));
53 return className.replace('/', '.');
54 }
55
56 private String toFolder(String packageName) {
57 return '/' + packageName.replace('.', '/');
58 }
59 }