Package org.apache.kato.tools.jdi

Source Code of org.apache.kato.tools.jdi.KatoReader

/*******************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.apache.kato.tools.jdi;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;

import javax.tools.diagnostics.FactoryRegistry;
import javax.tools.diagnostics.image.CorruptData;
import javax.tools.diagnostics.image.CorruptDataException;
import javax.tools.diagnostics.image.DataUnavailable;
import javax.tools.diagnostics.image.DiagnosticException;
import javax.tools.diagnostics.image.Image;
import javax.tools.diagnostics.image.ImageAddressSpace;
import javax.tools.diagnostics.image.ImageProcess;
import javax.tools.diagnostics.image.MemoryAccessException;
import javax.tools.diagnostics.runtime.java.JavaClass;
import javax.tools.diagnostics.runtime.java.JavaClassLoader;
import javax.tools.diagnostics.runtime.java.JavaField;
import javax.tools.diagnostics.runtime.java.JavaHeap;
import javax.tools.diagnostics.runtime.java.JavaLocation;
import javax.tools.diagnostics.runtime.java.JavaMethod;
import javax.tools.diagnostics.runtime.java.JavaMonitor;
import javax.tools.diagnostics.runtime.java.JavaObject;
import javax.tools.diagnostics.runtime.java.JavaRuntime;
import javax.tools.diagnostics.runtime.java.JavaStackFrame;
import javax.tools.diagnostics.runtime.java.JavaThread;
import javax.tools.diagnostics.runtime.java.JavaVariable;


/**
* KatoReader
*
* KatoReader is our second conversion layer (after JDWPServer).  KatoReader has two functions:
* <ol>
* <li> Convert JDWP <--> Kato</li>
* <li> Provide several convenience methods </li>
* </ol>
*
* <ol>
* <li>
*    <p>
*    KatoReader directly takes the raw protocol (in it's object version) and runs some calls to
*    get the JDWP reply.  Only a small portion of the JDWP protocol is specified in a way that
*    we can reliably create objects, so a lot of time the KatoReader methods will extract their
*    own information from a raw byte 'data' segment of the original packet.  On the reply, we
*    copy some of the information from the CommandPacket (such as sequence and origin socket)
*    and then create a data segment.
*    </p>
*    <br/>
*    <p> 
*    Most of the time the data segment is constructed using a Byte vector (that's Big Byte).
*    We do this so that we can easily add and remove to the vector, and add to the front if
*    we need to.  The JDWPServer converts the standard Packet stuff back to bytes and appends
*    our data segment on the outgoing packet.
*    </p>
* </li>
* <li>  
*   We provide bytes <--> int, bytes <--> long, vector --> byte[], and a few other assorted
*    methods for doing standard stuff.
* </li>
* </ol>
*
*/
public class KatoReader implements CacherProvider{
  private HashMap<Long, JavaClass> classes;
  //  Image is actually an 'image' of the core at crash time.
  //  Since it's the basis of every query, I'm saving it over queries
  private Image image = null;
  private HashMap<Long,String> vctrs;
  private String pathToCore;
  private int errorCode;
  private JDWPServer svr;

  public static final int FLAG_REPLY_PACKET = 0x80;

  private int LAST_ID = 1;
  private HashMap<Integer, JavaMethod> intToMethod;
  private HashMap<JavaMethod, Integer> methodToInt;
  private Vector<JavaField> fieldList;
  private JDILogger logr;
  public static final int ERROR_NONE = 0;
  public static final int ERROR_INVALID_OBJECT = 20;
  public static final int ERROR_INVALID_CLASS = 21;
  public static final int ERROR_INVALID_THREAD = 10;
  public static final int ERROR_INVALID_SLOT = 35;
  public static final int ERROR_NOT_IMPLEMENTED = 99;
  public static final int ERROR_ABSENT_INFORMATION = 101;
  public static final int ERROR_INTERNAL = 113;
  public static final int ERROR_INVALID_ARRAY = 508;
 
  public static final int INVALID_EVENT_TYPE = 102;
 
  private HashMap<Long, JavaObject> objectMap;
  private HashMap<Long, JavaMonitor> monitorMap;

  public static final int COMMANDSET_VIRTUAL_MACHINE = 1;
  public static final int COMMANDSET_REFERENCE_TYPE = 2;
  public static final int COMMANDSET_CLASS_TYPE = 3;
  public static final int COMMANDSET_ARRAY_TYPE = 4;
  public static final int COMMANDSET_INTERFACE_TYPE = 5;
  public static final int COMMANDSET_METHOD = 6;

  public static final int COMMANDSET_FIELD = 8;
  public static final int COMMANDSET_OBJECT_REFERENCE = 9;
  public static final int COMMANDSET_STRING_REFERENCE = 10;
  public static final int COMMANDSET_THREAD_REFERENCE = 11;
  public static final int COMMANDSET_THREAD_GROUP_REFERENCE = 12;
  public static final int COMMANDSET_ARRAY_REFERENCE = 13;
  public static final int COMMANDSET_CLASS_LOADER_REFERENCE = 14;
  public static final int COMMANDSET_EVENT_REQUEST = 15;
  public static final int COMMANDSET_STACK_FRAME = 16;
  public static final int COMMANDSET_CLASS_OBJECT_REFERENCE = 17;
  public static final int COMMANDSET_EVENT = 64;
 
  public static final int VIRTUAL_MACHINE_VERSION = 1;
  public static final int VIRTUAL_MACHINE_CLASSES_BY_SIGNATURE = 2;
  public static final int VIRTUAL_MACHINE_ALL_CLASSES = 3;
  public static final int VIRTUAL_MACHINE_ALL_THREADS = 4;
  public static final int VIRTUAL_MACHINE_TOP_LEVEL_THREAD_GROUPS = 5;
  public static final int VIRTUAL_MACHINE_DISPOSE = 6;
  public static final int VIRTUAL_MACHINE_IDSIZES = 7;
  public static final int VIRTUAL_MACHINE_SUSPEND = 8;
  public static final int VIRTUAL_MACHINE_RESUME = 9;
  public static final int VIRTUAL_MACHINE_EXIT = 10;
  public static final int VIRTUAL_MACHINE_CREATE_STRING = 11;
  public static final int VIRTUAL_MACHINE_CAPABILITIES = 12;
  public static final int VIRTUAL_MACHINE_CLASS_PATHS = 13;
  public static final int VIRTUAL_MACHINE_DISPOSE_OBJECTS = 14;
  public static final int VIRTUAL_MACHINE_HOLD_EVENTS = 15;
  public static final int VIRTUAL_MACHINE_RELEASE_EVENTS = 16;
  public static final int VIRTUAL_MACHINE_CAPABILITIES_NEW = 17;
  public static final int VIRTUAL_MACHINE_REDEFINE_CLASSES = 18;
  public static final int VIRTUAL_MACHINE_SET_DEFAULT_STRATUM = 19;
 
  public static final int REFERENCE_TYPE_SIGNATURE = 1;
  public static final int REFERENCE_TYPE_CLASS_LOADER = 2;
  public static final int REFERENCE_TYPE_MODIFIERS = 3;
  public static final int REFERENCE_TYPE_FIELDS = 4;
  public static final int REFERENCE_TYPE_METHODS = 5;
  public static final int REFERENCE_TYPE_GET_VALUES = 6;
  public static final int REFERENCE_TYPE_SOURCE_FILE = 7;
  public static final int REFERENCE_TYPE_NESTED_TYPES = 8;
  public static final int REFERENCE_TYPE_STATUS = 9;
  public static final int REFERENCE_TYPE_INTERFACES = 10;
  public static final int REFERENCE_TYPE_CLASS_OBJECT = 11;
  public static final int REFERENCE_TYPE_SOURCE_DEBUG_EXTENSION = 12;
 
  public static final int TAG_ARRAY = 91;
  public static final int TAG_BYTE = 66;
  public static final int TAG_CHAR = 67;
  public static final int TAG_OBJECT = 76;
  public static final int TAG_FLOAT = 70;
  public static final int TAG_DOUBLE = 68;
  public static final int TAG_INT = 73;
  public static final int TAG_LONG = 74;
  public static final int TAG_SHORT = 83;
  public static final int TAG_VOID = 86;
  public static final int TAG_BOOLEAN = 90;
  public static final int TAG_STRING = 115;
  public static final int TAG_THREAD = 116;
  public static final int TAG_THREAD_GROUP = 103;
  public static final int TAG_CLASS_LOADER = 108;
  public static final int TAG_CLASS_OBJECT = 99;
 




  public KatoReader(){

  }

