Trying to edit a property file in jar from a ear file. Best way to do it?
Using TrueZIP 7, you could use something like this:
public static void main(String args[]) throws IOException { // Remember to add the following dependencies to the class path: // Compile time artifactId(s): truezip-file // Run time artifactId(s): truezip-kernel, truezip-driver-file, truezip-driver-zip TFile.setDefaultArchiveDetector(new TDefaultArchiveDetector("ear|jar|war")); search(new TFile(args[0])); // e.g. "my.ear" TFile.umount(); // commit changes}private void search(TFile entry) throws IOException { if (entry.isDirectory()) { for (TFile member : dir.listFiles()) search(member); } else if (entry.isFile()) { if (entry.getName().endsWith(".properties"); update(entry); } // else is special file or non-existent}private void update(TFile file) throws IOException { Properties properties = new Properties(); InputStream in = new TFileInputStream(file); try { properties.load(in); } finally { in.close(); } // [your updates here] OutputStream out = new TFileOutputStream(file); try { properties.store(out, "updated"); } finally { out.close(); }}
I used the answer from @Christian Schlichtherle to get me started on what I was trying to accomplish, but the usage of True Zip has changed quite a bit. I thought I'd post what I needed to do here to hopefully help someone.
You need to create a class that extends TApplication. In my case I'm making it abstract so I can reuse the setup code in my implementing logic classes.
Application.java:
import de.schlichtherle.truezip.file.TApplication;import de.schlichtherle.truezip.file.TArchiveDetector;import de.schlichtherle.truezip.file.TConfig;import de.schlichtherle.truezip.fs.archive.zip.JarDriver;import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;import de.schlichtherle.truezip.socket.sl.IOPoolLocator;/** * An abstract class which configures the TrueZIP Path module. */abstract class Application<E extends Exception> extends TApplication<E> { /** * Runs the setup phase. * <p> * This method is {@link #run run} only once at the start of the life * cycle. */ @Override protected void setup() { TConfig.get().setArchiveDetector( new TArchiveDetector( TArchiveDetector.NULL, new Object[][] { { "zip", new ZipDriver(IOPoolLocator.SINGLETON)}, { "ear|jar|war", new JarDriver(IOPoolLocator.SINGLETON)}, })); }}
Then you just extend the abstract class and implement the "work" method as shown.
ChangeProperty.java:
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Properties;import java.util.ServiceConfigurationError;import de.schlichtherle.truezip.file.TFile;import de.schlichtherle.truezip.file.TFileInputStream;import de.schlichtherle.truezip.file.TFileOutputStream;public class ChangeProperty extends Application<IOException> { public static void main(String args[]) throws IOException { try { System.exit(new ChangeProperty().run(args)); } catch (ServiceConfigurationError e) { // Ignore this error because what we wanted to accomplish has been done. } } private void search(TFile entry) throws IOException { System.out.println("Scanning: " + entry); if (entry.isDirectory()) { for (TFile member : entry.listFiles()) search(member); } else if (entry.isFile()) { if (entry.getName().endsWith(".properties")) { update(entry); } } } private void update(TFile file) throws IOException { System.out.println("Updating: " + file); Properties properties = new Properties(); InputStream in = new TFileInputStream(file); try { properties.load(in); } finally { in.close(); } // [your updates here] // For example: properties.setProperty(key, newValue); OutputStream out = new TFileOutputStream(file); try { properties.store(out, "updated by loggerlevelchanger"); } finally { out.close(); } } @Override protected int work(String[] args) throws IOException { search(new TFile(args[0])); return 0; }}