Class ClassPathUtil


  • public class ClassPathUtil
    extends Object
    Utilities to perform bundle scanning - using only OSGi Core APIs (without using e.g., XBean Finder)
    Author:
    achim
    • Method Summary

      All Methods Static Methods Concrete Methods Deprecated Methods 
      Modifier and Type Method Description
      static List<URL> findEntries​(ClassLoader loader, String path, String pattern, boolean recurse)
      This method matches Bundle.findEntries(String, String, boolean) but should be used when we don't have access to any Bundle.
      static List<URL> findEntries​(Iterable<org.osgi.framework.Bundle> bundles, String path, String pattern, boolean recurse, boolean useBundleClasspath)
      This method uses BundleWiring.findEntries(java.lang.String, java.lang.String, int) that doesn't involve classloaders so we can get resources from fixed path.
      static List<URL> findEntries​(org.osgi.framework.Bundle bundle, String path, String pattern, boolean recurse, boolean useBundleClasspath)
      This method uses BundleWiring.findEntries(java.lang.String, java.lang.String, int) that doesn't involve classloaders so we can get resources from fixed path.
      static List<URL> findEntries​(org.osgi.framework.Bundle bundle, URL[] roots, String path, String pattern, boolean recurse)
      Third findEntries() method - this one starts with an array of roots (which are for example JARs from Bundle-ClassPath, but may be other "roots".
      static Set<org.osgi.framework.Bundle> getBundlesInClassSpace​(org.osgi.framework.Bundle bundle, Set<org.osgi.framework.Bundle> bundleSet, boolean recurse)
      Gets a list of bundles that are: imported by given bundle required by given bundle attached as fragments to given bundle extended by given bundle
      static URL[] getClassPathJars​(org.osgi.framework.Bundle bundle)
      static URL[] getClassPathJars​(org.osgi.framework.Bundle bundle, boolean useClassSpace)
      Returns a list of urls for jars that compose the Bundle-ClassPath and (with useClassSpace = true) also a list of different URLs for bundles in class space (which includes bundles for imported packages, fragments, wires of fragments and required bundles).
      static URL[] getClassPathNonJars​(org.osgi.framework.Bundle bundle)
      Returns a list of urls for all non-JAR entries that compose the Bundle-ClassPath.
      static URL[] getClassPathURLs​(org.osgi.framework.Bundle bundle)
      Returns a list of urls for all entries that compose the Bundle-ClassPath.
      static List<URL> getResources​(Iterable<org.osgi.framework.Bundle> bundles, String path)
      This method uses Bundle.getResources(String) that delegates to classloader.
      static URL[] getURLs​(ClassLoader loader)
      Helper method to get ClassLoaders URLs (if possible)
      static boolean jarClassPathEntryExists​(URL root)
      Checks whether jar: location exists as proper classpath element
      static URL[] jarToItsClassPath​(URL url)
      Used in tests, when there's only surefire on the classpath
      static List<URL> listResources​(Iterable<org.osgi.framework.Bundle> bundles, String path, String pattern, boolean recurse)
      This method uses BundleWiring.listResources(java.lang.String, java.lang.String, int) that delegates to classloader.
    • Method Detail

      • getClassPathJars

        public static URL[] getClassPathJars​(org.osgi.framework.Bundle bundle,
                                             boolean useClassSpace)

        Returns a list of urls for jars that compose the Bundle-ClassPath and (with useClassSpace = true) also a list of different URLs for bundles in class space (which includes bundles for imported packages, fragments, wires of fragments and required bundles).

        This method doesn't return the URL of passed bundle itself.

        Parameters:
        bundle - the bundle from which the class path should be taken
        useClassSpace - wheter to add also bundles reachable via different wires (required bundles, imported packages and fragments)
        Returns:
        list or urls to jars that composes the Bundle-ClassPath. Each JAR is returned as URL in the form jar:<location>!/, where <location> may be for example bundle://30.0:0/WEB-INF/lib/myfaces-impl-2.2.12.jar
      • getClassPathURLs

        public static URL[] getClassPathURLs​(org.osgi.framework.Bundle bundle)

        Returns a list of urls for all entries that compose the Bundle-ClassPath.

        Parameters:
        bundle -
        Returns:
      • getClassPathNonJars

        public static URL[] getClassPathNonJars​(org.osgi.framework.Bundle bundle)

        Returns a list of urls for all non-JAR entries that compose the Bundle-ClassPath.

        Parameters:
        bundle -
        Returns:
      • getClassPathJars

        @Deprecated
        public static URL[] getClassPathJars​(org.osgi.framework.Bundle bundle)
        Returns a list of urls to jars that composes the Bundle-ClassPath and also a list of different URLs for bundles in class space (which includes bundles for imported packages, fragments, wires of fragments and required bundles)
        Parameters:
        bundle - the bundle from which the class path should be taken
        Returns:
        list or urls to jars that composes the Bundle-ClassPath.
      • getBundlesInClassSpace

        public static Set<org.osgi.framework.Bundle> getBundlesInClassSpace​(org.osgi.framework.Bundle bundle,
                                                                            Set<org.osgi.framework.Bundle> bundleSet,
                                                                            boolean recurse)

        Gets a list of bundles that are:

        • imported by given bundle
        • required by given bundle
        • attached as fragments to given bundle
        • extended by given bundle

        Parameters:
        bundle -
        bundleSet -
        recurse - whether to use only 1st level dependencies of given bundle (recurse=false) or collect entire transitive closure (recurse=true)
        Returns:
      • listResources

        public static List<URL> listResources​(Iterable<org.osgi.framework.Bundle> bundles,
                                              String path,
                                              String pattern,
                                              boolean recurse)

        This method uses BundleWiring.listResources(java.lang.String, java.lang.String, int) that delegates to classloader. If there are more visible resources with the same name, only one is returned.

        This method is not a good choice to discover manifests or e.g., faces-context.xml files, if for single bundle many resources with the same path may be returned (as in case of WAR with Bundle-ClassPath or with fragments).

        This method is also not good choice to get /META-INF/services/* files, as these should be accessed using classloaders - a Bundle may have multiple entries on its Bundle-ClassPath, so such service descriptors should be loaded from all the roots.

        Parameters:
        bundles -
        path -
        pattern -
        recurse -
        Returns:
      • getResources

        public static List<URL> getResources​(Iterable<org.osgi.framework.Bundle> bundles,
                                             String path)

        This method uses Bundle.getResources(String) that delegates to classloader. If there are more visible resources with the same name, all are returned (differently than with listResources(java.lang.Iterable<org.osgi.framework.Bundle>, java.lang.String, java.lang.String, boolean)).

        This method is the only choice to load resources using classloaders (respecting Bundle-ClassPath), and checking attached bundle fragments, but the problem is that it doesn't allow to use patterns.

        The important thing to note is that if the bundle is in INSTALLED state, there'll be an attempt to resolve it.

        Parameters:
        bundles -
        path -
        Returns:
      • findEntries

        public static List<URL> findEntries​(org.osgi.framework.Bundle bundle,
                                            String path,
                                            String pattern,
                                            boolean recurse,
                                            boolean useBundleClasspath)
                                     throws IOException
        This method uses BundleWiring.findEntries(java.lang.String, java.lang.String, int) that doesn't involve classloaders so we can get resources from fixed path. This way we can find multiple resources with the same path (when for example a bundle has attached fragment, which has the same entries). Normally BundleWiring.findEntries(java.lang.String, java.lang.String, int) doesn't check JARs listed on Bundle-ClassPath (because it doesn't work at classloader level), however we can explicitly tell it to do so.
        Parameters:
        bundle -
        path -
        pattern -
        recurse -
        useBundleClasspath -
        Returns:
        Throws:
        IOException
      • findEntries

        public static List<URL> findEntries​(Iterable<org.osgi.framework.Bundle> bundles,
                                            String path,
                                            String pattern,
                                            boolean recurse,
                                            boolean useBundleClasspath)
                                     throws IOException
        This method uses BundleWiring.findEntries(java.lang.String, java.lang.String, int) that doesn't involve classloaders so we can get resources from fixed path. This way we can find multiple resources with the same path (when for example a bundle has attached fragment, which has the same entries). Normally BundleWiring.findEntries(java.lang.String, java.lang.String, int) doesn't check JARs listed on Bundle-ClassPath (because it doesn't work at classloader level), however we can explicitly tell it to do so.
        Parameters:
        bundles -
        path -
        pattern -
        recurse -
        useBundleClasspath - additionally search the JARs on Bundle-ClassPath
        Returns:
        Throws:
        IOException
      • getURLs

        public static URL[] getURLs​(ClassLoader loader)
        Helper method to get ClassLoaders URLs (if possible)
        Parameters:
        loader -
        Returns:
      • findEntries

        public static List<URL> findEntries​(ClassLoader loader,
                                            String path,
                                            String pattern,
                                            boolean recurse)
                                     throws IOException

        This method matches Bundle.findEntries(String, String, boolean) but should be used when we don't have access to any Bundle. It is used as a fallback in some resource-finding methods when FrameworkUtil.getBundle(Class) doesn't return anything (which may be a case in unit tests).

        This method is inspired by Spring's org.springframework.core.io.support.PathMatchingResourcePatternResolver#doFindAllClassPathResources() where the most important problem of "" resource base was cleverly solved. Though we won't traverse up the classloader parents and we won't check ClassLoader.getSystemResources(String).

        Spring's org.springframework.core.io.support.PathMatchingResourcePatternResolver#getResources() allows passing argument like classpath*:/META-INF/** /*.tld (ANT-style), however org.springframework.util.AntPathMatcher#doMatch() is a bit complicated and very different from Bundle.findEntries(String, String, boolean), so we'll just test the entry for:

        • begins with path
        • ends (or matches) pattern, where the patterns is simple glob (* and ? supported).
        • /META-INF/tlds/my.tld should NOT match when path=/META-INF/tlds and pattern=tlds/*.tld

        Parameters:
        loader -
        path - never a pattern. Should indicate the base used for relative path searching and is always treated as base directory
        pattern - file pattern (only for matching last path segment == no slashes) to match. If this pattern is null, we assume * which means directory listing in the base path
        recurse - whether we should look at any depth or only within path
        Returns:
        Throws:
        IOException
      • jarToItsClassPath

        public static URL[] jarToItsClassPath​(URL url)
                                       throws IOException
        Used in tests, when there's only surefire on the classpath
        Parameters:
        url -
        Returns:
        Throws:
        IOException
      • findEntries

        public static List<URL> findEntries​(org.osgi.framework.Bundle bundle,
                                            URL[] roots,
                                            String path,
                                            String pattern,
                                            boolean recurse)
                                     throws IOException
        Third findEntries() method - this one starts with an array of roots (which are for example JARs from Bundle-ClassPath, but may be other "roots".
        Parameters:
        bundle - the bundle from where the roots come from. It's needed if extracting a directory entry from a bundle
        roots - URLs that should end with "/" (jar: URLs should end with "!/")
        path -
        pattern -
        recurse -
        Returns:
        Throws:
        IOException
      • jarClassPathEntryExists

        public static boolean jarClassPathEntryExists​(URL root)
        Checks whether jar: location exists as proper classpath element
        Parameters:
        root -
        Returns: