Commit 027952f9358b099027c91317cd05be74f0e084f8

Authored by Mumfrey
1 parent 1ef9f4cf

refactoring enumerator

java/common/com/mumfrey/liteloader/api/ContainerRegistry.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +import java.io.File;
  4 +import java.util.Collection;
  5 +
  6 +import com.mumfrey.liteloader.core.ModInfo;
  7 +import com.mumfrey.liteloader.interfaces.Loadable;
  8 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  9 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  10 +
  11 +/**
  12 + * Registry for enabled, disabled, injected and bad containers
  13 + *
  14 + * @author Adam Mummery-Smith
  15 + */
  16 +public interface ContainerRegistry
  17 +{
  18 + public enum DisabledReason
  19 + {
  20 + UNKNOWN("Container %s is could not be loaded for UNKNOWN reason"),
  21 + USER_DISABLED("Container %s is disabled"),
  22 + MISSING_DEPENDENCY("Container %s is missing one or more dependencies"),
  23 + MISSING_API("Container %s is missing one or more required APIs");
  24 +
  25 + private final String message;
  26 +
  27 + private DisabledReason(String message)
  28 + {
  29 + this.message = message;
  30 + }
  31 +
  32 + public String getMessage(LoadableMod<?> container)
  33 + {
  34 + return String.format(this.message, container);
  35 + }
  36 + }
  37 +
  38 + /**
  39 + * Register an enabled container, removes the container from the disabled containers list if present
  40 + */
  41 + public abstract void registerEnabledContainer(LoadableMod<?> container);
  42 +
  43 + /**
  44 + * Get all enabled containers
  45 + */
  46 + public abstract Collection<? extends LoadableMod<?>> getEnabledContainers();
  47 +
  48 + /**
  49 + * Get a specific enabled container by id
  50 + */
  51 + public abstract LoadableMod<?> getEnabledContainer(String identifier);
  52 +
  53 + /**
  54 + * Register a disabled container
  55 + */
  56 + public abstract void registerDisabledContainer(LoadableMod<?> container, DisabledReason reason);
  57 +
  58 + /**
  59 + * Get all disabled containers
  60 + */
  61 + public abstract Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers();
  62 +
  63 + /**
  64 + * Check whether a specific container is registered as disabled
  65 + */
  66 + public abstract boolean isDisabledContainer(LoadableMod<?> container);
  67 +
  68 + /**
  69 + * Register a bad container
  70 + */
  71 + public abstract void registerBadContainer(Loadable<?> container, String reason);
  72 +
  73 + /**
  74 + * Get all bad containers
  75 + */
  76 + public abstract Collection<? extends ModInfo<Loadable<?>>> getBadContainers();
  77 +
  78 + /**
  79 + * Register a candidate tweak container
  80 + */
  81 + public abstract void registerTweakContainer(TweakContainer<File> container);
  82 +
  83 + /**
  84 + * Get all registered tweak containers
  85 + */
  86 + public abstract Collection<TweakContainer<File>> getTweakContainers();
  87 +
  88 + /**
  89 + * Register an injected tweak container
  90 + */
  91 + public abstract void registerInjectedTweak(TweakContainer<File> container);
  92 +
  93 + /**
  94 + * Get all injected tweak containers
  95 + */
  96 + public abstract Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
  97 +}
... ...
java/common/com/mumfrey/liteloader/api/EnumerationObserver.java
... ... @@ -2,10 +2,10 @@ package com.mumfrey.liteloader.api;
2 2  
3 3 import java.io.File;
4 4  
  5 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
5 6 import com.mumfrey.liteloader.core.ModInfo;
6 7 import com.mumfrey.liteloader.interfaces.LoadableMod;
7 8 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
8   -import com.mumfrey.liteloader.interfaces.LoaderEnumerator.DisabledReason;
9 9 import com.mumfrey.liteloader.interfaces.TweakContainer;
10 10  
11 11 /**
... ...
java/common/com/mumfrey/liteloader/api/EnumeratorPlugin.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  6 +import com.mumfrey.liteloader.launch.LoaderEnvironment;
  7 +import com.mumfrey.liteloader.launch.LoaderProperties;
  8 +
  9 +/**
  10 + * LiteLoader Extensible API - Interface for objects which can interact with the enumeration process, not yet available to APIs
  11 + *
  12 + * @author Adam Mummery-Smith
  13 + */
  14 +public interface EnumeratorPlugin
  15 +{
  16 + /**
  17 + * Initialise this plugin
  18 + */
  19 + public abstract void init(LoaderEnvironment environment, LoaderProperties properties);
  20 +
  21 + /**
  22 + * Get classes in the supplied container
  23 + *
  24 + * @param container Container to inspect
  25 + * @param classloader ClassLoader for this container
  26 + * @param superClass Superclass the class must implement
  27 + * @param supportedPrefixes Registered class prefixes
  28 + * @return
  29 + */
  30 + public abstract <T> List<Class<? extends T>> getClasses(LoadableMod<?> container, ClassLoader classloader, ModClassValidator validator);
  31 +
  32 + public abstract boolean checkEnabled(ContainerRegistry containers, LoadableMod<?> container);
  33 +
  34 + public abstract boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base);
  35 +
  36 + public abstract boolean checkAPIRequirements(ContainerRegistry containers, LoadableMod<?> container);
  37 +}
... ...
java/common/com/mumfrey/liteloader/api/ModClassValidator.java 0 → 100644
  1 +package com.mumfrey.liteloader.api;
  2 +
  3 +/**
  4 + * Interface for object which validates whether a supplied mod class can be loaded
  5 + *
  6 + * @author Adam Mummery-Smith
  7 + */
  8 +public interface ModClassValidator
  9 +{
  10 + public abstract boolean validateName(String className);
  11 +
  12 + public abstract boolean validateClass(ClassLoader classLoader, Class<?> candidateClass);
  13 +}
