View Javadoc
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                  //noinspection ConstantConditions
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);  // remove the leading /
52          className = className.substring(0, className.lastIndexOf('.')); // remove the .class
53          return className.replace('/', '.');
54      }
55  
56      private String toFolder(String packageName) {
57          return '/' + packageName.replace('.', '/');
58      }
59  }