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 }