February 28, 2020

Explode a WAR File Recursively

Abstract

Ever need to explode a WAR file as well as exploding all JAR files in the WAR file? Ya, me too!

I wrote ferris-war-exploder to explode either:

  1. A JAR file
  2. A WAR file which every JAR file it finds also exploded.
  3. An EAR file with every JAR file (see #1) and WAR file (see #2) also exploded.

Basically, ferris-war-exploder explodes anything which is a ZIP file format. Any entries which are in a ZIP file format will also be exploded. This happens recursively so anything that can be exploded is exploded.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Requirements

I did all of the work for this post using the following major technologies. You may be able to do the same thing with different technologies or versions, but no guarantees.

  • NetBeans 11.2
  • Maven 3.3.9 (Bundled with NetBeans)
  • Java 11 (zulu11.35.15-ca-jdk11.0.5-win_x64)

Download

Visit my GitHub page https://github.com/mjremijan to see all of my open source projects. The code for this post is located at: https://github.com/mjremijan/ferris-war-exploder

Let’s get to it

ferris-war-exploder explodes anything which is a ZIP file format. Any entries which are in a ZIP file format will also be exploded. This happens recursively so anything that can be exploded is exploded.

YOU need to tell it the archive (WAR, JAR, EAR, ZIP) to explode.

YOU need to tell it where to explode the archive.

NOTE See my ferris-magic-number to analyze all of the .class files once the WAR is exploded.

Listing 1 shows the main() method to start the application. I have 2 examples: Exploding a JAR and exploding a WAR.

Listing 1 - The main() method

public class Main {
  public static void main(String[] args) throws Exception
  {
    System.out.printf("=== Welcome to Ferris WAR Exploder ===%n");

    new Unzip("./src/test/jars/commons-lang3-3.7.jar", "./target/unzipped/jar")
      .unzip();

    new Unzip("./src/test/wars/sample.war", "./target/unzipped/war")
      .unzip();

    System.out.printf("%n=== DONE ===%n");
  }
}

Listing 2 shows the Unzip class. This class contains the interesting code to recursively explode an archive. Nothing in Listing 2 is difficult to understand, so I’ll leave it up to you to read through.

Listing 2 - The Unzip method

package org.ferris.war.exploder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 *
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
public class Unzip {

  protected File zipFile;
  protected File destinationDirectory;

  public Unzip(String zipFilePath, String destinationDirectoryPath) {
    setZipFile(zipFilePath);
    setDestinationDirectory(destinationDirectoryPath);
  }

  public Unzip(File zipFile) {
    this.zipFile = zipFile;
    setDestinationDirectory(zipFile.getParent());
  }

  protected void setDestinationDirectory(String destinationDirectoryPath) {
    destinationDirectory = new File(destinationDirectoryPath, zipFile.getName());
    if (destinationDirectory.exists() && destinationDirectory.isDirectory()) {
      throw new RuntimeException(
        String.format(
          "The destination directory \"%s\" already exists.",
           destinationDirectory.getPath()
        )
      );
    }
    if (destinationDirectory.exists() && destinationDirectory.isFile()) {
      destinationDirectory = new File(destinationDirectoryPath, zipFile.getName() + ".d");
    }

    mkdirs(destinationDirectory,
       "Failed to create the destination directory \"%s\"."
    );
  }

  protected void setZipFile(String zipFilePath) {
    zipFile = new File(zipFilePath);
    if (!zipFile.exists()) {
      throw new RuntimeException(
        String.format(
          "The file \"%s\" does not exist", zipFile.getPath()
        )
      );
    }
    if (!zipFile.canRead()) {
      throw new RuntimeException(
        String.format(
          "The file \"%s\" is not readable", zipFile.getPath()
        )
      );
    }
  }

  protected void unzip() throws Exception {
    System.out.printf("%n=== Unipping %s ===%n%n", zipFile.getPath());
    try (ZipInputStream zip
      = new ZipInputStream(new FileInputStream(zipFile));
    ){
      for (ZipEntry z = zip.getNextEntry(); z != null; z = zip.getNextEntry()) {
        if (z.isDirectory()) {
          mkdirs(new File(destinationDirectory, z.getName()),
            "Failed to create a zip entry directory \"%s\""
          );
        } else {
          File zfile = new File(destinationDirectory, z.getName());
          mkdirs(zfile.getParentFile(),
             "Failed to create parent directory for zip entry file \"%s\"."
          );
          File unzippedFile = unzipEntry(z, zip);
          if (isZip(unzippedFile)) {
            new Unzip(unzippedFile).unzip();
          }
        }
      }
    }
  }

  protected boolean isZip(File file) {
    boolean b = false;
    try {
      b = new ZipFile(file).getName().length() > 0;
    } catch (IOException ignore) {}
    return b;
  }

  protected File unzipEntry(ZipEntry z, ZipInputStream zip) throws Exception {
    File zfile = new File(destinationDirectory, z.getName());
    System.out.printf("  %s%n", zfile.getAbsolutePath());
    try ( FileOutputStream out = new FileOutputStream(zfile)) {
      zip.transferTo(out);
    }
    zip.closeEntry();;
    return zfile;
  }

  protected void mkdirs(File dir, String errorMessageFormat) {
    if (dir.exists() && dir.isDirectory()) {
      return;
    }
    dir.mkdirs();
    if (!dir.exists()) {
      throw new RuntimeException(
        String.format(errorMessageFormat, dir.getPath()
        )
      );
    }
  }
}

Summary

The ferris-war-exploder project isn’t too complicated, but it is very handy when you need to completely explode a WAR or EAR archive. Enjoy!

References

ZipOutputStream. (n.d.). Oracle. Retrieved from https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/zip/ZipOutputStream.html.

February 25, 2020

Discovering the Magic Version Number of .class Files

Abstract

What version of Java was used to create your .class files? For your own projects, this is easy to figure out because you choose your Java version when you compile. For the hundreds or thousands of dependencies in your project, this question is not so easy to answer. Inside every .class file is a magic number with a byte value indicating the Java version used to create the .class file. This blog describes some code in ferris-magic-number which analyzes and reports the Java versions on a directory full of .class files.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Requirements

I did all of the work for this post using the following major technologies. You may be able to do the same thing with different technologies or versions, but no guarantees.

  • NetBeans 11.2
  • Maven 3.3.9 (Bundled with NetBeans)
  • Java 11 (zulu11.35.15-ca-jdk11.0.5-win_x64)

Download

Visit my GitHub page https://github.com/mjremijan to see all of my open source projects. The code for this post is located at: https://github.com/mjremijan/ferris-magic-number

Let’s get to it

ferris-magic-number searches an entire directory tree for files that end with .class. It will analyze the Magic Number version number byte value of all the classes and print out a detailed and summary report (System.out.printf()…nothing too complicated).

YOU need to tell it the directory to search.

YOU need to unzip your JAR files.

NOTE See my ferris-war-exploder project to easily explode a WAR file along with every JAR file within the WAR file.

Listing 1 shows the main() method to start the application. Update the path appropriately.

Listing 1 - The main() method

package org.ferris.magic.number;

import java.nio.file.Paths;

public static void main(String[] args) throws Exception
{
   System.out.printf(
     "=== Welcome to Ferris Magic Number ===%n"
   );

   MagicNumbers.load(
    Paths.get("./src/test/jars")
  ).print();

  System.out.printf("%n=== DONE ===%n");
}

Listing 2 shows the MagicNumber class. This class contains the interesting code parsing the .class file and reading the major version byte value. Nothing in Listing 2 is difficult to understand, so I’ll leave it up to you to read through.

Listing 2 - The MagicNumber method

package org.ferris.magic.number;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Arrays;

public class MagicNumber {

  protected Path classFile;
  protected byte[] CAFEBABEs, minors, majors;
  protected Major major;

  public MagicNumber (Path classFile) throws IOException {
    try (
      InputStream is = new FileInputStream(classFile.toFile());
    ) {
      this.classFile = classFile;

      // Magic number info:
      // https://en.wikipedia.org/wiki/Java_class_file#Magic_Number
      CAFEBABEs = new byte[4];
      is.read(CAFEBABEs);

      minors = new byte[2];
      is.read(minors);

      majors = new byte[2];
      is.read(majors);

      major = new Major(majors[1]);
    }
  }

  @Override
  public String toString() {
    StringBuilder sp = new StringBuilder();
    sp.append(String.format(
      "  CLASS: %s%n", classFile.toString()));
    sp.append(String.format(
      "    minor[] = %s%n", Arrays.toString(minors)));
    sp.append(String.format(
      "    major[] = %s%n", Arrays.toString(majors)));
    sp.append(String.format(
      "    major = %s%n", major.toString()));
    return sp.toString();
  }

  public Major getMajor() {
    return major;
  }
}

Example Output

What does the output look like? See Listing 4. That’s the entire output and you’ll need to scroll a little bit :) The output in Listing 4 is the from the example .class files that come with the project. So if you clone the repository and execute as-is, you’ll get this output of Listing 4.

