001: /*
002: * Copyright 2004 Brian S O'Neill
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.cojen.classfile.attribute;
018:
019: import java.util.ArrayList;
020: import java.util.List;
021: import java.io.DataInput;
022: import java.io.DataOutput;
023: import java.io.IOException;
024: import org.cojen.classfile.Attribute;
025: import org.cojen.classfile.ConstantPool;
026: import org.cojen.classfile.Modifiers;
027: import org.cojen.classfile.constant.ConstantClassInfo;
028: import org.cojen.classfile.constant.ConstantUTFInfo;
029:
030: /**
031: * This class corresponds to the InnerClasses_attribute structure introduced in
032: * JDK1.1. It is not defined in the first edition of
033: * <i>The Java Virual Machine Specification</i>.
034: *
035: * @author Brian S O'Neill
036: */
037: public class InnerClassesAttr extends Attribute {
038:
039: private List mInnerClasses = new ArrayList();
040:
041: public InnerClassesAttr(ConstantPool cp) {
042: super (cp, INNER_CLASSES);
043: }
044:
045: public InnerClassesAttr(ConstantPool cp, String name) {
046: super (cp, name);
047: }
048:
049: public InnerClassesAttr(ConstantPool cp, String name, int length,
050: DataInput din) throws IOException {
051: super (cp, name);
052:
053: int size = din.readUnsignedShort();
054: for (int i = 0; i < size; i++) {
055: int inner_index = din.readUnsignedShort();
056: int outer_index = din.readUnsignedShort();
057: int name_index = din.readUnsignedShort();
058: int af = din.readUnsignedShort();
059:
060: ConstantClassInfo inner;
061: if (inner_index == 0) {
062: inner = null;
063: } else {
064: inner = (ConstantClassInfo) cp.getConstant(inner_index);
065: }
066:
067: ConstantClassInfo outer;
068: if (outer_index == 0) {
069: outer = null;
070: } else {
071: outer = (ConstantClassInfo) cp.getConstant(outer_index);
072: }
073:
074: ConstantUTFInfo innerName;
075: if (name_index == 0) {
076: innerName = null;
077: } else {
078: innerName = (ConstantUTFInfo) cp
079: .getConstant(name_index);
080: }
081:
082: mInnerClasses.add(new Info(inner, outer, innerName,
083: Modifiers.getInstance(af)));
084: }
085: }
086:
087: /**
088: * @param inner The full inner class name
089: * @param outer The full outer class name
090: * @param name The simple name of the inner class, or null if anonymous
091: * @param modifiers Modifiers for the inner class
092: */
093: public void addInnerClass(String inner, String outer, String name,
094: Modifiers modifiers) {
095:
096: ConstantClassInfo innerInfo = getConstantPool()
097: .addConstantClass(inner);
098: ConstantClassInfo outerInfo;
099: if (outer == null) {
100: outerInfo = null;
101: } else {
102: outerInfo = getConstantPool().addConstantClass(outer);
103: }
104:
105: ConstantUTFInfo nameInfo;
106: if (name == null) {
107: nameInfo = null;
108: } else {
109: nameInfo = getConstantPool().addConstantUTF(name);
110: }
111:
112: mInnerClasses.add(new Info(innerInfo, outerInfo, nameInfo,
113: modifiers));
114: }
115:
116: public Info[] getInnerClassesInfo() {
117: Info[] infos = new Info[mInnerClasses.size()];
118: return (Info[]) mInnerClasses.toArray(infos);
119: }
120:
121: public int getLength() {
122: return 2 + 8 * mInnerClasses.size();
123: }
124:
125: public void writeDataTo(DataOutput dout) throws IOException {
126: int size = mInnerClasses.size();
127: dout.writeShort(size);
128: for (int i = 0; i < size; i++) {
129: ((Info) mInnerClasses.get(i)).writeTo(dout);
130: }
131: }
132:
133: public static class Info {
134: private ConstantClassInfo mInner;
135: private ConstantClassInfo mOuter;
136: private ConstantUTFInfo mName;
137: private Modifiers mModifiers;
138:
139: Info(ConstantClassInfo inner, ConstantClassInfo outer,
140: ConstantUTFInfo name, Modifiers modifiers) {
141:
142: mInner = inner;
143: mOuter = outer;
144: mName = name;
145: mModifiers = modifiers;
146: }
147:
148: /**
149: * Returns null if no inner class specified.
150: */
151: public ConstantClassInfo getInnerClass() {
152: return mInner;
153: }
154:
155: /**
156: * Returns null if no outer class specified.
157: */
158: public ConstantClassInfo getOuterClass() {
159: return mOuter;
160: }
161:
162: /**
163: * Returns null if no inner class specified or is anonymous.
164: */
165: public ConstantUTFInfo getInnerClassName() {
166: return mName;
167: }
168:
169: /**
170: * Returns the modifiers.
171: */
172: public Modifiers getModifiers() {
173: return mModifiers;
174: }
175:
176: public void writeTo(DataOutput dout) throws IOException {
177: if (mInner == null) {
178: dout.writeShort(0);
179: } else {
180: dout.writeShort(mInner.getIndex());
181: }
182:
183: if (mOuter == null) {
184: dout.writeShort(0);
185: } else {
186: dout.writeShort(mOuter.getIndex());
187: }
188:
189: if (mName == null) {
190: dout.writeShort(0);
191: } else {
192: dout.writeShort(mName.getIndex());
193: }
194:
195: dout.writeShort(mModifiers.getBitmask());
196: }
197: }
198: }
|