PageRenderTime 48ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/jtopen-7.8/src/CopyrightInsertionTask.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 332 lines | 289 code | 35 blank | 8 comment | 31 complexity | c14b44c18550c959e8b201a79e018a50 MD5 | raw file
  1. import java.io.*;
  2. import org.apache.tools.ant.BuildException;
  3. import org.apache.tools.ant.DirectoryScanner;
  4. import org.apache.tools.ant.taskdefs.MatchingTask;
  5. public class CopyrightInsertionTask extends MatchingTask
  6. {
  7. private static final String copyrightStringPart1_ = "Copyright (C) ";
  8. private static final String copyrightStringPart2_ = "1997-2012";
  9. private static final String copyrightStringPart3_ = " International Business Machines Corporation and others.";
  10. private static final String copyrightString_ = copyrightStringPart1_ + copyrightStringPart2_ + copyrightStringPart3_;
  11. private static final int copyrightStringLength_ = copyrightString_.length();
  12. private boolean verbose_;
  13. private File destDir_; // directory where the *.class files are located
  14. private int numFilesProcessed_ = 0; // count of class files processed
  15. private int numFilesStamped_ = 0; // count of class files stamped
  16. private int numFilesAlreadyStamped_ = 0; // count of class files already stamped
  17. public void setDestdir(File destDir)
  18. {
  19. destDir_ = destDir;
  20. }
  21. public void setVerbose(boolean verbose)
  22. {
  23. verbose_ = verbose;
  24. }
  25. // Executes the task.
  26. public void execute() throws BuildException
  27. {
  28. DirectoryScanner scanner = getDirectoryScanner(destDir_);
  29. String[] classFileNames = scanner.getIncludedFiles();
  30. for (int i=0; i<classFileNames.length; ++i)
  31. {
  32. File classFile = new File(destDir_, classFileNames[i]);
  33. if (verbose_) System.out.println("Processing "+classFileNames[i]);
  34. insertCopyrightString(classFile);
  35. numFilesProcessed_++;
  36. }
  37. System.out.println("Number of class files processed: " + numFilesProcessed_);
  38. System.out.println("Number of class files stamped: " + numFilesStamped_);
  39. System.out.println("Number of class files already stamped: " + numFilesAlreadyStamped_);
  40. }
  41. private void insertCopyrightString(File classFile) throws BuildException {
  42. try
  43. {
  44. long start = System.currentTimeMillis();
  45. DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(classFile)));
  46. byte[] prePoolBytes = new byte[8];
  47. dis.read(prePoolBytes);
  48. int constantPoolCount = dis.readUnsignedShort();
  49. Constant[] entries = new Constant[constantPoolCount];
  50. // There is no 0th entry.
  51. for (int i=1; i<constantPoolCount; ++i)
  52. {
  53. int tag = dis.readUnsignedByte();
  54. entries[i] = new Constant(tag, dis);
  55. entries[i].read();
  56. String name = entries[i].getName();
  57. if (name != null &&
  58. name.length() == copyrightStringLength_ &&
  59. name.startsWith(copyrightStringPart1_) && // tolerate different dates
  60. name.endsWith(copyrightStringPart3_))
  61. {
  62. dis.close();
  63. if (verbose_) System.out.println("Already exists. Found it at index "+i);
  64. numFilesAlreadyStamped_++;
  65. return;
  66. }
  67. if (tag == Constant.CONSTANT_Long_info ||
  68. tag == Constant.CONSTANT_Double_info)
  69. {
  70. // These take up 2 entries in the constant pool.
  71. //entries[++i] = new Constant(tag, dis);
  72. ++i;
  73. }
  74. }
  75. int bytesLeft = dis.available();
  76. byte[] postPoolBytes = new byte[bytesLeft];
  77. dis.read(postPoolBytes);
  78. dis.close();
  79. // Add the copyright to the constant pool at the end.
  80. DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(classFile)));
  81. dos.write(prePoolBytes, 0, prePoolBytes.length);
  82. dos.writeShort(constantPoolCount+1);
  83. for (int i=1; i<constantPoolCount; ++i)
  84. {
  85. entries[i].write(dos);
  86. int tag = entries[i].getType();
  87. if (tag == Constant.CONSTANT_Long_info ||
  88. tag == Constant.CONSTANT_Double_info)
  89. {
  90. ++i;
  91. }
  92. }
  93. dos.writeByte(Constant.CONSTANT_Utf8_info);
  94. dos.writeUTF(copyrightString_);
  95. dos.write(postPoolBytes, 0, postPoolBytes.length);
  96. dos.flush();
  97. dos.close();
  98. long end = System.currentTimeMillis();
  99. if (verbose_) System.out.println("Stamped. Time: "+(end-start)+" ms");
  100. numFilesStamped_++;
  101. }
  102. catch (Exception e) { throw new BuildException(e); }
  103. }
  104. final class Constant
  105. {
  106. public static final int CONSTANT_Class_info = 7;
  107. public static final int CONSTANT_Fieldref_info = 9;
  108. public static final int CONSTANT_Methodref_info = 10;
  109. public static final int CONSTANT_InterfaceMethodref_info = 11;
  110. public static final int CONSTANT_String_info = 8;
  111. public static final int CONSTANT_Integer_info = 3;
  112. public static final int CONSTANT_Float_info = 4;
  113. public static final int CONSTANT_Long_info = 5;
  114. public static final int CONSTANT_Double_info = 6;
  115. public static final int CONSTANT_NameAndType_info = 12;
  116. public static final int CONSTANT_Utf8_info = 1;
  117. private int type_ = -1;
  118. private DataInputStream dataIn_ = null;
  119. private DataOutputStream dataOut_ = null;
  120. private int data1_ = -1;
  121. private int data2_ = -1;
  122. private int[] bytes_ = null;
  123. private String name_ = null;
  124. public Constant(int type, DataInputStream dataIn)
  125. {
  126. type_ = type;
  127. dataIn_ = dataIn;
  128. }
  129. public void read()
  130. throws IOException
  131. {
  132. switch(type_)
  133. {
  134. case CONSTANT_Utf8_info:
  135. data1_ = read(2);
  136. bytes_ = new int[data1_];
  137. for (int i=0; i<data1_; ++i)
  138. {
  139. bytes_[i] = read(1);
  140. }
  141. parseName();
  142. break;
  143. case CONSTANT_Class_info:
  144. case CONSTANT_String_info:
  145. data1_ = read(2);
  146. break;
  147. case CONSTANT_Double_info:
  148. case CONSTANT_Long_info:
  149. // These take up 2 entries in the constant pool.
  150. // The 2nd one is unusable. This has been noted as
  151. // a bad design choice by the JVM makers.
  152. data1_ = read(4);
  153. data2_ = read(4);
  154. break;
  155. case CONSTANT_Float_info:
  156. case CONSTANT_Integer_info:
  157. data1_ = read(4);
  158. break;
  159. case CONSTANT_Fieldref_info:
  160. case CONSTANT_InterfaceMethodref_info:
  161. case CONSTANT_Methodref_info:
  162. case CONSTANT_NameAndType_info:
  163. data1_ = read(2);
  164. data2_ = read(2);
  165. break;
  166. default:
  167. throw new IllegalArgumentException("wrong type: "+type_);
  168. }
  169. }
  170. public void write(DataOutputStream dataOut)
  171. throws IOException
  172. {
  173. dataOut_ = dataOut;
  174. write(1, type_);
  175. switch(type_)
  176. {
  177. case CONSTANT_Utf8_info:
  178. write(2, data1_);
  179. for (int i=0; i<data1_; ++i)
  180. {
  181. write(1, bytes_[i]);
  182. }
  183. break;
  184. case CONSTANT_Class_info:
  185. case CONSTANT_String_info:
  186. write(2, data1_);
  187. break;
  188. case CONSTANT_Double_info:
  189. case CONSTANT_Long_info:
  190. write(4, data1_);
  191. write(4, data2_);
  192. break;
  193. case CONSTANT_Float_info:
  194. case CONSTANT_Integer_info:
  195. write(4, data1_);
  196. break;
  197. case CONSTANT_Fieldref_info:
  198. case CONSTANT_InterfaceMethodref_info:
  199. case CONSTANT_Methodref_info:
  200. case CONSTANT_NameAndType_info:
  201. write(2, data1_);
  202. write(2, data2_);
  203. break;
  204. default:
  205. throw new IllegalArgumentException("wrong type: "+type_);
  206. }
  207. }
  208. public int read(int size)
  209. throws IOException
  210. {
  211. switch(size)
  212. {
  213. case 1:
  214. return dataIn_.readUnsignedByte();
  215. case 2:
  216. return dataIn_.readUnsignedShort();
  217. case 4:
  218. return dataIn_.readInt();
  219. default:
  220. throw new IllegalArgumentException("number of bytes to read: "+size);
  221. }
  222. }
  223. public void write(int size, int data)
  224. throws IOException
  225. {
  226. switch(size)
  227. {
  228. case 1:
  229. dataOut_.writeByte(data);
  230. break;
  231. case 2:
  232. dataOut_.writeShort(data);
  233. break;
  234. case 4:
  235. dataOut_.writeInt(data);
  236. break;
  237. default:
  238. throw new IllegalArgumentException("number of bytes to write: "+size);
  239. }
  240. }
  241. public int getType()
  242. {
  243. return type_;
  244. }
  245. public String getName()
  246. {
  247. if (type_ == CONSTANT_Utf8_info && name_ == null)
  248. {
  249. parseName();
  250. }
  251. return name_;
  252. }
  253. private void parseName()
  254. {
  255. int length = data1_;
  256. int[] bytes = bytes_;
  257. if (bytes == null) return;
  258. StringBuffer name = new StringBuffer();
  259. int i=0;
  260. while (i<length)
  261. {
  262. int ch;
  263. byte a = (byte)bytes[i];
  264. validate(a);
  265. if (a > 0x7F) // not a single-byte char
  266. {
  267. i++;
  268. byte b = (byte)bytes[i];
  269. validate(b);
  270. if (b > 0xBF) // not a double-byte char
  271. {
  272. i++;
  273. byte c = (byte)bytes[i];
  274. validate(c);
  275. ch = ((a & 0xf) << 12) + ((b & 0x3f) << 6) + (c & 0x3f);
  276. }
  277. else // is a double-byte
  278. {
  279. ch = ((a & 0x1f) << 6) + (b & 0x3f);
  280. }
  281. }
  282. else // is a single-byte
  283. {
  284. ch = a;
  285. }
  286. name.append((char)ch);
  287. i++;
  288. }
  289. name_ = name.toString();
  290. }
  291. private /*static*/ void validate(byte x)
  292. {
  293. if (x==0x0 || x>=0xf0)
  294. throw new NullPointerException("Invalid byte: "+x);
  295. }
  296. }
  297. }