What may be more useful is Listing 3, which shows just the summary output (scroll all the way to the bottom of Listing 4 to see the summary). Listing 3 shows how ferris-magic-number shows a breakdown of how many different Java versions were found and how many .class files for each version.

Listing 3 - Summary Output

=== SUMMARY ===

    Different major version count: 2
    'JDK 1.3 = 47' class count: 118
    'JDK 1.1 = 45' class count: 333

=== DONE ===

Listing 4 - Full Output

=== Welcome to Ferris Magic Number ===


=== 47 ===

    Count: 118

    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BasicDynaBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BasicDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BeanAccessLanguageException.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BeanUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BeanUtilsBean$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BeanUtilsBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\BeanUtilsBean2.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConstructorUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ContextClassLoaderLocal.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConversionException.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\Converter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\AbstractArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\AbstractConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\BigDecimalConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\BigIntegerConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\BooleanArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\BooleanConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ByteArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ByteConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\CalendarConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\CharacterArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\CharacterConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ClassConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ConverterFacade.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\DateConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\DateTimeConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\DoubleArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\DoubleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\FileConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\FloatArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\FloatConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\IntegerArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\IntegerConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\LongArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\LongConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\NumberConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ShortArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\ShortConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\SqlDateConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\SqlTimeConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\SqlTimestampConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\StringArrayConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\StringConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\converters\URLConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConvertingWrapDynaBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConvertUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConvertUtilsBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ConvertUtilsBean2.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\DynaBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\DynaBeanMapDecorator$MapEntry.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\DynaBeanMapDecorator.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\DynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\DynaProperty.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\expression\DefaultResolver.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\expression\Resolver.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\JDBCDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\LazyDynaBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\LazyDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\LazyDynaList.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\LazyDynaMap.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\BaseLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\BigDecimalLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\BigIntegerLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\ByteLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\DateLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\DecimalLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\DoubleLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\FloatLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\IntegerLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\LongLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\ShortLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\SqlDateLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\SqlTimeLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\SqlTimestampLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\converters\StringLocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleBeanUtils$Descriptor.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleBeanUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleBeanUtilsBean$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleBeanUtilsBean$Descriptor.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleBeanUtilsBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleConverter.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleConvertUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleConvertUtilsBean$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleConvertUtilsBean$DelegateFastHashMap.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\locale\LocaleConvertUtilsBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\MappedPropertyDescriptor$MappedMethodReference.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\MappedPropertyDescriptor.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\MethodUtils$MethodDescriptor.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\MethodUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\MutableDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\NestedNullException.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\PropertyUtils.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\PropertyUtilsBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ResultSetDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\ResultSetIterator.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\RowSetDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$CollectionView$CollectionViewIterator.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$CollectionView.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$EntrySet.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$KeySet.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap$Values.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WeakFastHashMap.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WrapDynaBean.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WrapDynaClass$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WrapDynaClass$2.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\beanutils\WrapDynaClass.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\ArrayStack.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\Buffer.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\BufferUnderflowException.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$1.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$CollectionView$CollectionViewIterator.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$CollectionView.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$EntrySet.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$KeySet.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap$Values.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'
    CLASS: .\src\test\jars\commons-beanutils-core-1.8.3\org\apache\commons\collections\FastHashMap.class
        minor[] = [0, 0]
        major[] = [0, 47]
        major = 'JDK 1.3 = 47'


