Uploaded image for project: 'ShrinkWrap'
  1. ShrinkWrap
  2. SHRINKWRAP-244

When calling JavaArchiveImpl.addClass(String, ClassLoader) the TCCL gets used instead

    Details

      Description

      When I call JavaArchiveImpl.addClass(String fqcn, ClassLoader cl) the cl gets used to load fqcn, but then further down the line, I find myself in ContainerBase.addPackages(), which is called indirectly from the previous addClass method. The addPackages still uses the TCCL while it should really use the cl passed in to the addClass method.

      This also applies to JavaArchiveImpl.addClass(Class cls) where the classloader to be used could be inferred from the cls argument, but instead the TCCL gets used...

        Gliffy Diagrams

          Activity

          Hide
          davided80 Davide D'Alto added a comment -

          I can work on this one

          Show
          davided80 Davide D'Alto added a comment - I can work on this one
          Hide
          davided80 Davide D'Alto added a comment -

          I'm working on this one but I'm not sure how to test it...any suggestions?

          Show
          davided80 Davide D'Alto added a comment - I'm working on this one but I'm not sure how to test it...any suggestions?
          Hide
          bosschaert David Bosschaert added a comment -

          Hi Davide,

          The main thing you need to do is get 2 classloaders. One that can load org.example.MyClass (or whatever) and another that can't. There are many ways to do that, for example you can do this by creating a jar file on disk with that class and then create a URLClassLoader that can load from that jar.
          Of the classloader that can't load the class you can use the current class's classloader (as long as it doesn't load the org.example.MyClass).

          Then:
          1. create a SW Java Archive instance
          2. Set TCCL to the one that doesn't see org.example.MyClass
          3. Let's say jcl is the classloader that loads the jar file that holds org.example.MyClass;
          4. call archive.addClass("org.example.MyClass", jcl)
          5. check the SW Java Archive.

          For the other API the sequence is:
          1. create a SW Java Archive instance
          2. Set TCCL to the one that doesn't see org.example.MyClass
          3. Let's say jcl is the classloader that loads the jar file that holds org.example.MyClass;
          4. Class<?> cls = jcl.loadClass("org.example.MyClass");
          5. call archive.addClass(cls)
          6. check the SW Java Archive.

          This is off the top of my head, but in general that should do it.

          Cheers,

          David

          Show
          bosschaert David Bosschaert added a comment - Hi Davide, The main thing you need to do is get 2 classloaders. One that can load org.example.MyClass (or whatever) and another that can't. There are many ways to do that, for example you can do this by creating a jar file on disk with that class and then create a URLClassLoader that can load from that jar. Of the classloader that can't load the class you can use the current class's classloader (as long as it doesn't load the org.example.MyClass). Then: 1. create a SW Java Archive instance 2. Set TCCL to the one that doesn't see org.example.MyClass 3. Let's say jcl is the classloader that loads the jar file that holds org.example.MyClass; 4. call archive.addClass("org.example.MyClass", jcl) 5. check the SW Java Archive. For the other API the sequence is: 1. create a SW Java Archive instance 2. Set TCCL to the one that doesn't see org.example.MyClass 3. Let's say jcl is the classloader that loads the jar file that holds org.example.MyClass; 4. Class<?> cls = jcl.loadClass("org.example.MyClass"); 5. call archive.addClass(cls) 6. check the SW Java Archive. This is off the top of my head, but in general that should do it. Cheers, David
          Hide
          davided80 Davide D'Alto added a comment -

          Hi David,
          following your suggestion I've added this test:
          https://github.com/DavideD/shrinkwrap/blob/SHRINKWRAP-244/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java#L827

          I've created a JAR that contains a class with an inner class and I check that in the generated archive the inner class is present.
          Is it correct?

          The problem that I have now is that the class is included in the archive without the inner class.
          It seems that the URLPackageScanner cannot see the inner class in my custom ClassLoader (even if I load the class in the classloader before adding the class to the archive).

          This is where the URLPackageScanner is called to include the inner classes in the archive:
          https://github.com/DavideD/shrinkwrap/blob/SHRINKWRAP-244/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java#L1146

          Thanks,
          Davide

          Show
          davided80 Davide D'Alto added a comment - Hi David, following your suggestion I've added this test: https://github.com/DavideD/shrinkwrap/blob/SHRINKWRAP-244/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/DynamicContainerTestBase.java#L827 I've created a JAR that contains a class with an inner class and I check that in the generated archive the inner class is present. Is it correct? The problem that I have now is that the class is included in the archive without the inner class. It seems that the URLPackageScanner cannot see the inner class in my custom ClassLoader (even if I load the class in the classloader before adding the class to the archive). This is where the URLPackageScanner is called to include the inner classes in the archive: https://github.com/DavideD/shrinkwrap/blob/SHRINKWRAP-244/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/container/ContainerBase.java#L1146 Thanks, Davide
          Hide
          davided80 Davide D'Alto added a comment -

          If I'm not wrong right now ShrinkWrap finds the inner classes looking among the resources in the classpath (it checks the .class files in the same folder as the class).

          In my test I create a Classloader using a JAR file so the inner classes are inside an archive not visible as resources.

          I tried using the method getDeclaredClasses() of Class but it doesn't include the anonymous inner classes (great unit tests by the way).

          Am I missing anything?

          Thanks for the help.

          Show
          davided80 Davide D'Alto added a comment - If I'm not wrong right now ShrinkWrap finds the inner classes looking among the resources in the classpath (it checks the .class files in the same folder as the class). In my test I create a Classloader using a JAR file so the inner classes are inside an archive not visible as resources. I tried using the method getDeclaredClasses() of Class but it doesn't include the anonymous inner classes (great unit tests by the way). Am I missing anything? Thanks for the help.
          Hide
          bosschaert David Bosschaert added a comment -

          I'm not sure how the inner class is relevant here. That seems like a completely different issue...

          In general I think the tests look good.
          I did leave a comment on the code change you're proposing in https://github.com/DavideD/shrinkwrap/commit/8c157bcebf6ee543a3a5108a7644efc92a2d44a2

          Probably best to get one of the real ShrinkWrap guys to review your changes too

          Show
          bosschaert David Bosschaert added a comment - I'm not sure how the inner class is relevant here. That seems like a completely different issue... In general I think the tests look good. I did leave a comment on the code change you're proposing in https://github.com/DavideD/shrinkwrap/commit/8c157bcebf6ee543a3a5108a7644efc92a2d44a2 Probably best to get one of the real ShrinkWrap guys to review your changes too
          Hide
          davided80 Davide D'Alto added a comment -

          I agree, the inner class is not relevant to this issue.
          I will fix the thing that you pointed out in the comment on github and then I will leave at the Shrinkwrap guys the last word

          Cheers

          Show
          davided80 Davide D'Alto added a comment - I agree, the inner class is not relevant to this issue. I will fix the thing that you pointed out in the comment on github and then I will leave at the Shrinkwrap guys the last word Cheers
          Hide
          alrubinger Andrew Rubinger added a comment -

          Commented on the line w/ DavidB. Once complete, ping me and I'll do final review for push. Overall, just make sure that the Class.getClassLoader is used to load the .class resource, and all's setty. The explicit CL is only needed when adding a class from a String arg.

          Show
          alrubinger Andrew Rubinger added a comment - Commented on the line w/ DavidB. Once complete, ping me and I'll do final review for push. Overall, just make sure that the Class.getClassLoader is used to load the .class resource, and all's setty. The explicit CL is only needed when adding a class from a String arg.
          Show
          alrubinger Andrew Rubinger added a comment - Upstream: https://github.com/shrinkwrap/shrinkwrap/commit/c382f93eae15012c8fce175d2c524154fe92273a

            People

            • Assignee:
              davided80 Davide D'Alto
              Reporter:
              bosschaert David Bosschaert
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development