  /**
   * Constructor to init Kato reader
   *
   * @param ipathToCore   Path to core (absolute or relative)
   * @param isvr       JDWPServer used for communication back up
   * @param logger    JDILogger to use to log against
   * @throws Exception  An error passed up from the Kato api, or sanity test fail
   */
  public KatoReader(String ipathToCore, JDWPServer isvr, JDILogger logger) throws Exception{
    logr = logger;
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "KatoReader 1.0"); //$NON-NLS-1$
    pathToCore = ipathToCore;
    svr = isvr;
    vctrs = new HashMap<Long, String>();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Starting to read core file"); //$NON-NLS-1$
    startRead();

  }

  /**
   * Given a Kato JavaField and JavaObject, add the tagged value to the vector vctr
   *
   * @param vctr      Current byte vector for the data segment of the packet
   * @param jObject    Object to which get the value from
   * @param jField    The field of a class to get the value from
   * @return        false if the operation failed, true if it succeeds
   * @throws Exception  Exception passed up if underlying Kato calls fail
   */

  private boolean getValueFromField(Vector<Byte> vctr, JavaObject jObject, JavaField jField) throws Exception{
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jField.getName() + "("+jField.getSignature()+")");   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
    byte signature = (byte)jField.getSignature().charAt(0);
    if (jField.getSignature().equals("Ljava/lang/String;")){ //$NON-NLS-1$
      signature = (byte)'s';
    }
    vctr.add(signature);
    switch (signature){
      case '[':
        try{
          if(jField.get(jObject) instanceof JavaObject){
            JavaObject jOut = (JavaObject)jField.get(jObject);
            if (!objectMap.containsKey(jOut.getID().getAddress())){
              objectMap.put(jOut.getID().getAddress(), jOut);
            }
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  ARRAY: " + jOut.getID().getAddress()); //$NON-NLS-1$
            addLongToVector(vctr, jOut.getID().getAddress());

          }else if (jField.get(jObject) instanceof JavaClass){
            logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  ARRAY: Actually a class?!"); //$NON-NLS-1$
            addLongToVector(vctr, 0);
          }else{
            logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  ARRAY: Not JavaObject"); //$NON-NLS-1$
            if (jField.get(jObject) == null){
              logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  ARRAY: is null");   //$NON-NLS-1$
            }
            addLongToVector(vctr, 0);
          }
        }
        catch(NullPointerException exxy){
          logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  ARRAY: Attemped access to field is null"); //$NON-NLS-1$
          exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
          addLongToVector(vctr, 0);
        }
        break;
      case 's':
      {
        try{
          //Add the string to the lookup table
          JavaObject jOut = (JavaObject)jField.get(jObject);
          vctrs.put(jOut.getID().getAddress(), jField.getString(jObject));
        }
        catch(NullPointerException exxy){}
        catch(CorruptDataException exxy){
          //Take back what I said
          int size = vctr.size();
          vctr.remove(size-1);
          vctr.add((byte)'L');
        }
      }

      case 'L':
      case 't':
      case 'g':
      case 'l':
      case 'c':
      {
        try{
          Object field = jField.get(jObject);
          if(field instanceof JavaObject){
            JavaObject jOut = (JavaObject)field;
            addLongToVector(vctr, jOut.getID().getAddress());
            if (!objectMap.containsKey(jOut.getID().getAddress())){
              objectMap.put(jOut.getID().getAddress(), jOut);
            }
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jOut.getID().getAddress()); //$NON-NLS-1$
          }else{
            addLongToVector(vctr, 0);
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Not JavaObject " + ((field == null) ? "null" : field.getClass().getName())); //$NON-NLS-1$
          }


        }
        catch(NullPointerException exxy){
          logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  Attemped access to field is null"); //$NON-NLS-1$
          addLongToVector(vctr, 0);
        }
      }
      break;
      case 'F':
      {
        int bits = Float.floatToRawIntBits(jField.getFloat(jObject));
        addIntToVector(vctr, bits);
      }
      break;
      case 'D':
      {
        long bits = Double.doubleToRawLongBits(jField.getDouble(jObject));
        addLongToVector(vctr, bits);
      }
      break;
      case 'S':
        vctr.add((byte)((jField.getShort(jObject) >> 8) & 0xFF));
        vctr.add((byte)(jField.getShort(jObject) & 0xFF));
        break;
      case 'B':
        vctr.add(jField.getByte(jObject));
        break;
      case 'C':
        vctr.add((byte)((jField.getChar(jObject) >> 8) & 0xFF));
        vctr.add((byte)(jField.getChar(jObject) & 0xFF));
        break;
      case 'Z':
        try{
          if (jField.getBoolean(jObject)){
            vctr.add((byte)1);
          }else{
            vctr.add((byte)0);
          }
        }catch(IllegalArgumentException exxy){
          vctr.add((byte)0);
        }
        break;
      case 'I':
        addIntToVector(vctr, jField.getInt(jObject));
        break;
      case 'J':
        addLongToVector(vctr, jField.getLong(jObject));
        break;
      default:
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Unhandled type!"); //$NON-NLS-1$
      return false;
    }
    return true;

  }

  public Packet query(Packet pckt) throws Exception{
    if(image == null){
      try{
        startRead();

      }catch (Exception exxy){
        throw exxy;
      }
    }
    CommandPacket cpckt = (CommandPacket)pckt;
    try{
      switch(cpckt.getCommandSet()){
        case COMMANDSET_VIRTUAL_MACHINE:
          return virtualMachine(cpckt);
        case COMMANDSET_REFERENCE_TYPE:
          return referenceType(cpckt);
        case COMMANDSET_CLASS_TYPE:
          return classType(cpckt);
        case COMMANDSET_METHOD:
          return method(cpckt);
        case COMMANDSET_OBJECT_REFERENCE:
          return objectReference(cpckt);
        case COMMANDSET_STRING_REFERENCE:
          return stringReference(cpckt);
        case COMMANDSET_THREAD_REFERENCE:
          return threadReference(cpckt);
        case COMMANDSET_ARRAY_REFERENCE:
          return arrayReference(cpckt);
        case COMMANDSET_EVENT_REQUEST:
          return eventRequest(cpckt);
        case COMMANDSET_STACK_FRAME:
          return stackFrame(cpckt);
        case COMMANDSET_CLASS_LOADER_REFERENCE:
          return classLoaderRef(cpckt);
        // Added for jdb
        case COMMANDSET_THREAD_GROUP_REFERENCE:
          return threadGroupReference(cpckt);
        default:
          logr.logError(JDILogger.LEVEL_VERBOSE, "Unknown command set: "+cpckt.getCommandSet()); //$NON-NLS-1$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
        return rpckt;
      }
    }
    catch(CorruptDataException exxy){
      logr.logError(JDILogger.LEVEL_VERBOSE, "Corrupt data."); //$NON-NLS-1$
      exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INTERNAL);
      rpckt.setData("CorruptDataException"); //$NON-NLS-1$
      return rpckt;
    }
    catch(Exception exxy){
      logr.logError(JDILogger.LEVEL_VERBOSE, "Exception occured: " + exxy.getMessage()); //$NON-NLS-1$
      exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INTERNAL);
      rpckt.setData("Exception"); //$NON-NLS-1$
      return rpckt;
    }
  }

  /**
   * Load in the core file stored in pathToCore, into image.
   * @throws Exception  Upstream error
   */

  public void startRead() throws Exception{
    logr.log(JDILogger.LEVEL_VERBOSE, "Starting to read " + pathToCore); //$NON-NLS-1$

    File f = new File(pathToCore);
    try {
      FactoryRegistry registry=null;
      registry=FactoryRegistry.getDefaultRegistry();     
     
      image =  registry.getImage(f);
    } catch (IOException e) {
      logr.logError(JDILogger.LEVEL_QUIET, "Could not find/use required file(s)"); //$NON-NLS-1$
      e.printStackTrace(new PrintStream(logr.getErrorStream()));
      errorCode = 4;
      throw e;
    }

    if (image == null) {
      return;
    }

    logr.log(JDILogger.LEVEL_VERBOSE, "Extra Information"); //$NON-NLS-1$

    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "    Creation Time:" + image.getCreationTime()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "        Host Name: " + image.getHostName()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, " Installed Memory: " + image.getInstalledMemory() + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "  Processor Count: " + image.getProcessorCount()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "   Processor Type: " + image.getProcessorType()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "Processor Subtype: " + image.getProcessorSubType()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "      System Type: " + image.getSystemType()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      logr.log(JDILogger.LEVEL_VERBOSE, "   System Subtype: " + image.getSystemSubType()); //$NON-NLS-1$
    }catch(Exception exxy){}
    try{
      Iterator itr = image.getIPAddresses();
      while (itr.hasNext()){
        InetAddress addr = (InetAddress)itr.next();
        logr.log(JDILogger.LEVEL_VERBOSE, "IP: " + addr.toString()); //$NON-NLS-1$

      }
    }catch(Exception exxy){}

    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building class list"); //$NON-NLS-1$
    this.classes = buildClasses();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Generating object list"); //$NON-NLS-1$
    this.objectMap = generateObjectHashmap();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building field list"); //$NON-NLS-1$
    this.fieldList = buildFields();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building method list"); //$NON-NLS-1$
    this.monitorMap = buildMonitors();
    buildMethods();
  }

  /**
   * Get the method object given a methodID
   * @param methodID  Address of the method as stored in the vector
   * @return The Kato JavaMethod
   */
  private JavaMethod getMethod(long methodID){
    if (intToMethod == null){
      buildMethods();
    }
    return intToMethod.get(methodID);

  }

  /**
   * Get the field object given a fieldID
   * @param fieldID  Address of a given field as stored in the vector
   * @return The Kato JavaField
   */
  private JavaField getField(long fieldID){
    if (fieldList == null){
      fieldList = buildFields();
    }
    return fieldList.elementAt((int)fieldID);

  }
 
  private HashMap<Long, JavaMonitor> buildMonitors(){
    HashMap<Long, JavaMonitor> monitors = new HashMap<Long, JavaMonitor>();
    Iterator asIt = image.getAddressSpaces( ).iterator();
    while ( asIt.hasNext( ) )
    {
      ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
      Iterator prIt = as.getProcesses( ).iterator();
      while ( prIt.hasNext( ) ){
        ImageProcess process = (ImageProcess) prIt.next( );

        Iterator runTimesIt = process.getRuntimes( ).iterator();
        while ( runTimesIt.hasNext( ) )
        {
          JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
          List<JavaMonitor> jms = javaRT.getMonitors();
          for (JavaMonitor jm: jms){
            monitors.put(jm.getObject().getID().getAddress(), jm);
          }
        }
      }
    }
    return monitors;
  }

  /**
   * Build the field vector by going through all the classes
   * @return A vector containing a list of JDIJavaFields
   */
  private Vector<JavaField> buildFields(){
    Vector<JavaField> fieldList = new Vector<JavaField>();
    Iterator<JavaClass> jClasses = classes.values().iterator();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building field list..."); //$NON-NLS-1$
    while(jClasses.hasNext()){
      JavaClass jClass = jClasses.next();
      Iterator jFields = jClass.getDeclaredFields().iterator();
      while(jFields.hasNext()){
        JavaField jField = (JavaField)jFields.next();
        try{
          fieldList.add(jField);

        }catch(Exception exxy){
          exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
          this.svr.stop();

        }


      }
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + fieldList.size() + " fields"); //$NON-NLS-1$ //$NON-NLS-2$
    return fieldList;

  }

  /**
   * Generate a list of fowards and backwards int to JavaMethod list.
   */
  private void buildMethods(){
    intToMethod = new HashMap<Integer, JavaMethod>();
    methodToInt = new HashMap<JavaMethod, Integer>();
    Iterator<JavaClass> jClasses = classes.values().iterator();
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building method list..."); //$NON-NLS-1$
    while(jClasses.hasNext()){
      JavaClass jClass = jClasses.next();
      Iterator jMethods = jClass.getDeclaredMethods().iterator();
      while(jMethods.hasNext()){
        JavaMethod jMethod = (JavaMethod)jMethods.next();
        try{
          int index = intToMethod.size();
          intToMethod.put(index, jMethod);
          methodToInt.put(jMethod, index);
          //logr.log(JDILogger.LEVEL_VERBOSE, jClass.getName()+"."+jMethod.getName()+"#"+methodList.indexOf(jMethod));
        }catch(Exception exxy){
          exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
          System.exit(1);
        }


      }
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + intToMethod.size() + " methods"); //$NON-NLS-1$ //$NON-NLS-2$

  }

  /**
   * Given a JavaMethod and class id, return the id of the method
   * @param refType The class id as found in the JavaClass vector
   * @param jMethod The Kato JavaMethod object
   * @return A unique ID for this method
   */

  private long getMethodId(long refType, JavaMethod jMethod){
    int id = methodToInt.get(jMethod);
    if (id < 0 || id > methodToInt.size()){
      logr.logError(JDILogger.LEVEL_VERBOSE, "  Could not find method in list"); //$NON-NLS-1$
      id = -1;
    }
    return id;
  }

  /**
   * Given a JavaField and class id, return the id of the field
   * @param refType The class id as found in the JavaClass vector
   * @param jField The Kato JavaField object
   * @return A unique ID for this field
   */

  private long getFieldId(long refType, JavaField jField){
    int id = fieldList.indexOf(jField);
    if (id < 0 || id > fieldList.size()){
      logr.logError(JDILogger.LEVEL_VERBOSE, "  Could not find field in list"); //$NON-NLS-1$
      id = -1;
    }
    return id;
  }


  /**
   * Given a vector, objectID, and fieldID, add the tagged value to the vector
   * @param vctr      The Byte vector for the current data segment
   * @param objectID    The unique objectID of the object we're inquiring about
   * @param fieldID    The unique fieldID of the field we're inquiring about
   * @return        false if we fail, true if we succeed
   * @throws Exception  Upstream exception thrown
   */
  private boolean getFieldFromObject(Vector<Byte> vctr, long objectID, long fieldID) throws Exception{

    JavaField jField = getField(fieldID);
    JavaObject jObject = getObject(objectID);
    if (jField != null && jObject != null){
      return getValueFromField(vctr, jObject, jField);
    }
    logr.logError(JDILogger.LEVEL_VERBOSE, "  Object " +objectID + " is not in the list of objects."); //$NON-NLS-1$ //$NON-NLS-2$


    logr.logError(JDILogger.LEVEL_VERBOSE, "  Cannot find class field from object"); //$NON-NLS-1$
    return false;
  }

  /**
   * Given a vector, reffTypeID, and fieldID, add the tagged value to the vector
   * @param vctr      The Byte vector for the current data segment
   * @param refType    The unique class ID of the object we're inquiring about
   * @param fieldID    The unique fieldID of the field we're inquiring about
   * @return        false if we fail, true if we succeed
   * @throws Exception  Upstream exception thrown
   */
  private boolean getFieldFromClass(Vector<Byte> vctr, long refType, long fieldID) throws Exception{

    JavaClass javaClass = getClass(refType);
    if (javaClass != null){
      JavaField jField = getField(fieldID);
      if (jField != null){
        return getValueFromField(vctr, javaClass.getObject(), jField);
      }
      logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  No such field"); //$NON-NLS-1$

    }else{
      logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  No such class"); //$NON-NLS-1$
      return false;
    }

    return false;
  }

  /**
   * Build a hashmap using the JavaClass address as a unique ID and key
   * @return A hashmap containing all the classes and addresses
   */
  private HashMap<Long, JavaClass> buildClasses() {
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Building class list"); //$NON-NLS-1$
    HashMap<Long, JavaClass> classes = new HashMap<Long, JavaClass>();
    Iterator asIt = image.getAddressSpaces( ).iterator();
    while ( asIt.hasNext( ) )
    {
      ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
      Iterator prIt = as.getProcesses( ).iterator();
      while ( prIt.hasNext( ) ){
        ImageProcess process = (ImageProcess) prIt.next( );

        Iterator runTimesIt = process.getRuntimes( ).iterator();
        while ( runTimesIt.hasNext( ) )
        {
          JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
          Iterator classLoaders = javaRT.getJavaClassLoaders().iterator();
          while (classLoaders.hasNext()){

            JavaClassLoader javaCL = (JavaClassLoader)classLoaders.next();
            Iterator javaClasses = javaCL.getDefinedClasses().iterator();

            while (javaClasses.hasNext()){
              JavaClass javaClass = (JavaClass)javaClasses.next();

              classes.put(javaClass.getID().getAddress(), javaClass);


            }
          }
        }
      }
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Built list of " + classes.size() + " classes"); //$NON-NLS-1$ //$NON-NLS-2$
    return classes;
  }

  /**
   * Transforms a JavaObject into a real java/lang/String object.
   * Does this by extracting the following fields from java/lang/String:
   * <pre>
   *   int offset, count;
   *  char[] value;
   *  </pre>
  
   * @param object
   *            JavaObject representation of a java.lang.String object.
   * @return String or null if there were problems.
   * @throws IllegalArgumentException thrown if JavaObject not java/lang/String
   */
  public static String javaObjectToString(JavaObject object)
      throws IllegalArgumentException {

    if (object == null) {
      return null;
    }

    String className = null;
    JavaClass stringClass = null;

    try {
      stringClass = object.getJavaClass();
      className = stringClass.getName();
    } catch (CorruptDataException e) {
      e.printStackTrace();
      return null;
    }

    if (!className.equals("java/lang/String")) {
      throw new IllegalArgumentException(
          "Mismatched types - expecting java/lang/String, got `"
              + className + "'");
    }

    int offset = 0, count = 0;
    char[] value = null;
    JavaObject valueArray = null;
    boolean gotValue = false, gotOffset = false, gotCount = false;

    // Get all fields, pick out interesting ones.
    for (Object fobj : stringClass.getDeclaredFields()) {
     

      if (fobj instanceof CorruptData) {
        continue;
      }

      JavaField field = (JavaField) fobj;
      try {
        String fieldName = field.getName();

        if (fieldName.equals("offset")) {
          offset = field.getInt(object);
          gotOffset = true;
        } else if (fieldName.equals("count")) {
          count = field.getInt(object);
          gotCount = true;
        } else if (fieldName.equals("value")) {
          valueArray = (JavaObject) field.get(object);
          gotValue = true;
        }

      } catch (DiagnosticException e) {
        e.printStackTrace();
        return null;
      }
    }

    try {
      // Check we got all of the fields.
      if ((gotOffset || gotCount || gotValue) == false) {
        return null;
      } else {
        int length = (int) valueArray.getArraySize();
        value = new char[length];
        try {
          valueArray.arraycopy(0, value, 0, length);
        } catch (IndexOutOfBoundsException e) {
          e.printStackTrace();
          return null;
        }
      }

      return new String(value, offset, count);
    } catch (CorruptDataException e) {
      e.printStackTrace();
      return null;
    } catch (MemoryAccessException e) {
      e.printStackTrace();
      return null;
    }
  }
  /**
   * Convert a Vector to a byte array
   * @param vctr The Vector to convert
   * @return An array consisting of bytes (Not Bytes)
   */


  public static byte[] vectorToByte(Vector<Byte> vctr){
    Byte []barray = new Byte[vctr.size()];
    vctr.copyInto(barray);
    //TODO - A better way to do this?
    byte []barray2 = new byte[barray.length];
    for (int i = 0; i < barray.length; i++){
      barray2[i] = barray[i];
    }
    return barray2;
  }


  /**
   * getByteFromInt is used to break down an int into a byte
   * @param orig The original integer
   * @param index Which byte to get (0-3 inclusive)
   * @return The byte
   */
  public static byte getByteFromInt(int orig, int index){
    if (index < 0 || index > 3)
      throw new ArrayIndexOutOfBoundsException();
    //Mask out the 4 bytes
    int mask = 0xFF;

    //Align the mask to what we want
    mask = mask << (index*8);

    //Mask out the byte we want
    orig = orig & mask;

    //Align back our new value
    orig = orig >> (index*8);

    //Truncate the rest of the useless bytes
    return (byte)orig;

  }

  /**
   * Add a 64bit long to the end of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inLong The long to add
   */

  public static void addLongToVector(Vector<Byte> vctr, long inLong){
    int topInt = (int)(inLong >> 32) & 0xFFFFFFFF;
    int bottomInt = (int)inLong & 0xFFFFFFFF;

    vctr.add(getByteFromInt(topInt, 3));
    vctr.add(getByteFromInt(topInt, 2));
    vctr.add(getByteFromInt(topInt, 1));
    vctr.add(getByteFromInt(topInt, 0));

    vctr.add(getByteFromInt(bottomInt, 3));
    vctr.add(getByteFromInt(bottomInt, 2));
    vctr.add(getByteFromInt(bottomInt, 1));
    vctr.add(getByteFromInt(bottomInt, 0));
  }

  /**
   * Add a 32bit int to the front of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inInt The int to add
   */
  public static void addIntToVectorFront(Vector<Byte> vctr, int inInt){
    vctr.add(0, getByteFromInt(inInt, 3));
    vctr.add(1, getByteFromInt(inInt, 2));
    vctr.add(2, getByteFromInt(inInt, 1));
    vctr.add(3, getByteFromInt(inInt, 0));
  }

  /**
   * Add a 32bit int to the end of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inInt The int to add
   */
  public static void addIntToVector(Vector<Byte> vctr, int inInt){
    vctr.add(getByteFromInt(inInt, 3));
    vctr.add(getByteFromInt(inInt, 2));
    vctr.add(getByteFromInt(inInt, 1));
    vctr.add(getByteFromInt(inInt, 0));
  }

  /**
   * Add a 16bit short to the front of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inShort The short to add
   */
  public static void addShortToVectorFront(Vector<Byte> vctr, short inShort){
    vctr.add(0, getByteFromInt(inShort, 1));
    vctr.add(1, getByteFromInt(inShort, 0));
  }

  /**
   * Add a 16bit short to the end of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inShort The int to add
   */
  public static void addShortToVector(Vector<Byte> vctr, int inShort){
    vctr.add(getByteFromInt(inShort, 1));
    vctr.add(getByteFromInt(inShort, 0));
  }
 
  /**
   * Add a 16bit char to the front of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inChar The short to add
   */
  public static void addCharToVectorFront(Vector<Byte> vctr, int inChar){
    vctr.add(0, getByteFromInt(inChar, 1));
    vctr.add(1, getByteFromInt(inChar, 0));
  }

  /**
   * Add a 16bit char to the end of the Byte Vector
   * @param vctr Vector to add the bytes to
   * @param inChar The int to add
   */
  public static void addCharToVector(Vector<Byte> vctr, int inChar){
    vctr.add(getByteFromInt(inChar, 1));
    vctr.add(getByteFromInt(inChar, 0));
 
  /**
   * Add a string to the end of the Byte Vector as specified in the JDWP docs (4 byte length + ASCII chars)
   * @param vctr Vector to add the bytes to
   * @param inString The string to add
   */
  public static void addStringToVector(Vector<Byte> vctr, String inString){
    addIntToVector(vctr, inString.length());

    byte[] str = inString.getBytes();
    for (int i = 0; i < str.length; i++){
      vctr.add(str[i]);
    }
  }

  /**
   * Given a byte array, extract a string as defined in the JDWP specs
   * @param inData The byte array to pull the data from
   * @param offset The index of the string (which is the length of the string)
   * @return The resultant string
   */
  public static String getStringFromBytes(byte []inData, int offset){
    int length = createIntFromBytes(inData, offset, 4);
    String ret = ""; //$NON-NLS-1$
    for(int i = offset + 4; i < offset + 4 + length; i++){
      ret = ret + (char)inData[i];
    }


    return ret;
  }

  /**
   * Given a byte array, extract a 32bit int
   * @param inData The byte array to pull the data from
   * @param offset The index of the int
   * @param size How many bytes to extract
   * @return The 32bit int
   */
  public static int createIntFromBytes(byte []inData, int offset, int size){


    int ret = 0;
    if (size == 0)
      size = 4;
    if (size != 4){
      throw new NumberFormatException("createIntFromBytes should be 4 bytes"); //$NON-NLS-1$
    }
    for(int i = offset; i < offset + size; i++){
      ret = ret << 8;
      ret |= (inData[i] & 0xFF);
    }

    return ret;

  }

  /**
   * Given a byte array, extract a 64bit long
   * @param inData The byte array to pull the data from
   * @param offset The index of the int
   * @param size How many bytes to extract
   * @return The 64bit long
   */
  public static long createLongFromBytes(byte []inData, int offset, int size){
    long ret = 0;
    if (size == 0)
      size = 8;
    if (size != 8){
      throw new NumberFormatException("createLongFromBytes should be 8 bytes"); //$NON-NLS-1$
    }
    for(int i = offset; i < offset + size; i++){
      ret = ret << 8;
      ret |= (inData[i] & 0xFF);
    }

    return ret;

  }

  /**
   * Return whether a class is an interface or not
   * @param classID The id of the class
   * @return true if the class is an interface
   * @throws CorruptDataException
   */
  private boolean isInterface(long classID) throws CorruptDataException{
    //Use modifier
    if (classes == null){
      buildClasses();
    }
    JavaClass jClass = getClass(classID);
    if (jClass != null){
      if (Modifier.isInterface(jClass.getModifiers())){
        return true;
      }
    }
    return false;
  }

  /**
   * Given a classID, get the Kato JavaClass
   * @param classID The unique class ID
   * @return The Kato JavaClass
   * @throws CorruptDataException
   */
  private JavaClass getClass(long classID){
    if (classes == null){
      classes = buildClasses();
    }
    JavaClass jcl = classes.get(classID);
    if (jcl == null){
      /**
       * Attemp to get directly, useful for system class loader which isn't covered
       * by build classes as it is not part of the class loader loaded classes.
       */
     
    }
    return classes.get(classID);

  }

  /**
   * Given a classID, check to see if the ID is actually a class or an object
   * @param classID The classID
   * @return true if classID is a class, false if it is not
   * @throws CorruptDataException
   */
  private boolean isClass(long classID){
    if (classes == null){
      classes = buildClasses();
    }
    return classes.containsKey(classID);
  }

  /**
   * Given a classID and a methodID, get the lowest line number known in all stack frames
   * @param refType The class ID of the method
   * @param methodID The method ID
   * @return The lowest known line number
   * @throws Exception
   */
  private int findLowestLineRef(long refType, long methodID) throws Exception{
    int lowest = 1999999999;
    Iterator asIt = image.getAddressSpaces( ).iterator();
    while ( asIt.hasNext( ) )
    {
      ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
      Iterator prIt = as.getProcesses( ).iterator();

      while ( prIt.hasNext( ) )
      {
        ImageProcess process = (ImageProcess) prIt.next( );
        Iterator runTimesIt = process.getRuntimes( ).iterator();
        while ( runTimesIt.hasNext( ) )
        {
          JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
          Iterator thds = javaRT.getThreads().iterator();
          while(thds.hasNext()){
            Object tmpobj = thds.next();
            if (tmpobj instanceof CorruptData){
              //ignore this thread
            }else{
              JavaThread thd = (JavaThread) tmpobj;
              Iterator frames = thd.getStackFrames().iterator();
              while(frames.hasNext()){
                JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                JavaLocation jLocation = jStackFrame.getLocation();
                JavaMethod jMethod = jLocation.getMethod();
                JavaClass jClass = jMethod.getDeclaringClass();


                if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){
                  int line = -1;
                  try{
                    line = jLocation.getLineNumber();
                  }
                  catch(Exception exxy){}
                  if (line > 0){
                    if (lowest > line){
                      lowest = line;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return lowest;
  }

  /**
   * Given a classID and a methodID, get the highest line number known in all stack frames
   * @param refType The class ID of the method
   * @param methodID The method ID
   * @return The highest known line number
   * @throws Exception
   */
  private int findHighestLineRef(long refType, long methodID) throws Exception{
    int highest = 0;
    Iterator asIt = image.getAddressSpaces( ).iterator();
    while ( asIt.hasNext( ) )
    {
      ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
      Iterator prIt = as.getProcesses( ).iterator();

      while ( prIt.hasNext( ) )
      {
        ImageProcess process = (ImageProcess) prIt.next( );
        Iterator runTimesIt = process.getRuntimes( ).iterator();
        while ( runTimesIt.hasNext( ) )
        {
          JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
          Iterator thds = javaRT.getThreads().iterator();
          while(thds.hasNext()){
            Object tmpobj = thds.next();
            if (tmpobj instanceof CorruptData){
              //ignore this thread
            }else{
              JavaThread thd = (JavaThread) tmpobj;
              Iterator frames = thd.getStackFrames().iterator();
              while(frames.hasNext()){
                JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                JavaLocation jLocation = jStackFrame.getLocation();
                JavaMethod jMethod = jLocation.getMethod();
                JavaClass jClass = jMethod.getDeclaringClass();


                if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){
                  int line = -1;
                  try{
                    line = jLocation.getLineNumber();
                  }
                  catch(Exception exxy){}
                  if (line > 0){
                    if (line > highest){
                      highest = line;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return highest;
  }

  /**
   * Take care of the virtualMachine command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */
  public ReplyPacket virtualMachine(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == VIRTUAL_MACHINE_VERSION){
      logr.log(JDILogger.LEVEL_VERBOSE, "Version()"); //$NON-NLS-1$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();
        while ( prIt.hasNext( ) ){
          ImageProcess process = (ImageProcess) prIt.next( );

          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            //Since there doesn't seem to be a matching Kato call to get
            //the information for JDWP, lets call NOT_IMPLEMENTED, but really
            //attach some information back
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            String description = "JDI Post Mortem Debugger"; //$NON-NLS-1$
            String vmVersion = javaRT.getVersion();
            String vmName = "JDI PMD"; //$NON-NLS-1$

            int jdwpMajor = 1;
            int jdwpMinor = 4;

            //We now have all the information for the reply.  Put it all together
            Vector<Byte> vctr = new Vector<Byte>();
            addStringToVector(vctr, description);
            addIntToVector(vctr, jdwpMajor);
            addIntToVector(vctr, jdwpMinor);
            addStringToVector(vctr, vmVersion);
            addStringToVector(vctr, vmName);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;

          }
        }
      }

    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_CLASS_PATHS){
     
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "This does not return the actual class path, simply allows JDB to work.");
      Vector<Byte> vctr = new Vector<Byte>();
      addStringToVector(vctr, "");
      addIntToVector(vctr, 0);
      addIntToVector(vctr, 0);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    } else if (cpckt.getCommand() == VIRTUAL_MACHINE_CLASSES_BY_SIGNATURE){
      Vector<Byte> vctr = new Vector<Byte>();
      byte []inData = cpckt.getByteData();
      String signature = getStringFromBytes(inData, 0);
      if (signature.charAt(0) == 'L'){
        signature = signature.substring(1, signature.length() - 1);
      }
      logr.log(JDILogger.LEVEL_VERBOSE, "ClassesBySignature(" + signature + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      int count = 0;
      Iterator <JavaClass> javaClasses = classes.values().iterator();
      while (javaClasses.hasNext()){
        JavaClass javaClass = javaClasses.next();
        String searched = javaClass.getName();

        if (searched.equals(signature)){
          count++;
          if (javaClass.isArray()){
            vctr.add((byte)3);
          }else if (isInterface(javaClass.getID().getAddress())){
            vctr.add((byte)2);
          }else{
            vctr.add((byte)1);
          }
          //vctr.add((byte)1);
          addLongToVector(vctr, javaClass.getID().getAddress());
          //Verified Prepared and Initialized
          addIntToVector(vctr, 1 | 2 | 4);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "Match: " + javaClass.getName() +" " + Long.toHexString(javaClass.getID().getAddress())); //$NON-NLS-1$
        }else{
          String mangledName = "" + searched + ""; //$NON-NLS-1$ //$NON-NLS-2$
          if (mangledName.equals(signature)){
            count++;
            if (javaClass.isArray()){
              vctr.add((byte)3);
            }else if (isInterface(javaClass.getID().getAddress())){
              vctr.add((byte)2);
            }else{
              vctr.add((byte)1);
            }
            //vctr.add((byte)1);
            addLongToVector(vctr, javaClass.getID().getAddress());
            //Verified Prepared and Initialized
            addIntToVector(vctr, 1 | 2 | 4);
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "Mangled Match: " + javaClass.getName()); //$NON-NLS-1$
          }else{
            String secondMangle = "[" + searched + ";"; //$NON-NLS-1$ //$NON-NLS-2$
            if (secondMangle.equals(signature)){
              count++;
              if (javaClass.isArray()){
                vctr.add((byte)3);
              }else if (isInterface(javaClass.getID().getAddress())){
                vctr.add((byte)2);
              }else{
                vctr.add((byte)1);
              }
              //vctr.add((byte)1);
              addLongToVector(vctr, javaClass.getID().getAddress());
              //Verified Prepared and Initialized
              addIntToVector(vctr, 1 | 2 | 4);
              logr.log(JDILogger.LEVEL_VERYVERBOSE, "Really mangled match: " + javaClass.getName()); //$NON-NLS-1$
            }
          }
        }

      }
      //Add the count to the front of the vector
      addIntToVectorFront(vctr, count);
      logr.log(JDILogger.LEVEL_VERYVERBOSE, count+" matches"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_ALL_CLASSES){
      logr.log(JDILogger.LEVEL_VERBOSE, "AllClasses()"); //$NON-NLS-1$
      Vector<Byte> vctr = new Vector<Byte>();
      int count = 0;
      Iterator <JavaClass> classList = classes.values().iterator();
      while(classList.hasNext()){
        JavaClass javaClass = (JavaClass)classList.next();
        long typeID = javaClass.getID().getAddress();
        String signature;

        if (javaClass.isArray()){
          vctr.add((byte)3);
          signature = "" + javaClass.getName() + ""; //$NON-NLS-1$ //$NON-NLS-2$
        }else if (isInterface(typeID)){
          vctr.add((byte)2);
          signature = "L" + javaClass.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
        }else{
          vctr.add((byte)1);
          signature = "L" + javaClass.getName() + ";"; //$NON-NLS-1$ //$NON-NLS-2$
        }
       
        int status = 7;
        addLongToVector(vctr, typeID);
        addStringToVector(vctr, signature);
        addIntToVector(vctr, status);
        count++;
       

      }

      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + count +" class(es) found"); //$NON-NLS-1$ //$NON-NLS-2$
      addIntToVectorFront(vctr, count);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_ALL_THREADS){
      logr.log(JDILogger.LEVEL_VERBOSE, "AllThreads()"); //$NON-NLS-1$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            Vector<Byte> vctr = new Vector<Byte>();
            int count = 0;
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                count++;
                JavaThread thd = (JavaThread)tmpobj;
                long hash = thd.getObject().getID().getAddress();
                logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread hash " + thd.getName() + " is " + hash); //$NON-NLS-1$ //$NON-NLS-2$
                addLongToVector(vctr, hash);
              }

            }
            addIntToVectorFront(vctr, count);
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            byte []barray2 = vectorToByte(vctr);
            rpckt.setData(barray2);
            return rpckt;


          }

        }
      }
    }
    else if (cpckt.getCommand() == VIRTUAL_MACHINE_TOP_LEVEL_THREAD_GROUPS){
     
      // return an arbitrary thread group name, return all of them in a single group.
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      Vector<Byte> vctr = new Vector<Byte>();
      addIntToVector(vctr, 1);
      addLongToVector(vctr, 1);
      byte []barray = vectorToByte(vctr);
      rpckt.setData(barray);
      return rpckt;
     
     
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_DISPOSE){
      //This is a disconnect request
      logr.log(JDILogger.LEVEL_VERBOSE, "Dispose()"); //$NON-NLS-1$
      svr.disconnect(cpckt.getVSock());
      return null;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_IDSIZES){
      //Here we specify a 4 byte (32bit) id size for everything
      //1.7 says that there are 5 fields, each with the number of bytes
      //used to identify each id.
      logr.log(JDILogger.LEVEL_VERBOSE, "IDSizes()"); //$NON-NLS-1$
      Vector<Byte> vctr = new Vector<Byte>();
      //fieldID
      addIntToVector(vctr, 8);
      //methodID
      addIntToVector(vctr, 8);
      //objectID
      addIntToVector(vctr, 8);
      //referenceTypeID (refType)
      addIntToVector(vctr, 8);
      //frameID
      addIntToVector(vctr, 8);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_SUSPEND){
      //Suspend the whole VM.  Which is what we're already doing
      //Just play along with it.
      logr.log(JDILogger.LEVEL_VERBOSE, "Suspend()"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_RESUME){
      //Resume the VM.  Which we can't do.
      //Just pretend.
      logr.log(JDILogger.LEVEL_VERBOSE, "Resume()"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_EXIT){
      shutDownKato();
      //This is a disconnect request
      logr.log(JDILogger.LEVEL_VERBOSE, "Exit()"); //$NON-NLS-1$
      logr.log(JDILogger.LEVEL_NORMAL, "Remove client asked termination of server"); //$NON-NLS-1$
      svr.stop();
      svr = null;
      return null;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_CREATE_STRING){
      Vector<Byte> vctr = new Vector<Byte>();
      addLongToVector(vctr, 0);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == VIRTUAL_MACHINE_CAPABILITIES_NEW){
      logr.log(JDILogger.LEVEL_VERBOSE, "CapabilitiesNew()"); //$NON-NLS-1$
      //This is the capabilities request.
      byte canWatchFieldModification = 0;
      byte canWatchFieldAccess = 0;
      byte canGetBytecodes = 1;
      byte canGetSyntheticAttribute = 0;
      byte canGetOwnedMonitorInfo = 1;
      byte canGetCurrentContendedMonitor = 1;
      byte canGetMonitorInfo = 1;
      byte canRedefineClasses = 0;
      byte canAddMethod = 0;
      byte canUnrestrictedlyRedfineClasses = 0;
      byte canPopFrames = 0;
      byte canUseInstanceFilters = 0;
      byte canGetSourceDebugExtension = 1;
      byte canRequestVMDeathEvent = 0;
      byte canSetDefaultStratum = 0;

      Vector<Byte> vctr = new Vector<Byte>();
      vctr.add(canWatchFieldModification);
      vctr.add(canWatchFieldAccess);
      vctr.add(canGetBytecodes);
      vctr.add(canGetSyntheticAttribute);
      vctr.add(canGetOwnedMonitorInfo);
      vctr.add(canGetCurrentContendedMonitor);
      vctr.add(canGetMonitorInfo);
      vctr.add(canRedefineClasses);
      vctr.add(canAddMethod);
      vctr.add(canUnrestrictedlyRedfineClasses);
      vctr.add(canPopFrames);
      vctr.add(canUseInstanceFilters);
      vctr.add(canGetSourceDebugExtension);
      vctr.add(canRequestVMDeathEvent);
      vctr.add(canSetDefaultStratum);
      //Fill unused
      for (int i = 0; i < 17; i++){
        vctr.add((byte)0);
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;


  }
  /**
   * Take care of the referenceType command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */
  public ReplyPacket referenceType(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == REFERENCE_TYPE_SIGNATURE){
      Vector<Byte> vctr = new Vector<Byte>();
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Signature(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        if (javaClass.isArray()){
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "" + javaClass.getName() + ""); //$NON-NLS-1$ //$NON-NLS-2$
          addStringToVector(vctr, "" + javaClass.getName() + ""); //$NON-NLS-1$ //$NON-NLS-2$
        }else{
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "L" + javaClass.getName() + ";"); //$NON-NLS-1$ //$NON-NLS-2$
          addStringToVector(vctr, "L" + javaClass.getName() + ";");
        } //$NON-NLS-1$ //$NON-NLS-2$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_CLASS_LOADER){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "ClassLoader(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        Vector<Byte> vctr = new Vector<Byte>();
        JavaObject obj = javaClass.getClassLoader().getObject();
        long address = 0L;
       
        if (obj != null) {
          address = obj.getID().getAddress();
        }
       
        addLongToVector(vctr, address);
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  0x" + Long.toHexString(address) ); //$NON-NLS-1$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;

      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_MODIFIERS){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Modifiers(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        Vector<Byte> vctr = new Vector<Byte>();
        addIntToVectorFront(vctr,javaClass.getModifiers());
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_FIELDS){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Fields(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        Iterator javaFields = javaClass.getDeclaredFields().iterator();
        logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
        Vector<Byte> vctr = new Vector<Byte>();
        int count = 0;
        while (javaFields.hasNext()){
          JavaField jField = (JavaField)javaFields.next();

          long fieldID = getFieldId(refType, jField);
          String name = jField.getName();
          String signature = jField.getSignature();
          int modBits = jField.getModifiers();
          addLongToVector(vctr, fieldID);
          addStringToVector(vctr, name);
          addStringToVector(vctr, signature);
          addIntToVector(vctr, modBits);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + name + " (" + signature + "," + fieldID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
          count++;
        }
        addIntToVectorFront(vctr,count);
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found " + count + " fields(s)"); //$NON-NLS-1$ //$NON-NLS-2$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_METHODS){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Methods(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        Iterator javaMethods = javaClass.getDeclaredMethods().iterator();
        logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
        Vector<Byte> vctr = new Vector<Byte>();
        int count = 0;
        while (javaMethods.hasNext()){
          JavaMethod jMethod = (JavaMethod)javaMethods.next();
          long methodID = getMethodId(refType, jMethod);
          String name = jMethod.getName();
          String signature = jMethod.getSignature();
          int modBits = jMethod.getModifiers();
          addLongToVector(vctr, methodID);
          addStringToVector(vctr, name);
          addStringToVector(vctr, signature);
          addIntToVector(vctr, modBits);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + name + " (" + signature + ", " + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
          count++;
        }
        addIntToVectorFront(vctr,count);
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found " + count + " method(s)"); //$NON-NLS-1$ //$NON-NLS-2$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }


      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_GET_VALUES){
      byte [] inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      int fields = createIntFromBytes(inData, 8, 4);
      logr.log(JDILogger.LEVEL_VERBOSE, "ReferenceType.GetValues(" + refType + ", " + fields + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      Vector<Byte> vctr = new Vector<Byte>();

      addIntToVector(vctr, fields);

      for(int i = 0; i < fields; i++){
        long fieldID = createLongFromBytes(inData, 12 + (i * 8), 8);
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + i + " of " + fields + " {" + fieldID+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        if (!getFieldFromClass(vctr, refType, fieldID)){
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
          return rpckt;
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_SOURCE_FILE){
      byte [] inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "SourceFile(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                Iterator frames = thd.getStackFrames().iterator();
                while(frames.hasNext()){
                  JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                  JavaLocation jLocation = jStackFrame.getLocation();
                  JavaMethod jMethod = jLocation.getMethod();
                  JavaClass jClass = jMethod.getDeclaringClass();


                  if (jClass.getID().getAddress() == refType){
                    Vector<Byte> vctr = new Vector<Byte>();
                    try{
                      addStringToVector(vctr, jLocation.getFilename());
                      logr.log(JDILogger.LEVEL_VERBOSE, "  " + jLocation.getFilename()); //$NON-NLS-1$
                      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                      rpckt.setData(vectorToByte(vctr));
                      return rpckt;
                    }
                    catch(Exception exxy){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Missing source file name information"); //$NON-NLS-1$
                      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION);
                      return rpckt;
                    }
                  }
                }
              }
            }
          }
        }
      }
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Not on stack, cannot retrieve information"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION);
      return rpckt;

    }else if (cpckt.getCommand() == REFERENCE_TYPE_INTERFACES){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Interfaces(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        Iterator javaInterfaces = javaClass.getInterfaces().iterator();
        logr.log(JDILogger.LEVEL_VERYVERBOSE, javaClass.getName() + ":"); //$NON-NLS-1$
        Vector<Byte> vctr = new Vector<Byte>();
        int count = 0;
        while (javaInterfaces.hasNext()){
          String iFaceName = (String)javaInterfaces.next();
        JavaClass jClass = javaClass.getClassLoader().findClass(iFaceName);
          long interfaceID;
          if (jClass == null){
            interfaceID = 0;
          }else{
            interfaceID = jClass.getID().getAddress();
          }
          addLongToVector(vctr, interfaceID);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + interfaceID); //$NON-NLS-1$

          count++;
        }
        addIntToVectorFront(vctr,count);
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Found " + count + " interface(s)"); //$NON-NLS-1$ //$NON-NLS-2$
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == REFERENCE_TYPE_CLASS_OBJECT){
      // Simply returns null for class object, jdb compatability
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "ObjectClass");
      Vector<Byte> vctr = new Vector<Byte>();
      addLongToVector(vctr, 0);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
    }else if (cpckt.getCommand() == REFERENCE_TYPE_SOURCE_DEBUG_EXTENSION){
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "SourceDebugExtension(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      Vector<Byte> vctr = new Vector<Byte>();
      addStringToVector(vctr, ""); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;
  }

  /**
   * Take care of the classType command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */
  private ReplyPacket classType(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      Vector<Byte> vctr = new Vector<Byte>();
      byte []inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Superclass(" + refType + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      JavaClass javaClass = getClass(refType);
      if (javaClass != null){
        JavaClass jSuperClass = javaClass.getSuperclass();
        if( jSuperClass != null) {
          addLongToVector(vctr, jSuperClass.getID().getAddress());
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jSuperClass.getID().getAddress()); //$NON-NLS-1$
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;
        } else {
          addLongToVector(vctr, 0);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Class "+javaClass.getName()+"{"+javaClass.getID().getAddress()+"} has no superclass"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt; 
        }       
      }
     
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Invalid class ID"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

    } else if (cpckt.getCommand() == 3){
      Vector<Byte> vctr = new Vector<Byte>();
      byte []inData = cpckt.getByteData();
      long classID = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERYVERBOSE,"Tried to invoke static method! "+classID);
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }

  /**
   * Take care of the method command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */
  private ReplyPacket method(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      byte [] inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      long methodID = createLongFromBytes(inData, 8, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "LineTable(" + refType + "," + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                Iterator frames = thd.getStackFrames().iterator();
                while(frames.hasNext()){
                  JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                  JavaLocation jLocation = jStackFrame.getLocation();
                  JavaMethod jMethod = jLocation.getMethod();
                  JavaClass jClass = jMethod.getDeclaringClass();

                  if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){
                    int line = -1;
                    try{
                      line = jLocation.getLineNumber();
                    }
                    catch(CorruptDataException exxy){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  CorruptData for:"); //$NON-NLS-1$
                    }
                    catch(DataUnavailable exxy){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  DataUnavailable for:"); //$NON-NLS-1$
                    }


                    Vector<Byte> vctr = new Vector<Byte>();
                    if (line > 0){

                      int lowest = findLowestLineRef(refType, methodID) - 1;
                      int highest = findHighestLineRef(refType, methodID) + 1;
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  (L)" + jClass.getName() + "." + jMethod.getName() + ":" + lowest + "<" + line + ">" + highest); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
                     
//                      //Code index start
//                      addLongToVector(vctr, lowest);
//                      //Code index end
//                      addLongToVector(vctr, highest);
//                      //Number of lines
//                      addIntToVector(vctr, highest - lowest);
//                      for(int i = lowest; i <= highest; i++){
//                        addLongToVector(vctr, i);
//                        addIntToVector(vctr, i);
//                      }
                     
                      //Code index start
                      addLongToVector(vctr, 0);
                      //Code index end
                      addLongToVector(vctr, 99999999); // TODO go through local variable tables looking for highest reference?
                      //Number of lines
                      addIntToVector(vctr, 1);
                      //for(int i = lowest; i <= highest; i++){
                        addLongToVector(vctr, jLocation.getAddress().getAddress()-1);
                        addIntToVector(vctr, jLocation.getLineNumber());
                      //}
                     
                     
                    }else{
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  (N)" + jClass.getName() + "." + jMethod.getName() + ":" + line); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                      //Code index start
                      addLongToVector(vctr, -1);
                      //Code index end
                      addLongToVector(vctr, -1);
                      //Number of lines
                      //We're native right now.
                      addIntToVector(vctr, 0);
                    }
                    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                    rpckt.setData(vectorToByte(vctr));
                    return rpckt;
                  }
                }
              }
            }
          }
        }
      }
     
      Vector<Byte> vctr = new Vector<Byte>();
      addLongToVector(vctr, -1);
      //Code index end
      addLongToVector(vctr, -1);
      //Number of lines
      //We're native right now.
      addIntToVector(vctr, 0);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == 2){
      byte [] inData = cpckt.getByteData();
      long refType = createLongFromBytes(inData, 0, 8);
      long methodID = createLongFromBytes(inData, 8, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Method.VariableTable(" + refType + "," + methodID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      int slotsUsed = 0;
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                Iterator frames = thd.getStackFrames().iterator();
                while(frames.hasNext()){
                  JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                  JavaLocation jLocation = jStackFrame.getLocation();
                  JavaMethod jMethod = jLocation.getMethod();
                  JavaClass jClass = jMethod.getDeclaringClass();
                 
                 
                  if (getMethodId(refType, jMethod) == methodID && jClass.getID().getAddress() == refType){
                    Vector<Byte> vctr = new Vector<Byte>();

                    List vars = jMethod.getVariables();
                    String sig = jMethod.getSignature();
                   
                    addIntToVector(vctr, methodSignatureSize(sig));
                    addIntToVector(vctr, vars.size());

                    logr.log(JDILogger.LEVEL_VERYVERBOSE, " "+jLocation+
                        " vars.size="+vars.size());
                   
                    for (Object nextVar : vars) {
                      if (nextVar instanceof CorruptData) {
                        logr.log(JDILogger.LEVEL_VERYVERBOSE, "Corrupt local variable data");
                        continue;
                      }

                      JavaVariable var = (JavaVariable) nextVar;
                     
                      addLongToVector(vctr, var.getStart());
                      addStringToVector(vctr, var.getName());
                      addStringToVector(vctr, var.getSignature());
                      addIntToVector(vctr, var.getLength());
                      addIntToVector(vctr, var.getSlot());
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "  start:"+var.getStart()+
                          " name:`"+var.getName()+ "'"+
                          " signature:`"+var.getSignature()+"'"+
                          " length: "+var.getLength()+
                          " slot: "+var.getSlot()); //$NON-NLS-1$ //$NON-NLS-2$

                    }
                    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                    rpckt.setData(vectorToByte(vctr));

                    return rpckt;
                  }               
                }
              }
            }
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_ABSENT_INFORMATION);
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }

 
  /**
   * Works out and returns the size of a method's arguments from it's signature.
   * doubles and longs and object references are regarded as
   *
   * @param signature JNI signature of method.
   * e.g. "(Ljava/lang/String;LB)I"
   *     which would be:
   *       int method(String arg0, long arg1, byte arg2);
   *
   * 
   * @return size of arguments
   */
  public static int methodSignatureSize(String signature) {
    int state = 0;
    int size = 0;
   
LOOP:  for (int i=0; i < signature.length(); i++) {
      char c = signature.charAt(i);
     
      switch(state) {
      case 0: // First character must be a "("
        switch(c) {
        case '(':
          state = 1;
          break;
        default:
          throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
        }
        break;
      case 1: // parse characters
        switch(c) {
        case 'Z':
        case 'B':
        case 'S':
        case 'C':
        case 'I':
        case 'F':
          size++;
          break;
        case 'D':
        case 'J':
          size +=2;
          break;
        case '[':
          size++;
          state = 2; // go to parse array state
          break;
        case 'L':
          size++;
          state = 3; // go to parse object state
          break;
        case ')':
          state = 4; // go to end state.
          break;
        default:
          throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
        }
        break;
      case 2: // Parse array
        switch(c) {
        case 'L':
          state = 3;
        case '[':
          // remain in this state
          break;
        case 'Z':
        case 'B':
        case 'S':
        case 'C':
        case 'I':
        case 'F':
        case 'D':
        case 'J':
          state = 1; // go back to character parsing state
          break;
        default:
          throw new IllegalArgumentException("Bad character `"+c+"' in signature `"+signature+"' in state "+state);
        }
      case 3: // Parse object
        switch (c) {
        case ';':
          state = 1; // reached end of object descriptor. stop.
          break;
        default:
          // anything else is fair game.
        }
      case 4: // end state - return value remains - just ignore characters.
        break LOOP; // Exit the loop, we won't parse the return type.
      default:
        throw new IllegalStateException("In unexpected state "+state+ "in signature `"+signature+"'");
      }           
    }
   
    return size;
  }
 
  /**
   * Create a hash map that stores objects for quick retrieval later
   * @return A hashmap of objects
   */
  private HashMap<Long, JavaObject> generateObjectHashmap(){
    HashMap<Long, JavaObject> objectMap = new HashMap<Long, JavaObject>();
    return objectMap;
  }


  /**
   * Given an objectID, return the object associated with it.  Check the cache first.
   * @param objectID The unique ID of the object
   * @return The Kato JavaObject
   */
  private JavaObject getObject(long objectID){
    if (objectMap == null){
      this.objectMap = generateObjectHashmap();
    }
    JavaObject tmpObj = objectMap.get(objectID);
    if (tmpObj == null){
      //Last ditch attempt to try and get object
      //Sometimes an object is really a class.
      try{
        if (isClass(objectID)){
          logr.logError(JDILogger.LEVEL_VERBOSE, "  Object is really a class"); //$NON-NLS-1$
          return getClass(objectID).getObject();
        }
      }catch(Exception exxy){}
      tmpObj = getSlowObject(objectID);
      if (tmpObj != null){
        objectMap.put(tmpObj.getID().getAddress(), tmpObj);
      }else{
        logr.logError(JDILogger.LEVEL_VERBOSE, "  Error finding object " + objectID); //$NON-NLS-1$
      }

    }
    return tmpObj;
  }
 

  /**
   * Get the object associated with the ID
   * @param objectID The unique ID for that object
   * @return
   */
  private JavaObject getSlowObject(long objectID){
   
   
    Iterator asIt = image.getAddressSpaces( ).iterator();
    while ( asIt.hasNext( ) )
    {
      ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
      Iterator prIt = as.getProcesses( ).iterator();
      while ( prIt.hasNext( ) ){
        ImageProcess process = (ImageProcess) prIt.next( );

        Iterator runTimesIt = process.getRuntimes( ).iterator();
        while ( runTimesIt.hasNext( ) )
        {
          JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
          try {
            JavaObject jObject = javaRT.getObjectAtAddress(as.getPointer(objectID));
            if (jObject != null){
              return jObject;
            }
          } catch (CorruptDataException e) {
            //e.printStackTrace();
          } catch (IllegalArgumentException e) {
            //e.printStackTrace();
          } catch (MemoryAccessException e) {
            //e.printStackTrace();
          } catch (DataUnavailable e) {
            //e.printStackTrace();
          }
         
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "Could not find class directly, searching through heap");
         
          // Old method for returning java objects
          Iterator heapList = javaRT.getHeaps().iterator();

          while (heapList.hasNext()){
            JavaHeap heap = (JavaHeap) heapList.next();
            Iterator objectList = heap.getObjects().iterator();
            while (objectList.hasNext()){
              JavaObject jObject = (JavaObject)objectList.next();
              if (jObject.getID().getAddress() == objectID){
                return jObject;
              }
            }
          }

        }
      }
    }
    return null;
  }

  /**
   * Given a the name for a class, iterate through all the classes
   * @param name The name of the class to search
   * @return The Kato JavaClass result
   * @throws Exception
   */
  private JavaClass findClassByName(String name) throws Exception{
    Iterator<JavaClass> jClasses = classes.values().iterator();
    while(jClasses.hasNext()){
      JavaClass jClass = jClasses.next();
      if (name.equalsIgnoreCase(jClass.getName())){
        return jClass;
      }
    }
    return null;
  }

  /**
   * Take care of the objectReference command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */

  private ReplyPacket objectReference(CommandPacket cpckt) throws Exception{

    if (cpckt.getCommand() == 1){
      //ReferenceType
      //Return the ID (reference) of the object's class and type
      byte [] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.ReferenceType(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      //Search inside hashmap first
      if (objectMap.containsKey(object)){
        JavaObject jObject = getObject(object);
        if (jObject != null){
          try{
            int refTypeTag = 1;

            JavaClass jClass = jObject.getJavaClass();
            if (jClass == null){

              Vector<Byte> vctr = new Vector<Byte>();
              vctr.add((byte)1);
              logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  Cannot get class type, returning object instead"); //$NON-NLS-1$
              JavaClass jOutClass = findClassByName("java/lang/Object"); //$NON-NLS-1$

              addLongToVector(vctr, jOutClass.getID().getAddress());
              ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
              rpckt.setData(vectorToByte(vctr));
              logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  Cannot get class type"); //$NON-NLS-1$
              return rpckt; 
            }
            long typeID = jObject.getJavaClass().getID().getAddress();
            if (!classes.containsKey(typeID)){
              logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Client may not have classID");   //$NON-NLS-1$
            }
           

            if (jObject.isArray()){
              refTypeTag = 3;
            }else if(isInterface(typeID)){
              refTypeTag = 2;
            }
           
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  refTagType " + refTypeTag); //$NON-NLS-1$
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  name " + jObject.getJavaClass().getName() + "{"+jObject.getJavaClass().getID().getAddress()+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
           

            Vector<Byte> vctr = new Vector<Byte>();
            vctr.add((byte)refTypeTag);
            addLongToVector(vctr, typeID);
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }catch(CorruptDataException exxy){
            logr.logError(JDILogger.LEVEL_VERBOSE, "  Corrupt data!"); //$NON-NLS-1$
            Vector<Byte> vctr = new Vector<Byte>();
            vctr.add((byte)1);
            JavaClass jClass = findClassByName("java/lang/Object"); //$NON-NLS-1$

            addLongToVector(vctr, jClass.getID().getAddress());
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
            rpckt.setData(vectorToByte(vctr));
            return rpckt;           

          }
        }
      }else{

        JavaClass javaClass = getClass(object);
        if (javaClass != null){
          int refTypeTag = 1;
          long typeID = javaClass.getID().getAddress();

          Vector<Byte> vctr = new Vector<Byte>();
          vctr.add((byte)refTypeTag);
          addLongToVector(vctr, typeID);
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;
        }
       
        JavaObject jObject = getObject(object);
        if (jObject != null){
         
          // This is a copy from above, could be made into a method
         
         
          try{
            int refTypeTag = 1;

            JavaClass jClass = jObject.getJavaClass();
            if (jClass == null){
             
               logr.log(JDILogger.LEVEL_VERYVERBOSE, "Found the object the slow route");
              Vector<Byte> vctr = new Vector<Byte>();
              vctr.add((byte)1);
              JavaClass jOutClass = findClassByName("java/lang/Object"); //$NON-NLS-1$

              addLongToVector(vctr, jOutClass.getID().getAddress());
              ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
              rpckt.setData(vectorToByte(vctr));
              logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  Cannot get class type"); //$NON-NLS-1$
              return rpckt; 
            }
            long typeID = jObject.getJavaClass().getID().getAddress();
            if (!classes.containsKey(typeID)){
              logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Client may not have classID");   //$NON-NLS-1$
            }
           
            if (jObject.isArray()){
              refTypeTag = 3;
            }else if(isInterface(typeID)){
              refTypeTag = 2;
            }
           
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  refTagType " + refTypeTag); //$NON-NLS-1$
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  name " + jObject.getJavaClass().getName() + "{"+jObject.getJavaClass().getID().getAddress()+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$


            Vector<Byte> vctr = new Vector<Byte>();
            vctr.add((byte)refTypeTag);
            addLongToVector(vctr, typeID);
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }catch(CorruptDataException exxy){
            logr.logError(JDILogger.LEVEL_VERBOSE, "  Corrupt data!"); //$NON-NLS-1$
            Vector<Byte> vctr = new Vector<Byte>();
            vctr.add((byte)1);
            JavaClass jClass = findClassByName("java/lang/Object"); //$NON-NLS-1$

            addLongToVector(vctr, jClass.getID().getAddress());
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            exxy.printStackTrace(new PrintStream(logr.getErrorStream()));
            rpckt.setData(vectorToByte(vctr));
            return rpckt;           

          }
       
        }
      }

      logr.log(JDILogger.LEVEL_VERYVERBOSE, "No matches"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == 2){
      byte [] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      int fields = createIntFromBytes(inData, 8, 4);
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.GetValues(" + object + "," + fields + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      Vector<Byte> vctr = new Vector<Byte>();
      addIntToVector(vctr, fields);
      for (int i = 0; i < fields; i++){
        long fieldID = createLongFromBytes(inData, 12 + (8*i), 8);
        if (objectMap.containsKey(object)){
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  O:" + fieldID); //$NON-NLS-1$
          if (!getFieldFromObject(vctr, object, fieldID)){
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  O:" + fieldID+" Invalid Object/Field"); //$NON-NLS-1$
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
            return rpckt;

          }

        }else{
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  C:" + fieldID); //$NON-NLS-1$
          if (!getFieldFromClass(vctr, object, fieldID)){
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  O:" + fieldID+" Invalid Object/Field"); //$NON-NLS-1$
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
            return rpckt;
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;

    }else if (cpckt.getCommand() == 5){
      // Monitor information, assume JNIEnv is the same as threadID...
      byte[] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      Vector<Byte> vctr = new Vector<Byte>();
      JavaMonitor jm = null;
      logr.log(JDILogger.LEVEL_VERBOSE,"ObjectReference.MonitorInfo("+object+")");
      if ((jm = monitorMap.get(objectMap))!= null){
        JavaThread owningThread = jm.getOwner();
       
        if (owningThread != null){
          addLongToVector(vctr, owningThread.getJNIEnv().getAddress());
        }else{
          addLongToVector(vctr, 0);
        }
        addIntToVector(vctr, 1);
        addIntToVector(vctr, jm.getEnterWaiters().size());
        for (JavaThread thr : jm.getEnterWaiters()){
          addLongToVector(vctr, thr.getJNIEnv().getAddress());
        }
        logr.log(JDILogger.LEVEL_VERYVERBOSE,"  "+jm.getEnterWaiters().size()+" waiting and owner is "+owningThread);
      }else{
        addLongToVector(vctr, 0);
        addIntToVector(vctr, 0);
        addIntToVector(vctr, 0);
        logr.log(JDILogger.LEVEL_VERYVERBOSE,"  no monitor information");
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
     
    }else if (cpckt.getCommand() == 6){
      byte [] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      long thread = createLongFromBytes(inData, 8, 8);
      long clazz = createLongFromBytes(inData, 16, 8);
      long method = createLongFromBytes(inData, 24, 8);
      int arguments = createIntFromBytes(inData, 32, 4);
      Vector<Byte> vctr = new Vector<Byte>();
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.InvokeMethod(" + object + "," + thread + ","+clazz+","+method+","+arguments+",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
      if (!isClass(object)){
        JavaObject jObject = getObject(object);
        if (jObject != null){
          //
          JavaClass jClass = jObject.getJavaClass();
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  object: " + jClass.getName() + ">>" + jObject.getJavaClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
          vctr.add((byte)'s');
          this.vctrs.put(jObject.getID().getAddress(), jObject.getJavaClass().getName());
          addLongToVector(vctr, jObject.getID().getAddress());
          vctr.add((byte)0);
        }

      }else{

        JavaClass javaClass = getClass(clazz);
        if (javaClass != null){
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  class: " + javaClass.getName()); //$NON-NLS-1$

          vctr.add((byte)'s');

          this.vctrs.put(javaClass.getID().getAddress(), javaClass.getName());
          addLongToVector(vctr, javaClass.getID().getAddress());
          vctr.add((byte)0);

        }


      }
      if (vctr.size() > 0){
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt; 
      }

      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Invalid object");
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;


    }else if (cpckt.getCommand() == 7){
      byte [] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      JavaObject obj = getObject(object);
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.DisableCollection(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      if (obj != null){
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        return rpckt;
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == 8){
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.EnableCollection(" + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }else if (cpckt.getCommand() == 9){
      byte [] inData = cpckt.getByteData();
      long object = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "ObjectReference.IsCollected(" + object + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      JavaObject obj = getObject(object);
      if (obj != null){
        Vector<Byte> vctr = new Vector<Byte>();
        vctr.add((byte) 0);
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;


  }

  /**
   * Take care of the strignReference command set of the JDWP specs.
   * @param cpckt The incoming command packet request
   * @return The reply packet to be returned to the client
   * @throws Exception
   */

  private ReplyPacket stringReference(CommandPacket cpckt) throws Exception{

    if (cpckt.getCommand() == 1){
      byte[] inData = cpckt.getByteData();
      long stringObject = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "StringReference.Value("+stringObject+")"); //$NON-NLS-1$ //$NON-NLS-2$
     
      if (vctrs.containsKey(stringObject)){
        Vector<Byte> vctr = new Vector<Byte>();
        //Truncate down to int, and hope we don't have more than 2^32-1 objects
        addStringToVector(vctr, vctrs.get(stringObject));
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;
      }else{
        // This catches cases where we have not occupied vctrs with a string reference (added to support name labels on arrays of objects)
        JavaObject obj = getObject(stringObject);
        if (obj != null) {
          for (JavaField field : obj.getJavaClass()
              .getDeclaredFields()) {
            if (field.getSignature().equals("[C")) {
              JavaObject stringObj = (JavaObject) field.get(obj);
              char charArray[] = new char[stringObj
                  .getArraySize()];
             
              stringObj.arraycopy(0, charArray, 0, stringObj
                  .getArraySize());
             
             
              String stringRef = new String(charArray);
              Vector<Byte> vctr = new Vector<Byte>();
              addStringToVector(vctr, stringRef);
              ReplyPacket rpckt = new ReplyPacket(cpckt
                  .getSequence(), FLAG_REPLY_PACKET,
                  ERROR_NONE);
              vctrs.put(stringObject, stringRef);
              rpckt.setData(vectorToByte(vctr));
              return rpckt;

            }
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;
  }
 
 

  private ReplyPacket threadReference(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      //Lets name a thread!
      byte[] inData = cpckt.getByteData();
      long thread = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "ThreadReference.Name(" + thread + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();

            int count = 0;
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                count++;
                JavaThread thd = (JavaThread)tmpobj;
                if (thread == thd.getObject().getID().getAddress()){
                  Vector<Byte> vctr = new Vector<Byte>();
                  addStringToVector(vctr, thd.getName());
                  ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                  rpckt.setData(vectorToByte(vctr));
                  return rpckt;
                }
              }
            }
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_THREAD);
      return rpckt;
    }else if (cpckt.getCommand() == 2){
      logr.log(JDILogger.LEVEL_VERBOSE, "Suspend()"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }else if (cpckt.getCommand() == 3){
      logr.log(JDILogger.LEVEL_VERBOSE, "Resume()"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }else if (cpckt.getCommand() == 4){
      byte []inData = cpckt.getByteData();
      long thread = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Status("+thread+")"); //$NON-NLS-1$ //$NON-NLS-2$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            Vector<Byte> vctr = new Vector<Byte>();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                if (thd.getObject().getID().getAddress() == thread){
                  int threadStatus = 1;

                  logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread Status: "+thd.getState()); //$NON-NLS-1$
                  logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Thread Name: " + thd.getName()); //$NON-NLS-1$
                  if ((thd.getState() & JavaThread.STATE_TERMINATED) > 0){
                    threadStatus = 0;
                    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is terminated"); //$NON-NLS-1$
                  }else if ((thd.getState() & JavaThread.STATE_SLEEPING) > 0){
                    threadStatus = 2;
                    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is sleeping"); //$NON-NLS-1$
                  }else if ((thd.getState() & JavaThread.STATE_IN_OBJECT_WAIT) > 0 || (thd.getState() & JavaThread.STATE_WAITING) > 0 || (thd.getState() & JavaThread.STATE_WAITING_INDEFINITELY) > 0 || (thd.getState() & JavaThread.STATE_WAITING_WITH_TIMEOUT) > 0){
                    threadStatus = 4;
                    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is waiting"); //$NON-NLS-1$
                  }else if ((thd.getState() & JavaThread.STATE_BLOCKED_ON_MONITOR_ENTER) > 0){
                    threadStatus = 3;
                    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is monitor"); //$NON-NLS-1$
                  }else{
                    threadStatus = 1;
                    logr.log(JDILogger.LEVEL_VERBOSE, "Thread is other (running)"); //$NON-NLS-1$
                    if ((thd.getState() & JavaThread.STATE_ALIVE) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is alive"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_IN_NATIVE) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is in native"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_PARKED) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is parked"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_INTERRUPTED) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is interrupted"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_VENDOR_1) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 1"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_VENDOR_3) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 2"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_VENDOR_2) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is vendor 3"); //$NON-NLS-1$
                    }
                    if ((thd.getState() & JavaThread.STATE_RUNNABLE) > 0){
                      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread is runnable"); //$NON-NLS-1$
                    }


                  }
                  //The thread always starts in Eclipse as running
                  //Even if it isn't (See bug #161781)
                  int suspendStatus = 1;
                  threadStatus = 2;
                  addIntToVector(vctr, threadStatus);
                  addIntToVector(vctr, suspendStatus);
                  ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                  rpckt.setData(vectorToByte(vctr));
                  return rpckt;

                }
              }

            }



          }

        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == 5){

      //ThreadGroup
      //This call returns the group of the input thread.
      //TODO - Since this doesn't seem available in Kato, let's fake it with 0
      // Lets fake it with 1 ...
      byte [] inData = cpckt.getByteData();
      long thread = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "ThreadGroup("+thread+")"); //$NON-NLS-1$ //$NON-NLS-2$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      Vector<Byte> vctr = new Vector<Byte>();
      addLongToVector(vctr, 1);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == 6){
      //List all the frames from the thread

      byte []inData = cpckt.getByteData();
      long thread = createLongFromBytes(inData, 0, 8);
      int startFrame = createIntFromBytes(inData, 8, 4);
      int length = createIntFromBytes(inData, 12, 4);
      logr.log(JDILogger.LEVEL_VERBOSE, "Frames(" + thread + "," + startFrame + "," + length + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                if (thd.getObject().getID().getAddress() == thread){
                  int currentFrame = 0;
                  int count = 0;
                  Iterator frames = thd.getStackFrames().iterator();
                  Vector<Byte> vctr = new Vector<Byte>();
                  int count2 = 0;
                  while(frames.hasNext()){
                    count2++;
                    if (length > 0){
                      if (currentFrame >= startFrame && currentFrame <= startFrame + length){
                        JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                        addLongToVector(vctr, jStackFrame.getBasePointer().getAddress());

                        JavaLocation jLoc = jStackFrame.getLocation();

                        JavaMethod jMethod = jLoc.getMethod();

                        JavaClass jClass = jMethod.getDeclaringClass();

                        if (jClass.isArray()){
                          vctr.add((byte)3);
                        }else if(isInterface(jClass.getID().getAddress())){
                          vctr.add((byte)2);
                        }else{
                          vctr.add((byte)1);
                        }

                        addLongToVector(vctr, jClass.getID().getAddress());
                        addLongToVector(vctr, getMethodId(jClass.getID().getAddress(), jMethod));

                        //This is the current memory address.
                        addLongToVector(vctr, jLoc.getAddress().getAddress());
                        try{
                          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jLoc.getFilename() + "@" + jLoc.getMethod().getDeclaringClass().getName() + "{"+jLoc.getMethod().getDeclaringClass().getID().getAddress()+"}." + jLoc.getMethod().getName() + "{"+getMethodId(jClass.getID().getAddress(), jLoc.getMethod())+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
                          try{
                            logr.log(JDILogger.LEVEL_VERYVERBOSE, "    :" + jLoc.getLineNumber()); //$NON-NLS-1$
                          }catch(Exception exxy){
                          }

                        }catch (Exception exxy){}
                        count++;
                      }
                    }else{
                      if (currentFrame >= startFrame){
                        JavaStackFrame jStackFrame = (JavaStackFrame)frames.next();
                        addLongToVector(vctr, jStackFrame.getBasePointer().getAddress());

                        JavaLocation jLoc = jStackFrame.getLocation();

                        JavaMethod jMethod = jLoc.getMethod();

                        JavaClass jClass = jMethod.getDeclaringClass();
                        if (jClass.isArray()){
                          vctr.add((byte)3);
                        }else if(isInterface(jClass.getID().getAddress())){
                          vctr.add((byte)2);
                        }else{
                          vctr.add((byte)1);
                        }

                        addLongToVector(vctr, jClass.getID().getAddress());
                        addLongToVector(vctr, getMethodId(jClass.getID().getAddress(), jMethod));

                        //Location is 8 bytes (2 ints)
                        //We pad with 4 bytes of zeros
                        try{
                          addLongToVector(vctr, jLoc.getAddress().getAddress());
                        }
                        catch(Exception exxy){
                          addLongToVector(vctr, -1);
                        }
                        try{
                          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jLoc.getFilename() + "@" + jLoc.getMethod().getDeclaringClass().getName() + "{"+jLoc.getMethod().getDeclaringClass().getID().getAddress()+"}." + jLoc.getMethod().getName() + "{"+getMethodId(jClass.getID().getAddress(),jLoc.getMethod())+"}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
                          try{
                            logr.log(JDILogger.LEVEL_VERYVERBOSE, "    :" + jLoc.getLineNumber()); //$NON-NLS-1$
                          }catch(Exception exxy){
                          }

                        }catch (Exception exxy){}

                        count++;
                      }
                    }
                  }
                  logr.log(JDILogger.LEVEL_VERYVERBOSE, count + " frames found (of " +count2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$
                  ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                  addIntToVectorFront(vctr, count);
                  rpckt.setData(vectorToByte(vctr));
                  return rpckt;

                }
              }
            }
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == 7){
      //List all the frames from the thread

      byte []inData = cpckt.getByteData();
      long thread = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "FrameCount(" + thread + ")"); //$NON-NLS-1$ //$NON-NLS-2$

      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                if (thd.getObject().getID().getAddress() == thread){
                  int count = 0;
                  Iterator frames = thd.getStackFrames().iterator();
                  Vector<Byte> vctr = new Vector<Byte>();
                  while(frames.hasNext()){
                    frames.next();
                    count++;
                  }
                  logr.log(JDILogger.LEVEL_VERYVERBOSE, count + " frames found"); //$NON-NLS-1$
                  ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                  addIntToVector(vctr, count);
                  rpckt.setData(vectorToByte(vctr));
                  return rpckt;

                }
              }
            }
          }
        }
      }
      logr.log(JDILogger.LEVEL_VERBOSE, "0 frames and no thread found"); //$NON-NLS-1$
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if(cpckt.getCommand() == 8){
      // Monitor information
      byte[] inData = cpckt.getByteData();
      long threadID = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Thread.OwnedMonitors(" + threadID + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      List<JavaObject> ownedMonitors = new ArrayList<JavaObject>();
      for (JavaMonitor jm : monitorMap.values()){
        JavaThread thr;
        if ((thr = jm.getOwner())!= null){
          if (thr.getJNIEnv().getAddress() == threadID){
            ownedMonitors.add(jm.getObject());
          }
        }
      }
      Vector<Byte> vctr = new Vector<Byte>();
      addIntToVector(vctr, ownedMonitors.size());
      for (JavaObject obj: ownedMonitors){
        vctr.add((byte)TAG_OBJECT);
        addLongToVector(vctr, obj.getID().getAddress());
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Owns "+obj.getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if(cpckt.getCommand() == 9){
      // Monitor information
      byte[] inData = cpckt.getByteData();
      long threadID = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "Thread.CurrentContendedMonitors(" + threadID + ")"); //$NON-NLS-1$ //$NON-NLS-2$
      JavaMonitor contended = null;
      for (JavaMonitor jm : monitorMap.values()){
        for (JavaThread thr: jm.getEnterWaiters()){
          if (thr.getJNIEnv().getAddress() == threadID){
            contended = jm;
          }
        }
      }
     
     
      Vector<Byte> vctr = new Vector<Byte>();
      if (contended == null){
        addLongToVector(vctr, 0);
      }else{
        addIntToVector(vctr, (byte)TAG_OBJECT);
        addLongToVector(vctr, contended.getObject().getID().getAddress());
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Contended on "+contended.getObject().getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
     
    }else if(cpckt.getCommand() == 12){
      logr.log(JDILogger.LEVEL_VERBOSE, "SuspendCount()"); //$NON-NLS-1$
      Vector<Byte> vctr = new Vector<Byte>();
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      addIntToVector(vctr, 1);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }

  private ReplyPacket arrayReference(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      byte [] inData = cpckt.getByteData();
      long arrayObject = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "ArrayReference.Length("+arrayObject+")"); //$NON-NLS-1$ //$NON-NLS-2$
      JavaObject jObject = getObject(arrayObject);
      if (jObject != null){
        ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
        Vector<Byte> vctr = new Vector<Byte>();
        addIntToVector(vctr, jObject.getArraySize());
        logr.log(JDILogger.LEVEL_VERBOSE, "  " + arrayObject + " Has length " + jObject.getArraySize()); //$NON-NLS-1$ //$NON-NLS-2$
        //addIntToVector(vctr, 0);
        rpckt.setData(vectorToByte(vctr));
        return rpckt;

      }


      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }else if (cpckt.getCommand() == 2){
      byte [] inData = cpckt.getByteData();
      long arrayObject = createLongFromBytes(inData, 0, 8);
      int firstIndex = createIntFromBytes(inData, 8, 4);
      int length = createIntFromBytes(inData, 12, 4);
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "ArrayReference.GetValues("+arrayObject+","+firstIndex+","+length+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
      JavaObject jObject = getObject(arrayObject);
      if (jObject != null){
        if (!jObject.isArray()){
          logr.logError(JDILogger.LEVEL_VERYVERBOSE, "  Not actually an array"); //$NON-NLS-1$
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
          return rpckt;
        }
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "  array type: " + jObject.getJavaClass().getName()); //$NON-NLS-1$
        if (jObject.getJavaClass().getName().equals("[I")){ //$NON-NLS-1$
          int []jObjs = new int[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);
          if (jObjs != null){
            Vector<Byte> vctr = new Vector<Byte>();
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$

            vctr.add((byte)'I');
            addIntToVector(vctr, jObjs.length);

            for(int i = 0; i < jObjs.length; i++){
              addIntToVector(vctr, jObjs[i]);

              logr.log(JDILogger.LEVEL_VERYVERBOSE, "  " + jObjs[i]);   //$NON-NLS-1$
            }
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }
        }else if (jObject.getJavaClass().getName().equals("[F")){ //$NON-NLS-1$
          float []jObjs = new float[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);
          if (jObjs != null){
            Vector<Byte> vctr = new Vector<Byte>();
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
            vctr.add((byte)'F');
            addIntToVector(vctr, jObjs.length);
            for(int i = 0; i < jObjs.length; i++){
              addIntToVector(vctr, Float.floatToIntBits(jObjs[i]));

            }
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }

        }else if (jObject.getJavaClass().getName().equals("[S")){ //$NON-NLS-1$
          short []jObjs = new short[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);
          if (jObjs != null){
            Vector<Byte> vctr = new Vector<Byte>();
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
            vctr.add((byte)'S');
            addIntToVector(vctr, jObjs.length);
            for(int i = 0; i < jObjs.length; i++){
              vctr.add((byte)((jObjs[i] >> 8) & 0xFF));
              vctr.add((byte)(jObjs[i] & 0xFF));

            }
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }

        }else if (jObject.getJavaClass().getName().equals("[J")){ //$NON-NLS-1$
          long []jObjs = new long[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);
          if (jObjs != null){
            Vector<Byte> vctr = new Vector<Byte>();
            logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
            vctr.add((byte)'J');
            addIntToVector(vctr, jObjs.length);
            for(int i = 0; i < jObjs.length; i++){
              addLongToVector(vctr, jObjs[i]);

            }
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            rpckt.setData(vectorToByte(vctr));
            return rpckt;
          }

        }else if (jObject.getJavaClass().getName().equals("[B")){ //$NON-NLS-1$
          byte []jObjs = new byte[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);

          Vector<Byte> vctr = new Vector<Byte>();
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
          vctr.add((byte)'B');
          addIntToVector(vctr, jObjs.length);
          for(int i = 0; i < jObjs.length; i++){
            vctr.add(jObjs[i]);

          }
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;


        }else if (jObject.getJavaClass().getName().equals("[Z")){ //$NON-NLS-1$
          byte []jObjs = new byte[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);

          Vector<Byte> vctr = new Vector<Byte>();
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
          vctr.add((byte)'Z');
          addIntToVector(vctr, jObjs.length);
          for(int i = 0; i < jObjs.length; i++){
            vctr.add(jObjs[i]);

          }
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;


        }else if (jObject.getJavaClass().getName().equals("[D")){ //$NON-NLS-1$
          double []jObjs = new double[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);

          Vector<Byte> vctr = new Vector<Byte>();
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
          vctr.add((byte)'D');
          addIntToVector(vctr, jObjs.length);
          for(int i = 0; i < jObjs.length; i++){
            addLongToVector(vctr, Double.doubleToLongBits(jObjs[i]));

          }
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;


        }else if (jObject.getJavaClass().getName().equals("[C")){ //$NON-NLS-1$
          char []jObjs = new char[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);

          Vector<Byte> vctr = new Vector<Byte>();
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + " objects"); //$NON-NLS-1$ //$NON-NLS-2$
          vctr.add((byte)'C');
          addIntToVector(vctr, jObjs.length);
          for(int i = 0; i < jObjs.length; i++){
            vctr.add((byte)((jObjs[i] >> 8) & 0xFF));
            vctr.add((byte)(jObjs[i] & 0xFF));

          }
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;


        } else{
          JavaObject []jObjs = new JavaObject[length];
          jObject.arraycopy(firstIndex, jObjs, 0, length);

          logr.log(JDILogger.LEVEL_VERYVERBOSE, "  got " + jObjs.length + "objects"); //$NON-NLS-1$ //$NON-NLS-2$
          Vector<Byte> vctr = new Vector<Byte>();
       
          vctr.add((byte)TAG_ARRAY);
         
          addIntToVector(vctr, jObjs.length);
         
          byte arrayTagType = (byte)TAG_OBJECT;
         
          String arrayName = jObject.getJavaClass().getName();
          if (arrayName.equals("[Ljava/lang/String;")){
            arrayTagType = (byte)TAG_STRING;
          }else if ( arrayName.charAt(1) == '['){
            arrayTagType = (byte)TAG_ARRAY;
          }
         
          for(int i = 0; i < jObjs.length; i++){
            // Also check if it is an array of interfaces
            if (jObjs[i] != null){
              vctr.add(arrayTagType);
              addLongToVector(vctr, jObjs[i].getID().getAddress());
              logr.log(JDILogger.LEVEL_VERYVERBOSE, "  jObjs["+i+"] address " + jObjs[i].getID().getAddress()); //$NON-NLS-1$ //$NON-NLS-2$
              logr.log(JDILogger.LEVEL_VERYVERBOSE, "  jObjs["+i+"] type " + jObjs[i].getJavaClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
              if (!objectMap.containsKey(jObjs[i].getID().getAddress())){
                objectMap.put(jObjs[i].getID().getAddress(), jObjs[i]);
              }
              if (!classes.containsKey(jObjs[i].getJavaClass().getID().getAddress())){
                logr.log(JDILogger.LEVEL_VERYVERBOSE, "  Class is not of registered type"); //$NON-NLS-1$
              }
            }else{
              vctr.add((byte)TAG_OBJECT);
              addLongToVector(vctr, 0);
            }
          }
          ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
          rpckt.setData(vectorToByte(vctr));
          return rpckt;

        }


      }

      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;

    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }

  private ReplyPacket eventRequest(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      byte [] inData = cpckt.getByteData();
      int eventKind = inData[0];
      int suspendPolicy = inData[1];
      int modifiers = createIntFromBytes(inData, 2, 4);
      logr.log(JDILogger.LEVEL_VERYVERBOSE, "Set("+eventKind+","+suspendPolicy+","+modifiers+", ...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
      for (int i = 0; i < modifiers; i++){
        int modKind = inData[6 + (6*i)];
        logr.log(JDILogger.LEVEL_VERYVERBOSE, "Set(Modkind"+modKind+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        if (modKind == 5){
          String classPattern = getStringFromBytes(inData, 6 + (6*i) + 1);
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "ClassMatch(\"" + classPattern + "\")"); //$NON-NLS-1$ //$NON-NLS-2$
        }else{
          logr.log(JDILogger.LEVEL_VERYVERBOSE, "modKind: " + modKind); //$NON-NLS-1$
        }


      }
      ReplyPacket rpckt;
      if (eventKind == 8){
        rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_CLASS);
        return rpckt;
      }else{
       
      }
      rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      Vector<Byte> vctr = new Vector<Byte>();
      addIntToVector(vctr, LAST_ID++);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }else if (cpckt.getCommand() == 2){
      logr.log(JDILogger.LEVEL_VERBOSE, "Ignoring event request");
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }

  private ReplyPacket stackFrame(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      byte []inData = cpckt.getByteData();
      long threadID = createLongFromBytes(inData, 0, 8);
      long frameID = createLongFromBytes(inData, 8, 8);
      int slots = createIntFromBytes(inData, 16, 4);
      logr.log(JDILogger.LEVEL_VERBOSE, "StackFrame.GetValues(" + threadID + "," + frameID + "," + slots + ",...)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
      Vector<Byte> vctr = new Vector<Byte>();
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      addIntToVector(vctr, slots);
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                if (thd.getObject().getID().getAddress() == threadID){
                  Iterator frames = thd.getStackFrames().iterator();

                  while(frames.hasNext()){
                    JavaStackFrame jFrame = (JavaStackFrame)frames.next();
                    if (jFrame.getBasePointer().getAddress() == frameID){
//                      vctr.add((byte)'L');
//                      addLongToVector(vctr,jFrame.getLocation().getMethod().getDeclaringClass().getID().getAddress());
//                      logr.log(JDILogger.LEVEL_VERBOSE, "  " + jFrame.getLocation().getMethod().getDeclaringClass().getID().getAddress()); //$NON-NLS-1$
                      // Get slot number and type of each requested variable.                     
GETVALUESLOTS:                for (int i=0; i < slots; i++) {
                        int slot = createIntFromBytes(inData, 20+5*i, 4);
                        byte type = inData[20+5*i+4];
                       
                        Object value = jFrame.getVariable(slot);
                        logr.log(JDILogger.LEVEL_VERYVERBOSE, "OBJECT("+value+")");
                        switch(type) {
                        case TAG_ARRAY:
                          long arrayAddress = 0L;
                          vctr.add((byte)TAG_ARRAY);
                          if (value instanceof JavaObject) {
                            JavaObject obj = (JavaObject) value;                           
                            if (obj.isArray()) {
                              arrayAddress = obj.getID().getAddress();                                                                                             
                            }
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " Array in slot=" + slot + " value="+arrayAddress);
                          addLongToVector(vctr, arrayAddress );
                          break;
                        case TAG_BYTE:
                          byte byteVal = -1;
                          vctr.add((byte)TAG_BYTE);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            byteVal = num.byteValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " byte in slot=" + slot + " value="+byteVal);
                          vctr.add(byteVal);
                          break;
                        case TAG_CHAR:
                          char charVal = (char) -1;
                          vctr.add((byte)TAG_CHAR);
                          if (value instanceof Character) {                           
                            charVal = (Character) value;
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " byte in slot=" + slot + " value="+charVal);
                          addCharToVector(vctr, charVal);
                          break;
                        case TAG_OBJECT:
                          long objectAddress = 0L;
                          byte typeTag = (byte)TAG_OBJECT;
                         
                          if (value instanceof JavaObject) {
                            JavaObject obj = (JavaObject) value;                           
                            objectAddress = obj.getID().getAddress();   
                            if (obj != null){
                              if (obj.getJavaClass().getName().equals("java/lang/String")){
                                typeTag = (byte)TAG_STRING;
                              }
                            }
                          }
                          vctr.add(typeTag);
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " Object in slot=" + slot + " value="+objectAddress);
                          addLongToVector(vctr, objectAddress );
                          break
                        case TAG_FLOAT:
                          float floatVal = -1;
                          vctr.add((byte)TAG_FLOAT);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            floatVal = num.floatValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " float in slot=" + slot + " value="+floatVal);
                          addIntToVector(vctr, Float.floatToIntBits(floatVal));
                          break;
                        case TAG_DOUBLE:
                          double doubleVal = -1;
                          vctr.add((byte)TAG_DOUBLE);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            doubleVal = num.doubleValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " double in slot=" + slot + " value="+doubleVal);
                          addLongToVector(vctr, Double.doubleToLongBits(doubleVal));
                         
                          break;
                        case TAG_INT:
                          int intVal = -1;
                          vctr.add((byte)TAG_INT);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            intVal = num.intValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " int in slot=" + slot + " value="+intVal);
                          addIntToVector(vctr, intVal);
                          break;
                        case TAG_LONG:
                          long longVal = -1;
                          vctr.add((byte)TAG_LONG);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            longVal = num.longValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " long in slot=" + slot + " value="+longVal);
                          addLongToVector(vctr, longVal);
                         
                          break;
                        case TAG_SHORT:
                          short shortVal = -1;
                          vctr.add((byte)TAG_SHORT);
                          if (value instanceof Number) {
                            Number num = (Number) value;
                            shortVal = num.shortValue();
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " short in slot=" + slot + " value="+shortVal);
                          addShortToVector(vctr, shortVal);
                         
                          break;
                        case TAG_BOOLEAN:
                          boolean booleanVal = false;
                          vctr.add((byte)TAG_BOOLEAN);
                          if (value instanceof Boolean) {
                            booleanVal = ((Boolean) value);
                          }
                         
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " boolean in slot=" + slot + " value="+booleanVal);
                         
                          vctr.add(booleanVal ? (byte) 1 : (byte) 0);
                          break;
                        case TAG_STRING:
                          String stringVal= "";
                          vctr.add((byte)TAG_STRING);
                          if (value instanceof JavaObject) {
                            stringVal = javaObjectToString( (JavaObject) value);
                          }
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " string in slot=" + slot + " value=\""+stringVal+"\"");
                          addStringToVector(vctr, stringVal);                         
                          break;
                        default:
                          logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " unable to handle type "+type+" in "+jFrame.getLocation());
                          rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                          vctr = new Vector<Byte>();
                          break GETVALUESLOTS;
                        }
                       
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      rpckt.setData(vectorToByte(vctr));
      return rpckt;



    }else if (cpckt.getCommand() == 3){
      byte []inData = cpckt.getByteData();
      long threadID = createLongFromBytes(inData, 0, 8);
      long frameID = createLongFromBytes(inData, 8, 8);
      //TODO - Get this to work
      logr.log(JDILogger.LEVEL_VERBOSE, "ThisObject(" + threadID + "," + frameID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                JavaThread thd = (JavaThread) tmpobj;
                if (thd.getObject().getID().getAddress() == threadID){
                  Iterator frames = thd.getStackFrames().iterator();

                  while(frames.hasNext()){
                    JavaStackFrame jFrame = (JavaStackFrame)frames.next();
                    if (jFrame.getBasePointer().getAddress() == frameID){
                      Vector<Byte> vctr = new Vector<Byte>();
                      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
                     
                      if ((jFrame.getLocation().getMethod().getModifiers() & Modifier.STATIC) !=0) {
                        addLongToVector(vctr, 0); // Return null as static method.
                      } else {
                        Object value = jFrame.getVariable(0);
                        long objectAddress = 0;
                        if (value != null  && value instanceof JavaObject) {
                          JavaObject obj = (JavaObject) value;                           
                          objectAddress = obj.getID().getAddress();                                                                                             
                        }
                        vctr.add((byte)TAG_OBJECT);
                        logr.log(JDILogger.LEVEL_VERBOSE, "  " +jFrame.getLocation() + " return this object value="+objectAddress+" "+value);
                        addLongToVector(vctr, objectAddress );
                      }
                      rpckt.setData(vectorToByte(vctr));
                      return rpckt;
                    }
                  }


                }
              }
            }
          }
        }
      }
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_INVALID_OBJECT);
      return rpckt;
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;

  }
 
  private byte getRefTypeTag(JavaClass jcl){
    byte refTypeTag = 1;
    try {
      if (jcl.isArray()){
        refTypeTag = 3;
      }else if(isInterface(jcl.getID().getAddress())){
        refTypeTag = 2;
      }
    } catch (CorruptDataException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return refTypeTag;
  }
 
  private ReplyPacket classLoaderRef(CommandPacket cpckt) throws Exception{
    if (cpckt.getCommand() == 1){
      byte []inData = cpckt.getByteData();
      long classLoaderID = createLongFromBytes(inData, 0, 8);
      logr.log(JDILogger.LEVEL_VERBOSE, "VisibleClasses(" + classLoaderID + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
      int count = 0;
      Vector<Byte> vctr = new Vector<Byte>();
      Vector<JavaClassLoader> jcls = new Vector<JavaClassLoader>();
      for (JavaClass jc: classes.values()){
        JavaObject obj;
        if ((obj = jc.getClassLoader().getObject()) != null){
          if (obj.getID().getAddress() == classLoaderID){
            jcls.add(jc.getClassLoader());
            jc = jc.getClassLoader().getObject().getJavaClass();
            while (jc.getClassLoader()!= null){
              jcls.add(jc.getClassLoader());
              jc = jc.getClassLoader().getObject().getJavaClass();
            }
            break;
          }
        }
      }
     
      for (JavaClass jc: classes.values()){
        for (JavaClassLoader jcl : jcls){
          if (jc.getClassLoader() == jcl){
            vctr.add(getRefTypeTag(jc));
            addLongToVector(vctr, jc.getID().getAddress());
            count++;
          }
        }
      }
      addIntToVectorFront(vctr, count);
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    }
    return null;
  }

  private ReplyPacket threadGroupReference(CommandPacket cpckt) throws Exception{
   
    if (cpckt.getCommand() == 1){
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      Vector<Byte> vctr = new Vector<Byte>();
      addStringToVector(vctr, "All threads");
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    } else if (cpckt.getCommand() == 2){
      ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
      Vector<Byte> vctr = new Vector<Byte>();
      addLongToVector(vctr, 0);
      rpckt.setData(vectorToByte(vctr));
      return rpckt;
    } else if (cpckt.getCommand() == 3){
      logr.log(JDILogger.LEVEL_VERBOSE, "Returning all threads as single group"); //$NON-NLS-1$
      Iterator asIt = image.getAddressSpaces( ).iterator();
      while ( asIt.hasNext( ) )
      {
        ImageAddressSpace as = (ImageAddressSpace) asIt.next( );
        Iterator prIt = as.getProcesses( ).iterator();

        while ( prIt.hasNext( ) )
        {
          ImageProcess process = (ImageProcess) prIt.next( );
          Iterator runTimesIt = process.getRuntimes( ).iterator();
          while ( runTimesIt.hasNext( ) )
          {
            JavaRuntime javaRT = (JavaRuntime) runTimesIt.next( );
            Iterator thds = javaRT.getThreads().iterator();
            Vector<Byte> vctr = new Vector<Byte>();
            int count = 0;
            while(thds.hasNext()){
              Object tmpobj = thds.next();
              if (tmpobj instanceof CorruptData){
                //ignore this thread
              }else{
                count++;
                JavaThread thd = (JavaThread)tmpobj;
                long hash = thd.getObject().getID().getAddress();
                logr.log(JDILogger.LEVEL_VERYVERBOSE, "Thread hash " + thd.getName() + " is " + hash + " id is "+thd.getObject().getID()) ; //$NON-NLS-1$ //$NON-NLS-2$
                addLongToVector(vctr, hash);
              }

            }
            addIntToVectorFront(vctr, count);
            addIntToVector(vctr, 0);
            ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NONE);
            byte []barray2 = vectorToByte(vctr);
            rpckt.setData(barray2);
            return rpckt;


          }

        }
      }
    }
    logr.log(JDILogger.LEVEL_VERYVERBOSE, "Unknown command "+cpckt.getCommandSet()+" "+cpckt.getCommand());
    ReplyPacket rpckt = new ReplyPacket(cpckt.getSequence(), FLAG_REPLY_PACKET, ERROR_NOT_IMPLEMENTED);
    return rpckt;
  }

  public boolean isOk(){
    return (errorCode == 0);
  }

  public void stop(){
    shutDownKato();
  }

  private void shutDownKato(){
    vctrs.clear();
    intToMethod.clear();
    classes.clear();
    intToMethod.clear();
    methodToInt.clear();
    fieldList.clear();
    objectMap.clear();

    image = null;
    vctrs = null;
    classes = null;
    intToMethod = null;
    methodToInt = null;
    fieldList = null;
    objectMap = null;

  }


}
TOP

Related Classes of org.apache.kato.tools.jdi.KatoReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.