=== 45 ===

    Count: 333

    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\DefaultXPathHandler$Singleton.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\DefaultXPathHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\Token.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\TokenTypes.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\XPathLexer.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\com\werken\saxpath\XPathReader.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Attribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\bean\BeanAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\bean\BeanAttributeList.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\bean\BeanDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\bean\BeanElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\bean\BeanMetaData.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Branch.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\CDATA.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\CharacterData.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Comment.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\DatatypeAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\DatatypeDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\DatatypeElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\DatatypeElementFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\InvalidSchemaException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\NamedTypeResolver.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\datatype\SchemaParser.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Document.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\DocumentException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\DocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\DocumentHelper.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\DocumentType.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMAttributeNodeMap.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMCDATA.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMComment.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMDocument.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMDocumentType.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMEntityReference.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMNamespace.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMNodeHelper$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMNodeHelper$EmptyNodeList.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMNodeHelper.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMProcessingInstruction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dom\DOMText.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dtd\AttributeDecl.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dtd\ElementDecl.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dtd\ExternalEntityDecl.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\dtd\InternalEntityDecl.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Element.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\ElementHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\ElementPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Entity.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\IllegalAddException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\InvalidXPathException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\aelfred\DefaultHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\aelfred\SAXDriver$Adapter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\aelfred\SAXDriver.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\aelfred\XmlParser.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DispatchHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DocumentInputSource$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DocumentInputSource.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DocumentResult.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DocumentSource.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DOMReader.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\DOMWriter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\ElementStack.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\HTMLWriter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\JAXPHelper.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\OutputFormat.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\PruningElementStack.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXContentHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXHelper.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXReader$SAXEntityResolver.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXReader.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXValidator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\SAXWriter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\XMLResult.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\XMLWriter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\io\XPPReader.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Namespace.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Node.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\NodeFilter.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\ProcessingInstruction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\QName.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\Action.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\Mode.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\NullAction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\pattern\DefaultPattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\pattern\NodeTypePattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\Pattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\Rule.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\RuleManager$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\RuleManager.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\RuleSet.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\rule\Stylesheet.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\BranchTreeNode$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\BranchTreeNode.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\DocumentTreeModel.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\LeafTreeNode$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\LeafTreeNode.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\XMLTableColumnDefinition.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\XMLTableDefinition.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\swing\XMLTableModel.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Text.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractBranch.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractCDATA.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractCharacterData.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractComment.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractDocument.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractDocumentType.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractEntity.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractNode.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractProcessingInstruction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\AbstractText.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\BackedList.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\BaseElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\ContentListFacade.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultCDATA.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultComment.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultDocument.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultDocumentType.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultEntity.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultNamespace.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultProcessingInstruction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\DefaultText.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\ElementIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\ElementNameIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\ElementQNameIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FilterIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightCDATA.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightComment.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightEntity.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightProcessingInstruction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\FlyweightText.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\NamespaceCache.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\NamespaceStack.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\QNameCache.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\tree\SingleIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\AttributeHelper.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\IndexedDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\IndexedElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\NodeComparator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\NonLazyDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\NonLazyElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\ProxyDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\UserDataAttribute.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\UserDataDocumentFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\UserDataElement.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\util\XMLErrorHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\Visitor.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\VisitorSupport.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\xpath\DefaultNamespaceContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\xpath\DefaultXPath$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\xpath\DefaultXPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\xpath\XPathPattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\XPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\XPathException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\dom4j\xpp\ProxyXmlStartTag.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\BaseXPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\Context.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\ContextSupport.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\DefaultNavigator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\dom4j\DocumentNavigator$Singleton.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\dom4j\DocumentNavigator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\dom4j\XPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\BinaryExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultAbsoluteLocationPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultAdditiveExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultAllNodeStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultAndExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultArithExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultBinaryExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultCommentNodeStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultDivExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultEqualityExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultEqualsExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultFilterExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultFunctionCallExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultGreaterThanEqualExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultGreaterThanExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultLessThanEqualExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultLessThanExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultLiteralExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultLocationPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultLogicalExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultMinusExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultModExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultMultiplicativeExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultMultiplyExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultNameStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultNotEqualsExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultNumberExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultOrExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultPathExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultPlusExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultPredicate.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultPredicated.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultProcessingInstructionNodeStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultRelationalExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultRelativeLocationPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultTextNodeStep.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultTruthExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultUnaryExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultUnionExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultVariableReferenceExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultXPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\DefaultXPathFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\Expr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\FilterExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\FunctionCallExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableAncestorAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableAncestorOrSelfAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableAttributeAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableChildAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableDescendantAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableDescendantOrSelfAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableFollowingAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableFollowingSiblingAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableNamespaceAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableParentAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterablePrecedingAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterablePrecedingSiblingAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\iter\IterableSelfAxis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\LiteralExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\LocationPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\NumberExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\PathExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\Predicate.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\Predicated.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\PredicateSet.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\Step.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\UnaryExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\UnionExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\VariableReferenceExpr.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\XPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\expr\XPathFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\BooleanFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\CeilingFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\ConcatFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\ContainsFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\CountFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\DocumentFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\ext\EvaluateFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\ext\MatrixConcatFunction$MatrixEnum.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\ext\MatrixConcatFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\FalseFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\FloorFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\IdFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\LastFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\LocalNameFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\NameFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\NamespaceUriFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\NormalizeSpaceFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\NotFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\NumberFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\PositionFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\RoundFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\StartsWithFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\StringFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\StringLengthFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\SubstringAfterFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\SubstringBeforeFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\SubstringFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\SumFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\function\TrueFunction.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\Function.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\FunctionCallException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\FunctionContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\JaxenException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\JaxenHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\JaXPath.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\NamespaceContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\Navigator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\AnyChildNodeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\AnyNodeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\LocationPathPattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\NamespaceTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\NameTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\NodeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\NodeTypeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\NoNodeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\Pattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\PatternHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\PatternParser.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\TextNodeTest.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\pattern\UnionPattern.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\QualifiedName.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\SimpleFunctionContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\SimpleNamespaceContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\SimpleVariableContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\UnresolvableException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\UnsupportedAxisException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\AncestorAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\AncestorOrSelfAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\DescendantAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\DescendantOrSelfAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\FollowingAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\FollowingSiblingAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$1.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$2.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$3.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$EmptyHashIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$Entry.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap$HashIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\IdentityHashMap.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\LinkedIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\PrecedingAxisIterator$ReverseDescendantOrSelfAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\PrecedingAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\PrecedingSiblingAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\SelfAxisIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\SingleObjectIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\util\StackedIterator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\VariableContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\XPathFunctionContext$Singleton.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\XPathFunctionContext.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\jaxen\XPathSyntaxException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\Axis.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\conformance\ConformanceXPathHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\helpers\XPathReaderFactory.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\Operator.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\SAXPathEventSource.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\SAXPathException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\SAXPathParseException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\XPathHandler.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\XPathReader.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'
    CLASS: .\src\test\jars\dom4j-1.1\org\saxpath\XPathSyntaxException.class
        minor[] = [0, 3]
        major[] = [0, 45]
        major = 'JDK 1.1 = 45'


