    001package cpw.mods.fml.common.discovery;
    002
    003import java.io.File;
    004import java.io.FileFilter;
    005import java.io.FileInputStream;
    006import java.util.Arrays;
    007import java.util.List;
    008import java.util.logging.Level;
    009import java.util.regex.Matcher;
    010
    011import com.google.common.base.Throwables;
    012import com.google.common.collect.Lists;
    013
    014import cpw.mods.fml.common.FMLLog;
    015import cpw.mods.fml.common.LoaderException;
    016import cpw.mods.fml.common.MetadataCollection;
    017import cpw.mods.fml.common.ModContainer;
    018import cpw.mods.fml.common.ModContainerFactory;
    019import cpw.mods.fml.common.discovery.asm.ASMModParser;
    020
    021public class DirectoryDiscoverer implements ITypeDiscoverer
    022{
    023    private class ClassFilter implements FileFilter
    024    {
    025        @Override
    026        public boolean accept(File file)
    027        {
    028            return (file.isFile() && classFile.matcher(file.getName()).find()) || file.isDirectory();
    029        }
    030    }
    031
    032    private ASMDataTable table;
    033
    034    @Override
    035    public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
    036    {
    037        this.table = table;
    038        List<ModContainer> found = Lists.newArrayList();
    039        FMLLog.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
    040        exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
    041        for (ModContainer mc : found)
    042        {
    043            table.addContainer(mc);
    044        }
    045        return found;
    046    }
    047
    048    public void exploreFileSystem(String path, File modDir, List<ModContainer> harvestedMods, ModCandidate candidate, MetadataCollection mc)
    049    {
    050        if (path.length() == 0)
    051        {
    052            File metadata = new File(modDir, "mcmod.info");
    053            try
    054            {
    055                FileInputStream fis = new FileInputStream(metadata);
    056                mc = MetadataCollection.from(fis,modDir.getName());
    057                fis.close();
    058                FMLLog.fine("Found an mcmod.info file in directory %s", modDir.getName());
    059            }
    060            catch (Exception e)
    061            {
    062                mc = MetadataCollection.from(null,"");
    063                FMLLog.fine("No mcmod.info file found in directory %s", modDir.getName());
    064            }
    065        }
    066
    067        File[] content = modDir.listFiles(new ClassFilter());
    068
    069        // Always sort our content
    070        Arrays.sort(content);
    071        for (File file : content)
    072        {
    073            if (file.isDirectory())
    074            {
    075                FMLLog.finest("Recursing into package %s", path + file.getName());
    076                exploreFileSystem(path + file.getName() + ".", file, harvestedMods, candidate, mc);
    077                continue;
    078            }
    079            Matcher match = classFile.matcher(file.getName());
    080
    081            if (match.matches())
    082            {
    083                ASMModParser modParser = null;
    084                try
    085                {
    086                    FileInputStream fis = new FileInputStream(file);
    087                    modParser = new ASMModParser(fis);
    088                    fis.close();
    089                }
    090                catch (LoaderException e)
    091                {
    092                    FMLLog.log(Level.SEVERE, e, "There was a problem reading the file %s - probably this is a corrupt file", file.getPath());
    093                    throw e;
    094                }
    095                catch (Exception e)
    096                {
    097                    Throwables.propagate(e);
    098                }
    099
    100                modParser.validate();
    101                modParser.sendToTable(table, candidate);
    102                ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
    103                if (container!=null)
    104                {
    105                    harvestedMods.add(container);
    106                    container.bindMetadata(mc);
    107                }
    108            }
    109
    110
    111        }
    112    }
    113
    114}