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.ByteArrayOutputStream; 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; public class DirLoader { public static ClassCollection loadClassesFromDirectory(NameSet ns, File dir, IProgressListener progress) throws IOException, ClassFormatException { Collection<ClassNode> classes = new ArrayList<>(); Map<String, byte[]> extraFiles = new HashMap<>(); loadFromDir("", dir, classes, extraFiles); ClassCollection cc = new ClassCollection(ns, classes); cc.getExtraFiles().putAll(extraFiles); return cc; } private static void loadFromDir(String prefix, File dir, Collection<ClassNode> result, Map<String, byte[]> extraFiles) throws IOException, ClassFormatException { if(dir.isDirectory()) { if(!prefix.equals("")) prefix += "/"; for(String fn : dir.list()) { loadFromDir(prefix + fn, new File(dir, fn), result, extraFiles); } } else if(prefix.endsWith(".class")) { try (FileInputStream in = new FileInputStream(dir)) { ClassNode cn = IOUtils.readClass(IOUtils.readStreamFully(in)); if(!prefix.equals(cn.name + ".class")) throw new ClassFormatException("Class '"+cn.name+"' has wrong path in folder: '"+prefix+"'"); result.add(cn); } } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (FileInputStream in = new FileInputStream(dir)) { byte[] buf = new byte[4096]; while(true) { int read = in.read(buf); if(read <= 0) break; baos.write(buf, 0, read); } } extraFiles.put(prefix, baos.toByteArray()); } } public static ReferenceDataCollection loadRefDataFromDirectory(NameSet ns, File dir, IProgressListener progress) throws IOException, ClassFormatException { ReferenceDataCollection rv = new ReferenceDataCollection(ns); loadFromDir("", dir, rv.getAllClasses()); return rv; } private static void loadFromDir(String prefix, File dir, Collection<ClassReferenceData> result) throws IOException, ClassFormatException { if(dir.isDirectory()) { if(!prefix.equals("")) prefix += "/"; for(String fn : dir.list()) { loadFromDir(prefix + fn, new File(dir, fn), result); } } else if(prefix.endsWith(".class")) { try (FileInputStream in = new FileInputStream(dir)) { ClassNode cn = IOUtils.readClass(IOUtils.readStreamFully(in)); if(!prefix.equals(cn.name + ".class")) throw new ClassFormatException("Class '"+cn.name+"' has wrong path in folder: '"+prefix+"'"); result.add(ClassReferenceData.fromClassNode(cn)); } } } }