1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.harmony.unpack200.bytecode;
20
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26
27
28
29 public class InnerClassesAttribute extends Attribute {
30
31 private static final class InnerClassesEntry {
32
33 CPClass innerClassInfo;
34 CPClass outerClassInfo;
35 CPUTF8 innerClassName;
36
37 int innerClassInfoIndex = -1;
38 int outerClassInfoIndex = -1;
39 int innerNameIndex = -1;
40 int innerClassAccessFlags = -1;
41
42 InnerClassesEntry(final CPClass innerClass, final CPClass outerClass, final CPUTF8 innerName, final int flags) {
43 this.innerClassInfo = innerClass;
44 this.outerClassInfo = outerClass;
45 this.innerClassName = innerName;
46 this.innerClassAccessFlags = flags;
47 }
48
49
50
51
52
53
54 public void resolve(final ClassConstantPool pool) {
55 if (innerClassInfo != null) {
56 innerClassInfo.resolve(pool);
57 innerClassInfoIndex = pool.indexOf(innerClassInfo);
58 } else {
59 innerClassInfoIndex = 0;
60 }
61
62 if (innerClassName != null) {
63 innerClassName.resolve(pool);
64 innerNameIndex = pool.indexOf(innerClassName);
65 } else {
66 innerNameIndex = 0;
67 }
68
69 if (outerClassInfo != null) {
70 outerClassInfo.resolve(pool);
71 outerClassInfoIndex = pool.indexOf(outerClassInfo);
72 } else {
73 outerClassInfoIndex = 0;
74 }
75 }
76
77 public void write(final DataOutputStream dos) throws IOException {
78 dos.writeShort(innerClassInfoIndex);
79 dos.writeShort(outerClassInfoIndex);
80 dos.writeShort(innerNameIndex);
81 dos.writeShort(innerClassAccessFlags);
82 }
83
84 }
85
86 private static CPUTF8 attributeName;
87
88 public static void setAttributeName(final CPUTF8 cpUTF8Value) {
89 attributeName = cpUTF8Value;
90 }
91
92 private final List<InnerClassesEntry> innerClasses = new ArrayList<>();
93 private final List<ConstantPoolEntry> nestedClassFileEntries = new ArrayList<>();
94
95 public InnerClassesAttribute(final String name) {
96 super(attributeName);
97 nestedClassFileEntries.add(getAttributeName());
98 }
99
100 public void addInnerClassesEntry(final CPClass innerClass, final CPClass outerClass, final CPUTF8 innerName, final int flags) {
101 if (innerClass != null) {
102 nestedClassFileEntries.add(innerClass);
103 }
104 if (outerClass != null) {
105 nestedClassFileEntries.add(outerClass);
106 }
107 if (innerName != null) {
108 nestedClassFileEntries.add(innerName);
109 }
110 addInnerClassesEntry(new InnerClassesEntry(innerClass, outerClass, innerName, flags));
111 }
112
113 private void addInnerClassesEntry(final InnerClassesEntry innerClassesEntry) {
114 innerClasses.add(innerClassesEntry);
115 }
116
117 @Override
118 public boolean equals(final Object obj) {
119 if (this == obj) {
120 return true;
121 }
122 if (!super.equals(obj) || this.getClass() != obj.getClass()) {
123 return false;
124 }
125 final InnerClassesAttribute other = (InnerClassesAttribute) obj;
126 if (getAttributeName() == null) {
127 if (other.getAttributeName() != null) {
128 return false;
129 }
130 } else if (!getAttributeName().equals(other.getAttributeName())) {
131 return false;
132 }
133 return true;
134 }
135
136 @Override
137 protected int getLength() {
138 return 2 + (2 + 2 + 2 + 2) * innerClasses.size();
139 }
140
141 @Override
142 protected ClassFileEntry[] getNestedClassFileEntries() {
143 return nestedClassFileEntries.toArray(NONE);
144 }
145
146 @Override
147 public int hashCode() {
148 final int PRIME = 31;
149 int result = super.hashCode();
150 result = PRIME * result + (getAttributeName() == null ? 0 : getAttributeName().hashCode());
151 return result;
152 }
153
154 @Override
155 protected void resolve(final ClassConstantPool pool) {
156 super.resolve(pool);
157 for (final InnerClassesEntry entry : innerClasses) {
158 entry.resolve(pool);
159 }
160 }
161
162 @Override
163 public String toString() {
164 return "InnerClasses: " + getAttributeName();
165 }
166
167 @Override
168 protected void writeBody(final DataOutputStream dos) throws IOException {
169 dos.writeShort(innerClasses.size());
170
171 for (final InnerClassesEntry entry : innerClasses) {
172 entry.write(dos);
173 }
174 }
175 }