001 package cpw.mods.fml.common.discovery;
002
003 import java.io.File;
004 import java.io.FileFilter;
005 import java.io.FileInputStream;
006 import java.util.Arrays;
007 import java.util.List;
008 import java.util.logging.Level;
009 import java.util.regex.Matcher;
010
011 import com.google.common.base.Throwables;
012 import com.google.common.collect.Lists;
013
014 import cpw.mods.fml.common.FMLLog;
015 import cpw.mods.fml.common.LoaderException;
016 import cpw.mods.fml.common.MetadataCollection;
017 import cpw.mods.fml.common.ModContainer;
018 import cpw.mods.fml.common.ModContainerFactory;
019 import cpw.mods.fml.common.discovery.asm.ASMModParser;
020
021 public 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 }