package immibis.bon.io; import immibis.bon.ClassCollection; import immibis.bon.ClassFormatException; import immibis.bon.ClassReferenceData; import immibis.bon.IProgressListener; import immibis.bon.NameSet; import immibis.bon.ReferenceDataCollection; import immibis.bon.org.objectweb.asm.tree.ClassNode; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; public class JarLoader { private static final boolean VERIFY_SIGNATURES = false; public static ClassCollection loadClassesFromJar(NameSet nameSet, File jarFile, IProgressListener progress) throws IOException, ClassFormatException { Collection<ClassNode> classes = new ArrayList<>(); Map<String, byte[]> extraFiles = new HashMap<>(); try (JarInputStream j_in = new JarInputStream(new FileInputStream(jarFile), VERIFY_SIGNATURES)) { JarEntry entry; while((entry = j_in.getNextJarEntry()) != null) { if(entry.isDirectory()) continue; String name = entry.getName(); if(name.endsWith(".class")) { try { ClassNode cn = IOUtils.readClass(IOUtils.readStreamFully(j_in)); if(!name.equals(cn.name + ".class")) throw new ClassFormatException("Class '"+cn.name+"' has wrong path in jar file: '"+name+"'"); classes.add(cn); } catch(ClassFormatException e) { throw new ClassFormatException("Unable to parse class file: "+name+" in "+jarFile.getName(), e); } } else { extraFiles.put(name, IOUtils.readStreamFully(j_in)); } } } ClassCollection cc = new ClassCollection(nameSet, classes); cc.getExtraFiles().putAll(extraFiles); return cc; } public static ReferenceDataCollection loadRefDataFromJar(NameSet ns, File jarFile, IProgressListener progress) throws IOException, ClassFormatException { ReferenceDataCollection rv = new ReferenceDataCollection(ns); try (JarInputStream j_in = new JarInputStream(new FileInputStream(jarFile), VERIFY_SIGNATURES)) { JarEntry entry; while((entry = j_in.getNextJarEntry()) != null) { if(entry.isDirectory()) continue; String name = entry.getName(); if(name.endsWith(".class")) { try { ClassNode cn = IOUtils.readClass(IOUtils.readStreamFully(j_in)); if(!name.equals(cn.name + ".class")) throw new ClassFormatException("Class '"+cn.name+"' has wrong path in jar file: '"+name+"'"); rv.getAllClasses().add(ClassReferenceData.fromClassNode(cn)); } catch(ClassFormatException e) { throw new ClassFormatException("Unable to parse class file: "+name+" in "+jarFile.getName(), e); } } } } return rv; } }