Unloading & Reloading Plugin

Discussion in 'Plugin Development' started by DonkeyTeeth2013, Sep 2, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    DonkeyTeeth2013

    I am making a plugin that will be able to unload, load, and reload any specific plugin without the use of /reload. Everything works fine, until the reload function is used on the plugin itself. The plugin unloads, and it cannot load itself since it is now unloaded. The code is below, how should I fix this?

    Main reload method:
    Code:java
    1. public void reload(String p) {
    2. unload(p);
    3. load(p);
    4. }


    Unload/Load methods:
    Code:java
    1. public int load(final String pluginName) {
    2. PluginManager pm = Bukkit.getServer().getPluginManager();
    3. boolean there = false;
    4. for (Plugin pl : pm.getPlugins())
    5. if (pl.getName().toLowerCase().startsWith(pluginName))
    6. there = true;
    7.  
    8. if (there)
    9. return 1; //plugin already exists
    10. else {
    11. String name = "";
    12. String path = getDataFolder().getParent();
    13. File folder = new File(path);
    14. ArrayList<File> files = new ArrayList<File>();
    15. File[] listOfFiles = folder.listFiles();
    16. for (File compare : listOfFiles) {
    17. if (compare.isFile()) {
    18. try {
    19. name = getPluginLoader().getPluginDescription(compare).getName();
    20. } catch (InvalidDescriptionException e) {
    21. getLogger().warning("[Loading Plugin] " + compare.getName() + " didn't match");
    22. }
    23. if (name.toLowerCase().startsWith(pluginName.toLowerCase())) {
    24. files.add(compare);
    25. try {
    26. Bukkit.getServer().getPluginManager().loadPlugin(compare);
    27. } catch (UnknownDependencyException e) {
    28. return 2; //missing dependent plugin
    29. } catch (InvalidPluginException e) {
    30. return -1; //not a plugin
    31. } catch (InvalidDescriptionException e) {
    32. return 3; //invalid description
    33. }
    34. }
    35. }
    36. }
    37.  
    38. Plugin[] plugins = pm.getPlugins();
    39. for (Plugin pl : plugins) {
    40. for (File compare : files) {
    41. try {
    42. if (pl.getName().equalsIgnoreCase(getPluginLoader().getPluginDescription(compare).getName()))
    43. pm.enablePlugin(pl);
    44. } catch (InvalidDescriptionException e) {
    45. e.printStackTrace();
    46. }
    47. }
    48. }
    49. }
    50. return 0; //success
    51. }
    52.  
    53. @SuppressWarnings("unchecked")
    54. public int unload(String pluginName) {
    55. pluginName = pluginName.toLowerCase().trim();
    56. PluginManager manager = Bukkit.getServer().getPluginManager();
    57. SimplePluginManager spm = (SimplePluginManager) manager;
    58. SimpleCommandMap commandMap = null;
    59. List<Plugin> plugins = null;
    60. Map<String, Plugin> lookupNames = null;
    61. Map<String, Command> knownCommands = null;
    62. Map<Event, SortedSet<RegisteredListener>> listeners = null;
    63. boolean reloadlisteners = true;
    64. try {
    65. if (spm != null) {
    66. Field pluginsField = spm.getClass().getDeclaredField("plugins");
    67. pluginsField.setAccessible(true);
    68. plugins = (List<Plugin>) pluginsField.get(spm);
    69.  
    70. Field lookupNamesField = spm.getClass().getDeclaredField("lookupNames");
    71. lookupNamesField.setAccessible(true);
    72. lookupNames = (Map<String, Plugin>) lookupNamesField.get(spm);
    73.  
    74. try {
    75. Field listenersField = spm.getClass().getDeclaredField("listeners");
    76. listenersField.setAccessible(true);
    77. listeners = (Map<Event, SortedSet<RegisteredListener>>) listenersField.get(spm);
    78. } catch (Exception e) {
    79. reloadlisteners = false;
    80. }
    81.  
    82. Field commandMapField = spm.getClass().getDeclaredField("commandMap");
    83. commandMapField.setAccessible(true);
    84. commandMap = (SimpleCommandMap) commandMapField.get(spm);
    85.  
    86. Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands");
    87. knownCommandsField.setAccessible(true);
    88. knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
    89. }
    90. } catch (Exception e) {
    91. e.printStackTrace();
    92. }
    93. boolean in = false;
    94.  
    95. for (Plugin pl : Bukkit.getServer().getPluginManager().getPlugins()) {
    96. if (in)
    97. break;
    98. if (pl.getName().toLowerCase().startsWith(pluginName.toLowerCase())) {
    99. manager.disablePlugin(pl);
    100. if (plugins != null && plugins.contains(pl))
    101. plugins.remove(pl);
    102.  
    103. if (lookupNames != null && lookupNames.containsKey(pl.getName())) {
    104. lookupNames.remove(pl.getName());
    105. }
    106.  
    107. if (listeners != null && reloadlisteners) {
    108. for (SortedSet<RegisteredListener> set : listeners.values()) {
    109. for (Iterator<RegisteredListener> it = set.iterator(); it.hasNext();) {
    110. RegisteredListener value = it.next();
    111.  
    112. if (value.getPlugin() == pl) {
    113. it.remove();
    114. }
    115. }
    116. }
    117. }
    118.  
    119. if (commandMap != null) {
    120. for (Iterator<Map.Entry<String, Command>> it = knownCommands.entrySet().iterator(); it.hasNext();) {
    121. Map.Entry<String, Command> entry = it.next();
    122. if (entry.getValue() instanceof PluginCommand) {
    123. PluginCommand c = (PluginCommand) entry.getValue();
    124. if (c.getPlugin() == pl) {
    125. c.unregister(commandMap);
    126. it.remove();
    127. }
    128. }
    129. }
    130. }
    131. for (Plugin plu : Bukkit.getServer().getPluginManager().getPlugins()) {
    132. if (plu.getDescription().getDepend() != null) {
    133. for (String depend : plu.getDescription().getDepend()) {
    134. if (depend.equalsIgnoreCase(pl.getName())) {
    135. getLogger().info("[Unloading Plugin] " + plu.getName() + " must be disabled!");
    136. unload(plu.getName());
    137. return 1; //dependencies also disabled
    138. }
    139. }
    140. }
    141. }
    142. in = true;
    143. }
    144. }
    145. if (!in) {
    146. getLogger().info("Not an existing plugin");
    147. return -1; //non-existent
    148. }
    149. System.gc();
    150. return 0; //success
    151. }
     
  2. Offline

    techboy291

    Can't you just check to make sure the plugin that's going to be reloaded isn't yours?
     
  3. Offline

    DonkeyTeeth2013

    techboy291 Well, I could do that, but I want the player to be able to reload the plugin itself too.
     
  4. Offline

    BillyGalbreath

    I want you to sit back, relax, and think about that for a few minutes...
     
  5. Offline

    DonkeyTeeth2013

    BillyGalbreath What I'm saying is, if there is an update for a plugin, I want them to easily reload the plugin to install the new update without lagging the server with /reload. If there's an update for the plugin I'm making, I want the same sequence of events to happen.
     
  6. Offline

    BillyGalbreath

    I understand what you want. But I dont think you understand how it will actually happen. If you unload your plugin, there is nothing left to control the loading back.

    Analogy time. Your plugin is a bouncer at a bar. The only way to get into this bar is to get invited in by the bouncer. If the bouncer kicks himself out, who's going to invite him back in?
     
    Skionz and izarooni like this.
  7. Offline

    DonkeyTeeth2013

    BillyGalbreath But this is Java, a programming language. There MUST be a way to do this.
     
  8. Offline

    BillyGalbreath

    You could have a second plugin jar that all it does is load back your main plugin jar when it unloads. But good luck getting users to install both willingly :S
     
  9. Offline

    SmooshCakez

    You could always have 2 seperate plugins, and you trigger a .reload() or something on the other plugin to reload the first. Although, this is highly inefficient, and annoying for people downloading your plugin.

    Are you trying to reload all instances, or just config files and such? If so, call file.load() or reloadConfig() in your JavaPlugin class.
     
  10. Offline

    Gater12

    DonkeyTeeth2013
    Once your plugin is disabled there's really nothing you can do since, well, the plugin is disabled.

    You would need an external program of some sort to re-enable it back.

    Pretty much like on how to restart a server via plugin. You can't because the server is disabled meaning the plugins are also disabled.

    (People edit there batch scripts to automatically restart the server)
     
  11. Offline

    DonkeyTeeth2013

    SmooshCakez Basically the plugin I'm making is a personal utility plugin that other custom plugins I'm making would rely on as an API to make things simpler. Apart from being an API, it also has useful commands for doing plugin debugging and getting UUIDs from players and such.
    Is there no way to set up some sort of timer or something that runs after the plugin is disabled to enable it again?

    Edit:
    BillyGalbreath I really do not want a separate plugin for this .-.
    Gater12 Yes, I have a batch script for my server to restart it. But is there no way to set up something similar inside a single plugin?
     
  12. Offline

    MCaeolus

    How can something run... if it's not on? You'd have to get something separate for the plugin to reload itself. With just the plugin, no. You could possibly make it so the first time the plugin is in the plugins folder it installs a second counterpart plugin to do that, but... no. One plugin cant stop, then start itself.
     
  13. Offline

    mythbusterma

  14. Offline

    BillyGalbreath

    Nope. A plugin's timers/schedulers are all cancelled when it disables.

    This stuff is beyond me, but if its anything like refelction then once the plugin is disabled the reflected classes will be gone, too.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 10, 2016
  15. Offline

    mythbusterma

    BillyGalbreath

    It's not reflection, though. It's actually modifying the loaded class.
     
  16. Offline

    xTigerRebornx

    BillyGalbreath mythbusterma Could use another thread that will run a delay for x seconds then load the plugin (PluginManager#loadPlugin(File)) again, taking care for thread safety and whatnot.
     
  17. Offline

    DonkeyTeeth2013

Thread Status:
Not open for further replies.

Share This Page