/*******************************************************************************
* Copyright (c) 2000, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.classfmt;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
/**
* Describes one entry in the classes table of the InnerClasses attribute. See the inner class
* specification (The class file attribute "InnerClasses").
*/
public class InnerClassInfo extends ClassFileStruct implements IBinaryNestedType {
int innerClassNameIndex= -1;
int outerClassNameIndex= -1;
int innerNameIndex= -1;
private char[] innerClassName;
private char[] outerClassName;
private char[] innerName;
private int accessFlags= -1;
private boolean readInnerClassName= false;
private boolean readOuterClassName= false;
private boolean readInnerName= false;
public InnerClassInfo(byte classFileBytes[], int offsets[], int offset) {
super(classFileBytes, offsets, offset);
this.innerClassNameIndex= u2At(0);
this.outerClassNameIndex= u2At(2);
this.innerNameIndex= u2At(4);
}
/**
* Answer the resolved name of the enclosing type in the class file format as specified in
* section 4.2 of the Java 2 VM spec.
*
* For example, java.lang.String is java/lang/String.
*
* @return char[]
*/
public char[] getEnclosingTypeName() {
if (!this.readOuterClassName) {
// read outer class name
this.readOuterClassName= true;
if (this.outerClassNameIndex != 0) {
int utf8Offset=
this.constantPoolOffsets[u2At(
this.constantPoolOffsets[this.outerClassNameIndex] - this.structOffset + 1)]
- this.structOffset;
this.outerClassName= utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
}
}
return this.outerClassName;
}
/**
* Answer an int whose bits are set according the access constants defined by the VM spec.
*
* @return int
*/
public int getModifiers() {
if (this.accessFlags == -1) {
// read access flag
this.accessFlags= u2At(6);
}
return this.accessFlags;
}
/**
* Answer the resolved name of the member type in the class file format as specified in section
* 4.2 of the Java 2 VM spec.
*
* For example, p1.p2.A.M is p1/p2/A$M.
*
* @return char[]
*/
public char[] getName() {
if (!this.readInnerClassName) {
// read the inner class name
this.readInnerClassName= true;
if (this.innerClassNameIndex != 0) {
int classOffset= this.constantPoolOffsets[this.innerClassNameIndex] - this.structOffset;
int utf8Offset= this.constantPoolOffsets[u2At(classOffset + 1)] - this.structOffset;
this.innerClassName= utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
}
}
return this.innerClassName;
}
/**
* Answer the source name of the member type.
*
* For example, p1.p2.A.M is M.
*
* @return char[]
*/
public char[] getSourceName() {
if (!this.readInnerName) {
this.readInnerName= true;
if (this.innerNameIndex != 0) {
int utf8Offset= this.constantPoolOffsets[this.innerNameIndex] - this.structOffset;
this.innerName= utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
}
}
return this.innerName;
}
/**
* Answer the string representation of the receiver
*
* @return java.lang.String
*/
public String toString() {
StringBuffer buffer= new StringBuffer();
if (getName() != null) {
buffer.append(getName());
}
buffer.append("\n"); //$NON-NLS-1$
if (getEnclosingTypeName() != null) {
buffer.append(getEnclosingTypeName());
}
buffer.append("\n"); //$NON-NLS-1$
if (getSourceName() != null) {
buffer.append(getSourceName());
}
return buffer.toString();
}
/**
* This method is used to fully initialize the contents of the receiver. All methodinfos, fields
* infos will be therefore fully initialized and we can get rid of the bytes.
*/
void initialize() {
getModifiers();
getName();
getSourceName();
getEnclosingTypeName();
reset();
}
}