... ...
java/common/com/mumfrey/liteloader/core/Containers.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import java.io.File;
  4 +import java.util.ArrayList;
  5 +import java.util.Collection;
  6 +import java.util.HashMap;
  7 +import java.util.HashSet;
  8 +import java.util.List;
  9 +import java.util.Map;
  10 +import java.util.Set;
  11 +
  12 +import com.mumfrey.liteloader.api.ContainerRegistry;
  13 +import com.mumfrey.liteloader.interfaces.Loadable;
  14 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  15 +import com.mumfrey.liteloader.interfaces.TweakContainer;
  16 +
  17 +/**
  18 + * Implementation of ContainerRegistry for LiteLoaderEnumerator
  19 + *
  20 + * @author Adam Mummery-Smith
  21 + */
  22 +class Containers implements ContainerRegistry
  23 +{
  24 + /**
  25 + * Mod containers which are disabled
  26 + */
  27 + private final Map<String, ModInfo<Loadable<?>>> disabledContainers = new HashMap<String, ModInfo<Loadable<?>>>();
  28 +
  29 + /**
  30 + * Mapping of identifiers to mod containers
  31 + */
  32 + private final Map<String, LoadableMod<?>> enabledContainers = new HashMap<String, LoadableMod<?>>();
  33 +
  34 + /**
  35 + * Map of containers which cannot be loaded to reasons
  36 + */
  37 + private final Set<ModInfo<Loadable<?>>> badContainers = new HashSet<ModInfo<Loadable<?>>>();
  38 +
  39 + /**
  40 + * Tweaks to inject
  41 + */
  42 + private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>();
  43 +
  44 + /**
  45 + * Other tweak-containing jars which we have injected
  46 + */
  47 + private final List<ModInfo<Loadable<?>>> injectedTweaks = new ArrayList<ModInfo<Loadable<?>>>();
  48 +
  49 + /* (non-Javadoc)
  50 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getDisabledContainers()
  51 + */
  52 + @Override
  53 + public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
  54 + {
  55 + return this.disabledContainers.values();
  56 + }
  57 +
  58 + /* (non-Javadoc)
  59 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getEnabledContainers()
  60 + */
  61 + @Override
  62 + public Collection<? extends LoadableMod<?>> getEnabledContainers()
  63 + {
  64 + return this.enabledContainers.values();
  65 + }
  66 +
  67 + /* (non-Javadoc)
  68 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getBadContainers()
  69 + */
  70 + @Override
  71 + public Collection<? extends ModInfo<Loadable<?>>> getBadContainers()
  72 + {
  73 + return this.badContainers;
  74 + }
  75 +
  76 + /* (non-Javadoc)
  77 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getTweakContainers()
  78 + */
  79 + @Override
  80 + public List<TweakContainer<File>> getTweakContainers()
  81 + {
  82 + return this.tweakContainers;
  83 + }
  84 +
  85 + /* (non-Javadoc)
  86 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getInjectedTweaks()
  87 + */
  88 + @Override
  89 + public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
  90 + {
  91 + return this.injectedTweaks;
  92 + }
  93 +
  94 + /* (non-Javadoc)
  95 + * @see com.mumfrey.liteloader.api.ContainerRegistry#isDisabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
  96 + */
  97 + @Override
  98 + public boolean isDisabledContainer(LoadableMod<?> container)
  99 + {
  100 + return this.disabledContainers.containsValue(container);
  101 + }
  102 +
  103 + /* (non-Javadoc)
  104 + * @see com.mumfrey.liteloader.api.ContainerRegistry#getEnabledContainer(java.lang.String)
  105 + */
  106 + @Override
  107 + public LoadableMod<?> getEnabledContainer(String identifier)
  108 + {
  109 + LoadableMod<?> container = this.enabledContainers.get(identifier);
  110 + return container != null ? container : LoadableMod.NONE;
  111 + }
  112 +
  113 + /* (non-Javadoc)
  114 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerBadContainer(com.mumfrey.liteloader.interfaces.Loadable, java.lang.String)
  115 + */
  116 + @Override
  117 + public void registerBadContainer(Loadable<?> container, String reason)
  118 + {
  119 + this.badContainers.add(new BadContainerInfo(container, reason));
  120 + }
  121 +
  122 + /* (non-Javadoc)
  123 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerEnabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
  124 + */
  125 + @Override
  126 + public void registerEnabledContainer(LoadableMod<?> container)
  127 + {
  128 + this.disabledContainers.remove(container.getIdentifier());
  129 + this.enabledContainers.put(container.getIdentifier(), container);
  130 + }
  131 +
  132 + /* (non-Javadoc)
  133 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerDisabledContainer(com.mumfrey.liteloader.interfaces.LoadableMod, com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason)
  134 + */
  135 + @Override
  136 + public void registerDisabledContainer(LoadableMod<?> container, DisabledReason reason)
  137 + {
  138 + this.enabledContainers.remove(container.getIdentifier());
  139 + this.disabledContainers.put(container.getIdentifier(), new NonMod(container, false));
  140 + }
  141 +
  142 + /* (non-Javadoc)
  143 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerTweakContainer(com.mumfrey.liteloader.interfaces.TweakContainer)
  144 + */
  145 + @Override
  146 + public void registerTweakContainer(TweakContainer<File> container)
  147 + {
  148 + this.tweakContainers.add(container);
  149 + }
  150 +
  151 + /* (non-Javadoc)
  152 + * @see com.mumfrey.liteloader.api.ContainerRegistry#registerInjectedTweak(com.mumfrey.liteloader.interfaces.TweakContainer)
  153 + */
  154 + @Override
  155 + public void registerInjectedTweak(TweakContainer<File> container)
  156 + {
  157 + this.injectedTweaks.add(new NonMod(container, true));
  158 + }
  159 +}
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderBootstrap.java
... ... @@ -27,6 +27,8 @@ import com.mumfrey.liteloader.api.manager.APIRegistry;
27 27 import com.mumfrey.liteloader.common.LoadingProgress;
28 28 import com.mumfrey.liteloader.core.api.LiteLoaderCoreAPI;
29 29 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
  30 +import com.mumfrey.liteloader.launch.ClassTransformerManager;
  31 +import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
30 32 import com.mumfrey.liteloader.launch.LoaderBootstrap;
31 33 import com.mumfrey.liteloader.launch.LoaderEnvironment;
32 34 import com.mumfrey.liteloader.launch.LoaderProperties;
... ... @@ -259,9 +261,25 @@ class LiteLoaderBootstrap implements LoaderBootstrap, LoaderEnvironment, LoaderP
259 261 }
260 262  
261 263 @Override
262   - public ITweaker getTweaker()
  264 + public boolean addCascadedTweaker(String tweakClass, int priority)