=== SUMMARY ===

    Different major version count: 2
    'JDK 1.3 = 47' class count: 118
    'JDK 1.1 = 45' class count: 333

=== DONE ===

Summary

The ferris-magic-number project isn’t too complicated. It produces some interesting information, but, if you are having a problem with a dependency having a newer Java version than you support, this is when it really can be useful. That exact problem is what I needed to solve. Enjoy!

References

Java class file. (n.d.). Wikipedia. Retrieved from https://en.wikipedia.org/wiki/Java_class_file#Magic_Number.

February 23, 2020

Testing Maven Release Plugin Auto-Increment Version Number

Abstract

The Maven release plugin is a very powerful tool and I rely on it heavily for coordinating software releases. Typically, software release version numbers follow a simple 1.0.0.0-SNAPSHOT format. But recently I had need to add a qualifier to the version number - something like 1.0-beta-SNAPSHOT or 1.0.0-fix-bug-description-SNAPSHOT. After my 1st attempt to add the qualifier, the Maven release plugin auto-incremented the version number in an unexpected way. Therefore, I needed to research the Maven release plugin version auto-increment behavior but do so without making a bunch of nonsense tags in the production Git repository (I didn’t have a dev repository to work with). The purpose of this blog is to show how the Maven release plugin can be configured so it can run locally and not make changes to production source control.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Requirements

