blob: b7da2eeac5731519c644dd630a2c87fb049af71f [file] [log] [blame]
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.ui.tree;
import java.util.*;
import sun.jvm.hotspot.oops.FieldIdentifier;
import sun.jvm.hotspot.oops.Oop;
import sun.jvm.hotspot.oops.UnknownOopException;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.CStringUtilities;
/** Encapsulates an arbitrary type value in a tree handled by SimpleTreeModel */
public class CTypeTreeNodeAdapter extends FieldTreeNodeAdapter {
final private Address addr;
final private Type type;
private CTypeFieldIdentifier[] fields = null;
private void collectFields(Type type, ArrayList list, boolean statics, boolean recurse) {
Type supertype = type.getSuperclass();
if (supertype != null && recurse) {
collectFields(supertype, list, statics, recurse);
}
Iterator i = type.getFields();
while (i.hasNext()) {
Field f = (Field) i.next();
if (f.isStatic() == statics) {
list.add(new CTypeFieldIdentifier(type, f));
}
}
}
private CTypeFieldIdentifier[] getFields() {
if (fields == null) {
ArrayList f = new ArrayList();
collectFields(type, f, false, true);
fields = (CTypeFieldIdentifier[]) f.toArray(new CTypeFieldIdentifier[0]);
}
return fields;
}
static class CTypeFieldIdentifier extends FieldIdentifier {
final private Field field;
final private Type holder;
CTypeFieldIdentifier(Type t, Field f) {
holder = t;
field = f;
}
public Field getField() {
return field;
}
public String getName() {
return field.getType().getName() + " " + holder.getName() + "::" + field.getName();
}
}
public CTypeTreeNodeAdapter(Address a, Type t, FieldIdentifier id) {
this(a, t, id, false);
}
public CTypeTreeNodeAdapter(Address a, Type t, FieldIdentifier id, boolean treeTableMode) {
super(id, treeTableMode);
type = t;
addr = a;
}
public CTypeTreeNodeAdapter(Type t) {
super(null, false);
type = t;
addr = null;
ArrayList statics = new ArrayList();
collectFields(type, statics, true, false);
fields = (CTypeFieldIdentifier[])statics.toArray(new CTypeFieldIdentifier[0]);
}
public CTypeTreeNodeAdapter(Iterator types) {
super(null, false);
addr = null;
type = null;
ArrayList statics = new ArrayList();
while (types.hasNext()) {
collectFields((Type)types.next(), statics, true, false);
}
fields = (CTypeFieldIdentifier[])statics.toArray(new CTypeFieldIdentifier[0]);
}
public int getChildCount() {
return getFields().length;
}
public SimpleTreeNode getChild(int index) {
CTypeFieldIdentifier cf = getFields()[index];
Field f = cf.getField();
Type t = f.getType();
try {
if (t.isOopType()) {
OopHandle handle;
if (f.isStatic()) {
handle = f.getOopHandle();
} else {
handle = f.getOopHandle(addr);
}
try {
Oop oop = VM.getVM().getObjectHeap().newOop(handle);
return new OopTreeNodeAdapter(oop, cf, getTreeTableMode());
} catch (AddressException e) {
return new BadAddressTreeNodeAdapter(handle,
new CTypeFieldIdentifier(type, f),
getTreeTableMode());
} catch (UnknownOopException e) {
return new BadAddressTreeNodeAdapter(handle,
new CTypeFieldIdentifier(type, f),
getTreeTableMode());
}
} else if (t.isCIntegerType()) {
long value = 0;
if (f.isStatic()) {
value = f.getCInteger((CIntegerType)t);
} else {
value = f.getCInteger(addr, (CIntegerType)t);
}
return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (t.isJavaPrimitiveType()) {
boolean isStatic = f.isStatic();
if (f instanceof JByteField) {
long value = isStatic? f.getJByte() : f.getJByte(addr);
return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JShortField) {
long value = isStatic? f.getJShort() : f.getJShort(addr);
return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JIntField) {
long value = isStatic? f.getJInt() : f.getJInt(addr);
return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JLongField) {
long value = isStatic? f.getJLong() : f.getJLong(addr);
return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JCharField) {
char value = isStatic? f.getJChar() : f.getJChar(addr);
return new CharTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JBooleanField) {
boolean value = isStatic? f.getJBoolean() : f.getJBoolean(addr);
return new BooleanTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JFloatField) {
float value = isStatic? f.getJFloat() : f.getJFloat(addr);
return new DoubleTreeNodeAdapter(value, cf, getTreeTableMode());
} else if (f instanceof JDoubleField) {
double value = isStatic? f.getJDouble() : f.getJDouble(addr);
return new DoubleTreeNodeAdapter(value, cf, getTreeTableMode());
} else {
throw new RuntimeException("unhandled type: " + t.getName());
}
} else if (t.isPointerType()) {
Address ptr;
if (f.isStatic()) {
ptr = f.getAddress();
} else {
ptr = f.getAddress(addr);
}
if (t.isCStringType()) {
return new CStringTreeNodeAdapter(CStringUtilities.getString(ptr), cf);
}
return new CTypeTreeNodeAdapter(ptr, ((PointerType) t).getTargetType(), cf, getTreeTableMode());
} else {
if (f.isStatic()) {
return new CTypeTreeNodeAdapter(f.getStaticFieldAddress(), f.getType(),
cf, getTreeTableMode());
} else {
return new CTypeTreeNodeAdapter(addr.addOffsetTo(f.getOffset()), f.getType(),
cf, getTreeTableMode());
}
}
} catch (AddressException e) {
return new BadAddressTreeNodeAdapter(e.getAddress(),
new CTypeFieldIdentifier(type, f),
getTreeTableMode());
}
}
public boolean isLeaf() {
return getFields().length == 0;
}
public int getIndexOfChild(SimpleTreeNode child) {
CTypeFieldIdentifier id = (CTypeFieldIdentifier)((FieldTreeNodeAdapter) child).getID();
CTypeFieldIdentifier[] f = getFields();
for (int i = 0; i < f.length; i++) {
if (id == f[i]) {
return i;
}
}
return -1;
}
public String getValue() {
if (type != null) {
return type.getName() + " @ " + addr;
} else {
return "<statics>";
}
}
}