Programmatically Creating Jars
I wanted to know if it was possible to, from an executable jar, create an executable jar.
I am attempting to create a program with several parts.
Part 1 is an Administrator Control Panel of sorts.
Then there will be several preceding parts, all with fairly similar designs.
What will happen is the Administrator will load a text file. Then, the data from the text file will be split up based on specifications. A jar needs to be created for each split where the specific data for each is contained within it (as a text file), as well as the runtime classes and a manifest. These jars will then be distrubted to the appropriate people.
Tell me if I explained that correct.
Re: Programmatically Creating Jars
You can use the exec to call the jar command...note that if this is a distributed app, jar must be installed on the computer running the app (if this is a problem you could just distribute the executable with the app and point the jar command below to its location).
Code java:
Runtime.getRuntime().exec("jar ... ");//run the System level jar command
Are these jar's intended to be executable?
Re: Programmatically Creating Jars
Have you looked at the java classes for jar files and zip files?
The doc says: "The JarOutputStream class is used to write the contents of a JAR file to any output stream."
Re: Programmatically Creating Jars
Quote:
Are these jar's intended to be executable?
Yes
Quote:
Have you looked at the java classes for jar files and zip files?
The doc says: "The JarOutputStream class is used to write the contents of a JAR file to any output stream."
Ok, so I'm reading up on that now and I'm a little confused. How does a ZipEntry work? I would assume that you would add Files with that, but I'm not understanding how it works.
Re: Programmatically Creating Jars
Did you look at the JarOutputStream class?
What do you get when you Google it?
Re: Programmatically Creating Jars
Re: Programmatically Creating Jars
Ok, with the help of examples, I am understanding this. But, I have a question.
The Administrator Part of this program (which is what will create the jars) will, inside its own jar, have the class files that will be needed to create the User Jars. That Data Files for each User Jar will be created at runtime, and thus be outside the Administrator Jar when it is time to add them.
I have played around with and edited the current code I have. How can I tell the Administrator Jar to get the class files for the User Jars from within itself? Is it done the same way as reading any old file inside one's own Jar, or is there something special that needs to be done since it is effectively copying the files instead of just reading them?
Here is the code I have:
Code to Create Jar:
Code java:
import java.io.*;
import java.util.jar.*;
public class JarCreatingProgram
{
public static void main(String[] args) throws IOException
{
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, "TestClass");
JarOutputStream target = new JarOutputStream(new FileOutputStream("output.jar"), manifest);
add(new File("TestClass.class"), target);
target.close();
}
private static void add(File source, JarOutputStream target) throws IOException
{
BufferedInputStream in = null;
try{
if (source.isDirectory())
{
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty())
{
if (!name.endsWith("/"))
name += "/";
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles())
add(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally{
if (in != null)
in.close();
}
}
}
Code for Test Jar Creation:
Code java:
import javax.swing.JFrame;
public class TestClass
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Executable Jar");
frame.setSize(200,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Keep in mind that this is not my final code that will be used in my actual program, but rather code that I can test a play with prior to real implementation.
Any help is appreciated.
Re: Programmatically Creating Jars
Quote:
How can I tell the Administrator Jar to get the class files for the User Jars from within itself? Is it done the same way as reading any old file inside one's own Jar, or is there something special that needs to be done since it is effectively copying the files instead of just reading them?
I'd word it a bit differently but your question is understandable.
A jar doesn't execute, classes execute.
You need to read a file to copy it. I guess copying requires writing after reading.
Quote:
the same way as reading any old file inside one's own Jar
Yes, I think that would be the way it worked
Have you tried it yet? The best answer would be a working example.
EDIT: It worked fine for me.
Re: Programmatically Creating Jars
I'm actually having to edit the code quite badly to allow me to use InputStreamReader to read from the jar. I am actually having difficulty doing this as I am now unsure how to create the JarEntry since it was previously a File for the constructor. However since I'm going to be attempting to read from the Jar, it needs to be some sort of InputStream, which means I cannot get the path of it to create the JarEntry (or at least i can't figure out how).
Also, when I ran my jar the first time, it had the IO Error when trying to find the files before terminating. Unforuntately, it doesn't appear to have released rights over the Jar that was executed AND the Jar it attempted to create, which means I cannot delete them or replace them. I would think I just need to terminate the process, but I am unsure what process that is.