JdwpPacket.java :  » IDE-Eclipse » jdt » org » eclipse » jdi » internal » jdwp » Java Open Source

Java Open Source » IDE Eclipse » jdt 
jdt » org » eclipse » jdi » internal » jdwp » JdwpPacket.java
/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdi.internal.jdwp;


import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * This class implements the corresponding Java Debug Wire Protocol (JDWP) packet
 * declared by the JDWP specification.
 *
 */
public abstract class JdwpPacket {
  /** General JDWP constants. */
  public static final byte FLAG_REPLY_PACKET = (byte)0x80;
  protected static final int MIN_PACKET_LENGTH = 11;
  
  /** Map with Strings for flag bits. */
  private static String[] fgFlagStrings = null;

  /** Header fields. */
  protected int fId = 0;
  protected byte fFlags = 0;
  protected byte[] fDataBuf = null;
  
  /**
   * Set Id.
   */
  /*package*/ void setId(int id) {
    fId = id;
  }

  /**
   * @return Returns Id.
   */
  public int getId() {
    return fId;
  }
  
  /**
   * Set Flags.
   */
  /*package*/ void setFlags(byte flags) {
    fFlags = flags;
  }
  
  /**
   * @return Returns Flags.
   */
  public byte getFlags() {
    return fFlags;
  }

  /**
   * @return Returns total length of packet.
   */
  public int getLength() {
    return MIN_PACKET_LENGTH + getDataLength();
  }
  
  /**
   * @return Returns length of data in packet.
   */
  public int getDataLength() {
    return fDataBuf == null ? 0 : fDataBuf.length;
  }
  
  /**
   * @return Returns data of packet.
   */
  public byte[] data() {
    return fDataBuf;
  }

  /**
   * @return Returns DataInputStream with reply data, or an empty stream if there is none.
   */
  public DataInputStream dataInStream() {
    if (fDataBuf != null) {
      return new DataInputStream(new ByteArrayInputStream(fDataBuf));
    }
    
    return new DataInputStream(new ByteArrayInputStream(new byte[0]));
  }

  /**
   * Assigns data to packet.
   */
  public void setData(byte[] data) {
    fDataBuf = data;
  }
  
  /**
   * Reads header fields that are specific for a type of packet.
   */
  protected abstract int readSpecificHeaderFields(byte[] bytes, int index) throws IOException;
  
  /**
   * Writes header fields that are specific for a type of packet.
   */
  protected abstract int writeSpecificHeaderFields(byte[] bytes, int index) throws IOException;
  
  /**
   * Constructs a JdwpPacket from a byte[].
   */
  public static JdwpPacket build(byte[] bytes) throws IOException {
    // length (int)
        int a = (bytes[0]&0xff) << 24;
        int b = (bytes[1]&0xff) << 16;
        int c = (bytes[2]&0xff) << 8;
        int d = (bytes[3]&0xff) << 0;
    int packetLength = a+b+c+d;

    // id (int)
    a = (bytes[4]&0xff) << 24;
    b = (bytes[5]&0xff) << 16;
    c = (bytes[6]&0xff) << 8;
    d = (bytes[7]&0xff) << 0;
    int id = a+b+c+d;

    // flags (byte)
    byte flags = bytes[8];

    // Determine type: command or reply.
    JdwpPacket packet;
    if ((flags & FLAG_REPLY_PACKET) != 0)
      packet = new JdwpReplyPacket();
    else
      packet = new JdwpCommandPacket();
      
    // Assign generic header fields.
    packet.setId(id);
    packet.setFlags(flags);
      
    // Read specific header fields and data.
    int index = 9;
    index += packet.readSpecificHeaderFields(bytes, 9);
    if (packetLength - MIN_PACKET_LENGTH > 0) {
      packet.fDataBuf = new byte[packetLength - MIN_PACKET_LENGTH];
      System.arraycopy(bytes, index, packet.fDataBuf, 0, packet.fDataBuf.length);
    }
    
    return packet;
  }
  
  public byte[] getPacketAsBytes() throws IOException {
      int len = getLength();
      byte[] bytes = new byte[len];
      
      //convert len to bytes
        bytes[0] = (byte) (len >>> 24);
        bytes[1] = (byte) (len >>> 16);
        bytes[2] = (byte) (len >>>  8);
        bytes[3] = (byte) (len >>>  0);
        
        //convert id to bytes
        int id = getId();
        bytes[4] = (byte) (id >>> 24);
        bytes[5] = (byte) (id >>> 16);
        bytes[6] = (byte) (id >>>  8);
        bytes[7] = (byte) (id >>>  0);
        
        //flags
        bytes[8] = getFlags();
        
        //convert specific header fields
        int index = 9;
        index += writeSpecificHeaderFields(bytes, index);
        
        if (index < len && fDataBuf!=null) {
            //copy data
            System.arraycopy(fDataBuf, 0, bytes, index, fDataBuf.length);
        }
        return bytes;
  }

  /**
   * Retrieves constant mappings.
   */
  public static void getConstantMaps() {
    if (fgFlagStrings != null) {
      return;
    }
    
    Field[] fields = JdwpPacket.class.getDeclaredFields();
    fgFlagStrings = new String[8];
    
    for (int i = 0; i < fields.length; i++) {
      Field field = fields[i];
      if ((field.getModifiers() & Modifier.PUBLIC) == 0 || (field.getModifiers() & Modifier.STATIC) == 0 || (field.getModifiers() & Modifier.FINAL) == 0) {
        continue;
      }
        
      String name = field.getName();
      if (!name.startsWith("FLAG_")) {//$NON-NLS-1$
        continue;
      }
        
      name = name.substring(5);
      
      try {
        byte value = field.getByte(null);
        
        for (int j = 0; j < fgFlagStrings.length; j++) {
          if ((1 << j & value) != 0) {
            fgFlagStrings[j]= name;
            break;
          }
        }
      } catch (IllegalAccessException e) {
        // Will not occur for own class.
      } catch (IllegalArgumentException e) {
        // Should not occur.
        // We should take care that all public static final constants
        // in this class are bytes.
      }
    }
  }
  
  /**
   * @return Returns a mapping with string representations of flags.
   */
  public static String[] getFlagMap() {
    getConstantMaps();
    return fgFlagStrings;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.