PageRenderTime 54ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/jsrc-core/ua/gradsoft/termware/debug/SDEInserter.java

https://github.com/rssh/termware2
Java | 273 lines | 218 code | 37 blank | 18 comment | 30 complexity | f2a7c43a86b6ec9b207db1f9bbc359a2 MD5 | raw file
  1. package ua.gradsoft.termware.debug;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.UnsupportedEncodingException;
  8. /**
  9. * This helper class inserts SDE (JSR 45 Software Debug Extension attribute) into class bytes.
  10. * Code is derived from Apache Jasper project.
  11. * SMAPUtils.SDEInstaller
  12. * <pre>
  13. * //*********************************************************************
  14. * // Installation logic (from Robert Field, JSR-045 spec lead)
  15. * </pre>
  16. */
  17. public class SDEInserter {
  18. static final String nameSDE = "SourceDebugExtension";
  19. byte[] orig;
  20. byte[] sdeAttr;
  21. byte[] gen;
  22. int origPos = 0;
  23. int genPos = 0;
  24. int sdeIndex;
  25. boolean isDebugEnabled=false;
  26. SDEInserter(byte[] originBytes, byte[] sdeAttr) throws UnsupportedEncodingException, IOException
  27. {
  28. this.sdeAttr = sdeAttr;
  29. // get the bytes
  30. orig = originBytes;
  31. gen = new byte[orig.length + sdeAttr.length + 100];
  32. // do it
  33. addSDE();
  34. byte[] newGen = new byte[genPos];
  35. System.arraycopy(gen,0,newGen,0,genPos);
  36. gen=newGen;
  37. }
  38. byte[] getResult()
  39. { return gen; }
  40. void debug(String line)
  41. {
  42. System.err.println(line);
  43. }
  44. void addSDE() throws UnsupportedEncodingException, IOException {
  45. int i;
  46. copy(4 + 2 + 2); // magic min/maj version
  47. int constantPoolCountPos = genPos;
  48. int constantPoolCount = readU2();
  49. if (isDebugEnabled) {
  50. System.err.println("constant pool count: " + constantPoolCount);
  51. }
  52. writeU2(constantPoolCount);
  53. // copy old constant pool return index of SDE symbol, if found
  54. sdeIndex = copyConstantPool(constantPoolCount);
  55. if (sdeIndex < 0) {
  56. // if "SourceDebugExtension" symbol not there add it
  57. writeUtf8ForSDE();
  58. // increment the countantPoolCount
  59. sdeIndex = constantPoolCount;
  60. ++constantPoolCount;
  61. randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
  62. if (isDebugEnabled) {
  63. debug("SourceDebugExtension not found, installed at: " + sdeIndex);
  64. }
  65. } else {
  66. if (isDebugEnabled) {
  67. debug("SourceDebugExtension found at: " + sdeIndex);
  68. }
  69. }
  70. copy(2 + 2 + 2); // access, this, super
  71. int interfaceCount = readU2();
  72. writeU2(interfaceCount);
  73. if (isDebugEnabled)
  74. debug("interfaceCount: " + interfaceCount);
  75. copy(interfaceCount * 2);
  76. copyMembers(); // fields
  77. copyMembers(); // methods
  78. int attrCountPos = genPos;
  79. int attrCount = readU2();
  80. writeU2(attrCount);
  81. if (isDebugEnabled)
  82. debug("class attrCount: " + attrCount);
  83. // copy the class attributes, return true if SDE attr found (not copied)
  84. if (!copyAttrs(attrCount)) {
  85. // we will be adding SDE and it isn't already counted
  86. ++attrCount;
  87. randomAccessWriteU2(attrCountPos, attrCount);
  88. if (isDebugEnabled)
  89. debug("class attrCount incremented");
  90. }
  91. writeAttrForSDE(sdeIndex);
  92. }
  93. void copyMembers() {
  94. int count = readU2();
  95. writeU2(count);
  96. if (isDebugEnabled)
  97. debug("members count: " + count);
  98. for (int i = 0; i < count; ++i) {
  99. copy(6); // access, name, descriptor
  100. int attrCount = readU2();
  101. writeU2(attrCount);
  102. if (isDebugEnabled)
  103. debug("member attr count: " + attrCount);
  104. copyAttrs(attrCount);
  105. }
  106. }
  107. boolean copyAttrs(int attrCount) {
  108. boolean sdeFound = false;
  109. for (int i = 0; i < attrCount; ++i) {
  110. int nameIndex = readU2();
  111. // don't write old SDE
  112. if (nameIndex == sdeIndex) {
  113. sdeFound = true;
  114. if (isDebugEnabled)
  115. debug("SDE attr found");
  116. } else {
  117. writeU2(nameIndex); // name
  118. int len = readU4();
  119. writeU4(len);
  120. copy(len);
  121. if (isDebugEnabled)
  122. debug("attr len: " + len);
  123. }
  124. }
  125. return sdeFound;
  126. }
  127. void writeAttrForSDE(int index) {
  128. writeU2(index);
  129. writeU4(sdeAttr.length);
  130. for (int i = 0; i < sdeAttr.length; ++i) {
  131. writeU1(sdeAttr[i]);
  132. }
  133. }
  134. void randomAccessWriteU2(int pos, int val) {
  135. int savePos = genPos;
  136. genPos = pos;
  137. writeU2(val);
  138. genPos = savePos;
  139. }
  140. int readU1() {
  141. return ((int)orig[origPos++]) & 0xFF;
  142. }
  143. int readU2() {
  144. int res = readU1();
  145. return (res << 8) + readU1();
  146. }
  147. int readU4() {
  148. int res = readU2();
  149. return (res << 16) + readU2();
  150. }
  151. void writeU1(int val) {
  152. gen[genPos++] = (byte)val;
  153. }
  154. void writeU2(int val) {
  155. writeU1(val >> 8);
  156. writeU1(val & 0xFF);
  157. }
  158. void writeU4(int val) {
  159. writeU2(val >> 16);
  160. writeU2(val & 0xFFFF);
  161. }
  162. void copy(int count) {
  163. for (int i = 0; i < count; ++i) {
  164. gen[genPos++] = orig[origPos++];
  165. }
  166. }
  167. byte[] readBytes(int count) {
  168. byte[] bytes = new byte[count];
  169. for (int i = 0; i < count; ++i) {
  170. bytes[i] = orig[origPos++];
  171. }
  172. return bytes;
  173. }
  174. void writeBytes(byte[] bytes) {
  175. for (int i = 0; i < bytes.length; ++i) {
  176. gen[genPos++] = bytes[i];
  177. }
  178. }
  179. int copyConstantPool(int constantPoolCount)
  180. throws UnsupportedEncodingException, IOException {
  181. int sdeIndex = -1;
  182. // copy const pool index zero not in class file
  183. for (int i = 1; i < constantPoolCount; ++i) {
  184. int tag = readU1();
  185. writeU1(tag);
  186. switch (tag) {
  187. case 7 : // Class
  188. case 8 : // String
  189. if (isDebugEnabled)
  190. debug(i + " copying 2 bytes");
  191. copy(2);
  192. break;
  193. case 9 : // Field
  194. case 10 : // Method
  195. case 11 : // InterfaceMethod
  196. case 3 : // Integer
  197. case 4 : // Float
  198. case 12 : // NameAndType
  199. if (isDebugEnabled)
  200. debug(i + " copying 4 bytes");
  201. copy(4);
  202. break;
  203. case 5 : // Long
  204. case 6 : // Double
  205. if (isDebugEnabled)
  206. debug(i + " copying 8 bytes");
  207. copy(8);
  208. i++;
  209. break;
  210. case 1 : // Utf8
  211. int len = readU2();
  212. writeU2(len);
  213. byte[] utf8 = readBytes(len);
  214. String str = new String(utf8, "UTF-8");
  215. if (isDebugEnabled)
  216. debug(i + " read class attr -- '" + str + "'");
  217. if (str.equals(nameSDE)) {
  218. sdeIndex = i;
  219. }
  220. writeBytes(utf8);
  221. break;
  222. default :
  223. throw new IOException("unexpected tag: " + tag);
  224. }
  225. }
  226. return sdeIndex;
  227. }
  228. void writeUtf8ForSDE() {
  229. int len = nameSDE.length();
  230. writeU1(1); // Utf8 tag
  231. writeU2(len);
  232. for (int i = 0; i < len; ++i) {
  233. writeU1(nameSDE.charAt(i));
  234. }
  235. }
  236. }