2
0

DynamicExtension.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package net.sf.l2j.gameserver.util;
  16. import java.io.FileInputStream;
  17. import java.io.FileNotFoundException;
  18. import java.util.Properties;
  19. import java.util.concurrent.ConcurrentHashMap;
  20. import java.util.logging.Level;
  21. import java.util.logging.Logger;
  22. import net.sf.l2j.Config;
  23. /**
  24. * extension loader for l2j
  25. * @author galun
  26. * @version $Id: DynamicExtension.java,v 1.3 2006/05/14 17:19:39 galun Exp $
  27. */
  28. public class DynamicExtension
  29. {
  30. private static Logger _log = Logger.getLogger(DynamicExtension.class.getCanonicalName());
  31. private JarClassLoader _classLoader;
  32. private Properties _prop;
  33. private ConcurrentHashMap<String, Object> _loadedExtensions;
  34. private static DynamicExtension _instance;
  35. private ConcurrentHashMap<String, ExtensionFunction> _getters;
  36. private ConcurrentHashMap<String, ExtensionFunction> _setters;
  37. /**
  38. * create an instance of DynamicExtension
  39. * this will be done by GameServer according to the altsettings.properties
  40. *
  41. */
  42. private DynamicExtension()
  43. {
  44. if (_instance == null)
  45. _instance = this;
  46. _getters = new ConcurrentHashMap<String, ExtensionFunction>();
  47. _setters = new ConcurrentHashMap<String, ExtensionFunction>();
  48. initExtensions();
  49. }
  50. /**
  51. * get the singleton of DynamicInstance
  52. * @return the singleton instance
  53. */
  54. public static DynamicExtension getInstance()
  55. {
  56. if (_instance == null)
  57. _instance = new DynamicExtension();
  58. return _instance;
  59. }
  60. /**
  61. * get an extension object by class name
  62. * @param className he class name as defined in the extension properties
  63. * @return the object or null if not found
  64. */
  65. public Object getExtension(String className)
  66. {
  67. return _loadedExtensions.get(className);
  68. }
  69. /**
  70. * initialize all configured extensions
  71. *
  72. */
  73. public String initExtensions()
  74. {
  75. _prop = new Properties();
  76. String res = "";
  77. _loadedExtensions = new ConcurrentHashMap<String, Object>();
  78. try
  79. {
  80. _prop.load(new FileInputStream(Config.EXTENSIONS_CONFIG_FILE));
  81. }
  82. catch (FileNotFoundException ex)
  83. {
  84. _log.info(ex.getMessage() + ": no extensions to load");
  85. }
  86. catch (Exception ex)
  87. {
  88. _log.log(Level.WARNING, "could not load properties", ex);
  89. }
  90. _classLoader = new JarClassLoader();
  91. for (Object o : _prop.keySet())
  92. {
  93. String k = (String) o;
  94. if (k.endsWith("Class"))
  95. {
  96. res += initExtension(_prop.getProperty(k)) + "\n";
  97. }
  98. }
  99. return res;
  100. }
  101. /**
  102. * init a named extension
  103. * @param name the class name and optionally a jar file name delimited with a '@' if the jar file is not
  104. * in the class path
  105. */
  106. public String initExtension(String name)
  107. {
  108. String className = name;
  109. String[] p = name.split("@");
  110. String res = name + " loaded";
  111. if (p.length > 1)
  112. {
  113. _classLoader.addJarFile(p[1]);
  114. className = p[0];
  115. }
  116. if (_loadedExtensions.containsKey(className))
  117. return "already loaded";
  118. try
  119. {
  120. Class<?> extension = Class.forName(className, true, _classLoader);
  121. Object obj = extension.newInstance();
  122. extension.getMethod("init", new Class[0]).invoke(obj, new Object[0]);
  123. _log.info("Extension " + className + " loaded.");
  124. _loadedExtensions.put(className, obj);
  125. }
  126. catch (Exception ex)
  127. {
  128. _log.log(Level.WARNING, name, ex);
  129. res = ex.toString();
  130. }
  131. return res;
  132. }
  133. /**
  134. * create a new class loader which resets the cache (jar files and loaded classes)
  135. * on next class loading request it will read the jar again
  136. */
  137. protected void clearCache()
  138. {
  139. _classLoader = new JarClassLoader();
  140. }
  141. /**
  142. * call unloadExtension() for all known extensions
  143. *
  144. */
  145. public String unloadExtensions()
  146. {
  147. String res = "";
  148. for (String e : _loadedExtensions.keySet())
  149. res += unloadExtension(e) + "\n";
  150. return res;
  151. }
  152. /**
  153. * get all loaded extensions
  154. * @return a String array with the class names
  155. */
  156. public String[] getExtensions()
  157. {
  158. String[] l = new String[_loadedExtensions.size()];
  159. _loadedExtensions.keySet().toArray(l);
  160. return l;
  161. }
  162. /**
  163. * unload a named extension
  164. * @param name the class name and optionally a jar file name delimited with a '@'
  165. */
  166. public String unloadExtension(String name)
  167. {
  168. String className = name;
  169. String[] p = name.split("@");
  170. if (p.length > 1)
  171. {
  172. _classLoader.addJarFile(p[1]);
  173. className = p[0];
  174. }
  175. String res = className + " unloaded";
  176. try
  177. {
  178. Object obj = _loadedExtensions.get(className);
  179. Class<?> extension = obj.getClass();
  180. _loadedExtensions.remove(className);
  181. extension.getMethod("unload", new Class[0]).invoke(obj, new Object[0]);
  182. _log.info("Extension " + className + " unloaded.");
  183. }
  184. catch (Exception ex)
  185. {
  186. _log.log(Level.WARNING, "could not unload " + className, ex);
  187. res = ex.toString();
  188. }
  189. return res;
  190. }
  191. /**
  192. * unloads all extensions, resets the cache and initializes all configured extensions
  193. *
  194. */
  195. public void reload()
  196. {
  197. unloadExtensions();
  198. clearCache();
  199. initExtensions();
  200. }
  201. /**
  202. * unloads a named extension, resets the cache and initializes the extension
  203. * @param name the class name and optionally a jar file name delimited with a '@' if the jar file is not
  204. * in the class path
  205. */
  206. public void reload(String name)
  207. {
  208. unloadExtension(name);
  209. clearCache();
  210. initExtension(name);
  211. }
  212. /**
  213. * register a getter function given a (hopefully) unique name
  214. * @param name the name of the function
  215. * @param function the ExtensionFunction implementation
  216. */
  217. public void addGetter(String name, ExtensionFunction function)
  218. {
  219. _getters.put(name, function);
  220. }
  221. /**
  222. * deregister a getter function
  223. * @param name the name used for registering
  224. */
  225. public void removeGetter(String name)
  226. {
  227. _getters.remove(name);
  228. }
  229. /**
  230. * call a getter function registered with DynamicExtension
  231. * @param name the function name
  232. * @param arg a function argument
  233. * @return an object from the extension
  234. */
  235. public Object get(String name, String arg)
  236. {
  237. ExtensionFunction func = _getters.get(name);
  238. if (func != null)
  239. return func.get(arg);
  240. return "<none>";
  241. }
  242. /**
  243. * register a setter function given a (hopefully) unique name
  244. * @param name the name of the function
  245. * @param function the ExtensionFunction implementation
  246. */
  247. public void addSetter(String name, ExtensionFunction function)
  248. {
  249. _setters.put(name, function);
  250. }
  251. /**
  252. * deregister a setter function
  253. * @param name the name used for registering
  254. */
  255. public void removeSetter(String name)
  256. {
  257. _setters.remove(name);
  258. }
  259. /**
  260. * call a setter function registered with DynamicExtension
  261. * @param name the function name
  262. * @param arg a function argument
  263. * @param obj an object to set
  264. */
  265. public void set(String name, String arg, Object obj)
  266. {
  267. ExtensionFunction func = _setters.get(name);
  268. if (func != null)
  269. func.set(arg, obj);
  270. }
  271. public JarClassLoader getClassLoader()
  272. {
  273. return _classLoader;
  274. }
  275. }