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    }