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