1 /*
   2  * Copyright (c) 2001, 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,
  20  * CA 94065 USA or visit www.oracle.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.bugspot.tree;
  26 
  27 import java.io.*;
  28 import sun.jvm.hotspot.debugger.*;
  29 import sun.jvm.hotspot.debugger.cdbg.*;
  30 import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
  31 
  32 /** An adapter class which allows C/C++ objects to be displayed in a
  33     tree via the SimpleTreeNode interface. */
  34 
  35 public class ObjectTreeNodeAdapter extends FieldTreeNodeAdapter {
  36   // Address of object
  37   private Address addr;
  38 
  39   /** The address may be null (for object fields of objcets which are
  40       null). The FieldIdentifier should not be null. treeTableMode
  41       defaults to false. */
  42   public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id) {
  43     this(addr, id, false);
  44   }
  45 
  46   /** The address may be null (for object fields of objcets which are
  47       null). The FieldIdentifier should not be null. */
  48   public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id, boolean treeTableMode) {
  49     super(id, treeTableMode);
  50     this.addr = addr;
  51   }
  52 
  53   public int getChildCount() {
  54     if (addr == null) {
  55       return 0;
  56     }
  57 
  58     Counter c = new Counter();
  59     getType().iterateObject(addr, c);
  60     return c.getNumFields();
  61   }
  62 
  63   public SimpleTreeNode getChild(int index) {
  64     if (addr == null) {
  65       return null;
  66     }
  67 
  68     Fetcher f = new Fetcher(index);
  69     getType().iterateObject(addr, f);
  70     return f.getChild();
  71   }
  72 
  73   public boolean isLeaf() {
  74     return (addr == null);
  75   }
  76 
  77   public int getIndexOfChild(SimpleTreeNode child) {
  78     FieldIdentifier id = ((FieldTreeNodeAdapter) child).getID();
  79     Finder f = new Finder(id);
  80     getType().iterateObject(addr, f);
  81     return f.getIndex();
  82   }
  83 
  84   public String getValue() {
  85     if (addr != null) {
  86       return addr.toString();
  87     }
  88     return "NULL";
  89   }
  90 
  91   /** Should be used only once, then have the number of fields
  92       fetched. */
  93   static class Counter extends DefaultObjectVisitor {
  94     private int numFields;
  95 
  96     public int getNumFields() {
  97       return numFields;
  98     }
  99 
 100     public void doBit(FieldIdentifier f, long val)                   { ++numFields; }
 101     public void doInt(FieldIdentifier f, long val)                   { ++numFields; }
 102     public void doEnum(FieldIdentifier f, long val, String enumName) { ++numFields; }
 103     public void doFloat(FieldIdentifier f, float val)                { ++numFields; }
 104     public void doDouble(FieldIdentifier f, double val)              { ++numFields; }
 105     public void doPointer(FieldIdentifier f, Address val)            { ++numFields; }
 106     public void doArray(FieldIdentifier f, Address val)              { ++numFields; }
 107     public void doRef(FieldIdentifier f, Address val)                { ++numFields; }
 108     public void doCompound(FieldIdentifier f, Address addr)          { ++numFields; }
 109   }
 110 
 111   /** Creates a new SimpleTreeNode for the given field. */
 112   class Fetcher extends DefaultObjectVisitor {
 113     private int index;
 114     private int curField;
 115     private SimpleTreeNode child;
 116 
 117     public Fetcher(int index) {
 118       this.index = index;
 119     }
 120 
 121     public SimpleTreeNode getChild() {
 122       return child;
 123     }
 124 
 125     public void doBit(FieldIdentifier f, long val) {
 126       if (curField == index) {
 127         child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
 128       }
 129       ++curField;
 130     }
 131 
 132     public void doInt(FieldIdentifier f, long val) {
 133       if (curField == index) {
 134         child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
 135       }
 136       ++curField;
 137     }
 138 
 139     public void doEnum(FieldIdentifier f, long val, String enumName) {
 140       if (curField == index) {
 141         child = new EnumTreeNodeAdapter(enumName, val, f, getTreeTableMode());
 142       }
 143       ++curField;
 144     }
 145 
 146     public void doFloat(FieldIdentifier f, float val) {
 147       if (curField == index) {
 148         child = new FloatTreeNodeAdapter(val, f, getTreeTableMode());
 149       }
 150       ++curField;
 151     }
 152 
 153     public void doDouble(FieldIdentifier f, double val) {
 154       if (curField == index) {
 155         child = new DoubleTreeNodeAdapter(val, f, getTreeTableMode());
 156       }
 157       ++curField;
 158     }
 159 
 160     public void doPointer(FieldIdentifier f, Address val) {
 161       if (curField == index) {
 162         child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
 163       }
 164       ++curField;
 165     }
 166 
 167     public void doArray(FieldIdentifier f, Address val) {
 168       if (curField == index) {
 169         child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
 170       }
 171       ++curField;
 172     }
 173 
 174     public void doRef(FieldIdentifier f, Address val) {
 175       if (curField == index) {
 176         child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
 177       }
 178       ++curField;
 179     }
 180 
 181     public void doCompound(FieldIdentifier f, Address val) {
 182       if (curField == index) {
 183         child = new ObjectTreeNodeAdapter(val, f, getTreeTableMode());
 184       }
 185       ++curField;
 186     }
 187   }
 188 
 189   /** Finds the index of the given FieldIdentifier. */
 190   static class Finder extends DefaultObjectVisitor {
 191     private FieldIdentifier id;
 192     private int curField;
 193     private int index = -1;
 194 
 195     public Finder(FieldIdentifier id) {
 196       this.id = id;
 197     }
 198 
 199     /** Returns -1 if not found */
 200     public int getIndex() {
 201       return index;
 202     }
 203 
 204     public void doBit(FieldIdentifier f, long val)        { if (f.equals(id)) { index = curField; } ++curField; }
 205     public void doInt(FieldIdentifier f, long val)        { if (f.equals(id)) { index = curField; } ++curField; }
 206     public void doEnum(FieldIdentifier f, long val,
 207                        String enumName)                   { if (f.equals(id)) { index = curField; } ++curField; }
 208     public void doFloat(FieldIdentifier f, float val)     { if (f.equals(id)) { index = curField; } ++curField; }
 209     public void doDouble(FieldIdentifier f, double val)   { if (f.equals(id)) { index = curField; } ++curField; }
 210     public void doPointer(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; }
 211     public void doArray(FieldIdentifier f, Address val)   { if (f.equals(id)) { index = curField; } ++curField; }
 212     public void doRef(FieldIdentifier f, Address val)     { if (f.equals(id)) { index = curField; } ++curField; }
 213     public void doCompound(FieldIdentifier f,
 214                            Address val)                   { if (f.equals(id)) { index = curField; } ++curField; }
 215   }
 216 }