263 265 {
264   - return this.tweaker;
  266 + if (this.tweaker instanceof LiteLoaderTweaker)
  267 + {
  268 + return ((LiteLoaderTweaker)this.tweaker).addCascadedTweaker(tweakClass, priority);
  269 + }
  270 +
  271 + return false;
  272 + }
  273 +
  274 + @Override
  275 + public ClassTransformerManager getTransformerManager()
  276 + {
  277 + if (this.tweaker instanceof LiteLoaderTweaker)
  278 + {
  279 + return ((LiteLoaderTweaker)this.tweaker).getTransformerManager();
  280 + }
  281 +
  282 + return null;
265 283 }
266 284  
267 285 /* (non-Javadoc)
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderEnumerator.java
... ... @@ -9,7 +9,6 @@ import java.util.Collections;
9 9 import java.util.HashMap;
10 10 import java.util.HashSet;
11 11 import java.util.LinkedHashSet;
12   -import java.util.LinkedList;
13 12 import java.util.List;
14 13 import java.util.Map;
15 14 import java.util.Set;
... ... @@ -19,17 +18,22 @@ import net.minecraft.launchwrapper.LaunchClassLoader;
19 18  
20 19 import com.google.common.base.Throwables;
21 20 import com.mumfrey.liteloader.LiteMod;
  21 +import com.mumfrey.liteloader.api.ContainerRegistry;
  22 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
22 23 import com.mumfrey.liteloader.api.EnumerationObserver;
23 24 import com.mumfrey.liteloader.api.EnumeratorModule;
  25 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
24 26 import com.mumfrey.liteloader.api.LiteAPI;
25   -import com.mumfrey.liteloader.api.manager.APIProvider;
  27 +import com.mumfrey.liteloader.api.ModClassValidator;
  28 +import com.mumfrey.liteloader.core.api.DefaultClassValidator;
  29 +import com.mumfrey.liteloader.core.api.DefaultEnumeratorPlugin;
26 30 import com.mumfrey.liteloader.core.event.HandlerList;
27   -import com.mumfrey.liteloader.core.exceptions.OutdatedLoaderException;
28 31 import com.mumfrey.liteloader.interfaces.FastIterableDeque;
29 32 import com.mumfrey.liteloader.interfaces.Loadable;
30 33 import com.mumfrey.liteloader.interfaces.LoadableMod;
31 34 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
32 35 import com.mumfrey.liteloader.interfaces.TweakContainer;
  36 +import com.mumfrey.liteloader.launch.ClassTransformerManager;
33 37 import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
34 38 import com.mumfrey.liteloader.launch.LoaderEnvironment;
35 39 import com.mumfrey.liteloader.launch.LoaderProperties;
... ... @@ -73,55 +77,32 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
73 77 private final LoaderEnvironment environment;
74 78  
75 79 private final LoaderProperties properties;
76   -
77   - private final LiteLoaderTweaker tweaker;
78 80  
79 81 /**
80 82 * Reference to the launch classloader
81 83 */
82 84 private final LaunchClassLoader classLoader;
83   -
84   - /**
85   - * Classes to load, mapped by class name
86   - */
87   - private final Set<ModInfo<LoadableMod<?>>> modsToLoad = new LinkedHashSet<ModInfo<LoadableMod<?>>>();
88 85  
89 86 /**
90   - * Mod containers which are disabled
91   - */
92   - private final Map<String, ModInfo<Loadable<?>>> disabledContainers = new HashMap<String, ModInfo<Loadable<?>>>();
93   -
94   - /**
95   - * Mapping of identifiers to mod containers
96   - */
97   - private final Map<String, LoadableMod<?>> enabledContainers = new HashMap<String, LoadableMod<?>>();
98   -
99   - /**
100   - * Map of containers which cannot be loaded to reasons
  87 + *
101 88 */
102   - private final Set<ModInfo<Loadable<?>>> badContainers = new HashSet<ModInfo<Loadable<?>>>();
  89 + private final List<EnumeratorModule> modules = new ArrayList<EnumeratorModule>();
103 90  
104   - /**
105   - * Containers which have already been checked for potential mod candidates
106   - */
107   - private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>();
  91 + private final List<EnumeratorPlugin> plugins = new ArrayList<EnumeratorPlugin>();
108 92  
109   - /**
110   - * Tweaks to inject
111   - */
112   - private final List<TweakContainer<File>> tweakContainers = new ArrayList<TweakContainer<File>>();
  93 + private final ContainerRegistry containers = new Containers();
113 94  
114 95 /**
115   - * Other tweak-containing jars which we have injected
  96 + * Containers which have already been checked for potential mod candidates
116 97 */
117   - private final List<ModInfo<Loadable<?>>> injectedTweaks = new ArrayList<ModInfo<Loadable<?>>>();
  98 + private final Set<LoadableMod<?>> enumeratedContainers = new HashSet<LoadableMod<?>>();
118 99  
119 100 /**
120   - *
  101 + * Classes to load, mapped by class name
121 102 */
122   - private final List<EnumeratorModule> modules = new ArrayList<EnumeratorModule>();
  103 + private final Set<ModInfo<LoadableMod<?>>> modsToLoad = new LinkedHashSet<ModInfo<LoadableMod<?>>>();
123 104  
124   - private final String[] supportedPrefixes;
  105 + private final ModClassValidator validator;
125 106  
126 107 private final FastIterableDeque<EnumerationObserver> observers = new HandlerList<EnumerationObserver>(EnumerationObserver.class);
127 108  
... ... @@ -136,9 +117,11 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
136 117 {
137 118 this.environment = environment;
138 119 this.properties = properties;
139   - this.tweaker = (LiteLoaderTweaker)environment.getTweaker();
140 120 this.classLoader = classLoader;
141   - this.supportedPrefixes = this.getSupportedPrefixes(environment);
  121 + this.validator = this.getValidator(environment);
  122 +
  123 + this.initModules(environment);
  124 + this.registerPlugin(new DefaultEnumeratorPlugin());
142 125  
143 126 // Initialise observers
144 127 this.observers.addAll(environment.getAPIAdapter().getPreInitObservers(EnumerationObserver.class));
... ... @@ -150,12 +133,30 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
150 133 /**
151 134 * @param environment
152 135 */
153   - private String[] getSupportedPrefixes(LoaderEnvironment environment)
  136 + private ModClassValidator getValidator(LoaderEnvironment environment)
154 137 {
155 138 List<String> prefixes = new ArrayList<String>();
156 139  
157 140 for (LiteAPI api : environment.getAPIProvider().getAPIs())
158 141 {
  142 + String prefix = api.getModClassPrefix();
  143 + if (prefix != null)
  144 + {
  145 + LiteLoaderLogger.info("Adding supported mod class prefix '%s'", prefix);
  146 + prefixes.add(prefix);
  147 + }
  148 + }
  149 +
  150 + return new DefaultClassValidator<LiteMod>(LiteMod.class, prefixes);
  151 + }
  152 +
  153 + /**
  154 + * @param environment
  155 + */
  156 + private void initModules(LoaderEnvironment environment)
  157 + {
  158 + for (LiteAPI api : environment.getAPIProvider().getAPIs())
  159 + {
159 160 List<EnumeratorModule> apiModules = api.getEnumeratorModules();
160 161  
161 162 if (apiModules != null)
... ... @@ -165,18 +166,9 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
165 166 this.registerModule(module);
166 167 }
167 168 }
168   -
169   - String prefix = api.getModClassPrefix();
170   - if (prefix != null)
171   - {
172   - LiteLoaderLogger.info("Adding supported mod class prefix '%s'", prefix);
173   - prefixes.add(prefix);
174   - }
175 169 }
176   -
177   - return prefixes.toArray(new String[prefixes.size()]);
178 170 }
179   -
  171 +
180 172 private void checkState(EnumeratorState state, String action)
181 173 {
182 174 if (this.state != state)
... ... @@ -243,6 +235,19 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
243 235 }
244 236 }
245 237  
  238 + @Override
  239 + public void registerPlugin(EnumeratorPlugin plugin)
  240 + {
  241 + this.checkState(EnumeratorState.INIT, "registerPlugin");
  242 +
  243 + if (plugin != null && !this.plugins.contains(plugin))
  244 + {
  245 + LiteLoaderLogger.info("Registering enumerator plugin %s: [%s]", plugin.getClass().getSimpleName(), plugin);
  246 + this.plugins.add(plugin);
  247 + plugin.init(this.environment, this.properties);
  248 + }
  249 + }
  250 +
246 251 /**
247 252 * Get the list of all enumerated mod classes to load
248 253 */
... ... @@ -250,7 +255,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
250 255 public Collection<? extends ModInfo<LoadableMod<?>>> getModsToLoad()
251 256 {
252 257 this.checkState(EnumeratorState.FINALISED, "getModsToLoad");
253   -
254 258 return Collections.unmodifiableSet(this.modsToLoad);
255 259 }
256 260  
... ... @@ -261,27 +265,24 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
261 265 public Collection<? extends ModInfo<Loadable<?>>> getDisabledContainers()
262 266 {
263 267 this.checkState(EnumeratorState.FINALISED, "getDisabledContainers");
264   -
265   - return this.disabledContainers.values();
  268 + return this.containers.getDisabledContainers();
266 269 }
267 270  
268 271 @Override
269 272 public Collection<? extends ModInfo<Loadable<?>>> getBadContainers()
270 273 {
271 274 this.checkState(EnumeratorState.FINALISED, "getBadContainers");
272   -
273   - return this.badContainers;
  275 + return this.containers.getBadContainers();
274 276 }
275 277  
276 278 /**
277 279 * Get the list of injected tweak containers
278 280 */
279 281 @Override
280   - public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
  282 + public Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
