/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.debugger.remote;

import java.rmi.*;
import java.util.*;
import java.lang.reflect.*;

import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.remote.sparc.*;
import sun.jvm.hotspot.debugger.remote.x86.*;
import sun.jvm.hotspot.debugger.remote.amd64.*;

/** An implementation of Debugger which wraps a
    RemoteDebugger, providing remote debugging via RMI.
    This implementation provides caching of the remote process's
    address space on the local machine where the user interface is
    running. */

public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
  private RemoteDebugger remoteDebugger;
  private RemoteThreadFactory threadFactory;
  private boolean unalignedAccessesOkay = false;
  private static final int cacheSize = 16 * 1024 * 1024; // 16 MB

  public RemoteDebuggerClient(RemoteDebugger remoteDebugger) throws DebuggerException {
    super();
    try {
      this.remoteDebugger = remoteDebugger;
      machDesc = remoteDebugger.getMachineDescription();
      utils = new DebuggerUtilities(machDesc.getAddressSize(), machDesc.isBigEndian());
      int cacheNumPages;
      int cachePageSize;
      String cpu = remoteDebugger.getCPU();
      // page size. (FIXME: should pick this up from the remoteDebugger.)
      if (cpu.equals("sparc")) {
        threadFactory = new RemoteSPARCThreadFactory(this);
        cachePageSize = 8192;
        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
      } else if (cpu.equals("x86")) {
        threadFactory = new RemoteX86ThreadFactory(this);
        cachePageSize = 4096;
        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
        unalignedAccessesOkay = true;
      } else if (cpu.equals("amd64") || cpu.equals("x86_64")) {
        threadFactory = new RemoteAMD64ThreadFactory(this);
        cachePageSize = 4096;
        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
        unalignedAccessesOkay = true;
      } else {
        try {
          Class tf = Class.forName("sun.jvm.hotspot.debugger.remote." +
            cpu.toLowerCase() + ".Remote" + cpu.toUpperCase() +
            "ThreadFactory");
          Constructor[] ctf = tf.getConstructors();
          threadFactory = (RemoteThreadFactory)ctf[0].newInstance(this);
        } catch (Exception e) {
          throw new DebuggerException("Thread access for CPU architecture " + cpu + " not yet supported");
        }
        cachePageSize = 4096;
        cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
        unalignedAccessesOkay = false;
      }

      // Cache portion of the remote process's address space.
      initCache(cachePageSize, cacheNumPages);

      jbooleanSize = remoteDebugger.getJBooleanSize();
      jbyteSize    = remoteDebugger.getJByteSize();
      jcharSize    = remoteDebugger.getJCharSize();
      jdoubleSize  = remoteDebugger.getJDoubleSize();
      jfloatSize   = remoteDebugger.getJFloatSize();
      jintSize     = remoteDebugger.getJIntSize();
      jlongSize    = remoteDebugger.getJLongSize();
      jshortSize   = remoteDebugger.getJShortSize();
      javaPrimitiveTypesConfigured = true;
      narrowOopBase  = remoteDebugger.getNarrowOopBase();
      narrowOopShift = remoteDebugger.getNarrowOopShift();
      narrowKlassBase  = remoteDebugger.getNarrowKlassBase();
      narrowKlassShift = remoteDebugger.getNarrowKlassShift();
      heapOopSize  = remoteDebugger.getHeapOopSize();
      klassPtrSize  = remoteDebugger.getKlassPtrSize();
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public long[] getThreadIntegerRegisterSet(Address addr) {
    try {
      return remoteDebugger.getThreadIntegerRegisterSet(getAddressValue(addr), true);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public long[] getThreadIntegerRegisterSet(long id) {
    try {
      return remoteDebugger.getThreadIntegerRegisterSet(id, false);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
  public boolean hasProcessList() throws DebuggerException {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
  public List getProcessList() throws DebuggerException {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
  public void attach(int processID) throws DebuggerException {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  /** Unimplemented in this class (remote remoteDebugger should already be attached) */
  public void attach(String executableName, String coreFileName) throws DebuggerException {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  /** Unimplemented in this class (remote remoteDebugger can not be detached) */
  public boolean detach() {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  public Address parseAddress(String addressString) throws NumberFormatException {
    long addr = utils.scanAddress(addressString);
    if (addr == 0) {
      return null;
    }
    return new RemoteAddress(this, addr);
  }

  public String getOS() throws DebuggerException {
    try {
      return remoteDebugger.getOS();
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public String getCPU() {
    try {
      return remoteDebugger.getCPU();
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public boolean hasConsole() throws DebuggerException {
    try {
       return remoteDebugger.hasConsole();
    } catch (RemoteException e) {
       throw new DebuggerException(e);
    }
  }

  public String consoleExecuteCommand(String cmd) throws DebuggerException {
    try {
      return remoteDebugger.consoleExecuteCommand(cmd);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public String getConsolePrompt() throws DebuggerException {
    try {
      return remoteDebugger.getConsolePrompt();
    } catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public CDebugger getCDebugger() throws DebuggerException {
    return null;
  }

  //--------------------------------------------------------------------------------
  // Implementation of SymbolLookup interface

  public Address lookup(String objectName, String symbol) {
    try {
      long addr = remoteDebugger.lookupInProcess(objectName, symbol);
      if (addr == 0) {
        return null;
      }
      return new RemoteAddress(this, addr);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public OopHandle lookupOop(String objectName, String symbol) {
    try {
      long addr = remoteDebugger.lookupInProcess(objectName, symbol);
      if (addr == 0) {
        return null;
      }
      return new RemoteOopHandle(this, addr);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  /** Need to override this to relax alignment checks on x86. */
  public long readCInteger(long address, long numBytes, boolean isUnsigned)
    throws UnmappedAddressException, UnalignedAddressException {
    if (!unalignedAccessesOkay) {
      utils.checkAlignment(address, numBytes);
    } else {
      // Only slightly relaxed semantics -- this is a hack, but is
      // necessary on x86 where it seems the compiler is
      // putting some global 64-bit data on 32-bit boundaries
      if (numBytes == 8) {
        utils.checkAlignment(address, 4);
      } else {
        utils.checkAlignment(address, numBytes);
      }
    }
    byte[] data = readBytes(address, numBytes);
    return utils.dataToCInteger(data, isUnsigned);
  }

  // Overridden from DebuggerBase because we need to relax alignment
  // constraints on x86
  public long readJLong(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    // FIXME: allow this to be configurable. Undesirable to add a
    // dependency on the runtime package here, though, since this
    // package should be strictly underneath it.
    if (unalignedAccessesOkay) {
      utils.checkAlignment(address, jintSize);
    } else {
      utils.checkAlignment(address, jlongSize);
    }
    byte[] data = readBytes(address, jlongSize);
    return utils.dataToJLong(data, jlongSize);
  }


  //--------------------------------------------------------------------------------
  // Implementation of JVMDebugger interface
  //

  /** Unimplemented in this class (remote remoteDebugger should already be configured) */
  public void configureJavaPrimitiveTypeSizes(long jbooleanSize,
                                              long jbyteSize,
                                              long jcharSize,
                                              long jdoubleSize,
                                              long jfloatSize,
                                              long jintSize,
                                              long jlongSize,
                                              long jshortSize) {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  public void setMachineDescription(MachineDescription machDesc) {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  public int getRemoteProcessAddressSize() {
    throw new DebuggerException("Should not be called on RemoteDebuggerClient");
  }

  public String addressValueToString(long addr) {
    return utils.addressValueToString(addr);
  }

  public long getAddressValue(Address addr) throws DebuggerException {
    if (addr == null) return 0;
    return ((RemoteAddress) addr).getValue();
  }

  public Address newAddress(long value) {
    if (value == 0) return null;
    return new RemoteAddress(this, value);
  }

  RemoteAddress readAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    long value = readAddressValue(address);
    return (value == 0 ? null : new RemoteAddress(this, value));
  }

  RemoteAddress readCompOopAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    long value = readCompOopAddressValue(address);
    return (value == 0 ? null : new RemoteAddress(this, value));
  }

  RemoteAddress readCompKlassAddress(long address)
    throws UnmappedAddressException, UnalignedAddressException {
    long value = readCompKlassAddressValue(address);
    return (value == 0 ? null : new RemoteAddress(this, value));
  }

  RemoteOopHandle readOopHandle(long address)
    throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
    long value = readAddressValue(address);
    return (value == 0 ? null : new RemoteOopHandle(this, value));
  }

  RemoteOopHandle readCompOopHandle(long address)
    throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
    long value = readCompOopAddressValue(address);
    return (value == 0 ? null : new RemoteOopHandle(this, value));
  }

  boolean areThreadsEqual(Address addr1, Address addr2) {
    try {
       return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true,
                                             getAddressValue(addr2), true);
    } catch (RemoteException e) {
    }
    return false;
  }

  boolean areThreadsEqual(long id1, long id2) {
    try {
       return remoteDebugger.areThreadsEqual(id1, false, id2, false);
    } catch (RemoteException e) {
    }
    return false;
  }

  boolean areThreadsEqual(Address addr1, long id2) {
    try {
       return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true, id2, false);
    } catch (RemoteException e) {
    }
    return false;
  }

  boolean areThreadsEqual(long id1, Address addr2) {
    try {
       return remoteDebugger.areThreadsEqual(id1, false, getAddressValue(addr2), true);
    } catch (RemoteException e) {
    }
    return false;
  }

  int getThreadHashCode(Address a) {
    try {
       return remoteDebugger.getThreadHashCode(getAddressValue(a), true);
    } catch (RemoteException e) {
    }
    return a.hashCode();
  }

  int getThreadHashCode(long id) {
    try {
       return remoteDebugger.getThreadHashCode(id, false);
    } catch (RemoteException e) {
    }
    return (int) id;
  }

  public ThreadProxy getThreadForIdentifierAddress(Address addr) {
     return threadFactory.createThreadWrapper(addr);
  }

  public ThreadProxy getThreadForThreadId(long id) {
     return threadFactory.createThreadWrapper(id);
  }

  public MachineDescription getMachineDescription() throws DebuggerException {
     return machDesc;
  }

  /** This reads bytes from the remote process. */
  public ReadResult readBytesFromProcess(long address, long numBytes) {
    try {
      return remoteDebugger.readBytesFromProcess(address, numBytes);
    }
    catch (RemoteException e) {
      throw new DebuggerException(e);
    }
  }

  public void writeBytesToProcess(long a, long b, byte[] c) {
     throw new DebuggerException("Unimplemented!");
  }
}
