    001    package cpw.mods.fml.common.discovery;
    002
    003    import java.io.File;
    004    import java.util.Arrays;
    005    import java.util.List;
    006    import java.util.logging.Level;
    007    import java.util.regex.Matcher;
    008    import java.util.regex.Pattern;
    009
    010    import com.google.common.base.Throwables;
    011    import com.google.common.collect.ImmutableList;
    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.ModClassLoader;
    017    import cpw.mods.fml.common.ModContainer;
    018    import cpw.mods.fml.relauncher.RelaunchLibraryManager;
    019
    020    public class ModDiscoverer
    021    {
    022        private static Pattern zipJar = Pattern.compile("(.+).(zip|jar)$");
    023
    024        private List<ModCandidate> candidates = Lists.newArrayList();
    025
    026        private ASMDataTable dataTable = new ASMDataTable();
    027
    028        private List<File> nonModLibs = Lists.newArrayList();
    029
    030        public void findClasspathMods(ModClassLoader modClassLoader)
    031        {
    032            List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
    033            File[] minecraftSources = modClassLoader.getParentSources();
    034            if (minecraftSources.length == 1 && minecraftSources[0].isFile())
    035            {
    036                FMLLog.fine("Minecraft is a file at %s, loading", minecraftSources[0].getAbsolutePath());
    037                candidates.add(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR, true, true));
    038            }
    039            else
    040            {
    041                for (int i = 0; i < minecraftSources.length; i++)
    042                {
    043                    if (minecraftSources[i].isFile())
    044                    {
    045                        if (knownLibraries.contains(minecraftSources[i].getName()))
    046                        {
    047                            FMLLog.fine("Skipping known library file %s", minecraftSources[i].getAbsolutePath());
    048                        }
    049                        else
    050                        {
    051                            FMLLog.fine("Found a minecraft related file at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
    052                            candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.JAR, i==0, true));
    053                        }
    054                    }
    055                    else if (minecraftSources[i].isDirectory())
    056                    {
    057                        FMLLog.fine("Found a minecraft related directory at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
    058                        candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.DIR, i==0, true));
    059                    }
    060                }
    061            }
    062
    063        }
    064
    065        public void findModDirMods(File modsDir)
    066        {
    067            File[] modList = modsDir.listFiles();
    068            // Sort the files into alphabetical order first
    069            Arrays.sort(modList);
    070
    071            for (File modFile : modList)
    072            {
    073                if (modFile.isDirectory())
    074                {
    075                    FMLLog.fine("Found a candidate mod directory %s", modFile.getName());
    076                    candidates.add(new ModCandidate(modFile, modFile, ContainerType.DIR));
    077                }
    078                else
    079                {
    080                    Matcher matcher = zipJar.matcher(modFile.getName());
    081
    082                    if (matcher.matches())
    083                    {
    084                        FMLLog.fine("Found a candidate zip or jar file %s", matcher.group(0));
    085                        candidates.add(new ModCandidate(modFile, modFile, ContainerType.JAR));
    086                    }
    087                    else
    088                    {
    089                        FMLLog.fine("Ignoring unknown file %s in mods directory", modFile.getName());
    090                    }
    091                }
    092            }
    093        }
    094
    095        public List<ModContainer> identifyMods()
    096        {
    097            List<ModContainer> modList = Lists.newArrayList();
    098
    099            for (ModCandidate candidate : candidates)
    100            {
    101                try
    102                {
    103                    List<ModContainer> mods = candidate.explore(dataTable);
    104                    if (mods.isEmpty() && !candidate.isClasspath())
    105                    {
    106                        nonModLibs.add(candidate.getModContainer());
    107                    }
    108                    else
    109                    {
    110                        modList.addAll(mods);
    111                    }
    112                }
    113                catch (LoaderException le)
    114                {
    115                    FMLLog.log(Level.WARNING, le, "Identified a problem with the mod candidate %s, ignoring this source", candidate.getModContainer());
    116                }
    117                catch (Throwable t)
    118                {
    119                    Throwables.propagate(t);
    120                }
    121            }
    122
    123            return modList;
    124        }
    125
    126        public ASMDataTable getASMTable()
    127        {
    128            return dataTable;
    129        }
    130
    131        public List<File> getNonModLibs()
    132        {
    133            return nonModLibs;
    134        }
    135
    136    }