    001/*
    002 * Forge Mod Loader
    003 * Copyright (c) 2012-2013 cpw.
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the GNU Lesser Public License v2.1
    006 * which accompanies this distribution, and is available at
    007 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    008 *
    009 * Contributors:
    010 *     cpw - implementation
    011 */
    012
    013package cpw.mods.fml.common.discovery;
    014
    015import java.util.Collections;
    016import java.util.List;
    017import java.util.logging.Level;
    018import java.util.regex.Matcher;
    019import java.util.zip.ZipEntry;
    020import java.util.zip.ZipFile;
    021
    022import com.google.common.collect.Lists;
    023
    024import cpw.mods.fml.common.FMLLog;
    025import cpw.mods.fml.common.LoaderException;
    026import cpw.mods.fml.common.MetadataCollection;
    027import cpw.mods.fml.common.ModContainer;
    028import cpw.mods.fml.common.ModContainerFactory;
    029import cpw.mods.fml.common.discovery.asm.ASMModParser;
    030
    031public class JarDiscoverer implements ITypeDiscoverer
    032{
    033    @Override
    034    public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
    035    {
    036        List<ModContainer> foundMods = Lists.newArrayList();
    037        FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
    038        ZipFile jar = null;
    039        try
    040        {
    041            jar = new ZipFile(candidate.getModContainer());
    042
    043            ZipEntry modInfo = jar.getEntry("mcmod.info");
    044            MetadataCollection mc = null;
    045            if (modInfo != null)
    046            {
    047                FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName());
    048                mc = MetadataCollection.from(jar.getInputStream(modInfo), candidate.getModContainer().getName());
    049            }
    050            else
    051            {
    052                FMLLog.fine("The mod container %s appears to be missing an mcmod.info file", candidate.getModContainer().getName());
    053                mc = MetadataCollection.from(null, "");
    054            }
    055            for (ZipEntry ze : Collections.list(jar.entries()))
    056            {
    057                if (ze.getName()!=null && ze.getName().startsWith("__MACOSX"))
    058                {
    059                    continue;
    060                }
    061                Matcher match = classFile.matcher(ze.getName());
    062                if (match.matches())
    063                {
    064                    ASMModParser modParser;
    065                    try
    066                    {
    067                        modParser = new ASMModParser(jar.getInputStream(ze));
    068                    }
    069                    catch (LoaderException e)
    070                    {
    071                        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());
    072                        jar.close();
    073                        throw e;
    074                    }
    075                    modParser.validate();
    076                    modParser.sendToTable(table, candidate);
    077                    ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
    078                    if (container!=null)
    079                    {
    080                        table.addContainer(container);
    081                        foundMods.add(container);
    082                        container.bindMetadata(mc);
    083                    }
    084                }
    085            }
    086        }
    087        catch (Exception e)
    088        {
    089            FMLLog.log(Level.WARNING, e, "Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
    090        }
    091        finally
    092        {
    093            if (jar != null)
    094            {
    095                try
    096                {
    097                    jar.close();
    098                }
    099                catch (Exception e)
    100                {
    101                }
    102            }
    103        }
    104        return foundMods;
    105    }
    106
    107}