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}