0

I am writing a java program that takes my generated .class files and Jars them then loads them into memory using a class loader.

I currently have a working jarring system with the code:

 public static int BUFFER_SIZE = 10240;
  protected static void createJarArchive(File archiveFile, File[] tobeJared) {
    try {
      byte buffer[] = new byte[BUFFER_SIZE];
      // Open archive file
      FileOutputStream stream = new FileOutputStream(archiveFile);
      JarOutputStream out = new JarOutputStream(stream, new Manifest());

      for (int i = 0; i < tobeJared.length; i++) {
        if (tobeJared[i] == null || !tobeJared[i].exists()
            || tobeJared[i].isDirectory())
          continue; // Just in case...
        System.out.println("Adding " + tobeJared[i].getName());

        // Add archive entry
        JarEntry jarAdd = new JarEntry(getPackageNameModified +tobeJared[i].getName());
        jarAdd.setTime(tobeJared[i].lastModified());
        out.putNextEntry(jarAdd);

        // Write file to archive
        FileInputStream in = new FileInputStream(tobeJared[i]);
        while (true) {
          int nRead = in.read(buffer, 0, buffer.length);
          if (nRead <= 0)
            break;
          out.write(buffer, 0, nRead);
        }
        in.close();
      }

      out.close();
      stream.close();
      System.out.println("Adding completed OK");
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("Error: " + ex.getMessage());
    }
  }

Reference to something in code:

getPackageNameModified = com\Test

However, when I go to load the jar into memory I get a error of:

Could not load jar C:\Users\Dalton\AppData\Local\Temp\Test.jar into JVM. (Could not find class com.Test.ObjectFactory.)

I am using a squoop class loader to do this.

AKA:

ClassLoaderStack.addJarFile(jarFileAbsolute, absoluteClass);

Using the following command line the class loader code works properly, but I want to avoid command line in a java program:

jar cf C:\Users\Dalton\AppData\Local\Temp\Test.jar -C C:\Users\Dalton\AppData\Local\Temp\Test\com.Test com\Test
Dalton Heiland
  • 117
  • 2
  • 7
  • You did use `jar tf` to verify the contents of the .jar file created by your program, right? – VGR Feb 15 '16 at 21:58
  • Names of jar (and zip) entries use / for the path delimiter, and include a delimiter between the last package (nominally directory) component and the basename. FYI: Windows pathnames can use either / or \ in java, it's only some programs and dialogs that require \. – dave_thompson_085 Feb 16 '16 at 01:07

1 Answers1

0

The following fixed my issue:

try
    {
        byte buffer[] = new byte[BUFFER_SIZE];
        // Open archive file
        FileOutputStream stream = new FileOutputStream(archiveFile);
        JarOutputStream out = new JarOutputStream(stream, new Manifest());

        for (int i = 0; i < tobeJared.length; i++)
        {
            if (tobeJared[i].toString().endsWith(CLASS))
            { 
                // the .replace \\ with / is a java JDK bug that requires all
                    // paths to use / and end in / for a jar to properly be made

                LOG.info("Adding "
                        + getPackageNameModified().replace(
                                DOUBLE_BACKSLASH, FORWARD_SLASH) + FORWARD_SLASH + tobeJared[i].getName()
                        + " to the temporary JAR.");

                // Add archive entry
                JarEntry jarAdd = new JarEntry(
                        getPackageNameModified().replace(DOUBLE_BACKSLASH,
                                FORWARD_SLASH) + FORWARD_SLASH + tobeJared[i].getName());
                jarAdd.setTime(tobeJared[i].lastModified());
                out.putNextEntry(jarAdd);

                // Write file to archive
                FileInputStream in = new FileInputStream(tobeJared[i]);
                while (true)
                {
                    int nRead = in.read(buffer, 0, buffer.length);
                    if (nRead <= 0) break;
                    out.write(buffer, 0, nRead);
                }
                in.close();
            }
        }

        out.close();
        stream.close();
        LOG.info("Adding complete --> Success");
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
        LOG.error("Error: " + ex.getMessage());
    }

Issue is in java the \ is a bug. All directory splits use a / instead, and end in /. I do not know why this is the issue, but because of it the generated JAR can class load.

Dalton Heiland
  • 117
  • 2
  • 7