    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    }