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    }