001 package cpw.mods.fml.common.discovery; 002 003 import java.util.Collections; 004 import java.util.List; 005 import java.util.logging.Level; 006 import java.util.regex.Matcher; 007 import java.util.zip.ZipEntry; 008 import java.util.zip.ZipFile; 009 010 import com.google.common.collect.Lists; 011 012 import cpw.mods.fml.common.FMLLog; 013 import cpw.mods.fml.common.LoaderException; 014 import cpw.mods.fml.common.MetadataCollection; 015 import cpw.mods.fml.common.ModContainer; 016 import cpw.mods.fml.common.ModContainerFactory; 017 import cpw.mods.fml.common.discovery.asm.ASMModParser; 018 019 public class JarDiscoverer implements ITypeDiscoverer 020 { 021 @Override 022 public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table) 023 { 024 List<ModContainer> foundMods = Lists.newArrayList(); 025 FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName()); 026 ZipFile jar = null; 027 try 028 { 029 jar = new ZipFile(candidate.getModContainer()); 030 031 ZipEntry modInfo = jar.getEntry("mcmod.info"); 032 MetadataCollection mc = null; 033 if (modInfo != null) 034 { 035 FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName()); 036 mc = MetadataCollection.from(jar.getInputStream(modInfo), candidate.getModContainer().getName()); 037 } 038 else 039 { 040 FMLLog.fine("The mod container %s appears to be missing an mcmod.info file", candidate.getModContainer().getName()); 041 mc = MetadataCollection.from(null, ""); 042 } 043 for (ZipEntry ze : Collections.list(jar.entries())) 044 { 045 if (ze.getName()!=null && ze.getName().startsWith("__MACOSX")) 046 { 047 continue; 048 } 049 Matcher match = classFile.matcher(ze.getName()); 050 if (match.matches()) 051 { 052 ASMModParser modParser; 053 try 054 { 055 modParser = new ASMModParser(jar.getInputStream(ze)); 056 } 057 catch (LoaderException e) 058 { 059 FMLLog.log(Level.SEVERE, e, "There was a problem reading the entry %s in the jar %s - probably a corrupt zip", ze.getName(), candidate.getModContainer().getPath()); 060 jar.close(); 061 throw e; 062 } 063 modParser.validate(); 064 modParser.sendToTable(table, candidate); 065 ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate); 066 if (container!=null) 067 { 068 table.addContainer(container); 069 foundMods.add(container); 070 container.bindMetadata(mc); 071 } 072 } 073 } 074 } 075 catch (Exception e) 076 { 077 FMLLog.log(Level.WARNING, e, "Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName()); 078 } 079 finally 080 { 081 if (jar != null) 082 { 083 try 084 { 085 jar.close(); 086 } 087 catch (Exception e) 088 { 089 } 090 } 091 } 092 return foundMods; 093 } 094 095 }