Search in sources :

Example 1 with DynamicClassLoader

use of com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader in project CommandHelper by EngineHub.

the class ExtensionManager method Cache.

public static void Cache(File extCache, Class... extraClasses) {
    // We will only cache on Windows, as Linux doesn't natively lock
    // files that are in use. Windows prevents any modification, making
    // it harder for server owners on Windows to update the jars.
    boolean onWindows = (OSUtils.GetOS() == OSUtils.OS.WINDOWS);
    if (!onWindows) {
        return;
    }
    // Create the directory if it doesn't exist.
    extCache.mkdirs();
    // cleanup wasn't successful on the last run.
    for (File f : extCache.listFiles()) {
        try {
            Files.delete(f.toPath());
        } catch (IOException ex) {
            Static.getLogger().log(Level.WARNING, "[CommandHelper] Could not delete loose file " + f.getAbsolutePath() + ": " + ex.getMessage());
        }
    }
    // The cache, cd and dcl here will just be thrown away.
    // They are only used here for the purposes of discovering what a given
    // jar has to offer.
    ClassDiscoveryCache cache = new ClassDiscoveryCache(CommandHelperFileLocations.getDefault().getCacheDirectory());
    cache.setLogger(Static.getLogger());
    DynamicClassLoader dcl = new DynamicClassLoader();
    ClassDiscovery cd = new ClassDiscovery();
    cd.setClassDiscoveryCache(cache);
    cd.addDiscoveryLocation(ClassDiscovery.GetClassContainer(ExtensionManager.class));
    for (Class klazz : extraClasses) {
        cd.addDiscoveryLocation(ClassDiscovery.GetClassContainer(klazz));
    }
    // Look in the given locations for jars, add them to our class discovery.
    List<File> toProcess = new ArrayList<>();
    for (File location : locations) {
        toProcess.addAll(getFiles(location));
    }
    // Load the files into the discovery mechanism.
    for (File file : toProcess) {
        if (!file.canRead()) {
            continue;
        }
        URL jar;
        try {
            jar = file.toURI().toURL();
        } catch (MalformedURLException ex) {
            Static.getLogger().log(Level.SEVERE, null, ex);
            continue;
        }
        dcl.addJar(jar);
        cd.addDiscoveryLocation(jar);
    }
    cd.setDefaultClassLoader(dcl);
    // Loop thru the found lifecycles, copy them to the cache using the name
    // given in the lifecycle. If more than one jar has the same internal
    // name, the filename will be given a number.
    Set<File> done = new HashSet<>();
    Map<String, Integer> namecount = new HashMap<>();
    // use their internal name.
    for (ClassMirror<? extends AbstractExtension> extmirror : cd.getClassesWithAnnotationThatExtend(MSExtension.class, AbstractExtension.class)) {
        if (extmirror.equals(new ClassMirror<>(AbstractExtension.class))) {
            continue;
        }
        AnnotationMirror plug = extmirror.getAnnotation(MSExtension.class);
        URL plugURL = extmirror.getContainer();
        // Get the internal name that this extension exposes.
        if (plugURL != null && plugURL.getPath().endsWith(".jar")) {
            File f;
            try {
                f = new File(URLDecoder.decode(plugURL.getFile(), "UTF8"));
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(ExtensionManager.class.getName()).log(Level.SEVERE, null, ex);
                continue;
            }
            // Skip extensions that originate from commandhelpercore.
            if (plugURL.equals(ClassDiscovery.GetClassContainer(ExtensionManager.class))) {
                done.add(f);
                continue;
            }
            // Skip files already processed.
            if (done.contains(f)) {
                CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.WARNING, f.getAbsolutePath() + " contains more than one extension" + " descriptor. Bug someone about it!", Target.UNKNOWN);
                continue;
            }
            done.add(f);
            String name = plug.getValue("value").toString();
            // lets track and rename them using a number scheme.
            if (namecount.containsKey(name.toLowerCase())) {
                int i = namecount.get(name.toLowerCase());
                name += "-" + i;
                namecount.put(name.toLowerCase(), i++);
                CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.WARNING, f.getAbsolutePath() + " contains a duplicate internally" + " named extension (" + name + "). Bug someone" + " about it!", Target.UNKNOWN);
            } else {
                namecount.put(name.toLowerCase(), 1);
            }
            // Rename the jar to use the plugin's internal name and
            // copy it into the cache.
            File newFile = new File(extCache, name.toLowerCase() + ".jar");
            try {
                Files.copy(f.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException ex) {
                Static.getLogger().log(Level.SEVERE, "Could not copy '" + f.getName() + "' to cache: " + ex.getMessage());
            }
        }
    }
    Set<ClassMirror<?>> classes = cd.getClassesWithAnnotation(api.class);
    // Now process @api annotated extensions, ignoring ones already processed.
    for (ClassMirror klass : classes) {
        URL plugURL = klass.getContainer();
        if (plugURL != null && plugURL.getPath().endsWith(".jar")) {
            File f;
            try {
                f = new File(URLDecoder.decode(plugURL.getFile(), "UTF8"));
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(ExtensionManager.class.getName()).log(Level.SEVERE, null, ex);
                continue;
            }
            // Skip files already processed.
            if (done.contains(f)) {
                continue;
            }
            // No special processing needed.
            if (cd.doesClassExtend(klass, Event.class) || cd.doesClassExtend(klass, Function.class)) {
                // We're processing it here instead of above, complain about it.
                CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.WARNING, f.getAbsolutePath() + " is an old-style extension!" + " Bug the author to update it to the new extension system!", Target.UNKNOWN);
                // Only process this file once.
                done.add(f);
                File newFile = new File(extCache, "oldstyle-" + f.getName());
                try {
                    Files.copy(f.toPath(), newFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException ex) {
                    Static.getLogger().log(Level.SEVERE, "Could not copy '" + f.getName() + "' to cache: " + ex.getMessage());
                }
            }
        }
    }
    // Shut down the original dcl to "unlock" the processed jars.
    // The cache and cd instances will just fall into oblivion.
    dcl.destroy();
    // Explicit call. Without this, jar files won't actually get unlocked on
    // Windows. Of course, this is hit and miss, but that's fine; we tried.
    System.gc();
}
Also used : DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) MalformedURLException(java.net.MalformedURLException) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ClassMirror(com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror) URL(java.net.URL) CFunction(com.laytonsmith.core.constructs.CFunction) Function(com.laytonsmith.core.functions.Function) HashSet(java.util.HashSet) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ClassDiscovery(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery) AnnotationMirror(com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.AnnotationMirror) Event(com.laytonsmith.core.events.Event) File(java.io.File) ClassDiscoveryCache(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscoveryCache)