281 283 {
282 284 this.checkState(EnumeratorState.FINALISED, "getInjectedTweaks");
283   -
284   - return this.injectedTweaks;
  285 + return this.containers.getInjectedTweaks();
285 286 }
286 287  
287 288 /**
... ... @@ -304,7 +305,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
304 305 public String getModMetaData(Class<? extends LiteMod> modClass, String metaDataKey, String defaultValue)
305 306 {
306 307 this.checkState(EnumeratorState.FINALISED, "getModMetaData");
307   -
308 308 return this.getContainerForMod(modClass).getMetaValue(metaDataKey, defaultValue);
309 309 }
310 310  
... ... @@ -315,17 +315,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
315 315 public LoadableMod<?> getContainer(String identifier)
316 316 {
317 317 this.checkState(EnumeratorState.FINALISED, "getContainer");
318   -
319   - return this.getContainerById(identifier);
320   - }
321   -
322   - /**
323   - * @param identifier
324   - */
325   - private LoadableMod<?> getContainerById(String identifier)
326   - {
327   - LoadableMod<?> container = this.enabledContainers.get(identifier);
328   - return container != null ? container : LoadableMod.NONE;
  318 + return this.containers.getEnabledContainer(identifier);
329 319 }
330 320  
331 321 /**
... ... @@ -335,7 +325,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
335 325 public LoadableMod<?> getContainer(Class<? extends LiteMod> modClass)
336 326 {
337 327 this.checkState(EnumeratorState.FINALISED, "getContainer");
338   -
339 328 return this.getContainerForMod(modClass);
340 329 }
341 330  
... ... @@ -403,7 +392,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
403 392 {
404 393 this.gotoState(EnumeratorState.INJECT);
405 394  
406   - for (TweakContainer<File> tweakContainer : this.tweakContainers)
  395 + for (TweakContainer<File> tweakContainer : this.containers.getTweakContainers())
407 396 {
408 397 this.addTweaksFrom(tweakContainer);
409 398 }
... ... @@ -418,36 +407,13 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
418 407 try
419 408 {
420 409 this.gotoState(EnumeratorState.INJECT);
421   -
422   - for (EnumeratorModule module : this.modules)
423   - {
424   - try
425   - {
426   - module.injectIntoClassLoader(this, this.classLoader);
427   - }
428   - catch (Throwable th)
429   - {
430   - LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst injecting", module.getClass().getName());
431   - }
432   - }
  410 + this.injectIntoClassLoader();
433 411  
434 412 this.gotoState(EnumeratorState.REGISTER);
435   -
436   - for (EnumeratorModule module : this.modules)
437   - {
438   - try
439   - {
440   - module.registerMods(this, this.classLoader);
441   - }
442   - catch (Throwable th)
443   - {
444   - LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst registering mods", module.getClass().getName());
445   - }
446   - }
447   -
448   - LiteLoaderLogger.info("Mod class discovery completed");
  413 + this.registerMods();
449 414  
450 415 this.gotoState(EnumeratorState.FINALISED);
  416 + LiteLoaderLogger.info("Mod class discovery completed");
451 417 }
452 418 catch (IllegalStateException ex) // wut?
453 419 {
... ... @@ -459,6 +425,42 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
459 425 }
460 426 }
461 427  
  428 + /**
  429 + *
  430 + */
  431 + private void injectIntoClassLoader()
  432 + {
  433 + for (EnumeratorModule module : this.modules)
  434 + {
  435 + try
  436 + {
  437 + module.injectIntoClassLoader(this, this.classLoader);
  438 + }
  439 + catch (Throwable th)
  440 + {
  441 + LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst injecting", module.getClass().getName());
  442 + }
  443 + }
  444 + }
  445 +
  446 + /**
  447 + *
  448 + */
  449 + private void registerMods()
  450 + {
  451 + for (EnumeratorModule module : this.modules)
  452 + {
  453 + try
  454 + {
  455 + module.registerMods(this, this.classLoader);
  456 + }
  457 + catch (Throwable th)
  458 + {
  459 + LiteLoaderLogger.warning(th, "Enumerator Module %s encountered an error whilst registering mods", module.getClass().getName());
  460 + }
  461 + }
  462 + }
  463 +
