3 Replies Latest reply on Oct 9, 2013 5:54 AM by Bartosz Majsak

    Add all classes in src/main/java

    Philippe Marschall Expert

      I have a beginner ShrinkWrap question:

      I need to add all classes in src/main/java to an archive. How do I do this?

        • 1. Re: Add all classes in src/main/java
          Bartosz Majsak Master

          Actually it is quite a tricky question

           

          DISCLAIMER: This solution depends on both build system and ClassLoader implementation used, but might work for you

           

          public static Collection<Class<?>> fetchAllClassesMatching(String classLocation)
             {
                final List<Class<?>> classes = new ArrayList<Class<?>>();
                try
                {
                   final ClassPath classPath = ClassPath.from(Thread.currentThread().getContextClassLoader());
                   for (ClassPath.ClassInfo classInfo : classPath.getTopLevelClasses())
                   {
                      try
                      {
                         final Class<?> cls = classInfo.load();
                         final CodeSource codeSource = cls.getProtectionDomain().getCodeSource();
                         if (codeSource == null)
                         {
                            continue;
                         }
          
                         final String location = codeSource.getLocation().getPath();
                         if (location != null && location.contains(classLocation) && !location.startsWith("file:") /*we omit jars*/)
                         {
                            classes.add(cls);
                         }
          
          
                      }
                      catch (java.lang.NoClassDefFoundError e)
                      {
                          // Log it somehow. this might occur on runtime, as we try to aggressively load all classes from all classloaders available.
                      }
                   }
                }
                catch (IOException e)
                {
                   throw new RuntimeException("Failed loading classes.", e);
                }
          
          
                return classes;
             }
          
          
          
          

           

          In case of using Maven all classes from src/main/java end up in /classes/ folder so this you can use as classLocation. This code will include all "main" classes from your classpath when Maven is used. From the command line this will be narrowed to the given maven module, but if you have multi-module maven project imported in the IDE (in my case IDEA) this will basically fetch "main" classes from all the modules imported.

           

          Possible improvement here might be to use package prefix to narrow down import. This is as simple as adding additional parameter to this method and replacing

          classPath.getTopLevelClasses();
          
          
          
          

          with

          classPath.getTopLevelClassesRecursive(packageName);
          
          
          
          

           

          I'm using Google Guava here for loading classes (but by all means highly recommended library for a lot of tasks)

          <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>14.0.1</version>
            <scope>test</scope>
          </dependency>
          
          
          
          

           

          This is the best I could come up with.

           

          On the other hand most of the times classes under src/test/java are either tests (so can be filtered out by some sort of class name prefix or suffix) or are utilities/test doubles which can be packaged into something having .test. in the package name (so again can be filtered out using ShrinkWrap filter).

          Small example on how to use Shrinkwrap filters:

          addPackages(true, Filters.exclude(“.*Test.*“), ….) 
          
          
          
          
          1 of 1 people found this helpful
          • 2. Re: Add all classes in src/main/java
            Philippe Marschall Expert

            Bartosz Majsak wrote:

             

            Actually it is quite a tricky question

             

            :-)

            Bartosz Majsak wrote:

            In case of using Maven all classes from src/main/java end up in /classes/ folder so this you can use as classLocation.

            Wouldn't it be simpler to just add this? I have one file in src/main/resources and need that as well. Something like

             

            .addAsDirectory("target/classes")

            • 3. Re: Add all classes in src/main/java
              Bartosz Majsak Master

              Yeah that would work too But as you see from my sample above, I prefer more juggling Simple solutions are boring ...

              XlRm9Y0.gif