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.

FieldInfo.java 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- 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. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.bytecode;
  17. import java.io.DataInputStream;
  18. import java.io.DataOutputStream;
  19. import java.io.IOException;
  20. import java.util.ArrayList;
  21. import java.util.List;
  22. /**
  23. * <code>field_info</code> structure.
  24. *
  25. * <p>The following code adds a public field <code>width</code>
  26. * of <code>int</code> type:
  27. * <blockquote><pre>
  28. * ClassFile cf = ...
  29. * FieldInfo f = new FieldInfo(cf.getConstPool(), "width", "I");
  30. * f.setAccessFlags(AccessFlag.PUBLIC);
  31. * cf.addField(f);
  32. * </pre></blockquote>
  33. *
  34. * @see javassist.CtField#getFieldInfo()
  35. */
  36. public final class FieldInfo {
  37. ConstPool constPool;
  38. int accessFlags;
  39. int name;
  40. String cachedName;
  41. String cachedType;
  42. int descriptor;
  43. List<AttributeInfo> attribute; // may be null.
  44. private FieldInfo(ConstPool cp) {
  45. constPool = cp;
  46. accessFlags = 0;
  47. attribute = null;
  48. }
  49. /**
  50. * Constructs a <code>field_info</code> structure.
  51. *
  52. * @param cp a constant pool table
  53. * @param fieldName field name
  54. * @param desc field descriptor
  55. *
  56. * @see Descriptor
  57. */
  58. public FieldInfo(ConstPool cp, String fieldName, String desc) {
  59. this(cp);
  60. name = cp.addUtf8Info(fieldName);
  61. cachedName = fieldName;
  62. descriptor = cp.addUtf8Info(desc);
  63. }
  64. FieldInfo(ConstPool cp, DataInputStream in) throws IOException {
  65. this(cp);
  66. read(in);
  67. }
  68. /**
  69. * Returns a string representation of the object.
  70. */
  71. @Override
  72. public String toString() {
  73. return getName() + " " + getDescriptor();
  74. }
  75. /**
  76. * Copies all constant pool items to a given new constant pool
  77. * and replaces the original items with the new ones.
  78. * This is used for garbage collecting the items of removed fields
  79. * and methods.
  80. *
  81. * @param cp the destination
  82. */
  83. void compact(ConstPool cp) {
  84. name = cp.addUtf8Info(getName());
  85. descriptor = cp.addUtf8Info(getDescriptor());
  86. attribute = AttributeInfo.copyAll(attribute, cp);
  87. constPool = cp;
  88. }
  89. void prune(ConstPool cp) {
  90. List<AttributeInfo> newAttributes = new ArrayList<AttributeInfo>();
  91. AttributeInfo invisibleAnnotations
  92. = getAttribute(AnnotationsAttribute.invisibleTag);
  93. if (invisibleAnnotations != null) {
  94. invisibleAnnotations = invisibleAnnotations.copy(cp, null);
  95. newAttributes.add(invisibleAnnotations);
  96. }
  97. AttributeInfo visibleAnnotations
  98. = getAttribute(AnnotationsAttribute.visibleTag);
  99. if (visibleAnnotations != null) {
  100. visibleAnnotations = visibleAnnotations.copy(cp, null);
  101. newAttributes.add(visibleAnnotations);
  102. }
  103. AttributeInfo signature
  104. = getAttribute(SignatureAttribute.tag);
  105. if (signature != null) {
  106. signature = signature.copy(cp, null);
  107. newAttributes.add(signature);
  108. }
  109. int index = getConstantValue();
  110. if (index != 0) {
  111. index = constPool.copy(index, cp, null);
  112. newAttributes.add(new ConstantAttribute(cp, index));
  113. }
  114. attribute = newAttributes;
  115. name = cp.addUtf8Info(getName());
  116. descriptor = cp.addUtf8Info(getDescriptor());
  117. constPool = cp;
  118. }
  119. /**
  120. * Returns the constant pool table used
  121. * by this <code>field_info</code>.
  122. */
  123. public ConstPool getConstPool() {
  124. return constPool;
  125. }
  126. /**
  127. * Returns the field name.
  128. */
  129. public String getName() {
  130. if (cachedName == null)
  131. cachedName = constPool.getUtf8Info(name);
  132. return cachedName;
  133. }
  134. /**
  135. * Sets the field name.
  136. */
  137. public void setName(String newName) {
  138. name = constPool.addUtf8Info(newName);
  139. cachedName = newName;
  140. }
  141. /**
  142. * Returns the access flags.
  143. *
  144. * @see AccessFlag
  145. */
  146. public int getAccessFlags() {
  147. return accessFlags;
  148. }
  149. /**
  150. * Sets the access flags.
  151. *
  152. * @see AccessFlag
  153. */
  154. public void setAccessFlags(int acc) {
  155. accessFlags = acc;
  156. }
  157. /**
  158. * Returns the field descriptor.
  159. *
  160. * @see Descriptor
  161. */
  162. public String getDescriptor() {
  163. return constPool.getUtf8Info(descriptor);
  164. }
  165. /**
  166. * Sets the field descriptor.
  167. *
  168. * @see Descriptor
  169. */
  170. public void setDescriptor(String desc) {
  171. if (!desc.equals(getDescriptor()))
  172. descriptor = constPool.addUtf8Info(desc);
  173. }
  174. /**
  175. * Finds a ConstantValue attribute and returns the index into
  176. * the <code>constant_pool</code> table.
  177. *
  178. * @return 0 if a ConstantValue attribute is not found.
  179. */
  180. public int getConstantValue() {
  181. if ((accessFlags & AccessFlag.STATIC) == 0)
  182. return 0;
  183. ConstantAttribute attr
  184. = (ConstantAttribute)getAttribute(ConstantAttribute.tag);
  185. if (attr == null)
  186. return 0;
  187. return attr.getConstantValue();
  188. }
  189. /**
  190. * Returns all the attributes. The returned <code>List</code> object
  191. * is shared with this object. If you add a new attribute to the list,
  192. * the attribute is also added to the field represented by this
  193. * object. If you remove an attribute from the list, it is also removed
  194. * from the field.
  195. *
  196. * @return a list of <code>AttributeInfo</code> objects.
  197. * @see AttributeInfo
  198. */
  199. public List<AttributeInfo> getAttributes() {
  200. if (attribute == null)
  201. attribute = new ArrayList<AttributeInfo>();
  202. return attribute;
  203. }
  204. /**
  205. * Returns the attribute with the specified name.
  206. * It returns null if the specified attribute is not found.
  207. *
  208. * <p>An attribute name can be obtained by, for example,
  209. * {@link AnnotationsAttribute#visibleTag} or
  210. * {@link AnnotationsAttribute#invisibleTag}.
  211. * </p>
  212. *
  213. * @param name attribute name
  214. * @see #getAttributes()
  215. */
  216. public AttributeInfo getAttribute(String name) {
  217. return AttributeInfo.lookup(attribute, name);
  218. }
  219. /**
  220. * Removes an attribute with the specified name.
  221. *
  222. * @param name attribute name.
  223. * @return the removed attribute or null.
  224. * @since 3.21
  225. */
  226. public AttributeInfo removeAttribute(String name) {
  227. return AttributeInfo.remove(attribute, name);
  228. }
  229. /**
  230. * Appends an attribute. If there is already an attribute with
  231. * the same name, the new one substitutes for it.
  232. *
  233. * @see #getAttributes()
  234. */
  235. public void addAttribute(AttributeInfo info) {
  236. if (attribute == null)
  237. attribute = new ArrayList<AttributeInfo>();
  238. AttributeInfo.remove(attribute, info.getName());
  239. attribute.add(info);
  240. }
  241. private void read(DataInputStream in) throws IOException {
  242. accessFlags = in.readUnsignedShort();
  243. name = in.readUnsignedShort();
  244. descriptor = in.readUnsignedShort();
  245. int n = in.readUnsignedShort();
  246. attribute = new ArrayList<AttributeInfo>();
  247. for (int i = 0; i < n; ++i)
  248. attribute.add(AttributeInfo.read(constPool, in));
  249. }
  250. void write(DataOutputStream out) throws IOException {
  251. out.writeShort(accessFlags);
  252. out.writeShort(name);
  253. out.writeShort(descriptor);
  254. if (attribute == null)
  255. out.writeShort(0);
  256. else {
  257. out.writeShort(attribute.size());
  258. AttributeInfo.writeAll(attribute, out);
  259. }
  260. }
  261. }