462 464 /* (non-Javadoc)
463 465 * @see com.mumfrey.liteloader.interfaces.ModularEnumerator#registerModContainer(com.mumfrey.liteloader.interfaces.LoadableMod)
464 466 */
... ... @@ -469,7 +471,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
469 471  
470 472 if (container != null)
471 473 {
472   - if (!container.isEnabled(this.environment))
  474 + if (!this.checkEnabled(container))
473 475 {
474 476 this.registerDisabledContainer(container, DisabledReason.USER_DISABLED);
475 477 return false;
... ... @@ -492,14 +494,12 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
492 494  
493 495 return true;
494 496 }
495   -
  497 +
496 498 @Override
497 499 public void registerBadContainer(Loadable<?> container, String reason)
498 500 {
499 501 this.checkState(EnumeratorState.DISCOVER, "registerBadContainer");
500   -
501   - BadContainerInfo badMod = new BadContainerInfo(container, reason);
502   - this.badContainers.add(badMod);
  502 + this.containers.registerBadContainer(container, reason);
503 503 }
504 504  
505 505 /**
... ... @@ -508,10 +508,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
508 508 protected void registerEnabledContainer(LoadableMod<?> container)
509 509 {
510 510 this.checkState(EnumeratorState.DISCOVER, "registerEnabledContainer");
511   -
512   - this.disabledContainers.remove(container.getIdentifier());
513   - this.enabledContainers.put(container.getIdentifier(), container);
514   -
  511 + this.containers.registerEnabledContainer(container);
515 512 this.observers.all().onRegisterEnabledContainer(this, container);
516 513 }
517 514  
... ... @@ -523,10 +520,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
523 520 this.checkState(EnumeratorState.DISCOVER, "registerDisabledContainer");
524 521  
525 522 LiteLoaderLogger.info(Verbosity.REDUCED, reason.getMessage(container));
526   -
527   - this.enabledContainers.remove(container.getIdentifier());
528   - this.disabledContainers.put(container.getIdentifier(), new NonMod(container, false));
529   -
  523 + this.containers.registerDisabledContainer(container, reason);
530 524 this.observers.all().onRegisterDisabledContainer(this, container, reason);
531 525 }
532 526  
... ... @@ -544,7 +538,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
544 538 return false;
545 539 }
546 540  
547   - this.tweakContainers.add(container);
  541 + this.containers.registerTweakContainer(container);
548 542 this.observers.all().onRegisterTweakContainer(this, container);
549 543 return true;
550 544 }
... ... @@ -577,14 +571,14 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
577 571 String tweakClass = container.getTweakClassName();
578 572 int tweakPriority = container.getTweakPriority();
579 573 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides tweakClass '%s', adding to Launch queue with priority %d", container.getName(), tweakClass, tweakPriority);
580   - if (this.tweaker.addCascadedTweaker(tweakClass, tweakPriority))
  574 + if (this.environment.addCascadedTweaker(tweakClass, tweakPriority))
581 575 {
582 576 LiteLoaderLogger.info(Verbosity.REDUCED, "tweakClass '%s' was successfully added", tweakClass);
583 577 container.injectIntoClassPath(this.classLoader, true);
584 578  
585 579 if (container.isExternalJar())
586 580 {
587   - this.injectedTweaks.add(new NonMod(container, true));
  581 + this.containers.registerInjectedTweak(container);
588 582 }
589 583  
590 584 String[] classPathEntries = container.getClassPathEntries();
... ... @@ -618,7 +612,8 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
618 612 for (String classTransformerClass : classTransformerClasses)
619 613 {
620 614 LiteLoaderLogger.info(Verbosity.REDUCED, "Mod file '%s' provides classTransformer '%s', adding to class loader", container.getName(), classTransformerClass);
621   - if (this.tweaker.getTransformerManager().injectTransformer(classTransformerClass))
  615 + ClassTransformerManager transformerManager = this.environment.getTransformerManager();
  616 + if (transformerManager != null && transformerManager.injectTransformer(classTransformerClass))
622 617 {
623 618 LiteLoaderLogger.info(Verbosity.REDUCED, "classTransformer '%s' was successfully added", classTransformerClass);
624 619 container.injectIntoClassPath(this.classLoader, true);
... ... @@ -638,7 +633,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
638 633 {
639 634 this.checkState(EnumeratorState.REGISTER, "registerModsFrom");
640 635  
641   - if (this.disabledContainers.containsValue(container))
  636 + if (this.containers.isDisabledContainer(container))
642 637 {
643 638 throw new IllegalArgumentException("Attempted to register mods from a disabled container '" + container.getName() + "'");
644 639 }
... ... @@ -651,7 +646,15 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
651 646  
652 647 this.enumeratedContainers.add(container);
653 648  
654   - LinkedList<Class<? extends LiteMod>> modClasses = LiteLoaderEnumerator.<LiteMod>getSubclassesFor(container, this.classLoader, LiteMod.class, this.supportedPrefixes);
  649 + List<Class<? extends LiteMod>> modClasses = new ArrayList<Class<? extends LiteMod>>();
  650 +
  651 + for (EnumeratorPlugin plugin : this.plugins)
  652 + {
  653 + List<Class<? extends LiteMod>> classes = plugin.getClasses(container, this.classLoader, this.validator);
  654 + LiteLoaderLogger.debug("Plugin %s returned %d classes for %s", plugin.getClass(), classes.size(), container.getDisplayName());
  655 + modClasses.addAll(classes);
  656 + }
  657 +
655 658 for (Class<? extends LiteMod> modClass : modClasses)
656 659 {
657 660 Mod mod = new Mod(container, modClass);
... ... @@ -661,9 +664,7 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
661 664 if (modClasses.size() > 0)
662 665 {
663 666 LiteLoaderLogger.info("Found %d potential matches", modClasses.size());
664   -
665   - this.disabledContainers.remove(container.getIdentifier());
666   - this.enabledContainers.put(container.getIdentifier(), container);
  667 + this.containers.registerEnabledContainer(container);
667 668 }
668 669 }
669 670  
... ... @@ -684,169 +685,37 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
684 685  
685 686 this.observers.all().onModAdded(this, mod);
686 687 }
687   -
688   - /**
689   - * Enumerate classes on the classpath which are subclasses of the specified
690   - * class
691   - *
692   - * @param superClass
693   - */
694   - private static <T> LinkedList<Class<? extends T>> getSubclassesFor(LoadableMod<?> container, ClassLoader classloader, Class<T> superClass, String[] supportedPrefixes)
  688 +
  689 + private boolean checkEnabled(LoadableMod<?> container)
695 690 {
696   - LinkedList<Class<? extends T>> classes = new LinkedList<Class<? extends T>>();
697   -
698   - if (container != null)
  691 + for (EnumeratorPlugin plugin : this.plugins)
699 692 {
700   - try
701   - {
702   - for (String fullClassName : container.getContainedClassNames())
703   - {
704   - boolean isDefaultPackage = fullClassName.lastIndexOf('.') == -1;
705   - String className = isDefaultPackage ? fullClassName : fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
706   - if (supportedPrefixes == null || supportedPrefixes.length == 0 || LiteLoaderEnumerator.startsWithAny(className, supportedPrefixes))
707   - {
708   - LiteLoaderEnumerator.<T>checkAndAddClass(classloader, superClass, classes, fullClassName);
709   - }
710   - }
711   - }
712   - catch (OutdatedLoaderException ex)
713   - {
714   - classes.clear();
715   - LiteLoaderLogger.info(Verbosity.REDUCED, "Error searching in '%s', missing API component '%s', your loader is probably out of date", container, ex.getMessage());
716   - }
717   - catch (Throwable th)
718   - {
719   - LiteLoaderLogger.warning(th, "Enumeration error");
720   - }
  693 + if (!plugin.checkEnabled(this.containers, container)) return false;
721 694 }
722 695  
723   - return classes;
  696 + return true;
724 697 }
725 698  
726   - /**
727   - * @param classloader
728   - * @param superClass
729   - * @param classes
730   - * @param className
731   - * @throws OutdatedLoaderException
732   - */
733   - private static <T> void checkAndAddClass(ClassLoader classloader, Class<T> superClass, LinkedList<Class<? extends T>> classes, String className) throws OutdatedLoaderException
  699 + @Override
  700 + public boolean checkAPIRequirements(LoadableMod<?> container)
734 701 {
735   - if (className.indexOf('$') > -1)
736   - return;
737   -
738   - try
  702 + for (EnumeratorPlugin plugin : this.plugins)
739 703 {
740   - Class<?> subClass = classloader.loadClass(className);
741   -
742   - if (subClass != null && !superClass.equals(subClass) && superClass.isAssignableFrom(subClass) && !subClass.isInterface() && !classes.contains(subClass))
743   - {
744   - @SuppressWarnings("unchecked")
745   - Class<? extends T> matchingClass = (Class<? extends T>)subClass;
746   - classes.add(matchingClass);
747   - }
  704 + if (!plugin.checkAPIRequirements(this.containers, container)) return false;
748 705 }
749   - catch (Throwable th)
750   - {
751   - if (th.getCause() != null)
752   - {
753   - String missingClassName = th.getCause().getMessage();
754   - if (th.getCause() instanceof NoClassDefFoundError && missingClassName != null)
755   - {
756   - if (missingClassName.startsWith("com/mumfrey/liteloader/"))
757   - {
758   - throw new OutdatedLoaderException(missingClassName.substring(missingClassName.lastIndexOf('/') + 1));
759   - }
760   -
761   -// String mahClassName = LiteLoaderEnumerator.getMissingAPIHandlerClass(classloader, className);
762   -// if (mahClassName != null)
763   -// {
764   -// LiteLoaderEnumerator.checkAndAddClass(classloader, superClass, classes, mahClassName);
765   -// return;
766   -// }
767   - }
768   - }
769   -
770   - LiteLoaderLogger.warning(th, "checkAndAddClass error while checking '%s'", className);
771   - }
772   - }
773   -
774   -// private static String getMissingAPIHandlerClass(ClassLoader classloader, String className)
775   -// {
776   -// String mahTypeDescriptor = Type.getDescriptor(MissingAPIHandlerClass.class);
777   -//
778   -// if (classloader instanceof LaunchClassLoader)
779   -// {
780   -// try
781   -// {
782   -// byte[] basicClass = ((LaunchClassLoader)classloader).getClassBytes(className);
783   -// ClassNode classNode = LiteLoaderEnumerator.readClass(basicClass);
784   -//
785   -// if (classNode.invisibleAnnotations != null)
786   -// {
787   -// for (AnnotationNode annotation : classNode.invisibleAnnotations)
788   -// {
789   -// if (mahTypeDescriptor.equals(annotation.desc))
790   -// {
791   -// return LiteLoaderEnumerator.<String>getAnnotationValue(annotation, "value");
792   -// }
793   -// }
794   -// }
795   -// }
796   -// catch (IOException ex)
797   -// {
798   -// ex.printStackTrace();
799   -// }
800   -// }
801   -//
802   -// return null;
803   -// }
804   -//
805   -// /**
806   -// * @param basicClass
807   -// * @return
808   -// */
809   -// private static ClassNode readClass(byte[] basicClass)
810   -// {
811   -// ClassReader classReader = new ClassReader(basicClass);
812   -// ClassNode classNode = new ClassNode();
813   -// classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
814   -// return classNode;
815   -// }
816   -//
817   -// /**
818   -// * @param annotation
819   -// * @param key
820   -// * @return
821   -// */
822   -// @SuppressWarnings("unchecked")
823   -// private static <T> T getAnnotationValue(AnnotationNode annotation, String key)
824   -// {
825   -// boolean getNextValue = false;
826   -// for (Object value : annotation.values)
827   -// {
828   -// if (getNextValue) return (T)value;
829   -// if (value.equals(key)) getNextValue = true;
830   -// }
831   -// return null;
832   -// }
833   -
  706 +
  707 + return true;
  708 + }
  709 +
