From c6758f9a2a8798baa99335a48a0adbf6741a2b36 Mon Sep 17 00:00:00 2001 From: Rahul Shinde Date: Fri, 3 Aug 2018 13:59:06 -0700 Subject: Bug 537701 - Additional hook for lookup of filtered classpath entries Change-Id: Ifd788d04314fe1b1c7a8192afc908413f96f2b8d Signed-off-by: Rahul Shinde --- .../internal/hookregistry/ClassLoaderHook.java | 17 ++ .../loader/classpath/ClasspathManager.java | 195 +++++++++++++++------ 2 files changed, 154 insertions(+), 58 deletions(-) (limited to 'bundles') diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java index 0f0b02b92..2cd8863a7 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/ClassLoaderHook.java @@ -305,4 +305,21 @@ public abstract class ClassLoaderHook { return false; } + /** + * Returns the filtered list of ClasspathEntry instances for the given class, resource or entry. + * A {@code null} value may be returned in which case the find process will go over all the host and + * fragment entries in order to find the given entity which is the default behavior. + * Any non-null return value including an empty list will only look at the entries in the returned list. + * + * This method is used within {@link ClasspathManager#findLocalResource(String)}, {@link ClasspathManager#findLocalResources(String)}, + * {@link ClasspathManager#findLocalClass(String) } and {@link ClasspathManager#findLocalEntry(String) } + * + * @param name the name of the requested class, resource or entry + * @param manager the classpath manager used to find the requested class, resource or entry + * @return the array of ClassPathEntry objects to use to load this given entity + */ + public ClasspathEntry[] getClassPathEntries(String name, ClasspathManager manager) { + // do nothing by default + return null; + } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java index ee0377c55..9d5006808 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/classpath/ClasspathManager.java @@ -371,25 +371,44 @@ public class ClasspathManager { private URL findLocalResourceImpl(String resource, int classPathIndex) { Module m = generation.getRevision().getRevisions().getModule(); URL result = null; - int curIndex = 0; - for (ClasspathEntry cpEntry : entries) { - if (cpEntry != null) { - result = cpEntry.findResource(resource, m, curIndex); - if (result != null && (classPathIndex == -1 || classPathIndex == curIndex)) { - return result; - } + int[] curIndex = {0}; + + // look in hook specific entries if any + for (ClassLoaderHook hook : hookRegistry.getClassLoaderHooks()) { + ClasspathEntry[] hookEntries = hook.getClassPathEntries(resource, this); + if (hookEntries != null) { + return findLocalResourceImpl(resource, hookEntries, m, classPathIndex, curIndex); } - curIndex++; } - // look in fragments + + curIndex[0] = 0; + // look in classpath entries + result = findLocalResourceImpl(resource, entries, m, classPathIndex, curIndex); + if (result != null) { + return result; + } + + // look in fragment entries for (FragmentClasspath fragCP : getFragmentClasspaths()) { - for (ClasspathEntry cpEntry : fragCP.getEntries()) { - result = cpEntry.findResource(resource, m, curIndex); - if (result != null && (classPathIndex == -1 || classPathIndex == curIndex)) { + result = findLocalResourceImpl(resource, fragCP.getEntries(), m, classPathIndex, curIndex); + if (result != null) { + return result; + } + } + + return null; + } + + private URL findLocalResourceImpl(String resource, ClasspathEntry[] cpEntries, Module m, int classPathIndex, int[] curIndex) { + URL result; + for (ClasspathEntry cpEntry : cpEntries) { + if (cpEntry != null) { + result = cpEntry.findResource(resource, m, curIndex[0]); + if (result != null && (classPathIndex == -1 || classPathIndex == curIndex[0])) { return result; } - curIndex++; } + curIndex[0]++; } return null; } @@ -402,29 +421,40 @@ public class ClasspathManager { public Enumeration findLocalResources(String resource) { Module m = generation.getRevision().getRevisions().getModule(); List resources = new ArrayList<>(6); - int classPathIndex = 0; - for (ClasspathEntry cpEntry : entries) { - if (cpEntry != null) { - URL url = cpEntry.findResource(resource, m, classPathIndex); - if (url != null) { - resources.add(url); - } + int[] classPathIndex = {0}; + + // look in hook specific entries if any + for (ClassLoaderHook hook : hookRegistry.getClassLoaderHooks()) { + ClasspathEntry[] hookEntries = hook.getClassPathEntries(resource, this); + if (hookEntries != null) { + findLocalResources(resource, hookEntries, m, classPathIndex, resources); + return resources.size() > 0 ? Collections.enumeration(resources): EMPTY_ENUMERATION; } - classPathIndex++; } - // look in fragments + + classPathIndex[0] = 0; + // look in host classpath entries + findLocalResources(resource, entries, m, classPathIndex, resources); + // look in fragment entries for (FragmentClasspath fragCP : getFragmentClasspaths()) { - for (ClasspathEntry cpEntry : fragCP.getEntries()) { - URL url = cpEntry.findResource(resource, m, classPathIndex); + findLocalResources(resource, fragCP.getEntries(), m, classPathIndex, resources); + } + + if (resources.size() > 0) + return Collections.enumeration(resources); + return EMPTY_ENUMERATION; + } + + private void findLocalResources(String resource, ClasspathEntry[] cpEntries, Module m, int[] classPathIndex, List resources) { + for (ClasspathEntry cpEntry : cpEntries) { + if (cpEntry != null) { + URL url = cpEntry.findResource(resource, m, classPathIndex[0]); if (url != null) { resources.add(url); } - classPathIndex++; } + classPathIndex[0]++; } - if (resources.size() > 0) - return Collections.enumeration(resources); - return EMPTY_ENUMERATION; } /** @@ -445,29 +475,48 @@ public class ClasspathManager { */ public BundleEntry findLocalEntry(String path, int classPathIndex) { BundleEntry result = null; - int curIndex = 0; - for (int i = 0; i < entries.length; i++) { - if (entries[i] != null) { - result = entries[i].findEntry(path); - if (result != null && (classPathIndex == -1 || classPathIndex == curIndex)) - return result; + int[] curIndex = {0}; + + // look in hook specific entries if any + for (ClassLoaderHook hook : hookRegistry.getClassLoaderHooks()) { + ClasspathEntry[] hookEntries = hook.getClassPathEntries(path, this); + if (hookEntries != null) { + return findLocalEntry(path, hookEntries, classPathIndex, curIndex); } - curIndex++; } - // look in fragments - FragmentClasspath[] currentFragments = getFragmentClasspaths(); - for (int i = 0; i < currentFragments.length; i++) { - ClasspathEntry[] fragEntries = currentFragments[i].getEntries(); - for (int j = 0; j < fragEntries.length; j++) { - result = fragEntries[j].findEntry(path); - if (result != null && (classPathIndex == -1 || classPathIndex == curIndex)) - return result; - curIndex++; + + curIndex[0] = 0; + // look in classpath entries + result = findLocalEntry(path, entries, classPathIndex, curIndex); + if (result != null) { + return result; + } + + // look in fragment entries + for (FragmentClasspath fragCP : getFragmentClasspaths()) { + result = findLocalEntry(path, fragCP.getEntries(), classPathIndex, curIndex); + if (result != null) { + return result; } } + return null; } + private BundleEntry findLocalEntry(String path, ClasspathEntry[] cpEntries, int classPathIndex, int[] curIndex) { + BundleEntry result = null; + for (ClasspathEntry cpEntry : cpEntries) { + if (cpEntry != null) { + result = cpEntry.findEntry(path); + if (result != null && (classPathIndex == -1 || classPathIndex == curIndex[0])) { + return result; + } + } + curIndex[0]++; + } + return result; + } + /** * Finds a local class by searching the ClasspathEntry objects of the classpath manager. * This method will first call all the configured class loader hooks @@ -508,27 +557,46 @@ public class ClasspathManager { } private Class findLocalClassImpl(String classname, List hooks) throws ClassNotFoundException { - Class result = null; - for (int i = 0; i < entries.length; i++) { - if (entries[i] != null) { - result = findClassImpl(classname, entries[i], hooks); - if (result != null) - return result; + Class result; + + // look in hook specific entries if any + for (ClassLoaderHook hook : hookRegistry.getClassLoaderHooks()) { + ClasspathEntry[] hookEntries = hook.getClassPathEntries(classname, this); + if (hookEntries != null) { + return findLocalClassImpl(classname, hookEntries, hooks); } } - // look in fragments. - FragmentClasspath[] currentFragments = getFragmentClasspaths(); - for (int i = 0; i < currentFragments.length; i++) { - ClasspathEntry[] fragEntries = currentFragments[i].getEntries(); - for (int j = 0; j < fragEntries.length; j++) { - result = findClassImpl(classname, fragEntries[j], hooks); - if (result != null) - return result; + + // look in classpath entries + result = findLocalClassImpl(classname, entries, hooks); + if (result != null) { + return result; + } + + // look in fragment entries + for (FragmentClasspath fragCP : getFragmentClasspaths()) { + result = findLocalClassImpl(classname, fragCP.getEntries(), hooks); + if (result != null) { + return result; } } + throw new ClassNotFoundException(classname); } + private Class findLocalClassImpl(String classname, ClasspathEntry[] cpEntries, List hooks) { + Class result; + for (ClasspathEntry cpEntry : cpEntries) { + if (cpEntry != null) { + result = findClassImpl(classname, cpEntry, hooks); + if (result != null) { + return result; + } + } + } + return null; + } + private Class findClassImpl(String name, ClasspathEntry classpathEntry, List hooks) { if (debug.DEBUG_LOADER) Debug.println("ModuleClassLoader[" + classloader.getBundleLoader() + " - " + classpathEntry.getBundleFile() + "].findClassImpl(" + name + ")"); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ @@ -805,6 +873,17 @@ public class ClasspathManager { public Collection listLocalResources(String path, String filePattern, int options) { List bundleFiles = new ArrayList<>(); + // look for path first in hook specific entries if any + for (ClassLoaderHook hook : hookRegistry.getClassLoaderHooks()) { + ClasspathEntry[] hookEntries = hook.getClassPathEntries(path, this); + if (hookEntries != null) { + for (ClasspathEntry cpEntry : hookEntries) { + cpEntry.addBundleFiles(bundleFiles); + } + return Storage.listEntryPaths(bundleFiles, path, filePattern, options); + } + } + ClasspathEntry[] cpEntries = getHostClasspathEntries(); for (ClasspathEntry cpEntry : cpEntries) { cpEntry.addBundleFiles(bundleFiles); -- cgit v1.2.3