/*
 * Copyright (c) 2002, 2013, 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.tools;

import java.io.PrintStream;

import sun.jvm.hotspot.HotSpotAgent;
import sun.jvm.hotspot.debugger.DebuggerException;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.runtime.VM;

// generic command line or GUI tool.
// override run & code main as shown below.

public abstract class Tool implements Runnable {
   private HotSpotAgent agent;
   private JVMDebugger jvmDebugger;
   private int debugeeType;

   // debugeeType is one of constants below
   protected static final int DEBUGEE_PID    = 0;
   protected static final int DEBUGEE_CORE   = 1;
   protected static final int DEBUGEE_REMOTE = 2;

   public Tool() {
   }

   public Tool(JVMDebugger d) {
      jvmDebugger = d;
   }

   public String getName() {
      return getClass().getName();
   }

   protected boolean needsJavaPrefix() {
      return true;
   }

   protected void setAgent(HotSpotAgent a) {
      agent = a;
   }

   protected void setDebugeeType(int dt) {
      debugeeType = dt;
   }

   protected HotSpotAgent getAgent() {
      return agent;
   }

   protected int getDebugeeType() {
      return debugeeType;
   }

   protected void printUsage() {
      String name = null;
      if (needsJavaPrefix()) {
         name = "java " + getName();
      } else {
         name = getName();
      }
      System.out.println("Usage: " + name + " [option] <pid>");
      System.out.println("\t\t(to connect to a live java process)");
      System.out.println("   or " + name + " [option] <executable> <core>");
      System.out.println("\t\t(to connect to a core file)");
      System.out.println("   or " + name + " [option] [server_id@]<remote server IP or hostname>");
      System.out.println("\t\t(to connect to a remote debug server)");
      System.out.println();
      System.out.println("where option must be one of:");
      printFlagsUsage();
   }

   protected void printFlagsUsage() {
       System.out.println("    -h | -help\tto print this help message");
   }

   protected void usage() {
      printUsage();
   }

   /*
      Derived class main should be of the following form:

      public static void main(String[] args) {
         <derived class> obj = new <derived class>;
         obj.execute(args);
      }

   */

   protected void execute(String[] args) {
       int returnStatus = 1;

       try {
           returnStatus = start(args);
       } finally {
           stop();
       }

       // Exit with 0 or 1
       System.exit(returnStatus);
   }

   public void stop() {
      if (agent != null) {
         agent.detach();
      }
   }

   private int start(String[] args) {

      if ((args.length < 1) || (args.length > 2)) {
         usage();
         return 1;
      }

      // Attempt to handle -h or -help or some invalid flag
      if (args[0].startsWith("-h")) {
          usage();
          return 0;
      } else if (args[0].startsWith("-")) {
          usage();
          return 1;
      }

      PrintStream err = System.err;
      PrintStream out = System.out;

      int pid = 0;
      String coreFileName   = null;
      String executableName = null;
      String remoteServer   = null;

      switch (args.length) {
        case 1:
           try {
              pid = Integer.parseInt(args[0]);
              debugeeType = DEBUGEE_PID;
           } catch (NumberFormatException e) {
              // try remote server
              remoteServer = args[0];
              debugeeType  = DEBUGEE_REMOTE;
           }
           break;

        case 2:
           executableName = args[0];
           coreFileName   = args[1];
           debugeeType    = DEBUGEE_CORE;
           break;

        default:
           usage();
           return 1;
      }

      agent = new HotSpotAgent();
      try {
        switch (debugeeType) {
          case DEBUGEE_PID:
             out.println("Attaching to process ID " + pid + ", please wait...");
             agent.attach(pid);
             break;

          case DEBUGEE_CORE:
             out.println("Attaching to core " + coreFileName +
                         " from executable " + executableName + ", please wait...");
             agent.attach(executableName, coreFileName);
             break;

          case DEBUGEE_REMOTE:
             out.println("Attaching to remote server " + remoteServer + ", please wait...");
             agent.attach(remoteServer);
             break;
        }
      }
      catch (DebuggerException e) {
        switch (debugeeType) {
          case DEBUGEE_PID:
             err.print("Error attaching to process: ");
             break;

          case DEBUGEE_CORE:
             err.print("Error attaching to core file: ");
             break;

          case DEBUGEE_REMOTE:
             err.print("Error attaching to remote server: ");
             break;
        }
        if (e.getMessage() != null) {
          err.println(e.getMessage());
          e.printStackTrace();
        }
        err.println();
        return 1;
      }

      out.println("Debugger attached successfully.");
      startInternal();
      return 0;
   }

   // When using an existing JVMDebugger.
   public void start() {

      if (jvmDebugger == null) {
         throw new RuntimeException("Tool.start() called with no JVMDebugger set.");
      }
      agent = new HotSpotAgent();
      agent.attach(jvmDebugger);
      startInternal();
   }

   // Remains of the start mechanism, common to both start methods.
   private void startInternal() {

      PrintStream out = System.out;
      VM vm = VM.getVM();
      if (vm.isCore()) {
        out.println("Core build detected.");
      } else if (vm.isClientCompiler()) {
        out.println("Client compiler detected.");
      } else if (vm.isServerCompiler()) {
        out.println("Server compiler detected.");
      } else {
        throw new RuntimeException("Fatal error: "
            + "should have been able to detect core/C1/C2 build");
      }

      String version = vm.getVMRelease();
      if (version != null) {
        out.print("JVM version is ");
        out.println(version);
      }

      run();
   }
}
