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}