You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClassPoolTail.java 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist;
  16. import java.io.*;
  17. import java.util.zip.*;
  18. final class ClassPathList {
  19. ClassPathList next;
  20. ClassPath path;
  21. ClassPathList(ClassPath p, ClassPathList n) {
  22. next = n;
  23. path = p;
  24. }
  25. }
  26. final class SystemClassPath implements ClassPath {
  27. Class thisClass;
  28. SystemClassPath() {
  29. /* The value of thisClass was this.getClass() in early versions:
  30. *
  31. * thisClass = this.getClass();
  32. *
  33. * However, this made openClassfile() not search all the system
  34. * class paths if javassist.jar is put in jre/lib/ext/
  35. * (with JDK1.4).
  36. */
  37. thisClass = java.lang.Object.class;
  38. }
  39. public InputStream openClassfile(String classname) {
  40. String jarname = "/" + classname.replace('.', '/') + ".class";
  41. return thisClass.getResourceAsStream(jarname);
  42. }
  43. public void close() {}
  44. public String toString() {
  45. return "*system class path*";
  46. }
  47. }
  48. final class DirClassPath implements ClassPath {
  49. String directory;
  50. DirClassPath(String dirName) {
  51. directory = dirName;
  52. }
  53. public InputStream openClassfile(String classname) {
  54. try {
  55. char sep = File.separatorChar;
  56. String filename = directory + sep
  57. + classname.replace('.', sep) + ".class";
  58. return new FileInputStream(filename.toString());
  59. }
  60. catch (FileNotFoundException e) {}
  61. catch (SecurityException e) {}
  62. return null;
  63. }
  64. public void close() {}
  65. public String toString() {
  66. return directory;
  67. }
  68. }
  69. final class JarClassPath implements ClassPath {
  70. ZipFile jarfile;
  71. JarClassPath(String pathname) throws NotFoundException {
  72. try {
  73. jarfile = new ZipFile(pathname);
  74. return;
  75. }
  76. catch (ZipException e) {}
  77. catch (IOException e) {}
  78. throw new NotFoundException(pathname);
  79. }
  80. public InputStream openClassfile(String classname)
  81. throws NotFoundException
  82. {
  83. try {
  84. String jarname = classname.replace('.', '/') + ".class";
  85. ZipEntry ze = jarfile.getEntry(jarname);
  86. if (ze != null)
  87. return jarfile.getInputStream(ze);
  88. else
  89. return null; // not found
  90. }
  91. catch (ZipException e) {}
  92. catch (IOException e) {}
  93. throw new NotFoundException("broken jar file?: "
  94. + jarfile.getName());
  95. }
  96. public void close() {
  97. try {
  98. jarfile.close();
  99. jarfile = null;
  100. }
  101. catch (IOException e) {}
  102. }
  103. public String toString() {
  104. return jarfile == null ? "<null>" : jarfile.toString();
  105. }
  106. }
  107. final class ClassPoolTail extends ClassPool {
  108. protected ClassPathList pathList;
  109. private Class thisClass;
  110. public ClassPoolTail() {
  111. pathList = null;
  112. thisClass = getClass();
  113. }
  114. public String toString() {
  115. StringBuffer buf = new StringBuffer();
  116. buf.append("[class path: ");
  117. ClassPathList list = pathList;
  118. while (list != null) {
  119. buf.append(list.path.toString());
  120. buf.append(File.pathSeparatorChar);
  121. list = list.next;
  122. }
  123. buf.append(']');
  124. return buf.toString();
  125. }
  126. public byte[] write(String classname)
  127. throws NotFoundException, IOException
  128. {
  129. return readClassfile(classname);
  130. }
  131. public void write(String classname, DataOutputStream out)
  132. throws NotFoundException, CannotCompileException, IOException
  133. {
  134. byte[] b = write(classname);
  135. out.write(b, 0, b.length);
  136. }
  137. public CtClass get(String classname) throws NotFoundException {
  138. throw new RuntimeException("fatal error");
  139. }
  140. public CtClass makeClass(String classname) {
  141. throw new RuntimeException("fatal error");
  142. }
  143. void checkClassName(String classname)
  144. throws NotFoundException
  145. {
  146. InputStream fin = openClassfile(classname);
  147. try {
  148. fin.close();
  149. }
  150. catch (IOException e) { /* ignore */ }
  151. }
  152. public synchronized ClassPath insertClassPath(ClassPath cp) {
  153. pathList = new ClassPathList(cp, pathList);
  154. return cp;
  155. }
  156. public synchronized ClassPath appendClassPath(ClassPath cp) {
  157. ClassPathList tail = new ClassPathList(cp, null);
  158. ClassPathList list = pathList;
  159. if (list == null)
  160. pathList = tail;
  161. else {
  162. while (list.next != null)
  163. list = list.next;
  164. list.next = tail;
  165. }
  166. return cp;
  167. }
  168. public synchronized void removeClassPath(ClassPath cp) {
  169. ClassPathList list = pathList;
  170. if (list != null)
  171. if (list.path == cp)
  172. pathList = list.next;
  173. else {
  174. while (list.next != null)
  175. if (list.next.path == cp)
  176. list.next = list.next.next;
  177. else
  178. list = list.next;
  179. }
  180. cp.close();
  181. }
  182. public ClassPath appendSystemPath() {
  183. return appendClassPath(new SystemClassPath());
  184. }
  185. public ClassPath insertClassPath(String pathname)
  186. throws NotFoundException
  187. {
  188. return insertClassPath(makePathObject(pathname));
  189. }
  190. public ClassPath appendClassPath(String pathname)
  191. throws NotFoundException
  192. {
  193. return appendClassPath(makePathObject(pathname));
  194. }
  195. private static ClassPath makePathObject(String pathname)
  196. throws NotFoundException
  197. {
  198. int i = pathname.lastIndexOf('.');
  199. if (i >= 0) {
  200. String ext = pathname.substring(i).toLowerCase();
  201. if (ext.equals(".jar") || ext.equals(".zip"))
  202. return new JarClassPath(pathname);
  203. }
  204. return new DirClassPath(pathname);
  205. }
  206. /**
  207. * Obtains the contents of the class file for the class
  208. * specified by <code>classname</code>.
  209. *
  210. * @param classname a fully-qualified class name
  211. */
  212. byte[] readClassfile(String classname)
  213. throws NotFoundException, IOException
  214. {
  215. InputStream fin = openClassfile(classname);
  216. byte[] b = readStream(fin);
  217. fin.close();
  218. return b;
  219. }
  220. /**
  221. * Opens the class file for the class specified by
  222. * <code>classname</code>.
  223. *
  224. * @param classname a fully-qualified class name
  225. */
  226. public InputStream openClassfile(String classname)
  227. throws NotFoundException
  228. {
  229. ClassPathList list = pathList;
  230. InputStream ins = null;
  231. NotFoundException error = null;
  232. while (list != null) {
  233. try {
  234. ins = list.path.openClassfile(classname);
  235. }
  236. catch (NotFoundException e) {
  237. if (error == null)
  238. error = e;
  239. }
  240. if (ins == null)
  241. list = list.next;
  242. else
  243. return ins;
  244. }
  245. if (error != null)
  246. throw error;
  247. else
  248. throw new NotFoundException(classname);
  249. }
  250. /**
  251. * Reads an input stream until it reaches the end.
  252. *
  253. * @return the contents of that input stream
  254. */
  255. public static byte[] readStream(InputStream fin) throws IOException {
  256. byte[][] bufs = new byte[8][];
  257. int bufsize = 4096;
  258. for (int i = 0; i < 8; ++i) {
  259. bufs[i] = new byte[bufsize];
  260. int size = 0;
  261. int len = 0;
  262. do {
  263. len = fin.read(bufs[i], size, bufsize - size);
  264. if (len >= 0)
  265. size += len;
  266. else {
  267. byte[] result = new byte[bufsize - 4096 + size];
  268. int s = 0;
  269. for (int j = 0; j < i; ++j) {
  270. System.arraycopy(bufs[j], 0, result, s, s + 4096);
  271. s = s + s + 4096;
  272. }
  273. System.arraycopy(bufs[i], 0, result, s, size);
  274. return result;
  275. }
  276. } while (size < bufsize);
  277. bufsize *= 2;
  278. }
  279. throw new IOException("too much data");
  280. }
  281. }