1/*
2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25package sun.jvm.hotspot.ui.tree;
26
27import java.util.*;
28import sun.jvm.hotspot.oops.FieldIdentifier;
29import sun.jvm.hotspot.oops.Oop;
30import sun.jvm.hotspot.oops.UnknownOopException;
31import sun.jvm.hotspot.debugger.*;
32import sun.jvm.hotspot.runtime.*;
33import sun.jvm.hotspot.types.*;
34import sun.jvm.hotspot.utilities.CStringUtilities;
35
36/** Encapsulates an arbitrary type value in a tree handled by SimpleTreeModel */
37
38public class CTypeTreeNodeAdapter extends FieldTreeNodeAdapter {
39  final private Address addr;
40  final private Type type;
41  private CTypeFieldIdentifier[] fields = null;
42
43  private void collectFields(Type type, ArrayList list, boolean statics, boolean recurse) {
44    Type supertype = type.getSuperclass();
45    if (supertype != null && recurse) {
46      collectFields(supertype, list, statics, recurse);
47    }
48    Iterator i = type.getFields();
49    while (i.hasNext()) {
50      Field f = (Field) i.next();
51      if (f.isStatic() == statics) {
52        list.add(new CTypeFieldIdentifier(type, f));
53      }
54    }
55  }
56
57
58  private CTypeFieldIdentifier[] getFields() {
59    if (fields == null) {
60      ArrayList f = new ArrayList();
61      collectFields(type, f, false, true);
62      fields = (CTypeFieldIdentifier[]) f.toArray(new CTypeFieldIdentifier[0]);
63    }
64    return fields;
65  }
66
67  static class CTypeFieldIdentifier extends FieldIdentifier {
68    final private Field field;
69    final private Type holder;
70
71    CTypeFieldIdentifier(Type t, Field f) {
72      holder = t;
73      field = f;
74    }
75
76    public Field getField() {
77      return field;
78    }
79
80    public String getName() {
81      return field.getType().getName() + " " + holder.getName() + "::" + field.getName();
82    }
83  }
84
85
86  public CTypeTreeNodeAdapter(Address a, Type t, FieldIdentifier id) {
87    this(a, t, id, false);
88  }
89
90  public CTypeTreeNodeAdapter(Address a, Type t, FieldIdentifier id, boolean treeTableMode) {
91    super(id, treeTableMode);
92    type = t;
93    addr = a;
94  }
95
96  public CTypeTreeNodeAdapter(Type t) {
97    super(null, false);
98    type = t;
99    addr = null;
100    ArrayList statics = new ArrayList();
101    collectFields(type, statics, true, false);
102    fields = (CTypeFieldIdentifier[])statics.toArray(new CTypeFieldIdentifier[0]);
103  }
104
105  public CTypeTreeNodeAdapter(Iterator types) {
106    super(null, false);
107    addr = null;
108    type = null;
109    ArrayList statics = new ArrayList();
110    while (types.hasNext()) {
111      collectFields((Type)types.next(), statics, true, false);
112    }
113    fields = (CTypeFieldIdentifier[])statics.toArray(new CTypeFieldIdentifier[0]);
114  }
115
116  public int getChildCount() {
117    return getFields().length;
118  }
119
120  public SimpleTreeNode getChild(int index) {
121    CTypeFieldIdentifier cf = getFields()[index];
122    Field f = cf.getField();
123    Type t = f.getType();
124    try {
125      if (t.isOopType()) {
126        OopHandle handle;
127        if (f.isStatic()) {
128          handle = f.getOopHandle();
129        } else {
130          handle = f.getOopHandle(addr);
131        }
132        try {
133          Oop oop = VM.getVM().getObjectHeap().newOop(handle);
134          return new OopTreeNodeAdapter(oop, cf, getTreeTableMode());
135        } catch (AddressException e) {
136          return new BadAddressTreeNodeAdapter(handle,
137                                           new CTypeFieldIdentifier(type, f),
138                                           getTreeTableMode());
139        } catch (UnknownOopException e) {
140          return new BadAddressTreeNodeAdapter(handle,
141                                           new CTypeFieldIdentifier(type, f),
142                                           getTreeTableMode());
143        }
144      } else if (t.isCIntegerType()) {
145        long value = 0;
146        if (f.isStatic()) {
147          value = f.getCInteger((CIntegerType)t);
148        } else {
149          value = f.getCInteger(addr, (CIntegerType)t);
150        }
151        return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
152      } else if (t.isJavaPrimitiveType()) {
153        boolean isStatic = f.isStatic();
154        if (f instanceof JByteField) {
155          long value = isStatic? f.getJByte() : f.getJByte(addr);
156          return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
157        } else if (f instanceof JShortField) {
158          long value = isStatic? f.getJShort() : f.getJShort(addr);
159          return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
160        } else if (f instanceof JIntField) {
161          long value = isStatic? f.getJInt() : f.getJInt(addr);
162          return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
163        } else if (f instanceof JLongField) {
164          long value = isStatic? f.getJLong() : f.getJLong(addr);
165          return new LongTreeNodeAdapter(value, cf, getTreeTableMode());
166        } else if (f instanceof JCharField) {
167          char value = isStatic? f.getJChar() : f.getJChar(addr);
168          return new CharTreeNodeAdapter(value, cf, getTreeTableMode());
169        } else if (f instanceof JBooleanField) {
170          boolean value = isStatic? f.getJBoolean() : f.getJBoolean(addr);
171          return new BooleanTreeNodeAdapter(value, cf, getTreeTableMode());
172        } else if (f instanceof JFloatField) {
173          float value = isStatic? f.getJFloat() : f.getJFloat(addr);
174          return new DoubleTreeNodeAdapter(value, cf, getTreeTableMode());
175        } else if (f instanceof JDoubleField) {
176          double value = isStatic? f.getJDouble() : f.getJDouble(addr);
177          return new DoubleTreeNodeAdapter(value, cf, getTreeTableMode());
178        } else {
179          throw new RuntimeException("unhandled type: " + t.getName());
180        }
181      } else if (t.isPointerType()) {
182        Address ptr;
183        if (f.isStatic()) {
184          ptr = f.getAddress();
185        } else {
186          ptr = f.getAddress(addr);
187        }
188
189        if (t.isCStringType()) {
190            return new CStringTreeNodeAdapter(CStringUtilities.getString(ptr), cf);
191        }
192
193        return new CTypeTreeNodeAdapter(ptr, ((PointerType) t).getTargetType(), cf, getTreeTableMode());
194      } else {
195        if (f.isStatic()) {
196            return new CTypeTreeNodeAdapter(f.getStaticFieldAddress(), f.getType(),
197                                        cf, getTreeTableMode());
198        } else {
199            return new CTypeTreeNodeAdapter(addr.addOffsetTo(f.getOffset()), f.getType(),
200                                        cf, getTreeTableMode());
201        }
202      }
203    } catch (AddressException e) {
204      return new BadAddressTreeNodeAdapter(e.getAddress(),
205                                           new CTypeFieldIdentifier(type, f),
206                                           getTreeTableMode());
207    }
208  }
209
210  public boolean isLeaf() {
211    return getFields().length == 0;
212  }
213
214  public int getIndexOfChild(SimpleTreeNode child) {
215    CTypeFieldIdentifier id = (CTypeFieldIdentifier)((FieldTreeNodeAdapter) child).getID();
216    CTypeFieldIdentifier[] f = getFields();
217    for (int i = 0; i < f.length; i++) {
218      if (id == f[i]) {
219        return i;
220      }
221    }
222    return -1;
223  }
224
225  public String getValue() {
226    if (type != null) {
227      return type.getName() + " @ " + addr;
228    } else {
229      return "<statics>";
230    }
231  }
232}
233