I did all of the work for this post using the following major technologies. You may be able to do the same thing with different technologies or versions, but no guarantees.

  • NetBeans 11.2
  • Maven 3.3.9 (Bundled with NetBeans)
  • maven-release-plugin 2.5.1
  • Java 11 (zulu11.35.15-ca-jdk11.0.5-win_x64)
  • Git for Windows 2.25.0

NOTE The Maven release plugin assumes executables (like git) are on the PATH. If you get an error that the git command is not found, you need to make sure Git is installed independent of your IDE and on the PATH.

Download

Visit my GitHub page https://github.com/mjremijan to see all of my open source projects. The code for this post is located at: https://github.com/mjremijan/thoth-maven-release-plugin

Install Git

The 1st thing you’ll need to do is install Git. Even if Git is integrated into your IDE (like with NetBeans), the Maven release plugin assumes the executables it needs are available on the PATH. Download, install, and configure PATH for your environment.

POM <scm> Tag

The 2nd thing you’ll need to do is configure the POM <scm> tag. When the Maven release plugin runs, it uses the <scm> tag values to identify the location of the source control system.

The relevant configuration is below, see the full pom.xml on GitHub.

Because I want to run locally and not connect to a production source control system, my example uses Git. Git runs very nicely without needing a server. Let’s take a look at the <scm> tag.

