private File initialiseDataFolder() { if (Utils.getOrDefault(rdescription, "jxpl.hasdatafolder", false)) { File tempFolder = new File(file.getParentFile(), description.getName()); if (Utils.dirExistOrCreate(tempFolder)) return tempFolder; } return null; }
public synchronized Plugin loadPlugin(File paramFile, boolean ignoresoftdepends) throws InvalidPluginException, UnknownDependencyException, InvalidDescriptionFileException { CommonPlugin result; PluginDescriptionFile desc; CommonClassLoader loader; desc = getDescription(paramFile); File dataFolder = new File(paramFile.getParentFile(), desc.getName()); processDependencies(desc); if (!ignoresoftdepends) { processSoftDependencies(desc); } try { if (engine.getPlatform() == Platform.CLIENT) { loader = new ClientClassLoader(this, this.getClass().getClassLoader()); } else { loader = new CommonClassLoader(this, this.getClass().getClassLoader()); } loader.addURL(paramFile.toURI().toURL()); Class<?> main = Class.forName(desc.getMain(), true, loader); Class<? extends CommonPlugin> plugin = main.asSubclass(CommonPlugin.class); boolean locked = manager.lock(key); Constructor<? extends CommonPlugin> constructor = plugin.getConstructor(); result = constructor.newInstance(); result.initialize(this, engine, desc, dataFolder, paramFile, loader); if (!locked) { manager.unlock(key); } } catch (Exception e) { throw new InvalidPluginException(e); } loader.setPlugin(result); loaders.put(desc.getName(), loader); return result; }
public ScriptPlugin(PluginLoader pluginLoader, Server instance, File plugin, ScriptEngine engine) throws InvalidDescriptionException { loader = pluginLoader; server = instance; file = plugin; rdescription = (Map<String, Object>) Utils.getOrExcept(engine, "SCRIPT_PDF"); description = Utils.getPdfFromMap(rdescription); logger = Logger.getLogger("Minecraft.JxplPlugin." + description.getName()); dataFolder = initialiseDataFolder(); helper = new PluginHelper(); engine.put(Utils.getOrDefault(rdescription, "jxpl.helpervarname", "helper"), helper); engine.put(Utils.getOrDefault(rdescription, "jxpl.pluginvarname", "plugin"), this); engine.put(Utils.getOrDefault(rdescription, "jxpl.servervarname", "server"), server); sEngine = (Invocable) engine; if (dataFolder != null && Utils.getOrDefault(rdescription, "jxpl.hasconfig", false)) { configFile = new File(dataFolder, "config.yml"); } else { configFile = null; } }
/** * Loads the plugins contained within the specified directory * * @param directory Directory to check for plugins * @return A list of all plugins loaded */ public Plugin[] loadPlugins(File directory) { Validate.notNull(directory, "Directory cannot be null"); Validate.isTrue(directory.isDirectory(), "Directory must be a directory"); List<Plugin> result = new ArrayList<Plugin>(); Set<Pattern> filters = fileAssociations.keySet(); if (!(server.getUpdateFolder().equals(""))) { updateDirectory = new File(directory, server.getUpdateFolder()); } Map<String, File> plugins = new HashMap<String, File>(); Set<String> loadedPlugins = new HashSet<String>(); Map<String, Collection<String>> dependencies = new HashMap<String, Collection<String>>(); Map<String, Collection<String>> softDependencies = new HashMap<String, Collection<String>>(); // This is where it figures out all possible plugins for (File file : directory.listFiles()) { PluginLoader loader = null; for (Pattern filter : filters) { Matcher match = filter.matcher(file.getName()); if (match.find()) { loader = fileAssociations.get(filter); } } if (loader == null) continue; PluginDescriptionFile description = null; try { description = loader.getPluginDescription(file); } catch (InvalidDescriptionException ex) { server .getLogger() .log( Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); continue; } plugins.put(description.getName(), file); Collection<String> softDependencySet = description.getSoftDepend(); if (softDependencySet != null) { if (softDependencies.containsKey(description.getName())) { // Duplicates do not matter, they will be removed together if applicable softDependencies.get(description.getName()).addAll(softDependencySet); } else { softDependencies.put(description.getName(), new LinkedList<String>(softDependencySet)); } } Collection<String> dependencySet = description.getDepend(); if (dependencySet != null) { dependencies.put(description.getName(), new LinkedList<String>(dependencySet)); } Collection<String> loadBeforeSet = description.getLoadBefore(); if (loadBeforeSet != null) { for (String loadBeforeTarget : loadBeforeSet) { if (softDependencies.containsKey(loadBeforeTarget)) { softDependencies.get(loadBeforeTarget).add(description.getName()); } else { // softDependencies is never iterated, so 'ghost' plugins aren't an issue Collection<String> shortSoftDependency = new LinkedList<String>(); shortSoftDependency.add(description.getName()); softDependencies.put(loadBeforeTarget, shortSoftDependency); } } } } while (!plugins.isEmpty()) { boolean missingDependency = true; Iterator<String> pluginIterator = plugins.keySet().iterator(); while (pluginIterator.hasNext()) { String plugin = pluginIterator.next(); if (dependencies.containsKey(plugin)) { Iterator<String> dependencyIterator = dependencies.get(plugin).iterator(); while (dependencyIterator.hasNext()) { String dependency = dependencyIterator.next(); // Dependency loaded if (loadedPlugins.contains(dependency)) { dependencyIterator.remove(); // We have a dependency not found } else if (!plugins.containsKey(dependency)) { missingDependency = false; File file = plugins.get(plugin); pluginIterator.remove(); softDependencies.remove(plugin); dependencies.remove(plugin); server .getLogger() .log( Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", new UnknownDependencyException(dependency)); break; } } if (dependencies.containsKey(plugin) && dependencies.get(plugin).isEmpty()) { dependencies.remove(plugin); } } if (softDependencies.containsKey(plugin)) { Iterator<String> softDependencyIterator = softDependencies.get(plugin).iterator(); while (softDependencyIterator.hasNext()) { String softDependency = softDependencyIterator.next(); // Soft depend is no longer around if (!plugins.containsKey(softDependency)) { softDependencyIterator.remove(); } } if (softDependencies.get(plugin).isEmpty()) { softDependencies.remove(plugin); } } if (!(dependencies.containsKey(plugin) || softDependencies.containsKey(plugin)) && plugins.containsKey(plugin)) { // We're clear to load, no more soft or hard dependencies left File file = plugins.get(plugin); pluginIterator.remove(); missingDependency = false; try { result.add(loadPlugin(file)); loadedPlugins.add(plugin); continue; } catch (InvalidPluginException ex) { server .getLogger() .log( Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); } } } if (missingDependency) { // We now iterate over plugins until something loads // This loop will ignore soft dependencies pluginIterator = plugins.keySet().iterator(); while (pluginIterator.hasNext()) { String plugin = pluginIterator.next(); if (!dependencies.containsKey(plugin)) { softDependencies.remove(plugin); missingDependency = false; File file = plugins.get(plugin); pluginIterator.remove(); try { result.add(loadPlugin(file)); loadedPlugins.add(plugin); break; } catch (InvalidPluginException ex) { server .getLogger() .log( Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); } } } // We have no plugins left without a depend if (missingDependency) { softDependencies.clear(); dependencies.clear(); Iterator<File> failedPluginIterator = plugins.values().iterator(); while (failedPluginIterator.hasNext()) { File file = failedPluginIterator.next(); failedPluginIterator.remove(); server .getLogger() .log( Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': circular dependency detected"); } } } } return result.toArray(new Plugin[result.size()]); }
private void log(Level l, String message, Throwable t) { logger.log(l, String.format("[jxpl.%s] %s", description.getName(), message), t); }
public Plugin loadPlugin(File file, boolean ignoreSoftDependencies) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { JavaPlugin result = null; PluginDescriptionFile description = null; if (!file.exists()) { throw new InvalidPluginException( new FileNotFoundException(String.format("%s does not exist", file.getPath()))); } try { JarFile jar = new JarFile(file); JarEntry entry = jar.getJarEntry("plugin.yml"); if (entry == null) { throw new InvalidPluginException( new FileNotFoundException("Jar does not contain plugin.yml")); } InputStream stream = jar.getInputStream(entry); description = new PluginDescriptionFile(stream); stream.close(); jar.close(); } catch (IOException ex) { throw new InvalidPluginException(ex); } catch (YAMLException ex) { throw new InvalidPluginException(ex); } File dataFolder = new File(file.getParentFile(), description.getName()); File oldDataFolder = getDataFolder(file); // Found old data folder if (dataFolder.equals(oldDataFolder)) { // They are equal -- nothing needs to be done! } else if (dataFolder.isDirectory() && oldDataFolder.isDirectory()) { server .getLogger() .log( Level.INFO, String.format( "While loading %s (%s) found old-data folder: %s next to the new one: %s", description.getName(), file, oldDataFolder, dataFolder)); } else if (oldDataFolder.isDirectory() && !dataFolder.exists()) { if (!oldDataFolder.renameTo(dataFolder)) { throw new InvalidPluginException( new Exception( "Unable to rename old data folder: '" + oldDataFolder + "' to: '" + dataFolder + "'")); } server .getLogger() .log( Level.INFO, String.format( "While loading %s (%s) renamed data folder: '%s' to '%s'", description.getName(), file, oldDataFolder, dataFolder)); } if (dataFolder.exists() && !dataFolder.isDirectory()) { throw new InvalidPluginException( new Exception( String.format( "Projected datafolder: '%s' for %s (%s) exists and is not a directory", dataFolder, description.getName(), file))); } ArrayList<String> depend; try { depend = (ArrayList) description.getDepend(); if (depend == null) { depend = new ArrayList<String>(); } } catch (ClassCastException ex) { throw new InvalidPluginException(ex); } for (String pluginName : depend) { if (loaders == null) { throw new UnknownDependencyException(pluginName); } PluginClassLoader current = loaders.get(pluginName); if (current == null) { throw new UnknownDependencyException(pluginName); } } if (!ignoreSoftDependencies) { ArrayList<String> softDepend; try { softDepend = (ArrayList) description.getSoftDepend(); if (softDepend == null) { softDepend = new ArrayList<String>(); } } catch (ClassCastException ex) { throw new InvalidPluginException(ex); } for (String pluginName : softDepend) { if (loaders == null) { throw new UnknownSoftDependencyException(pluginName); } PluginClassLoader current = loaders.get(pluginName); if (current == null) { throw new UnknownSoftDependencyException(pluginName); } } } PluginClassLoader loader = null; try { URL[] urls = new URL[1]; urls[0] = file.toURI().toURL(); loader = new PluginClassLoader(this, urls, getClass().getClassLoader()); Class<?> jarClass = Class.forName(description.getMain(), true, loader); Class<? extends JavaPlugin> plugin = jarClass.asSubclass(JavaPlugin.class); Constructor<? extends JavaPlugin> constructor = plugin.getConstructor(); result = constructor.newInstance(); result.initialize(this, server, description, dataFolder, file, loader); } catch (Throwable ex) { throw new InvalidPluginException(ex); } loaders.put(description.getName(), loader); return result; }