1 2 3 Previous Next 32 Replies Latest reply on Jun 14, 2010 8:13 AM by alesj

    Wildcard support in Dynamic-imports

    alesj

      I've implemented an initial version of wildcard support.

      e.g. Dynamic-import: com.acme.foo.*

       

      When creating lazy delegate in Module (which we do for all dynamic requirements),

      we differentiate between wildcards and plain dynamic import.

       

               if (pr.isWildcard())
               {
                  ClassLoaderPolicyFactory factory = new WildcardClassLoaderPolicyFactory(domain, item);
                  return new WildcardDelegateLoader(factory, filter);
               }

       

      Our wildcard policy tracks potential matching modules via ModuleRegistry notion from ClassLoading instance.

      Hence wildcard factory registers the policy as a listener.

       

         public ClassLoaderPolicy createClassLoaderPolicy()
         {
            WildcardClassLoaderPolicy policy = new WildcardClassLoaderPolicy(domain, requirement, module);
            ClassLoading classLoading = domain.getClassLoading();
            classLoading.addModuleRegistry(policy); // so we know when to reset on module change
            return policy;
         }

       

      What our wildcard policy does is actually delegation to other existing matching modules.

       

         public URL getResource(String path)
         {
            Module cached = resourceCache.get(path);
            if (cached != null)
               return cached.getResource(path);
      
            ClassFilter filter = requirement.toClassFilter();
            if (filter.matchesResourcePath(path))
            {
               for (Module m : modules)
               {
                  URL url = m.getResource(path);
                  if (url != null)
                  {
                     resourceCache.put(path, m);
                     used.add(m);
                     return url;
                  }
               }
            }
            return null;
         }
      

       

      "modules" list gets populated via tracking, where we only include potential matching modules.

       

         public void addModule(Module module)
         {
            Domain md = getDomain(module);
            if (md != null && module.canResolve(requirement))
            {
               boolean isAncestor = (domain != md); // not the same domain, so it must be ancestor
               synchronized (this)
               {
                  if (isAncestor)
                  {
                     if (domain.isParentFirst())
                     {
                        modules.add(0, module);
                        parentsBefore++;
                     }
                     else
                        modules.add(module);
                  }
                  else
                     modules.add(parentsBefore, module);
               }
      
               reset();
            }
         }
      

       

      Same on removal, where we also try to bounce our module if we see that some module we used went away.

      We also remove ourselves from module listening when undeploying.

       

         public void removeModule(Module module)
         {
            synchronized (this)
            {
               if (modules.remove(module))
               {
                  Domain md = getDomain(module);
                  boolean isAncestor = (domain != md);
                  if (isAncestor && domain.isParentFirst())
                     parentsBefore--;
      
                  reset();
               }
            }
      
            boolean sameModule = this.module == module;
      
            // Unregister this policy as module listener
            if (sameModule)
            {
               ClassLoading classLoading = domain.getClassLoading();
               classLoading.removeModuleRegistry(this);
               this.module = null;
            }
      
            // It's not us (we're already uninstalling) and we used this, let's bounce.
            if (used.remove(module) && sameModule == false)
            {
               LifeCycle lifeCycle = this.module.getLifeCycle();
               if (lifeCycle != null && module.isCascadeShutdown() == false)
               {
                  try
                  {
                     lifeCycle.bounce();
                  }
                  catch (Exception e)
                  {
                     throw new IllegalArgumentException("Error bouncing module: " + this.module);
                  }
               }
            }
         }
      

       

      Then comes the tricky part. :-)

      Since the policy is mostly just used to find the matching resource, where its underlying classloader should do the real loading.

      But in our case where we delegate all of the things, this needed some hacking into existing code.

       

      To find the right ClassLoader I hacked BaseDelegateLoader's getBaseClassLoader method to protected (don't see why it should really be pckg protected), and then overriden it in WildcardDelegateLoader.

       

         protected BaseClassLoader getBaseClassLoader(String message, String context)
         {
            ClassLoaderPolicy policy = getPolicy();
            if (policy instanceof WildcardClassLoaderPolicy == false)
               throw new IllegalArgumentException("Can only handle wildcard policy: " + policy);
      
            WildcardClassLoaderPolicy wclp = (WildcardClassLoaderPolicy) policy;
            return wclp.getBaseClassLoader(context);
         }
      

       

      Which then delegates to the policy with additional context parameter -- which is really the path of the requested resource.

       

         BaseClassLoader getBaseClassLoader(String context)
         {
            Module m = findModule(context);
            if (m != null)
            {
               ClassLoader cl = ClassLoading.getClassLoaderForModule(m);
               if (cl instanceof BaseClassLoader)
                  return BaseClassLoader.class.cast(cl);
            }
            return null;
         }

       

      But the changes don't stop there, as the ClassLoadingManager/Task also asume there is a single matching classloader.

      So, I introduced a new protected method on BaseClassLoaderPolicy.

       

         /**
          * Get the classloader based on classloading task.
          *
          * Since ClassLoadingTask ctor is package protected
          * this method cannot be easily abused, since the only
          * code that can instantiate ClassLoadingTask is our ClassLoaderManager.
          *
          * @param task the classloading task info
          * @return the classloader
          */
         protected synchronized BaseClassLoader getClassLoader(ClassLoadingTask task)
         {
            return getClassLoader();
         }

       

      Which is then overriden in wildcard policy.

       

         protected BaseClassLoader getClassLoader(ClassLoadingTask task)
         {
            if (task == null)
               throw new IllegalArgumentException("Null task");
      
            String path = ClassLoaderUtils.classNameToPath(task.getClassName());
            return getBaseClassLoader(path);
         }
      
        • 1. Re: Wildcard support in Dynamic-imports
          thomas.diesler

          This approach causes these tests to fail

           

          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)

           

          AFAICS, the module tracking only works when the exporting module gets installed *after* the importing module has its policy setup.

          The WildcardClassLoaderPolicy should probably also scan allready existing modules when it is setup. More generally, perhaps a ModuleTracker that works simmilar to BundleTracker is needed.

           

          Even then, addModule

           

          public void addModule(Module current)
             {
                Domain md = getDomain(current);
                if (md != null && current.canResolve(requirement))
                {
                ...
                }
          
          

           

          will not add the exporting module because Module.canResolve(req) would not return 'true' for DynamicImport-Package: *

          • 2. Re: Wildcard support in Dynamic-imports
            thomas.diesler

            I fixed the module tracking issue

             

                  // Add the modules that can resolve the requirement
                  for (Module aux : domain.getModules(null, null))
                  {
                     // The wildcard policy should not load from this module
                     if (aux == module)
                        continue;
                     
                     // Add the module if it can resolve the requirement
                     if (aux.canResolve(requirement))
                        modules.add(aux);
                  }
            

             

            and the capability resolve issue. I now see

             

            2010-05-15 08:31:19,327 WARN  [org.jboss.detailed.classloader.ClassLoaderManager] Unexpected error during load of:org.jboss.test.osgi.classloader.support.a.A
            java.lang.IllegalStateException: No classloader for this module OSGiModule dynamic-wildcard-c:0.0.0
                at org.jboss.classloading.spi.dependency.Module.getResource(Module.java:587)
                at org.jboss.classloading.spi.dependency.policy.WildcardClassLoaderPolicy.findModule(WildcardClassLoaderPolicy.java:113)
                at org.jboss.classloading.spi.dependency.policy.WildcardClassLoaderPolicy.getBaseClassLoader(WildcardClassLoaderPolicy.java:289)
                at org.jboss.classloading.spi.dependency.policy.WildcardDelegateLoader.getBaseClassLoader(WildcardDelegateLoader.java:51)
                at org.jboss.classloader.spi.base.BaseDelegateLoader.getPackage(BaseDelegateLoader.java:160)
                at org.jboss.classloader.spi.filter.FilteredDelegateLoader.getPackage(FilteredDelegateLoader.java:173)
                at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackageFromImports(BaseClassLoaderDomain.java:1014)
                at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackage(BaseClassLoaderDomain.java:590)
                at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackage(BaseClassLoaderDomain.java:1218)
                at org.jboss.classloader.spi.base.BaseClassLoader.getPackage(BaseClassLoader.java:262)
                at org.jboss.classloader.spi.base.BaseClassLoader.definePackage(BaseClassLoader.java:806)
                at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:645)
                at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:609)
                at java.security.AccessController.doPrivileged(Native Method)
                at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:608)
                at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:585)
                at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:138)
                at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:461)
                at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:262)
                at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:161)
                at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:262)
                at org.jboss.osgi.framework.classloading.OSGiClassLoaderDomain.loadClass(OSGiClassLoaderDomain.java:55)
                at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1164)
                at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:883)
                at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassLoader.java:505)
                at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:450)
                at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
                at org.jboss.osgi.framework.bundle.OSGiBundleState.loadClass(OSGiBundleState.java:145)
                at org.jboss.osgi.framework.bundle.OSGiBundleWrapper.loadClass(OSGiBundleWrapper.java:171)
                at org.jboss.osgi.testing.OSGiTestHelper.assertLoadClass(OSGiTestHelper.java:278)
                at org.jboss.osgi.testing.OSGiTest.assertLoadClass(OSGiTest.java:213)
                at org.jboss.osgi.testing.OSGiFrameworkTest.assertLoadClass(OSGiFrameworkTest.java:193)
                at org.jboss.test.osgi.classloader.DynamicImportPackageTestCase.testAllPackagesWildcardNotWired(DynamicImportPackageTestCase.java:195)
            
            

             

            This seems to be caused by an issue that the exporting bundle is not RESOLVED. The BaseClassLoaderDomain can find the resource, but when it comes to the actual load the module has no ClassLoader associated. In OSGi a call to Bundle.loadClass() triggers bundle resolution for the exporting module.

             

            How can we assure that the module transistions to CLASSLOADER stage after the resource was found, but before the class is loaded. Perhaps that should be done in WildcardClassLoaderPolicy when a resource is found in an unresolved module.

            • 3. Re: Wildcard support in Dynamic-imports
              thomas.diesler

              I worked arround this issue by attempting to resolve all installed bundles on Bundle.loadClass()

               

              http://github.com/jbosgi/jbosgi-framework/commit/836b70511956b7d9e66bb780f464b3acc934725a

               

              The general issue at the MC layer still remains

              • 4. Re: Wildcard support in Dynamic-imports
                alesj
                AFAICS, the module tracking only works when the exporting module gets installed *after* the importing module has its policy setup.

                The WildcardClassLoaderPolicy should probably also scan allready existing modules when it is setup. More generally, perhaps a ModuleTracker that works simmilar to BundleTracker is needed.

                Yes, forgot about that, I'll add that, properly.

                Even then, addModule

                 

                public void addModule(Module current)
                   {
                      Domain md = getDomain(current);
                      if (md != null && current.canResolve(requirement))
                      {
                      ...
                      }
                 
                

                 

                will not add the exporting module because Module.canResolve(req) would not return 'true' for DynamicImport-Package: *

                Why is that?

                • 5. Re: Wildcard support in Dynamic-imports
                  alesj
                  I fixed the module tracking issue

                   

                        // Add the modules that can resolve the requirement
                        for (Module aux : domain.getModules(null, null))
                        {
                           // The wildcard policy should not load from this module
                           if (aux == module)
                              continue;
                           
                           // Add the module if it can resolve the requirement
                           if (aux.canResolve(requirement))
                              modules.add(aux);
                        }
                  

                   

                  and the capability resolve issue.

                  This is not done right, as you're not taking parent order into account.

                  And the capability issue is a hack, hence it will be removed -- module needs a name.

                  2010-05-15 08:31:19,327 WARN  [org.jboss.detailed.classloader.ClassLoaderManager] Unexpected error during load of:org.jboss.test.osgi.classloader.support.a.A java.lang.IllegalStateException: No classloader for this module OSGiModule dynamic-wildcard-c:0.0.0     at org.jboss.classloading.spi.dependency.Module.getResource(Module.java:587)     at org.jboss.classloading.spi.dependency.policy.WildcardClassLoaderPolicy.findModule(WildcardClassLoaderPolicy.java:113)     at org.jboss.classloading.spi.dependency.policy.WildcardClassLoaderPolicy.getBaseClassLoader(WildcardClassLoaderPolicy.java:289)     at org.jboss.classloading.spi.dependency.policy.WildcardDelegateLoader.getBaseClassLoader(WildcardDelegateLoader.java:51)     at org.jboss.classloader.spi.base.BaseDelegateLoader.getPackage(BaseDelegateLoader.java:160)     at org.jboss.classloader.spi.filter.FilteredDelegateLoader.getPackage(FilteredDelegateLoader.java:173)     at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackageFromImports(BaseClassLoaderDomain.java:1014)     at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackage(BaseClassLoaderDomain.java:590)     at org.jboss.classloader.spi.base.BaseClassLoaderDomain.getPackage(BaseClassLoaderDomain.java:1218)     at org.jboss.classloader.spi.base.BaseClassLoader.getPackage(BaseClassLoader.java:262)     at org.jboss.classloader.spi.base.BaseClassLoader.definePackage(BaseClassLoader.java:806)     at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:645)     at org.jboss.classloader.spi.base.BaseClassLoader$2.run(BaseClassLoader.java:609)     at java.security.AccessController.doPrivileged(Native Method)     at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:608)     at org.jboss.classloader.spi.base.BaseClassLoader.loadClassLocally(BaseClassLoader.java:585)     at org.jboss.classloader.spi.base.BaseDelegateLoader.loadClass(BaseDelegateLoader.java:138)     at org.jboss.classloader.spi.base.ClassLoadingTask$ThreadTask.run(ClassLoadingTask.java:461)     at org.jboss.classloader.spi.base.ClassLoaderManager.nextTask(ClassLoaderManager.java:262)     at org.jboss.classloader.spi.base.ClassLoaderManager.process(ClassLoaderManager.java:161)     at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:262)     at org.jboss.osgi.framework.classloading.OSGiClassLoaderDomain.loadClass(OSGiClassLoaderDomain.java:55)     at org.jboss.classloader.spi.base.BaseClassLoaderDomain.loadClass(BaseClassLoaderDomain.java:1164)     at org.jboss.classloader.spi.base.BaseClassLoader.loadClassFromDomain(BaseClassLoader.java:883)     at org.jboss.classloader.spi.base.BaseClassLoader.doLoadClass(BaseClassLoader.java:505)     at org.jboss.classloader.spi.base.BaseClassLoader.loadClass(BaseClassLoader.java:450)     at java.lang.ClassLoader.loadClass(ClassLoader.java:248)     at org.jboss.osgi.framework.bundle.OSGiBundleState.loadClass(OSGiBundleState.java:145)     at org.jboss.osgi.framework.bundle.OSGiBundleWrapper.loadClass(OSGiBundleWrapper.java:171)     at org.jboss.osgi.testing.OSGiTestHelper.assertLoadClass(OSGiTestHelper.java:278)     at org.jboss.osgi.testing.OSGiTest.assertLoadClass(OSGiTest.java:213)     at org.jboss.osgi.testing.OSGiFrameworkTest.assertLoadClass(OSGiFrameworkTest.java:193)     at org.jboss.test.osgi.classloader.DynamicImportPackageTestCase.testAllPackagesWildcardNotWired(DynamicImportPackageTestCase.java:195)

                   

                  This seems to be caused by an issue that the exporting bundle is not RESOLVED. The BaseClassLoaderDomain can find the resource, but when it comes to the actual load the module has no ClassLoader associated. In OSGi a call to Bundle.loadClass() triggers bundle resolution for the exporting module.

                   

                  How can we assure that the module transistions to CLASSLOADER stage after the resource was found, but before the class is loaded. Perhaps that should be done in WildcardClassLoaderPolicy when a resource is found in an unresolved module.

                  I'll add an extra check whether the Module is actually capabale of loading the class.

                  • 6. Re: Wildcard support in Dynamic-imports
                    alesj
                    This is not done right, as you're not taking parent order into account.

                    The way I did it now is also not done right, but it should do for simple domain hierarchy.

                    I'll think about it some more on how to make it right.

                    • 7. Re: Wildcard support in Dynamic-imports
                      alesj
                      I'll add an extra check whether the Module is actually capabale of loading the class.

                      I'm checking if the module's classloader is already available:

                       

                         protected boolean isResolved(Module m)
                         {
                            ClassLoader cl = ClassLoading.getClassLoaderForModule(m);
                            return cl != null;
                         }
                      • 8. Re: Wildcard support in Dynamic-imports
                        alesj
                        I'm checking if the module's classloader is already available:
                           protected boolean isResolved(Module m)
                           {
                              ClassLoader cl = ClassLoading.getClassLoaderForModule(m);
                              return cl != null;
                           }
                        

                        This needed changing, since GC shutdown based modules should still be able to load classes / resources,

                        but they cleanup their classloader, hence a separate weak value classloader cache is maintained.

                        • 9. Re: Wildcard support in Dynamic-imports
                          warjort

                          You seem to have realized part of the problem, in that the existing stuff assumed

                          one requirement -- one dependency -- one import delegate

                           

                          But you haven't relaxed either restriction to work properly.

                           

                          If you had, the "lazy resolve" feature would have solved the issue with the dependee not moving

                          from the DESCRIBED stage to the CLASSLOADER stage, when it did Module.resolve()

                           

                          Instead you've bypassed the resolution process and gone straight for Module.getResource() which is not correct.

                          I'd also guess the way you are delegating to the classloader might be confusing something in the caching mechanism

                          when using imports? - look at how the ClassLoaderInformation works when doing imports

                           

                          The way it should work is that a dynamic import should allow for the number of classloading delegates

                          and MC dependencies of a requirement to be added to dynamically.

                          You need at least the second part to solve the wildcard for optional imports as well.

                           

                          Somthing like:

                           

                          1) Allow a Requirement to have multiple RequirementDependencyItems, which for dynamic classloading

                          can be added to at runtime. For optional imports it would just be a fixed set of what is available when it is resolved.

                           

                          2) Allow a dynamic import classloading delegate factory to add import delegates to the host

                          ClassLoadingPolicy for each used package when it is dealing with wildcards.

                           

                          Then when it comes to resolve the dynamic import it would go something like:

                           

                          1) It doesn't match any already resolved imports - it hit your delegate - so see if we can match it now.

                          2) Add a new dependency item for the now known package name

                          3) Go through the module resolve processing to determine what we should import - this will

                          also move the dependency from DESCRIBED to CLASSLOADER if its lifecycle is configured for lazyResolve=true

                          4) Once resolved, create a new delegate from what gets resolved and add it to the import delegates in the ClassLoaderPolicy.

                          5) Use the new delegate to do the current classloading request

                           

                          Of course any failure in steps (3) to (5) would lead to a ClassNotFoundException because the dynamic import

                          cannot be satisfied.

                           

                          NOTE: The getClassLoader() is meant to be package private because we  don't want the importer to be

                          able to get access to the underlying classloader which would  bypass the "getClassLoader" permission check

                          and at least allow access to private classes, if not other sensitive classloading information.

                           

                          You should also be careful about leaking protected information in extension points

                          especially when the information comes from other applications, in this  case somebody else's classloader,

                          which would not normally be accessible in a properly secured environment except wrapped in the delegation mechanism.

                          • 10. Re: Wildcard support in Dynamic-imports
                            warjort

                            Adrian Brock wrote:

                            1) Allow a Requirement to have multiple RequirementDependencyItems, which for dynamic classloading

                            can be added to at runtime. For optional imports it would just be a fixed set of what is available when it is resolved.


                            This is also required to do split packages properly.

                            • 11. Re: Wildcard support in Dynamic-imports
                              alesj

                              It now boils down to this prototype (with lots of details yet to impl).

                              Is this what you had in mind - roughly speaking :-)?

                               

                              public class WildcardDelegateLoader extends FilteredDelegateLoader
                              {
                                 private Controller controller;
                                 private Module module;
                                 private VersionRange range;
                              
                                 public WildcardDelegateLoader(Controller controller, ClassLoaderPolicyFactory factory, ClassFilter filter, RequirementDependencyItem item)
                                 {
                                    super(factory, filter);
                                    if (controller == null)
                                       throw new IllegalArgumentException("Null controller");
                                    if (item == null)
                                       throw new IllegalArgumentException("Null item");
                                    Requirement requirement = item.getRequirement();
                                    if (requirement instanceof PackageRequirement == false)
                                       throw new IllegalArgumentException("Illegal package requirement: " + requirement);
                              
                                    this.controller = controller;
                                    this.module = item.getModule();
                                    this.range = ((PackageRequirement)requirement).getVersionRange();
                                 }
                              
                                 protected Module resolve(String pckg)
                                 {
                                    Requirement requirement = new PackageRequirement(pckg, range);
                                    // TODO -- add this DI to module? new DI impl to remove delegate from policy when resolved module goes away?
                                    RequirementDependencyItem item = new RequirementDependencyItem(module, requirement, module.getClassLoaderState(), ControllerState.INSTALLED);
                                    if (item.resolve(controller))
                                    {
                                       ClassLoaderPolicy policy = getPolicy();
                                       // TODO -- add delegate to policy
                                    }
                                    return item.getResolvedModule();
                                 }
                              
                                 @Override
                                 protected Class<?> doLoadClass(String className)
                                 {
                                    Module resolvedModule = resolve(ClassLoaderUtils.getClassPackageName(className));
                                    try
                                    {
                                       return resolvedModule != null ? resolvedModule.loadClass(className) : null;
                                    }
                                    catch (ClassNotFoundException e)
                                    {
                                       throw new RuntimeException(e);
                                    }
                                 }
                              
                                 @Override
                                 protected URL doGetResource(String name)
                                 {
                                    Module resolvedModule = resolve(ClassLoaderUtils.getResourcePackageName(name)); // TODO -- extract package name
                                    return resolvedModule != null ? resolvedModule.getResource(name) : null;
                                 }
                              
                                 @Override
                                 protected void doGetResources(String name, Set<URL> urls) throws IOException
                                 {
                                    Module resolvedModule = resolve(ClassLoaderUtils.getResourcePackageName(name)); // TODO -- extract package name
                                    if (resolvedModule != null)
                                    {
                                       Enumeration<URL> ue = resolvedModule.getResources(name);
                                       while (ue.hasMoreElements())
                                          urls.add(ue.nextElement());
                                    }
                                 }
                              
                                 @Override
                                 protected Package doGetPackage(String name)
                                 {
                                    return null; // TODO -- how to get package from here, from resolved Module?
                                 }
                              
                                 @Override
                                 protected void doGetPackages(Set<Package> packages)
                                 {
                                    // do nothing?
                                 }
                              }
                              
                              • 12. Re: Wildcard support in Dynamic-imports
                                warjort

                                Looks kind of ok. But...

                                 

                                1) You should use the delegate you just created NOT the module.

                                The operations on the module don't respect export restrictions, they can see private stuff.

                                Like I said before, you shouldn't be using those module operations. They are for debug purposes on the management console.

                                i.e. the request starts from that module which is not the case here.

                                 

                                You want the operation to go through the delegate to the other policy with whatever export/import restrictions apply.

                                 

                                   protected DelegateLoader resolve(String pckg)
                                   {
                                      Requirement requirement = new PackageRequirement(pckg, range);
                                      // TODO -- add this DI to module? new DI impl to remove delegate from policy when resolved module goes away?
                                      RequirementDependencyItem item = new RequirementDependencyItem(module, requirement, module.getClassLoaderState(), ControllerState.INSTALLED);
                                      if (item.resolve(controller))
                                      {
                                         ClassLoaderPolicy policy = getPolicy();
                                         // TODO -- add delegate to policy
                                         return delegate;
                                      }
                                      return null;
                                   }

                                 

                                2) I think you should return null for failures, I didn't check but I remember trying to write the internal handling of "not found" to not throw

                                ClassNotFoundExceptions all over the place. Throwing the RuntimeException would likely mean it doesn't go onto the next delegate?

                                 

                                3) You don't show how you are handling the undeploy of the dynamically resolved module when it is not shutdownPolicy=GarbageCollection.

                                It will move your ClassLoaderPolicy back to DESCRIBED since one of the dependencies has been removed. But I think you should also

                                remove the dynamic wildcard dependency items you will be adding in the first TODO shown above.

                                For shutdownPolicy=GarbageCollection you still need to do something in the Module to make the refreshPackages() stuff work properly.

                                For the GC policy used by OSGi, the dependsOnMe are tracked inside the Module rather than the DependencyInfo.

                                • 13. Re: Wildcard support in Dynamic-imports
                                  warjort

                                  Adrian Brock wrote:

                                  You want the operation to go through the delegate to the other policy with whatever export/import restrictions apply.

                                   

                                     protected DelegateLoader resolve(String pckg)
                                     {
                                        Requirement requirement = new PackageRequirement(pckg, range);
                                        // TODO -- add this DI to module? new DI impl to remove delegate from policy when resolved module goes away?
                                        RequirementDependencyItem item = new RequirementDependencyItem(module, requirement, module.getClassLoaderState(), ControllerState.INSTALLED);
                                        if (item.resolve(controller))
                                        {
                                           ClassLoaderPolicy policy = getPolicy();
                                           // TODO -- add delegate to policy
                                           return delegate;
                                        }
                                        return null;
                                     }

                                  This fixes a lot of your TODOs above. :-.)

                                  • 14. Re: Wildcard support in Dynamic-imports
                                    alesj
                                    This fixes a lot of your TODOs above. :-.)

                                    The main TODOs are in the details -- using the delegate after that is the easy part. :-)

                                     

                                    1) How to add this new RequirementDependencyItem (RDI) to existing Module's requirementDependencies? -- package protected

                                    2) How to get the DelegateLoader from resolved Module / RDI? -- BaseCLPolicy::getExported? -- again protected

                                    3) How add / remove this new DelegateLoader to / from host CLPolicy? -- protected, CLPolicy only has getter

                                    1 2 3 Previous Next