Listing 1 - <scm> tag

<scm>
  <url>scm:git:file://D:/Projects/thoth-maven-release-plugin/.git</url>
  <connection>
    scm:git:file://D:/Projects/thoth-maven-release-plugin/.git</connection>
  <developerConnection>
    scm:git:file://D:/Projects/thoth-maven-release-plugin/.git
  </developerConnection>
</scm>

The code in Listing 1 shows my configuration for the <scm> tag. Obviously, the reference to the project’s .git folder on the file system of my computer should stand out to you. You must change this value for your computer. Remember, the goal is to work locally! This configuration gets you there.

After configuring the <scm> tag, the next thing to do is configure the maven-release-plugin. Let’s look at that next.

POM maven-relase-plugin

The 3rd thing to do is configure the maven-release-plugin artifact. This configuration is for the Maven staging repository.

The relevant configuration is below, see the full pom.xml on GitHub. Let’s take a look at this configuration.

Listing 2 - maven-release-plugin tag

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-release-plugin</artifactId>
      <version>2.5.1</version>
      <dependencies>
        <dependency>
          <groupId>org.apache.maven.shared</groupId>
          <artifactId>maven-invoker</artifactId>
          <version>2.2</version>
        </dependency>
      </dependencies>
      <configuration>
        <stagingRepository>
          localforme::default::file://C:/Users/Michael/.m2/repository
        </stagingRepository>
      </configuration>
    </plugin>
    ....
</build>

Line 6 sets the maven-release-plugin to version 2.5.1. This was current at the time of my research (2019 Q2). Using a version below 2.5.2 has some additional gotchas which I’ll get to next.

Line 8 sets the maven-invoker dependency to version 2.2. Maven 3.3 changed the script name (on Windows) from mvn.bat to mvn.cmd. The maven-release-plugin below version 2.5.2 assumes mvn.bat. Changing maven-invoker to version 2.2 changes the assumption to mvn.cmd so Maven 3.3+ can be used (Lucas, 2015). If you use maven-release-plugin greater than or equal to version 2.5.2, you don’t need this maven-invoker configuration.

Line 15 sets the location of the Maven staging repository. Typically you would have this set in settings.xml. If it’s not set, you’ll get build errors. I show how to configure it here. If you have it in settings.xml you can remove this configuration.

Now that the pom.xml is configured, let’s look next at how to run this.

MVN Command

With the configuration now set, it’s time to run the Maven project and test that everything is working. Listing 3 shows the properties and switches for mvn.

Listing 3 - mvn command

mvn
  -Dmaven.test.skip=true
  -Dmaven.javadoc.failOnError=false
  --batch-mode release:clean release:prepare release:stage

There is not much to this command line. Line 4 is the most important. It specifies the maven-release-plugin goals to execute.

Now you are ready for testing. Run the command and see what happens.

Summary

If you are using an IDE like NetBeans which automatically watches and reloads files when changes are detected on the file system, you can open the pom.xml, then run the mvn command, and finally watch the <version> tag automatically change as Maven is running. This way you can start with whatever value you want for the <version> tag and research how it automatically gets changed. Enjoy!

References

Lucas. (2015, July 1). Failed to execute goal maven preprepared [Web log comment]. Stackoverflow. Retrieved from https://stackoverflow.com/questions/29755620/failed-to-execute-goal-maven-releaseprepare.

January 21, 2020

Java Mail Sent Over TLS

Blogger

Abstract

The purpose of this blog is to demonstrate how to use Java Mail to send an email using an SMTP server with a TLS connection.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Requirements

I did all of the work for this post using the following major technologies. You may be able to do the same thing with different technologies or versions, but no guarantees.

  • NetBeans 11.2
  • Maven 3.3.9 (bundled with NetBeans)
  • Java 11 (zulu11.35.15-ca-jdk11.0.5-win_x64)
