Attribute.java 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright (c) 1997 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.bytecode;
  4. import java.io.*;
  5. /**
  6. * Represents an Attribute of an AttrContainer.
  7. * <p>
  8. * Various sub-classses are used for standard attributes,
  9. * or you can use MiscAttr for a generic attribute.
  10. * @author Per Bothner
  11. */
  12. public abstract class Attribute
  13. {
  14. /** Every Attribute belongs to some AttrContainer object. */
  15. AttrContainer container;
  16. /** Return the Attribute container that contains this Attribute. */
  17. public final AttrContainer getContainer() { return container; }
  18. public final void setContainer(AttrContainer container)
  19. { this.container = container; }
  20. private Attribute next;
  21. /** Get the next Attribute belonging to getContainer(). */
  22. public final Attribute getNext() { return next; }
  23. /** Set the next Attribute in the chain belonging to getContainer(). */
  24. public final void setNext(Attribute next) { this.next = next; }
  25. public ConstantPool getConstants ()
  26. {
  27. return getContainer().getConstants();
  28. }
  29. /** Add this to (the front of) of the specified attribute container. */
  30. public void addToFrontOf(AttrContainer container)
  31. {
  32. setContainer(container);
  33. setNext(container.getAttributes());
  34. container.setAttributes(this);
  35. }
  36. String name; // This is an interned string.
  37. // If > 0, the constant-pool index of name.
  38. // If -1, means attribute should be skipped on output.
  39. int name_index;
  40. /** Returns true if this attribute should be skipped on output. */
  41. public final boolean isSkipped() { return name_index < 0; }
  42. /** Iff skip, cause this attributed to be skipped on output. */
  43. public final void setSkipped(boolean skip) { name_index = skip ? -1 : 0; }
  44. /** Cause this attributed to be skipped on output. */
  45. public final void setSkipped() { name_index = -1; }
  46. public final String getName() { return name; }
  47. public final void setName(String name) { this.name = name.intern(); }
  48. public final int getNameIndex() { return name_index; }
  49. public final void setNameIndex(int index) { name_index = index; }
  50. /** Create a new Attribute.
  51. * @param name - an interned String that names the Attribute. */
  52. public Attribute (String name)
  53. {
  54. this.name = name;
  55. }
  56. /** Find an Attribute by name, in an attribute cointainer.
  57. * @param container the attribute container to search
  58. * @param name the (interned) name of the attribute we are seeking
  59. * @return the matching Attribute, or null if the search failed.
  60. */
  61. public static Attribute get (AttrContainer container, String name)
  62. {
  63. for (Attribute attr = container.getAttributes();
  64. attr != null; attr = attr.next)
  65. {
  66. if (attr.getName() == name)
  67. return attr;
  68. }
  69. return null;
  70. }
  71. /** Add any needed constant pool entries for this Attribute.
  72. * Overridden by sub-classes.
  73. * Do any other cleanup needed before writing out a .class file. */
  74. public void assignConstants (ClassType cl)
  75. {
  76. if (name_index == 0)
  77. name_index = cl.getConstants().addUtf8(name).getIndex();
  78. }
  79. /** Add any needed constant pool entries for all attributes in a container.
  80. * Do any other cleanup needed before writing out a .class file. */
  81. public static void assignConstants (AttrContainer container, ClassType cl)
  82. {
  83. for (Attribute attr = container.getAttributes();
  84. attr != null; attr = attr.next)
  85. {
  86. if (! attr.isSkipped())
  87. attr.assignConstants(cl);
  88. }
  89. }
  90. /** Return the length of the attribute in bytes.
  91. * Does not include the 6-byte header (for the name_index and the length).*/
  92. abstract public int getLength();
  93. /** Return the length of all the attributes (with headers) in bytes. */
  94. public static int getLengthAll (AttrContainer container)
  95. {
  96. int length = 0;
  97. for (Attribute attr = container.getAttributes();
  98. attr != null; attr = attr.next)
  99. {
  100. if (! attr.isSkipped())
  101. length += 6 + attr.getLength();
  102. }
  103. return length;
  104. }
  105. /** Write out the contents of the Attribute.
  106. * Does not write the 6-byte attribute header. */
  107. abstract public void write (DataOutputStream dstr)
  108. throws java.io.IOException;
  109. public static int count (AttrContainer container)
  110. {
  111. int count = 0;
  112. for (Attribute attr = container.getAttributes();
  113. attr != null; attr = attr.next)
  114. {
  115. if (!attr.isSkipped())
  116. count++;
  117. }
  118. return count;
  119. }
  120. public static void writeAll (AttrContainer container, DataOutputStream dstr)
  121. throws java.io.IOException
  122. {
  123. int count = count(container);
  124. dstr.writeShort(count);
  125. for (Attribute attr = container.getAttributes();
  126. attr != null; attr = attr.next)
  127. {
  128. if (attr.isSkipped())
  129. continue;
  130. if (attr.name_index == 0)
  131. throw new Error("Attribute.writeAll called without assignConstants");
  132. dstr.writeShort(attr.name_index);
  133. dstr.writeInt(attr.getLength());
  134. attr.write(dstr);
  135. }
  136. }
  137. public void print (ClassTypeWriter dst)
  138. {
  139. dst.print("Attribute \"");
  140. dst.print(getName());
  141. dst.print("\", length:");
  142. dst.println(getLength());
  143. }
  144. };