3 Replies Latest reply on May 15, 2010 12:08 AM by thomas.diesler

    Support for dynamic imports with wildcards

    thomas.diesler

      Relates to

       

      https://jira.jboss.org/jira/browse/JBOSGI-323

      https://jira.jboss.org/jira/browse/JBCL-131

       

      I added a ClassNotFoundHandler to the OSGiClassLoaderPolicy which kicks in if the policy has a PackageRequirement defined that is dynamic, uses wildcards and matches the requested resource.

       

                  // Iterate over the package requirements and check if
                  // the requested class matches any of the filters
                  for (Requirement req : osgiModule.getRequirements())
                  {
                     if (req instanceof PackageRequirement)
                     {
                        PackageRequirement preq = (PackageRequirement)req;
                        if (preq.isDynamic() && preq.isWildcard())
                        {
                           ClassFilter filter = preq.toClassFilter();
                           if (filter.matchesPackageName(packageName))
                           {
                              matchingReq = preq;
                              break;
                           }
                        }
                     }
                  }
                  
                  if (matchingReq == null)
                     return false;
      
      

       

      If there is a matching requirement the hander iterates over all INSTALLED, RESOLVED, ACTIVE bundles to find a potential exporter for the class that could not be loaded. If an exporter could be found, the handler creates a LoaderDelegate and adds it to list of delegates defined on the policy.

       

                     DeploymentUnit unit = depBundle.getDeploymentUnit();
                     OSGiModule module = (OSGiModule)unit.getAttachment(Module.class);
                     OSGiClassLoaderPolicy policy = (OSGiClassLoaderPolicy)module.getPolicy();
                     FilteredDelegateLoader delegate = new FilteredDelegateLoader(policy, matchingReq.toClassFilter());
                     delegate.setImportType(ImportType.AFTER);
                     
                     if (delegate.getResource(resourceName) != null)
                     {
                        List<DelegateLoader> delegates = (List<DelegateLoader>)getDelegates();
                        if (delegates == null)
                        {
                           delegates = new CopyOnWriteArrayList<DelegateLoader>();
                           setDelegates(delegates);
                        }
                        delegates.add(delegate);
                        return true;
                     }
      

       

      Additionally I added code to the BaseClassLoaderDomain that finds the loader that the handler had just added.

       

            // Process potential delegates that were added lazily to the policy
            // This could for example be done in a {@link ClassNotFoundHandler}
            List<? extends DelegateLoader> policyDelegates = info.getPolicy().getDelegates();
            if (policyDelegates != null && policyDelegates.isEmpty() == false)
            {
               for (DelegateLoader delegate : policyDelegates)
               {
                  if (delegates.contains(delegate) || delegate.getImportType() != type)
                     continue;
                  
                  if (trace)
                     log.trace(this + " trying to load " + name + " from delegate added lazily to policy " + delegate + " for " + info.getClassLoader());
                  
                  if (delegate.getResource(name) != null)
                  {
                     info.cacheLoader(name, delegate);
                     return delegate;
                  }
               }
            }
      

       

      Have a look at this changeset http://fisheye.jboss.org/changelog/JBossAS/projects/jboss-cl/branches/tdi/jbosgi323?cs=104780

      which I havn't merged to trunk yet.

       

      This approach fixes all DynamicImport-Package test cases that we have in the framework both for explicit and wildcard packages.

       

      However I believe, this is somewhat of a hack and should be done differently to maintain consistency for module dependencies. The exporter for a DynamicImport-Package should probably be added to the list of dependencies like an exporter for any other ImportPackage. Only that this can happen after the Module is already resolved.

       

      The additional code in BaseClassLoaderDomain was needed because ClassLoaderInformation that it works of is not accessible for clients. The general question is, what should a ClassNotFoundHandler do to make loadClass succeed? AFAICS, it must modify or replace the ClassLoaderInformation somehow, but I could not figure out how that would be done.

        • 1. Re: Support for dynamic imports with wildcards
          alesj

          Your impl depends on too much impl details.

          And modifying the delegates at runtime is not the right way to go.

           

          The information where you build your delegates is static; e.g. it's all already in your manifest / metadata.

          So there is no need for dynamic modification of delegates.

          It should be the wildcard delegate that knows how to handle this.

           

          And above all, I don't know why you hacked this, as I though we agreed I have a look at this.

          Which I already did -- it's all implemented in CL trunk.

           

          There could definitely be some issues the way I did it (just about to describe it in MC dev forum),

          so feel free to disclose them on MC dev forum.

          • 2. Re: Support for dynamic imports with wildcards
            alesj
            Which I already did -- it's all implemented in CL trunk.

            * https://community.jboss.org/message/543069#543069

            • 3. Re: Support for dynamic imports with wildcards
              thomas.diesler

              With the current jboss-cl/trunk I see these failures when I disable the ClassNotFoundHandler

               

              Failed tests:
                testDynamicImportWithWildcard(org.jboss.test.osgi.core.jbosgi323.OSGi323TestCase)
                testAllPackagesWildcard(org.jboss.test.osgi.classloader.DynamicImportPackageTestCase)
                testAllPackagesWildcardNotWired(org.jboss.test.osgi.classloader.DynamicImportPackageTestCase)
                testPackageWildcardWired(org.jboss.test.osgi.classloader.DynamicImportPackageTestCase)
                testPackageWildcardNotWired(org.jboss.test.osgi.classloader.DynamicImportPackageTestCase)

               

              Did you try your approach against the framework testsuite?

               

              I'll try to dig into it and post here: https://community.jboss.org/message/543069