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 Matcher match = classFile.matcher(ze.getName());
046 if (match.matches())
047 {
048 ASMModParser modParser;
049 try
050 {
051 modParser = new ASMModParser(jar.getInputStream(ze));
052 }
053 catch (LoaderException e)
054 {
055 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());
056 jar.close();
057 throw e;
058 }
059 modParser.validate();
060 modParser.sendToTable(table, candidate);
061 ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
062 if (container!=null)
063 {
064 table.addContainer(container);
065 foundMods.add(container);
066 container.bindMetadata(mc);
067 }
068 }
069 }
070 }
071 catch (Exception e)
072 {
073 FMLLog.log(Level.WARNING, e, "Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
074 }
075 finally
076 {
077 if (jar != null)
078 {
079 try
080 {
081 jar.close();
082 }
083 catch (Exception e)
084 {
085 }
086 }
087 }
088 return foundMods;
089 }
090
091 }