PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/JARClassLoader.java

#
Java | 288 lines | 179 code | 38 blank | 71 comment | 31 complexity | 1c71b87336c44f11362aed8aa00f10c5 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * JARClassLoader.java - Loads classes from JAR files
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2003 Slava Pestov
  7. * Portions copyright (C) 1999 mike dillon
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. package org.gjt.sp.jedit;
  24. //{{{ Imports
  25. import java.io.InputStream;
  26. import java.io.IOException;
  27. import java.net.URL;
  28. import java.util.Hashtable;
  29. import java.util.Iterator;
  30. import java.util.zip.ZipEntry;
  31. import java.util.zip.ZipFile;
  32. import org.gjt.sp.util.Log;
  33. //}}}
  34. /**
  35. * A class loader implementation that loads classes from JAR files.
  36. * @author Slava Pestov
  37. * @version $Id: JARClassLoader.java 4669 2003-05-01 02:21:27Z spestov $
  38. */
  39. public class JARClassLoader extends ClassLoader
  40. {
  41. //{{{ JARClassLoader constructor
  42. /**
  43. * This constructor creates a class loader for loading classes from all
  44. * plugins. For example BeanShell uses one of these so that scripts can
  45. * use plugin classes.
  46. */
  47. public JARClassLoader()
  48. {
  49. } //}}}
  50. //{{{ loadClass() method
  51. /**
  52. * @exception ClassNotFoundException if the class could not be found
  53. */
  54. public Class loadClass(String clazz, boolean resolveIt)
  55. throws ClassNotFoundException
  56. {
  57. // see what JARClassLoader this class is in
  58. Object obj = classHash.get(clazz);
  59. if(obj == NO_CLASS)
  60. {
  61. // we remember which classes we don't exist
  62. // because BeanShell tries loading all possible
  63. // <imported prefix>.<class name> combinations
  64. throw new ClassNotFoundException(clazz);
  65. }
  66. else if(obj instanceof JARClassLoader)
  67. {
  68. JARClassLoader classLoader = (JARClassLoader)obj;
  69. return classLoader._loadClass(clazz,resolveIt);
  70. }
  71. // if it's not in the class hash, and not marked as
  72. // non-existent, try loading it from the CLASSPATH
  73. try
  74. {
  75. Class cls;
  76. /* Defer to whoever loaded us (such as JShell,
  77. * Echidna, etc) */
  78. ClassLoader parentLoader = getClass().getClassLoader();
  79. if (parentLoader != null)
  80. cls = parentLoader.loadClass(clazz);
  81. else
  82. cls = findSystemClass(clazz);
  83. return cls;
  84. }
  85. catch(ClassNotFoundException cnf)
  86. {
  87. // remember that this class doesn't exist for
  88. // future reference
  89. classHash.put(clazz,NO_CLASS);
  90. throw cnf;
  91. }
  92. } //}}}
  93. //{{{ getResourceAsStream() method
  94. public InputStream getResourceAsStream(String name)
  95. {
  96. if(jar == null)
  97. return null;
  98. try
  99. {
  100. ZipFile zipFile = jar.getZipFile();
  101. ZipEntry entry = zipFile.getEntry(name);
  102. if(entry == null)
  103. return getSystemResourceAsStream(name);
  104. else
  105. return zipFile.getInputStream(entry);
  106. }
  107. catch(IOException io)
  108. {
  109. Log.log(Log.ERROR,this,io);
  110. return null;
  111. }
  112. } //}}}
  113. //{{{ getResource() method
  114. public URL getResource(String name)
  115. {
  116. if(jar == null)
  117. return null;
  118. try
  119. {
  120. ZipFile zipFile = jar.getZipFile();
  121. ZipEntry entry = zipFile.getEntry(name);
  122. if(entry == null)
  123. return getSystemResource(name);
  124. else
  125. return new URL(getResourceAsPath(name));
  126. }
  127. catch(IOException io)
  128. {
  129. Log.log(Log.ERROR,this,io);
  130. return null;
  131. }
  132. } //}}}
  133. //{{{ getResourceAsPath() method
  134. public String getResourceAsPath(String name)
  135. {
  136. if(jar == null)
  137. return null;
  138. if(!name.startsWith("/"))
  139. name = "/" + name;
  140. return "jeditresource:/" + MiscUtilities.getFileName(
  141. jar.getPath()) + "!" + name;
  142. } //}}}
  143. //{{{ getZipFile() method
  144. /**
  145. * @deprecated Call <code>PluginJAR.getZipFile()</code> instead.
  146. */
  147. public ZipFile getZipFile()
  148. {
  149. try
  150. {
  151. return jar.getZipFile();
  152. }
  153. catch(IOException io)
  154. {
  155. Log.log(Log.ERROR,this,io);
  156. return null;
  157. }
  158. } //}}}
  159. //{{{ Package-private members
  160. //{{{ JARClassLoader constructor
  161. /**
  162. * @since jEdit 4.2pre1
  163. */
  164. JARClassLoader(PluginJAR jar)
  165. {
  166. this.jar = jar;
  167. } //}}}
  168. //{{{ activate() method
  169. void activate()
  170. {
  171. String[] classes = jar.getClasses();
  172. if(classes != null)
  173. {
  174. for(int i = 0; i < classes.length; i++)
  175. {
  176. classHash.put(classes[i],this);
  177. }
  178. }
  179. } //}}}
  180. //{{{ deactivate() method
  181. void deactivate()
  182. {
  183. String[] classes = jar.getClasses();
  184. for(int i = 0; i < classes.length; i++)
  185. {
  186. Object loader = classHash.get(classes[i]);
  187. if(loader == this)
  188. classHash.remove(classes[i]);
  189. else
  190. /* two plugins provide same class! */;
  191. }
  192. } //}}}
  193. //}}}
  194. //{{{ Private members
  195. // used to mark non-existent classes in class hash
  196. private static final Object NO_CLASS = new Object();
  197. private static Hashtable classHash = new Hashtable();
  198. private PluginJAR jar;
  199. //{{{ _loadClass() method
  200. /**
  201. * Load class from this JAR only.
  202. */
  203. private Class _loadClass(String clazz, boolean resolveIt)
  204. throws ClassNotFoundException
  205. {
  206. jar.activatePlugin();
  207. Class cls = findLoadedClass(clazz);
  208. if(cls != null)
  209. {
  210. if(resolveIt)
  211. resolveClass(cls);
  212. return cls;
  213. }
  214. String name = MiscUtilities.classToFile(clazz);
  215. try
  216. {
  217. ZipFile zipFile = jar.getZipFile();
  218. ZipEntry entry = zipFile.getEntry(name);
  219. if(entry == null)
  220. throw new ClassNotFoundException(clazz);
  221. InputStream in = zipFile.getInputStream(entry);
  222. int len = (int)entry.getSize();
  223. byte[] data = new byte[len];
  224. int success = 0;
  225. int offset = 0;
  226. while(success < len)
  227. {
  228. len -= success;
  229. offset += success;
  230. success = in.read(data,offset,len);
  231. if(success == -1)
  232. {
  233. Log.log(Log.ERROR,this,"Failed to load class "
  234. + clazz + " from " + zipFile.getName());
  235. throw new ClassNotFoundException(clazz);
  236. }
  237. }
  238. cls = defineClass(clazz,data,0,data.length);
  239. if(resolveIt)
  240. resolveClass(cls);
  241. return cls;
  242. }
  243. catch(IOException io)
  244. {
  245. Log.log(Log.ERROR,this,io);
  246. throw new ClassNotFoundException(clazz);
  247. }
  248. } //}}}
  249. //}}}
  250. }