Skip to content

Instantly share code, notes, and snippets.

@rahulsh1
Created August 10, 2018 08:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rahulsh1/53987611b6f92dc8fd428983be2b1594 to your computer and use it in GitHub Desktop.
Save rahulsh1/53987611b6f92dc8fd428983be2b1594 to your computer and use it in GitHub Desktop.
OSGI BundleHook Implementation
package my.hooks;
import org.eclipse.osgi.internal.hookregistry.ClassLoaderHook;
import org.eclipse.osgi.internal.loader.ModuleClassLoader;
import org.eclipse.osgi.internal.loader.classpath.ClasspathEntry;
import org.eclipse.osgi.internal.loader.classpath.ClasspathManager;
import org.eclipse.osgi.internal.loader.classpath.FragmentClasspath;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
/**
* Hook to scan each bundle and build a caching layer around the entries in the bundle and its ClasspathEntry.
*/
public class BundleCacheHook extends ClassLoaderHook {
private Map<String, BundleCache> bundleCaches;
private Supplier<BundleCache> bundleCacheSupplier;
BundleCacheHook(Supplier<BundleCache> cacheSupplier) {
bundleCaches = new HashMap<>();
bundleCacheSupplier = cacheSupplier;
}
@Override
public void classLoaderCreated(ModuleClassLoader classLoader) {
ClasspathManager classpathManager = classLoader.getClasspathManager();
BundleCache cache = bundleCaches.computeIfAbsent(
classLoader.getClasspathManager().getGeneration().getBundleFile().toString(),
v -> bundleCacheSupplier.get());
// Scan the host entries first
for (ClasspathEntry entry : classLoader.getClasspathManager().getHostClasspathEntries()) {
scanBundle(entry.getBundleFile(), entry, cache);
}
// Scan the fragments
for (FragmentClasspath currentFragment : classpathManager.getFragmentClasspaths()) {
for (ClasspathEntry entry : currentFragment.getEntries()) {
scanBundle(entry.getBundleFile(), entry, cache);
}
}
}
private void scanBundle(BundleFile bundleFile, ClasspathEntry cpEntry, BundleCache cache) {
// Iterate over the contents of the bundle and populate the cache
Enumeration<String> entryPaths = bundleFile.getEntryPaths("/", true);
if (entryPaths != null) {
while (entryPaths.hasMoreElements()) {
String path = entryPaths.nextElement();
cache.put(path, cpEntry);
}
}
}
@Override
public ClasspathEntry[] getClassPathEntries(String name, ClasspathManager manager) {
BundleCache cache = bundleCaches.get(manager.getGeneration().getBundleFile().toString());
return cache != null ? cache.get(name) : null;
}
interface BundleCache {
ClasspathEntry[] get(String name);
void put(String name, ClasspathEntry cpEntry);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment