user14074829
user14074829

Reputation:

Replace string in pre-existing jar file

I'm looking for a way to replace %%__USER__%% string in a pre-existing .jar file and then let the user to download it. I don't have any code to share as this is only theoretical, and I have no clue where to start from.

I'm not aware of any way this could be achieved, possibly through bytecode? Any help would be appreciated.

More information: Files are already compiled and stored on web server. They are uploaded by community members, and the %%__USER__%% code would be used to track license analytics. Would need to change this code to downloading user's code every time file is downloaded.

Upvotes: 1

Views: 834

Answers (2)

Reto Höhener
Reto Höhener

Reputation: 5848

Maybe (assuming you want / need to change that String inside an existing class):

  • extract jar
  • read and modify the class file with javassist, or maybe ByteBuddy? I haven't done this, but this SO answer seems to imply that it is possible.
  • zip / jar again (if it was signed you might have to resign)

Upvotes: 0

Andreas
Andreas

Reputation: 159165

A JAR file is basically just a ZIP file. To live update a file in the JAR file, as it is being downloaded by a user, you can use ZipInputStream and ZipOutputStream.

Example:

response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"foo.jar\"");
try (
    ZipInputStream in = new ZipInputStream(this.getClass().getResourceAsStream("template.jar"));
    ZipOutputStream out = new ZipOutputStream(response.getOutputStream());
) {
    for (ZipEntry zipEntry; (zipEntry = in.getNextEntry()) != null; ) {
        out.putNextEntry(new ZipEntry(zipEntry.getName()));
        if (zipEntry.getName().equals("special.txt")) {
            copySpecial(in, out);
        } else {
            copyStream(in, out); // doesn't close streams
        }
    }
}
static void copySpecial(InputStream in, OutputStream out) {
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
    for (String line; (line = reader.readLine()) != null; ) {
        line = line.replace("%%__USER__%%", "John Doe");
        writer.println(line);
    }
    writer.flush();
    // Don't close reader/writer
}

Upvotes: 1

Related Questions