package org.objectweb.asm.commons.util;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/**
* @author Tyler Sedlar
*/
public class JarArchive {
private final Map<String, ClassNode> nodes = new HashMap<>();
private final File file;
private Manifest manifest;
public JarArchive(File file) {
this.file = file;
}
public Map<String, ClassNode> build() {
if (!nodes.isEmpty())
return nodes;
JarFile jar = null;
try {
jar = new JarFile(file);
manifest = jar.getManifest();
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.endsWith(".class")) {
ClassNode cn = new ClassNode();
ClassReader reader = new ClassReader(jar.getInputStream(entry));
reader.accept(cn, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
nodes.put(name.replace(".class", ""), cn);
}
}
} catch (IOException e) {
throw new RuntimeException("Error building classes (" + file.getName() + "): ", e.getCause());
} finally {
try {
if(jar != null)
jar.close();
} catch (IOException e) {
}
}
return nodes;
}
public void write(File target) {
try (JarOutputStream output = (manifest != null ? new JarOutputStream(new FileOutputStream(target), manifest) :
new JarOutputStream(new FileOutputStream(target)))) {
for (Map.Entry<String, ClassNode> entry : build().entrySet()) {
output.putNextEntry(new JarEntry(entry.getKey().replaceAll("\\.", "/") + ".class"));
ClassWriter writer = new ClassWriter(0);
entry.getValue().accept(writer);
output.write(writer.toByteArray());
output.closeEntry();
}
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void write() {
write(file);
}
}