<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.4</version>
  <scope>test</scope>
</dependency>

Download

Visit my GitHub page https://github.com/mjremijan to see all of my open source projects. The code for this post is located at https://github.com/mjremijan/thoth-email in the thoth-email-via-tls module.

Properties

This example uses an smtp-tls-outlook.properties file to hold the SMTP server information. I used my personal Outlook account for testing, hence the use of the word outlook in the name of the properties file. What’s important are the contents of the file, shown in Listing 1.

Listing 1 - Properties file

# This is the name of the SMTP host machine.
host=

# This is the port number of the SMTP host machine.
# The same host may support both SSL and TLS but on
# different ports. So make sure you get the TLS port.
port=

# This is what you use in the “username” field when
# you login. Typically this is the same as your email
# address, but this isn’t always the case.
username=

# This is what you use in the “password” field when
# you login. This value is CLEAR TEXT, so keep this
# properties file safe.
password=

# This is the email address you want for the
# email’s FROM field. Enter the value using
# the format shown below. Typically this is
# just your email address for the account.
from=FIRSTNAME LASTNAME <ADDRESS@EMAIL.COM>

# This is the email address you want for the
# email’s REPLY_TO field. Enter the value using
# the format shown below. Typically this is
# just your email address for the account. Also
# typically this is the same as `from` above.
# But be warned, if an email’s FROM and REPLY_TO 
# are different, that’s may be flagged as spam
# and never be delivered. So keep `from` and
# `reply` the same for initial testing
reply=FIRSTNAME LASTNAME <ADDRESS@EMAIL.COM>

# This is the email address you want to send
# the email to. For testing, it’s a good idea
# to send it to yourself first.
to=FIRSTNAME LASTNAME <ADDRESS@EMAIL.COM>

Now that you have a properties file, next let’s take a look at the code.

Code

This is a JUnit test demonstrating how to use Java Mail to send an email using an SMTP server with a TLS connection. Listing 2 shows the code.

NOTE For initial testing, always check your SPAM folder. A rule can always be added to deliver to your INBOX.

Listing 2 - Java Mail example

package org.thoth.email.via.tls;

import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class TlsTest {

  public TlsTest() {
  }

  protected String now, hostname;

  protected Properties outlook;

  @BeforeEach
  public void setUp() throws Exception {
    now = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss a").format(new Date());
    hostname = InetAddress.getLocalHost().getHostName();
    outlook = new Properties();
    outlook.load(this.getClass().getResourceAsStream("/smtp-tls-outlook.properties"));
  }

  @Test
  public void a_test() throws Exception {

    // Create MimeMultipart
    MimeMultipart content = new MimeMultipart("related");

    // html part
    {
      MimeBodyPart textPart = new MimeBodyPart();
      textPart.setText("<html><body>"
        + "<p>Time: "+now+"</p>"
        + "<p>From: "+hostname+"</p>"
        + "</body></html>"
        , "UTF8", "html");
      content.addBodyPart(textPart);
    }

    // properties
    Properties props = new Properties();
    {
      props.setProperty("mail.smtp.auth", "true");
      props.setProperty("mail.smtp.host", outlook.getProperty("host"));
      props.setProperty("mail.smtp.port", outlook.getProperty("port"));
      props.setProperty("mail.smtp.starttls.enable", "true");

    }

    Session smtp = null;
    {
      smtp = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
          return new PasswordAuthentication(
              outlook.getProperty("username")
            , outlook.getProperty("password")
          );
        }
      });
      smtp.setDebug(true);
      smtp.setDebugOut(System.out);
    }


    MimeMessage m = new MimeMessage(smtp);
    {
      m.setRecipient(Message.RecipientType.TO, new InternetAddress(outlook.getProperty("to")));
      m.setSubject("thoth-email TLS test " + now);

      InternetAddress from = null;
      {
        from = new InternetAddress(outlook.getProperty("from"));
        from.setPersonal("Thoth Email");
        m.setFrom(from);
      }

      InternetAddress reply = null;
      {
        reply = new InternetAddress(outlook.getProperty("reply"));
        m.setReplyTo(new InternetAddress[] {reply});
      }


      m.setContent(content);
    }

    Transport.send(m);
  }

}

Summary

The code for sending mail is not very hard. Successfully receiving an email without being flagged as SPAM is another matter. But if you follow this example, use a valid account, and don’t overuse it, you should be OK. This blog shows how to use Java Mail to send an email using an SMTP server with a TLS connection.