834 710 @Override
835   - public boolean checkAPIRequirements(LoadableMod<?> container)
  711 + public boolean checkDependencies(LoadableMod<?> container)
836 712 {
837   - boolean result = true;
838   - APIProvider apiProvider = this.environment.getAPIProvider();
839   -
840   - for (String identifier : container.getRequiredAPIs())
  713 + for (EnumeratorPlugin plugin : this.plugins)
841 714 {
842   - if (!apiProvider.isAPIAvailable(identifier))
843   - {
844   - container.registerMissingAPI(identifier);
845   - result = false;
846   - }
  715 + if (!plugin.checkDependencies(this.containers, container)) return false;
847 716 }
848 717  
849   - return result;
  718 + return true;
850 719 }
851 720  
852 721 @SuppressWarnings("unchecked")
... ... @@ -860,59 +729,6 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
860 729 return true;
861 730 }
862 731  
863   - @Override
864   - public boolean checkDependencies(LoadableMod<?> base)
865   - {
866   - if (base == null || !base.hasDependencies()) return true;
867   -
868   - HashSet<String> circularDependencySet = new HashSet<String>();
869   - circularDependencySet.add(base.getIdentifier());
870   -
871   - boolean result = this.checkDependencies(base, base, circularDependencySet);
872   - LiteLoaderLogger.info(Verbosity.REDUCED, "Dependency check for %s %s", base.getIdentifier(), result ? "passed" : "failed");
873   -
874   - return result;
875   - }
876   -
877   - private boolean checkDependencies(LoadableMod<?> base, LoadableMod<?> container, Set<String> circularDependencySet)
878   - {
879   - if (container.getDependencies().size() == 0)
880   - return true;
881   -
882   - boolean result = true;
883   -
884   - for (String dependency : container.getDependencies())
885   - {
886   - if (!circularDependencySet.contains(dependency))
887   - {
888   - circularDependencySet.add(dependency);
889   -
890   - LoadableMod<?> dependencyContainer = this.getContainerById(dependency);
891   - if (dependencyContainer != LoadableMod.NONE)
892   - {
893   - if (this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), dependency))
894   - {
895   - result &= this.checkDependencies(base, dependencyContainer, circularDependencySet);
896   - }
897   - else
898   - {
899   -// LiteLoaderLogger.warning("Dependency %s required by %s is currently disabled", dependency, base.getIdentifier());
900   - base.registerMissingDependency(dependency);
901   - result = false;
902   - }
903   - }
904   - else
905   - {
906   -// LiteLoaderLogger.info("Dependency %s for %s is was not located, no container ", dependency, base.getIdentifier());
907   - base.registerMissingDependency(dependency);
908   - result = false;
909   - }
910   - }
911   - }
912   -
913   - return result;
914   - }
915   -
916 732 public static String getModClassName(LiteMod mod)
917 733 {
918 734 return LiteLoaderEnumerator.getModClassName(mod.getClass());
... ... @@ -922,12 +738,4 @@ public class LiteLoaderEnumerator implements LoaderEnumerator
922 738 {
923 739 return mod.getSimpleName().substring(7);
924 740 }
925   -
926   - private static boolean startsWithAny(String string, String[] candidates)
927   - {
928   - for (String candidate : candidates)
929   - if (string.startsWith(candidate)) return true;
930   -
931   - return false;
932   - }
933 741 }
934 742 \ No newline at end of file
... ...
java/common/com/mumfrey/liteloader/core/LiteLoaderMods.java
1 1 package com.mumfrey.liteloader.core;
2 2  
3 3 import java.io.File;
  4 +import java.util.Collection;
4 5 import java.util.Collections;
5 6 import java.util.Deque;
6 7 import java.util.HashMap;
... ... @@ -19,7 +20,6 @@ import com.mumfrey.liteloader.interfaces.LoadableMod;
19 20 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
20 21 import com.mumfrey.liteloader.interfaces.TweakContainer;
21 22 import com.mumfrey.liteloader.launch.ClassTransformerManager;
22   -import com.mumfrey.liteloader.launch.LiteLoaderTweaker;
23 23 import com.mumfrey.liteloader.launch.LoaderEnvironment;
24 24 import com.mumfrey.liteloader.launch.LoaderProperties;
25 25 import com.mumfrey.liteloader.modconfig.ConfigManager;
... ... @@ -57,11 +57,6 @@ public class LiteLoaderMods
57 57 protected final LoaderEnumerator enumerator;
58 58  
59 59 /**
60   - * Tweaker
61   - */
62   - private final LiteLoaderTweaker tweaker;
63   -
64   - /**
65 60 * Configuration manager
66 61 */
67 62 private final ConfigManager configManager;
... ... @@ -113,7 +108,6 @@ public class LiteLoaderMods
113 108 this.loader = loader;
114 109 this.environment = environment;
115 110 this.enumerator = environment.getEnumerator();
116   - this.tweaker = (LiteLoaderTweaker)environment.getTweaker();
117 111 this.properties = properties;
118 112 this.configManager = configManager;
119 113 }
... ... @@ -179,7 +173,7 @@ public class LiteLoaderMods
179 173 /**
180 174 * Get the list of injected tweak containers
181 175 */
182   - public List<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
  176 + public Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks()
