/* PacketProcessor.java -- a thread which processes command packets
   from the debugger
   Copyright (C) 2005, 2006 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.classpath.jdwp.processor;

import gnu.classpath.jdwp.Jdwp;
import gnu.classpath.jdwp.JdwpConstants;
import gnu.classpath.jdwp.exception.JdwpException;
import gnu.classpath.jdwp.transport.JdwpCommandPacket;
import gnu.classpath.jdwp.transport.JdwpConnection;
import gnu.classpath.jdwp.transport.JdwpPacket;
import gnu.classpath.jdwp.transport.JdwpReplyPacket;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.PrivilegedAction;

/**
 * This class is responsible for processing packets from the
 * debugger. It waits for an available packet from the connection
 * ({@link gnu.classpath.jdwp.transport.JdwpConnection}) and then
 * processes the packet and any reply.
 *
 * @author Keith Seitz (keiths@redhat.com)
 */
public class PacketProcessor
  implements PrivilegedAction
{
  // The connection to the debugger
  private JdwpConnection _connection;
  
  // Shutdown this thread?
  private boolean _shutdown;
  
  // A Mapping of the command set (Byte) to the specific CommandSet
  private CommandSet[] _sets;

  // Contents of the ReplyPackets data field
  private ByteArrayOutputStream _outputBytes;

  // Output stream around _outputBytes
  private DataOutputStream _os;
  
  /**
   * Constructs a new <code>PacketProcessor</code> object
   * Connection must be validated before getting here!
   *
   * @param con  the connection
   */
  public PacketProcessor (JdwpConnection con)
  {
    _connection = con;
    _shutdown = false;
    
    // MAXIMUM is the value of the largest command set we may receive 
    _sets = new CommandSet[JdwpConstants.CommandSet.MAXIMUM + 1];
    _outputBytes = new ByteArrayOutputStream();
    _os = new DataOutputStream (_outputBytes);

    // Create all the Command Sets and add them to our array
    _sets[JdwpConstants.CommandSet.VirtualMachine.CS_VALUE] =
      new VirtualMachineCommandSet();
    _sets[JdwpConstants.CommandSet.ReferenceType.CS_VALUE] =
      new ReferenceTypeCommandSet();
    _sets[JdwpConstants.CommandSet.ClassType.CS_VALUE] =
      new ClassTypeCommandSet();
    _sets[JdwpConstants.CommandSet.ArrayType.CS_VALUE] =
      new ArrayTypeCommandSet();
    _sets[JdwpConstants.CommandSet.InterfaceType.CS_VALUE] =
      new InterfaceTypeCommandSet();
    _sets[JdwpConstants.CommandSet.Method.CS_VALUE] =
      new MethodCommandSet();
    _sets[JdwpConstants.CommandSet.Field.CS_VALUE] =
      new FieldCommandSet();
    _sets[JdwpConstants.CommandSet.ObjectReference.CS_VALUE] =
      new ObjectReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.StringReference.CS_VALUE] =
      new StringReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.ThreadReference.CS_VALUE] =
      new ThreadReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.ThreadGroupReference.CS_VALUE] =
      new ThreadGroupReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.ArrayReference.CS_VALUE] =
      new ArrayReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.ClassLoaderReference.CS_VALUE] =
      new ClassLoaderReferenceCommandSet();
    _sets[JdwpConstants.CommandSet.EventRequest.CS_VALUE] =
      new EventRequestCommandSet();
    _sets[JdwpConstants.CommandSet.StackFrame.CS_VALUE] =
      new StackFrameCommandSet();
    _sets[JdwpConstants.CommandSet.ClassObjectReference.CS_VALUE] =
      new ClassObjectReferenceCommandSet();
  }
  
  /**
   * Main run routine for this thread. Will loop getting packets
   * from the connection and processing them.
   */
  public Object run ()
  {
    // Notify initialization thread (gnu.classpath.jdwp.Jdwp) that
    // the PacketProcessor thread is ready.
    Jdwp.getDefault().subcomponentInitialized ();
	
    try
      {
        while (!_shutdown)
          {
            _processOnePacket ();
          }
      }
    catch (Exception ex)
      {
        ex.printStackTrace();
      }
    // Time to shutdown, tell Jdwp to shutdown
    Jdwp.getDefault().shutdown();
    return null;
  }
  
  /**
   * Shutdown the packet processor
   */
  public void shutdown ()
  {
    _shutdown = true;
  }
  
  // Helper function which actually does all the work of waiting
  // for a packet and getting it processed.
  private void _processOnePacket ()
    throws IOException
  {
    JdwpPacket pkt = _connection.getPacket ();
    
    if (!(pkt instanceof JdwpCommandPacket))
      {
        // We're not supposed to get these from the debugger!
        // Drop it on the floor
        return;
      }
    
    if (pkt != null)
      {
        JdwpCommandPacket commandPkt = (JdwpCommandPacket) pkt;
        JdwpReplyPacket reply = new JdwpReplyPacket(commandPkt);
        
        // Reset our output stream
        _outputBytes.reset();
        
        // Create a ByteBuffer around the command packet 
        ByteBuffer bb = ByteBuffer.wrap(commandPkt.getData());
        byte command = commandPkt.getCommand();
        byte commandSet = commandPkt.getCommandSet();
        
        CommandSet set = null;
        try
          {
            // There is no command set with value 0
            if (commandSet > 0 && commandSet < _sets.length)
              {
                set = _sets[commandPkt.getCommandSet()];
              }
            if (set != null) 
              {
                _shutdown = set.runCommand(bb, _os, command);
                reply.setData(_outputBytes.toByteArray());
              }
            else
              {
                // This command set wasn't in our tree
                reply.setErrorCode(JdwpConstants.Error.NOT_IMPLEMENTED);
              }
          }
          catch (JdwpException ex)
            {
            reply.setErrorCode(ex.getErrorCode ());
            }
          _connection.sendPacket (reply);
      }
  }
}
