PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java

https://gitlab.com/Skull3x/WorldEdit
Java | 178 lines | 107 code | 18 blank | 53 comment | 16 complexity | d04cb109b9a4a99f1100c0f7c951dec1 MD5 | raw file
  1. /*
  2. * WorldEdit, a Minecraft world manipulation toolkit
  3. * Copyright (C) sk89q <http://www.sk89q.com>
  4. * Copyright (C) WorldEdit team and contributors
  5. *
  6. * This program is free software: you can redistribute it and/or modify it
  7. * under the terms of the GNU Lesser General Public License as published by the
  8. * Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
  14. * for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package com.sk89q.worldedit.bukkit.adapter;
  20. import com.sk89q.worldedit.util.io.Closer;
  21. import java.io.File;
  22. import java.io.IOException;
  23. import java.net.URL;
  24. import java.util.ArrayList;
  25. import java.util.Enumeration;
  26. import java.util.List;
  27. import java.util.jar.JarEntry;
  28. import java.util.jar.JarFile;
  29. import java.util.logging.Level;
  30. import java.util.logging.Logger;
  31. /**
  32. * Loads Bukkit implementation adapters.
  33. */
  34. public class BukkitImplLoader {
  35. private static final Logger log = Logger.getLogger(BukkitImplLoader.class.getCanonicalName());
  36. private final List<String> adapterCandidates = new ArrayList<String>();
  37. private String customCandidate;
  38. private static final String SEARCH_PACKAGE = "com.sk89q.worldedit.bukkit.adapter.impl";
  39. private static final String SEARCH_PACKAGE_DOT = SEARCH_PACKAGE + ".";
  40. private static final String SEARCH_PATH = SEARCH_PACKAGE.replace(".", "/");
  41. private static final String CLASS_SUFFIX = ".class";
  42. private static final String LOAD_ERROR_MESSAGE =
  43. "\n**********************************************\n" +
  44. "** This WorldEdit version does not fully support your version of Bukkit.\n" +
  45. "**\n" +
  46. "** When working with blocks or undoing, chests will be empty, signs\n" +
  47. "** will be blank, and so on. There will be no support for entity\n" +
  48. "** and biome-related functions.\n" +
  49. "**\n" +
  50. "** Please see http://wiki.sk89q.com/wiki/WorldEdit/Bukkit_adapters\n" +
  51. "**********************************************\n";
  52. /**
  53. * Create a new instance.
  54. */
  55. public BukkitImplLoader() {
  56. addDefaults();
  57. }
  58. /**
  59. * Add default candidates, such as any defined with
  60. * {@code -Dworldedit.bukkit.adapter}.
  61. */
  62. private void addDefaults() {
  63. String className = System.getProperty("worldedit.bukkit.adapter");
  64. if (className != null) {
  65. customCandidate = className;
  66. adapterCandidates.add(className);
  67. log.log(Level.INFO, "-Dworldedit.bukkit.adapter used to add " + className + " to the list of available Bukkit adapters");
  68. }
  69. }
  70. /**
  71. * Search the given JAR for candidate implementations.
  72. *
  73. * @param file the file
  74. * @throws IOException thrown on I/O error
  75. */
  76. public void addFromJar(File file) throws IOException {
  77. Closer closer = Closer.create();
  78. JarFile jar = closer.register(new JarFile(file));
  79. try {
  80. Enumeration entries = jar.entries();
  81. while (entries.hasMoreElements()) {
  82. JarEntry jarEntry = (JarEntry) entries.nextElement();
  83. String className = jarEntry.getName().replaceAll("[/\\\\]+", ".");
  84. if (!className.startsWith(SEARCH_PACKAGE_DOT) || jarEntry.isDirectory()) continue;
  85. int beginIndex = 0;
  86. int endIndex = className.length() - CLASS_SUFFIX.length();
  87. className = className.substring(beginIndex, endIndex);
  88. adapterCandidates.add(className);
  89. }
  90. } finally {
  91. closer.close();
  92. }
  93. }
  94. /**
  95. * Search for classes stored as separate files available via the given
  96. * class loader.
  97. *
  98. * @param classLoader the class loader
  99. * @throws IOException thrown on error
  100. */
  101. public void addFromPath(ClassLoader classLoader) throws IOException {
  102. Enumeration<URL> resources = classLoader.getResources(SEARCH_PATH);
  103. while (resources.hasMoreElements()) {
  104. File file = new File(resources.nextElement().getFile());
  105. addFromPath(file);
  106. }
  107. }
  108. /**
  109. * Search for classes stored as separate files available via the given
  110. * path.
  111. *
  112. * @param file the path
  113. */
  114. private void addFromPath(File file) {
  115. String resource = SEARCH_PACKAGE_DOT + file.getName();
  116. if (file.isDirectory()) {
  117. File[] files = file.listFiles();
  118. if (files != null) {
  119. for (File child : files) {
  120. addFromPath(child);
  121. }
  122. }
  123. } else if (resource.endsWith(CLASS_SUFFIX)) {
  124. int beginIndex = 0;
  125. int endIndex = resource.length() - CLASS_SUFFIX.length();
  126. String className = resource.substring(beginIndex, endIndex);
  127. adapterCandidates.add(className);
  128. }
  129. }
  130. /**
  131. * Iterate through the list of candidates and load an adapter.
  132. *
  133. * @return an adapter
  134. * @throws AdapterLoadException thrown if no adapter could be found
  135. */
  136. public BukkitImplAdapter loadAdapter() throws AdapterLoadException {
  137. for (String className : adapterCandidates) {
  138. try {
  139. Class<?> cls = Class.forName(className);
  140. if (BukkitImplAdapter.class.isAssignableFrom(cls)) {
  141. return (BukkitImplAdapter) cls.newInstance();
  142. } else {
  143. log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
  144. "' because it does not implement " + BukkitImplAdapter.class.getCanonicalName());
  145. }
  146. } catch (ClassNotFoundException e) {
  147. log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
  148. "' that is not supposed to be missing", e);
  149. } catch (IllegalAccessException e) {
  150. log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className +
  151. "' that is not supposed to be raising this error", e);
  152. } catch (Throwable e) {
  153. if (className.equals(customCandidate)) {
  154. log.log(Level.WARNING, "Failed to load the Bukkit adapter class '" + className + "'", e);
  155. }
  156. }
  157. }
  158. throw new AdapterLoadException(LOAD_ERROR_MESSAGE);
  159. }
  160. }