    001package cpw.mods.fml.common.discovery;
    002
    003import java.util.Collections;
    004import java.util.List;
    005import java.util.logging.Level;
    006import java.util.regex.Matcher;
    007import java.util.zip.ZipEntry;
    008import java.util.zip.ZipFile;
    009
    010import com.google.common.collect.Lists;
    011
    012import cpw.mods.fml.common.FMLLog;
    013import cpw.mods.fml.common.LoaderException;
    014import cpw.mods.fml.common.MetadataCollection;
    015import cpw.mods.fml.common.ModContainer;
    016import cpw.mods.fml.common.ModContainerFactory;
    017import cpw.mods.fml.common.discovery.asm.ASMModParser;
    018
    019public 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}