183 177 {
184 178 return this.enumerator.getInjectedTweaks();
185 179 }
... ... @@ -672,7 +666,7 @@ public class LiteLoaderMods
672 666 */
673 667 private void validateModTransformers()
674 668 {
675   - ClassTransformerManager transformerManager = this.tweaker.getTransformerManager();
  669 + ClassTransformerManager transformerManager = this.environment.getTransformerManager();
676 670 Set<String> injectedTransformers = transformerManager.getInjectedTransformers();
677 671  
678 672 for (Mod mod : this.loadedMods)
... ... @@ -728,7 +722,7 @@ public class LiteLoaderMods
728 722 {
729 723 if (!mod.hasClassTransformers()) return false;
730 724  
731   - Set<String> injectedTransformers = this.tweaker.getTransformerManager().getInjectedTransformers();
  725 + Set<String> injectedTransformers = this.environment.getTransformerManager().getInjectedTransformers();
732 726 List<String> modTransformers = ((TweakContainer<?>)mod.getContainer()).getClassTransformerClassNames();
733 727  
734 728 for (String modTransformer : modTransformers)
... ...
java/common/com/mumfrey/liteloader/core/api/DefaultClassValidator.java 0 → 100644
  1 +package com.mumfrey.liteloader.core.api;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.mumfrey.liteloader.api.ModClassValidator;
  6 +
  7 +public class DefaultClassValidator<T> implements ModClassValidator
  8 +{
  9 + private final Class<T> superClass;
  10 +
  11 + private final List<String> supportedPrefixes;
  12 +
  13 + public DefaultClassValidator(Class<T> superClass, List<String> supportedPrefixes)
  14 + {
  15 + this.supportedPrefixes = supportedPrefixes;
  16 + this.superClass = superClass;
  17 + }
  18 +
  19 + @Override
  20 + public boolean validateName(String className)
  21 + {
  22 + return this.supportedPrefixes == null || this.supportedPrefixes.size() == 0 || DefaultClassValidator.startsWithAny(className, this.supportedPrefixes);
  23 + }
  24 +
  25 + @Override
  26 + public boolean validateClass(ClassLoader classLoader, Class<?> candidateClass)
  27 + {
  28 + return (candidateClass != null && !this.superClass.equals(candidateClass) && this.superClass.isAssignableFrom(candidateClass) && !candidateClass.isInterface());
  29 + }
  30 +
  31 + private static boolean startsWithAny(String string, List<String> candidates)
  32 + {
  33 + for (String candidate : candidates)
  34 + if (string.startsWith(candidate)) return true;
  35 +
  36 + return false;
  37 + }
  38 +}
... ...
java/common/com/mumfrey/liteloader/core/api/DefaultEnumeratorPlugin.java 0 → 100644
  1 +package com.mumfrey.liteloader.core.api;
  2 +
  3 +import java.util.ArrayList;
  4 +import java.util.HashSet;
  5 +import java.util.List;
  6 +import java.util.Set;
  7 +
  8 +import com.mumfrey.liteloader.api.ContainerRegistry;
  9 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
  10 +import com.mumfrey.liteloader.api.ModClassValidator;
  11 +import com.mumfrey.liteloader.api.manager.APIProvider;
  12 +import com.mumfrey.liteloader.core.exceptions.OutdatedLoaderException;
  13 +import com.mumfrey.liteloader.interfaces.LoadableMod;
  14 +import com.mumfrey.liteloader.launch.LoaderEnvironment;
  15 +import com.mumfrey.liteloader.launch.LoaderProperties;
  16 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
  17 +import com.mumfrey.liteloader.util.log.LiteLoaderLogger.Verbosity;
  18 +
  19 +public class DefaultEnumeratorPlugin implements EnumeratorPlugin
  20 +{
  21 + private LoaderEnvironment environment;
  22 +
  23 + @Override
  24 + public void init(LoaderEnvironment environment, LoaderProperties properties)
  25 + {
  26 + this.environment = environment;
  27 + }
  28 +
  29 + @Override
  30 + public boolean checkEnabled(ContainerRegistry containers, LoadableMod<?> container)
  31 + {
  32 + return container.isEnabled(this.environment);
  33 + }
  34 +
  35 + @Override
  36 + public boolean checkAPIRequirements(ContainerRegistry containers, LoadableMod<?> container)
  37 + {
  38 + boolean result = true;
  39 + APIProvider apiProvider = this.environment.getAPIProvider();
  40 +
  41 + for (String identifier : container.getRequiredAPIs())
  42 + {
  43 + if (!apiProvider.isAPIAvailable(identifier))
  44 + {
  45 + container.registerMissingAPI(identifier);
  46 + result = false;
  47 + }
  48 + }
  49 +
  50 + return result;
  51 + }
  52 +
  53 + @Override
  54 + public boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base)
  55 + {
  56 + if (base == null || !base.hasDependencies()) return true;
  57 +
  58 + HashSet<String> circularDependencySet = new HashSet<String>();
  59 + circularDependencySet.add(base.getIdentifier());
  60 +
  61 + boolean result = this.checkDependencies(containers, base, base, circularDependencySet);
  62 + LiteLoaderLogger.info(Verbosity.REDUCED, "Dependency check for %s %s", base.getIdentifier(), result ? "passed" : "failed");
  63 +
  64 + return result;
  65 + }
  66 +
  67 + private boolean checkDependencies(ContainerRegistry containers, LoadableMod<?> base, LoadableMod<?> container, Set<String> circularDependencySet)
  68 + {
  69 + if (container.getDependencies().size() == 0)
  70 + return true;
  71 +
  72 + boolean result = true;
  73 +
  74 + for (String dependency : container.getDependencies())
  75 + {
  76 + if (!circularDependencySet.contains(dependency))
  77 + {
  78 + circularDependencySet.add(dependency);
  79 +
  80 + LoadableMod<?> dependencyContainer = containers.getEnabledContainer(dependency);
  81 + if (dependencyContainer != LoadableMod.NONE)
  82 + {
  83 + String identifier = dependency;
  84 + if (this.environment.getEnabledModsList().isEnabled(this.environment.getProfile(), identifier))
  85 + {
  86 + result &= this.checkDependencies(containers, base, dependencyContainer, circularDependencySet);
  87 + }
  88 + else
  89 + {
  90 +// LiteLoaderLogger.warning("Dependency %s required by %s is currently disabled", dependency, base.getIdentifier());
  91 + base.registerMissingDependency(dependency);
  92 + result = false;
  93 + }
  94 + }
  95 + else
  96 + {
  97 +// LiteLoaderLogger.info("Dependency %s for %s is was not located, no container ", dependency, base.getIdentifier());
  98 + base.registerMissingDependency(dependency);
  99 + result = false;
  100 + }
  101 + }
  102 + }
  103 +
  104 + return result;
  105 + }
  106 +
  107 + /**
  108 + * Enumerate classes on the classpath which are subclasses of the specified
  109 + * class
  110 + *
  111 + * @param superClass
  112 + */
  113 + @Override
  114 + public <T> List<Class<? extends T>> getClasses(LoadableMod<?> container, ClassLoader classloader, ModClassValidator validator)
  115 + {
  116 + List<Class<? extends T>> classes = new ArrayList<Class<? extends T>>();
  117 +
  118 + if (container != null)
  119 + {
  120 + try
  121 + {
  122 + for (String fullClassName : container.getContainedClassNames())
  123 + {
  124 + boolean isDefaultPackage = fullClassName.lastIndexOf('.') == -1;
  125 + String className = isDefaultPackage ? fullClassName : fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
  126 + if (validator.validateName(className))
  127 + {
  128 + Class<? extends T> clazz = DefaultEnumeratorPlugin.<T>checkClass(classloader, validator, fullClassName);
  129 + if (clazz != null && !classes.contains(clazz))
  130 + {
  131 + classes.add(clazz);
  132 + }
  133 + }
  134 + }
  135 + }
  136 + catch (OutdatedLoaderException ex)
  137 + {
  138 + classes.clear();
  139 + LiteLoaderLogger.info(Verbosity.REDUCED, "Error searching in '%s', missing API component '%s', your loader is probably out of date", container, ex.getMessage());
  140 + }
  141 + catch (Throwable th)
  142 + {
  143 + LiteLoaderLogger.warning(th, "Enumeration error");
  144 + }
  145 + }
  146 +
  147 + return classes;
  148 + }
  149 +
  150 + @SuppressWarnings("unchecked")
  151 + private static <T> Class<? extends T> checkClass(ClassLoader classLoader, ModClassValidator validator, String className) throws OutdatedLoaderException
  152 + {
  153 + if (className.indexOf('$') > -1)
  154 + return null;
  155 +
  156 + try
  157 + {
  158 + Class<?> candidateClass = classLoader.loadClass(className);
  159 +
  160 + if (validator.validateClass(classLoader, candidateClass))
  161 + {
  162 + return (Class<? extends T>)candidateClass;
  163 + }
  164 + }
  165 + catch (Throwable th)
  166 + {
  167 + th.printStackTrace();
  168 +
  169 + if (th.getCause() != null)
  170 + {
  171 + String missingClassName = th.getCause().getMessage();
  172 + if (th.getCause() instanceof NoClassDefFoundError && missingClassName != null)
  173 + {
  174 + if (missingClassName.startsWith("com/mumfrey/liteloader/"))
  175 + {
  176 + throw new OutdatedLoaderException(missingClassName.substring(missingClassName.lastIndexOf('/') + 1));
  177 + }
  178 + }
  179 + }
  180 +
  181 + LiteLoaderLogger.warning(th, "checkAndAddClass error while checking '%s'", className);
  182 + }
  183 +
  184 + return null;
  185 + }
  186 +}
... ...
java/common/com/mumfrey/liteloader/interfaces/LoaderEnumerator.java
1 1 package com.mumfrey.liteloader.interfaces;
2 2  
3 3 import java.util.Collection;
4   -import java.util.List;
5 4 import java.util.Map;
6 5  
7 6 import com.mumfrey.liteloader.LiteMod;
... ... @@ -14,26 +13,6 @@ import com.mumfrey.liteloader.core.ModInfo;
14 13 */
15 14 public interface LoaderEnumerator extends ModularEnumerator
16 15 {
17   - public enum DisabledReason
18   - {
19   - UNKNOWN("Container %s is could not be loaded for UNKNOWN reason"),
20   - USER_DISABLED("Container %s is disabled"),
21   - MISSING_DEPENDENCY("Container %s is missing one or more dependencies"),
22   - MISSING_API("Container %s is missing one or more required APIs");
23   -
24   - private final String message;
25   -
26   - private DisabledReason(String message)
27   - {
28   - this.message = message;
29   - }
30   -
31   - public String getMessage(LoadableMod<?> container)
32   - {
33   - return String.format(this.message, container);
34   - }
35   - }
36   -
37 16 /**
38 17 * Perform pre-init tasks (container discovery)
39 18 */
... ... @@ -109,7 +88,7 @@ public interface LoaderEnumerator extends ModularEnumerator
109 88 /**
110 89 * Get all tweakers which were injected
111 90 */
112   - public abstract List<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
  91 + public abstract Collection<? extends ModInfo<Loadable<?>>> getInjectedTweaks();
113 92  
114 93 /**
115 94 * Get the shared modlist data
... ...
java/common/com/mumfrey/liteloader/interfaces/ModularEnumerator.java
... ... @@ -3,6 +3,7 @@ package com.mumfrey.liteloader.interfaces;
3 3 import java.io.File;
4 4  
5 5 import com.mumfrey.liteloader.api.EnumeratorModule;
  6 +import com.mumfrey.liteloader.api.EnumeratorPlugin;
6 7 import com.mumfrey.liteloader.core.ModInfo;
7 8  
8 9 /**
... ... @@ -20,6 +21,13 @@ public interface ModularEnumerator
20 21 public abstract void registerModule(EnumeratorModule module);
21 22  
22 23 /**
  24 + * Register a plugin into the enumerator
  25 + *
  26 + * @param plugin
  27 + */
  28 + public abstract void registerPlugin(EnumeratorPlugin plugin);
  29 +
  30 + /**
23 31 * @param container
24 32 */
25 33 public abstract boolean registerModContainer(LoadableMod<?> container);
... ...
java/common/com/mumfrey/liteloader/launch/LoaderEnvironment.java
... ... @@ -2,8 +2,6 @@ package com.mumfrey.liteloader.launch;
2 2  
3 3 import java.io.File;
4 4  
5   -import net.minecraft.launchwrapper.ITweaker;
6   -
7 5 import com.mumfrey.liteloader.api.manager.APIAdapter;
8 6 import com.mumfrey.liteloader.api.manager.APIProvider;
9 7 import com.mumfrey.liteloader.core.EnabledModsList;
... ... @@ -75,8 +73,7 @@ public interface LoaderEnvironment extends GameEnvironment
75 73 */
76 74 public abstract File inflectVersionedConfigPath(LiteLoaderVersion version);
77 75  
78   - /**
79   - * Get the tweaker
80   - */
81   - public abstract ITweaker getTweaker();
  76 + public abstract boolean addCascadedTweaker(String tweakClass, int priority);
  77 +
  78 + public abstract ClassTransformerManager getTransformerManager();
82 79 }
... ...
java/common/com/mumfrey/liteloader/transformers/event/json/ModEvents.java
... ... @@ -8,13 +8,13 @@ import java.util.Map;
8 8 import net.minecraft.launchwrapper.Launch;
9 9  
10 10 import com.google.common.base.Charsets;
  11 +import com.mumfrey.liteloader.api.ContainerRegistry.DisabledReason;
11 12 import com.mumfrey.liteloader.api.EnumerationObserver;
12 13 import com.mumfrey.liteloader.core.ModInfo;
13 14 import com.mumfrey.liteloader.core.api.LoadableModFile;
14 15 import com.mumfrey.liteloader.interfaces.LoadableMod;
15 16 import com.mumfrey.liteloader.interfaces.LoaderEnumerator;
16 17 import com.mumfrey.liteloader.interfaces.TweakContainer;
17   -import com.mumfrey.liteloader.interfaces.LoaderEnumerator.DisabledReason;
18 18 import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
19 19  
20 20 public class ModEvents implements EnumerationObserver
... ...