Example 2 with DynamicClassLoader

use of com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader in project CommandHelper by EngineHub.

the class ExtensionDocGen method generate.

public static void generate(File inputExtension, OutputStream outputStream) throws InstantiationException, IllegalAccessException, MalformedURLException, IOException {
    ClassDiscovery customDiscovery = new ClassDiscovery();
    ClassDiscoveryCache cache = new ClassDiscoveryCache(CommandHelperFileLocations.getDefault().getCacheDirectory());
    customDiscovery.setClassDiscoveryCache(cache);
    URL url = new URL("jar:" + inputExtension.toURI().toURL() + "!/");
    customDiscovery.addDiscoveryLocation(url);
    customDiscovery.setDefaultClassLoader(ExtensionDocGen.class.getClassLoader());
    StringBuilder fdocs = new StringBuilder();
    DynamicClassLoader classloader = new DynamicClassLoader();
    classloader.addJar(url);
    // functions
    HashMap<Class<?>, ArrayList<Class<? extends Function>>> functionMap = new HashMap<>();
    for (Class<? extends Function> cf : customDiscovery.loadClassesWithAnnotationThatExtend(api.class, Function.class, classloader, true)) {
        Class enclosing = cf.getEnclosingClass();
        if (functionMap.containsKey(enclosing)) {
            functionMap.get(enclosing).add(cf);
        } else {
            functionMap.put(enclosing, new ArrayList<Class<? extends Function>>());
            functionMap.get(enclosing).add(cf);
        }
    }
    ArrayList<Entry<Class<?>, ArrayList<Class<? extends Function>>>> functionEntryList = new ArrayList<>(functionMap.entrySet());
    Collections.sort(functionEntryList, new Comparator<Entry<Class<?>, ArrayList<Class<? extends Function>>>>() {

        @Override
        public int compare(Entry<Class<?>, ArrayList<Class<? extends Function>>> o1, Entry<Class<?>, ArrayList<Class<? extends Function>>> o2) {
            return o1.getKey().getName().compareTo(o2.getKey().getName());
        }
    });
    for (Entry<Class<?>, ArrayList<Class<? extends Function>>> e : functionEntryList) {
        Collections.sort(e.getValue(), new Comparator<Class<? extends Function>>() {

            @Override
            public int compare(Class<? extends Function> o1, Class<? extends Function> o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
    }
    if (!functionEntryList.isEmpty()) {
        fdocs.append("# Functions").append(nl);
    }
    for (Entry<Class<?>, ArrayList<Class<? extends Function>>> entry : functionEntryList) {
        Class enclosingClass = entry.getKey();
        String[] split = enclosingClass.getName().split("\\.");
        fdocs.append("## ").append(split[split.length - 1]).append(nl);
        try {
            Method docsMethod = enclosingClass.getMethod("docs", (Class[]) null);
            Object o = enclosingClass.newInstance();
            fdocs.append((String) docsMethod.invoke(o, (Object[]) null)).append(nl).append(nl);
        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
        }
        for (Class<? extends Function> cf : entry.getValue()) {
            Function f = cf.newInstance();
            if (f.appearInDocumentation()) {
                DocGen.DocInfo di = new DocGen.DocInfo(f.docs());
                String d = "### " + markdownEscape(di.ret) + " " + markdownEscape(f.getName()) + "(" + markdownEscape(di.originalArgs) + "):" + nl + convertWiki(di.topDesc != null ? di.topDesc : di.desc) + nl + convertWiki(di.extendedDesc != null ? nl + di.extendedDesc + nl : "");
                fdocs.append(d).append(nl);
            }
        }
    }
    // events
    HashMap<Class<?>, ArrayList<Class<? extends Event>>> eventMap = new HashMap<>();
    for (Class<? extends Event> ce : customDiscovery.loadClassesWithAnnotationThatExtend(api.class, Event.class, classloader, true)) {
        Class<?> enclosing = ce.getEnclosingClass();
        if (eventMap.containsKey(enclosing)) {
            eventMap.get(enclosing).add(ce);
        } else {
            eventMap.put(enclosing, new ArrayList<Class<? extends Event>>());
            eventMap.get(enclosing).add(ce);
        }
    }
    ArrayList<Entry<Class<?>, ArrayList<Class<? extends Event>>>> eventEntryList = new ArrayList<>(eventMap.entrySet());
    Collections.sort(eventEntryList, new Comparator<Entry<Class<?>, ArrayList<Class<? extends Event>>>>() {

        @Override
        public int compare(Entry<Class<?>, ArrayList<Class<? extends Event>>> o1, Entry<Class<?>, ArrayList<Class<? extends Event>>> o2) {
            return o1.getKey().getName().compareTo(o2.getKey().getName());
        }
    });
    for (Entry<Class<?>, ArrayList<Class<? extends Event>>> e : eventEntryList) {
        Collections.sort(e.getValue(), new Comparator<Class<? extends Event>>() {

            @Override
            public int compare(Class<? extends Event> o1, Class<? extends Event> o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
    }
    if (!eventEntryList.isEmpty()) {
        fdocs.append("# Events").append(nl);
    }
    for (Entry<Class<?>, ArrayList<Class<? extends Event>>> entry : eventEntryList) {
        Class enclosingClass = entry.getKey();
        String[] split = enclosingClass.getName().split("\\.");
        fdocs.append("## ").append(split[split.length - 1]).append(nl);
        try {
            Method docsMethod = enclosingClass.getMethod("docs", (Class[]) null);
            Object o = enclosingClass.newInstance();
            fdocs.append((String) docsMethod.invoke(o, (Object[]) null)).append(nl).append(nl);
        } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) {
        }
        for (Class<? extends Event> ce : entry.getValue()) {
            Event e = ce.newInstance();
            Pattern p = Pattern.compile("\\{(.*?)\\} *?(.*?) *?\\{(.*?)\\} *?\\{(.*?)\\}");
            Matcher m = p.matcher(e.docs());
            if (m.find()) {
                String name = e.getName();
                String description = m.group(2).trim();
                String prefilter = DocGen.PrefilterData.Get(m.group(1).split("\\|"), DocGen.MarkupType.MARKDOWN);
                String eventData = DocGen.EventData.Get(m.group(3).split("\\|"), DocGen.MarkupType.MARKDOWN);
                String mutability = DocGen.MutabilityData.Get(m.group(4).split("\\|"), DocGen.MarkupType.MARKDOWN);
                // String manualTrigger = ManualTriggerData.Get(m.group(5).split("\\|"), DocGen.MarkupType.MARKDOWN);
                // String since = e.since().toString();
                fdocs.append("### ").append(markdownEscape(name)).append(nl);
                fdocs.append(description).append(nl);
                fdocs.append("#### Prefilters").append(nl).append(prefilter).append(nl);
                fdocs.append("#### Event Data").append(nl).append(eventData).append(nl);
                fdocs.append("#### Mutable Fields").append(nl).append(mutability).append(nl);
            }
        }
    }
    outputStream.write(fdocs.toString().getBytes("UTF-8"));
}
Also used : DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) URL(java.net.URL) Function(com.laytonsmith.core.functions.Function) Entry(java.util.Map.Entry) Pattern(java.util.regex.Pattern) Method(java.lang.reflect.Method) ClassDiscovery(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery) InvocationTargetException(java.lang.reflect.InvocationTargetException) Event(com.laytonsmith.core.events.Event) ClassDiscoveryCache(com.laytonsmith.PureUtilities.ClassLoading.ClassDiscoveryCache)

Example 3 with DynamicClassLoader

use of com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader in project CommandHelper by EngineHub.

the class ExtensionManager method Cleanup.

/**
 * To be run when we are shutting everything down.
 */
public static void Cleanup() {
    // Shutdown and release all the extensions
    Shutdown();
    for (ExtensionTracker trk : extensions.values()) {
        trk.shutdownTracker();
    }
    extensions.clear();
    // Clean up the loaders and discovery instances.
    ClassDiscovery.getDefaultInstance().invalidateCaches();
    ClassLoader loader = ClassDiscovery.getDefaultInstance().getDefaultClassLoader();
    if (loader instanceof DynamicClassLoader) {
        DynamicClassLoader dcl = (DynamicClassLoader) loader;
        dcl.destroy();
    }
    // Explicit call. Without this, jar files won't actually get unlocked on
    // Windows. Of course, this is hit and miss, but that's fine; we tried.
    System.gc();
    File cacheDir = CommandHelperFileLocations.getDefault().getExtensionCacheDirectory();
    if (!cacheDir.exists() || !cacheDir.isDirectory()) {
        return;
    }
    // Try to delete any loose files in the cache dir.
    for (File f : cacheDir.listFiles()) {
        try {
            Files.delete(f.toPath());
        } catch (IOException ex) {
            StreamUtils.GetSystemOut().println("[CommandHelper] Could not delete loose file " + f.getAbsolutePath() + ": " + ex.getMessage());
        }
    }
}
Also used : DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) IOException(java.io.IOException) File(java.io.File)

Example 4 with DynamicClassLoader

use of com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader in project CommandHelper by EngineHub.

the class ExtensionManager method Initialize.

/**
 * Initializes the extension manager. This operation is not necessarily required, and must be guaranteed to not run
 * more than once per ClassDiscovery object.
 *
 * @param cd the ClassDiscovery to use for loading files.
 */
public static void Initialize(ClassDiscovery cd) {
    extensions.clear();
    // Look in the extension folder for jars, add them to our class discover,
    // then initialize everything
    List<File> toProcess = new ArrayList<>();
    // Grab files from the cache if on Windows. Otherwise just load
    // directly from the stored locations.
    boolean onWindows = (OSUtils.GetOS() == OSUtils.OS.WINDOWS);
    if (onWindows) {
        toProcess.addAll(getFiles(CommandHelperFileLocations.getDefault().getExtensionCacheDirectory()));
    } else {
        for (File location : locations) {
            toProcess.addAll(getFiles(location));
        }
    }
    DynamicClassLoader dcl = new DynamicClassLoader();
    cd.setDefaultClassLoader(dcl);
    for (File f : toProcess) {
        if (f.getName().endsWith(".jar")) {
            try {
                // First, load it with our custom class loader
                URL jar = f.toURI().toURL();
                dcl.addJar(jar);
                cd.addDiscoveryLocation(jar);
                CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.DEBUG, "Loaded " + f.getAbsolutePath(), Target.UNKNOWN);
            } catch (MalformedURLException ex) {
                Static.getLogger().log(Level.SEVERE, null, ex);
            }
        }
    }
    // one found defines the internal name.
    for (ClassMirror<? extends AbstractExtension> extmirror : cd.getClassesWithAnnotationThatExtend(MSExtension.class, AbstractExtension.class)) {
        if (extmirror.equals(new ClassMirror<>(AbstractExtension.class))) {
            continue;
        }
        Extension ext;
        URL url = extmirror.getContainer();
        Class<? extends AbstractExtension> extcls;
        if (extmirror.getModifiers().isAbstract()) {
            Static.getLogger().log(Level.SEVERE, "Probably won't be able to" + " instantiate " + extmirror.getClassName() + ": The" + " class is marked as abstract! Will try anyway.");
        }
        try {
            extcls = extmirror.loadClass(dcl, true);
        } catch (Throwable ex) {
            // May throw anything, and kill the loading process.
            // Lets prevent that!
            Static.getLogger().log(Level.SEVERE, "Could not load class '" + extmirror.getClassName() + "'");
            ex.printStackTrace();
            continue;
        }
        try {
            ext = extcls.newInstance();
        } catch (InstantiationException | IllegalAccessException ex) {
            // Error, but skip this one, don't throw an exception ourselves, just log it.
            Static.getLogger().log(Level.SEVERE, "Could not instantiate " + extcls.getName() + ": " + ex.getMessage());
            continue;
        }
        ExtensionTracker trk = extensions.get(url);
        if (trk == null) {
            trk = new ExtensionTracker(url, cd, dcl);
            extensions.put(url, trk);
        }
        // use it.
        if (trk.identifier == null) {
            trk.identifier = ext.getName();
            try {
                trk.version = ext.getVersion();
            } catch (AbstractMethodError ex) {
                // getVersion() was added later. This is a temporary fix
                // to allow extension authors some time to update.
                // TODO: Remove this soon.
                trk.version = new SimpleVersion("0.0.0");
            }
        }
        trk.allExtensions.add(ext);
    }
    // Lets store info about the functions and events extensions have.
    // This will aide in gracefully unloading stuff later.
    Set<ClassMirror<?>> classes = cd.getClassesWithAnnotation(api.class);
    // Temp tracking for loading messages later on.
    List<String> events = new ArrayList<>();
    List<String> functions = new ArrayList<>();
    // and store the instances in their trackers.
    for (ClassMirror klass : classes) {
        URL url = klass.getContainer();
        if (cd.doesClassExtend(klass, Event.class) || cd.doesClassExtend(klass, Function.class)) {
            Class c;
            try {
                c = klass.loadClass(dcl, true);
            } catch (Throwable ex) {
                // May throw anything, and kill the loading process.
                // Lets prevent that!
                Static.getLogger().log(Level.SEVERE, "Could not load class '" + klass.getClassName() + "'");
                ex.printStackTrace();
                continue;
            }
            ExtensionTracker trk = extensions.get(url);
            if (trk == null) {
                trk = new ExtensionTracker(url, cd, dcl);
                extensions.put(url, trk);
            }
            // Instantiate, register and store.
            try {
                if (Event.class.isAssignableFrom(c)) {
                    Class<Event> cls = (Class<Event>) c;
                    if (klass.getModifiers().isAbstract()) {
                        // Abstract? Looks like they accidently @api'd
                        // a cheater class. We can't be sure that it is fully
                        // defined, so complain to the console.
                        CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.ERROR, "Class " + c.getName() + " in " + url + " is" + " marked as an event but is also abstract." + " Bugs might occur! Bug someone about this!", Target.UNKNOWN);
                    }
                    Event e = cls.newInstance();
                    events.add(e.getName());
                    trk.registerEvent(e);
                } else if (Function.class.isAssignableFrom(c)) {
                    Class<Function> cls = (Class<Function>) c;
                    if (klass.getModifiers().isAbstract()) {
                        // Abstract? Looks like they accidently @api'd
                        // a cheater class. We can't be sure that it is fully
                        // defined, so complain to the console.
                        CHLog.GetLogger().Log(CHLog.Tags.EXTENSIONS, LogLevel.ERROR, "Class " + c.getName() + " in " + url + " is" + " marked as a function but is also abstract." + " Bugs might occur! Bug someone about this!", Target.UNKNOWN);
                    }
                    Function f = cls.newInstance();
                    functions.add(f.getName());
                    trk.registerFunction(f);
                }
            } catch (InstantiationException ex) {
                Static.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
            } catch (IllegalAccessException ex) {
                Static.getLogger().log(Level.SEVERE, null, ex);
            }
        }
    }
    // Lets print out the details to the console, if we are in debug mode.
    try {
        if (Prefs.DebugMode()) {
            Collections.sort(events);
            String eventString = StringUtils.Join(events, ", ", ", and ", " and ");
            Collections.sort(functions);
            String functionString = StringUtils.Join(functions, ", ", ", and ", " and ");
            StreamUtils.GetSystemOut().println(Implementation.GetServerType().getBranding() + ": Loaded the following functions: " + functionString.trim());
            StreamUtils.GetSystemOut().println(Implementation.GetServerType().getBranding() + ": Loaded " + functions.size() + " function" + (functions.size() == 1 ? "." : "s."));
            StreamUtils.GetSystemOut().println(Implementation.GetServerType().getBranding() + ": Loaded the following events: " + eventString.trim());
            StreamUtils.GetSystemOut().println(Implementation.GetServerType().getBranding() + ": Loaded " + events.size() + " event" + (events.size() == 1 ? "." : "s."));
        }
    } catch (Throwable e) {
    // Prefs weren't loaded, probably caused by running tests.
    }
}
Also used : DynamicClassLoader(com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader) MalformedURLException(java.net.MalformedURLException) ArrayList(java.util.ArrayList) ClassMirror(com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror) URL(java.net.URL) CFunction(com.laytonsmith.core.constructs.CFunction) Function(com.laytonsmith.core.functions.Function) SimpleVersion(com.laytonsmith.PureUtilities.SimpleVersion) Event(com.laytonsmith.core.events.Event) File(java.io.File)

Aggregations

DynamicClassLoader (com.laytonsmith.PureUtilities.ClassLoading.DynamicClassLoader)4 Event (com.laytonsmith.core.events.Event)3 Function (com.laytonsmith.core.functions.Function)3 File (java.io.File)3 URL (java.net.URL)3 ArrayList (java.util.ArrayList)3 ClassDiscovery (com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery)2 ClassDiscoveryCache (com.laytonsmith.PureUtilities.ClassLoading.ClassDiscoveryCache)2 ClassMirror (com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror)2 CFunction (com.laytonsmith.core.constructs.CFunction)2 IOException (java.io.IOException)2 MalformedURLException (java.net.MalformedURLException)2 HashMap (java.util.HashMap)2 AnnotationMirror (com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.AnnotationMirror)1 SimpleVersion (com.laytonsmith.PureUtilities.SimpleVersion)1 UnsupportedEncodingException (java.io.UnsupportedEncodingException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 HashSet (java.util.HashSet)1 Entry (java.util.Map.Entry)1