Use Tree Navigation
public class

SunCommandLineLauncher

extends Object
implements Connector LaunchingConnector
/*
 * Copyright (c) 1998, 2004, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 com.sun.tools.jdi;

import com.sun.tools.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import com.sun.jdi.VirtualMachine;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.io.IOException;
import java.io.File;

public class SunCommandLineLauncher extends AbstractLauncher implements LaunchingConnector {

   
static private final String ARG_HOME = "home";
   
static private final String ARG_OPTIONS = "options";
   
static private final String ARG_MAIN = "main";
   
static private final String ARG_INIT_SUSPEND = "suspend";
   
static private final String ARG_QUOTE = "quote";
   
static private final String ARG_VM_EXEC = "vmexec";

   
TransportService transportService;
   
Transport transport;
   
boolean usingSharedMemory = false;

   
TransportService transportService() {
       
return transportService;
   
}

   
public Transport transport() {
       
return transport;
   
}

   
public SunCommandLineLauncher() {
       
super();

       
/**
         * By default this connector uses either the shared memory
         * transport or the socket transport
         */

       
try {
           
Class c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
            transportService
= (TransportService)c.newInstance();
            transport
= new Transport() {
               
public String name() {
                   
return "dt_shmem";
               
}
           
};
            usingSharedMemory
= true;
       
} catch (ClassNotFoundException x) {
       
} catch (UnsatisfiedLinkError x) {
       
} catch (InstantiationException x) {
       
} catch (IllegalAccessException x) {
       
};
       
if (transportService == null) {
            transportService
= new SocketTransportService();
            transport
= new Transport() {
               
public String name() {
                   
return "dt_socket";
               
}
           
};
       
}

        addStringArgument
(
                ARG_HOME
,
                getString
("sun.home.label"),
                getString
("sun.home"),
               
System.getProperty("java.home"),
               
false);
        addStringArgument
(
                ARG_OPTIONS
,
                getString
("sun.options.label"),
                getString
("sun.options"),
               
"",
               
false);
        addStringArgument
(
                ARG_MAIN
,
                getString
("sun.main.label"),
                getString
("sun.main"),
               
"",
               
true);

        addBooleanArgument
(
                ARG_INIT_SUSPEND
,
                getString
("sun.init_suspend.label"),
                getString
("sun.init_suspend"),
               
true,
               
false);

        addStringArgument
(
                ARG_QUOTE
,
                getString
("sun.quote.label"),
                getString
("sun.quote"),
               
"\"",
               
true);
        addStringArgument
(
                ARG_VM_EXEC
,
                getString
("sun.vm_exec.label"),
                getString
("sun.vm_exec"),
               
"java",
               
true);
   
}

   
static boolean hasWhitespace(String string) {
       
int length = string.length();
       
for (int i = 0; i < length; i++) {
           
if (Character.isWhitespace(string.charAt(i))) {
               
return true;
           
}
       
}
       
return false;
   
}

   
public VirtualMachine
        launch
(Map<String,? extends Connector.Argument> arguments)
       
throws IOException, IllegalConnectorArgumentsException,
               
VMStartException
   
{
       
VirtualMachine vm;

       
String home = argument(ARG_HOME, arguments).value();
       
String options = argument(ARG_OPTIONS, arguments).value();
       
String mainClassAndArgs = argument(ARG_MAIN, arguments).value();
       
boolean wait = ((BooleanArgumentImpl)argument(ARG_INIT_SUSPEND,
                                                  arguments
)).booleanValue();
       
String quote = argument(ARG_QUOTE, arguments).value();
       
String exe = argument(ARG_VM_EXEC, arguments).value();
       
String exePath = null;

       
if (quote.length() > 1) {
           
throw new IllegalConnectorArgumentsException("Invalid length",
                                                         ARG_QUOTE
);
       
}

       
if ((options.indexOf("-Djava.compiler=") != -1) &&
           
(options.toLowerCase().indexOf("-djava.compiler=none") == -1)) {
           
throw new IllegalConnectorArgumentsException("Cannot debug with a JIT compiler",
                                                         ARG_OPTIONS
);
       
}

       
/*
         * Start listening.
         * If we're using the shared memory transport then we pick a
         * random address rather than using the (fixed) default.
         * Random() uses System.currentTimeMillis() as the seed
         * which can be a problem on windows (many calls to
         * currentTimeMillis can return the same value), so
         * we do a few retries if we get an IOException (we
         * assume the IOException is the filename is already in use.)
         */

       
TransportService.ListenKey listenKey;
       
if (usingSharedMemory) {
           
Random rr = new Random();
           
int failCount = 0;
           
while(true) {
               
try {
                   
String address = "javadebug" +
                       
String.valueOf(rr.nextInt(100000));
                    listenKey
= transportService().startListening(address);
                   
break;
               
} catch (IOException ioe) {
                   
if (++failCount > 5) {
                       
throw ioe;
                   
}
               
}
           
}
       
} else {
            listenKey
= transportService().startListening();
       
}
       
String address = listenKey.address();

       
try {
           
if (home.length() > 0) {
               
/*
                 * A wrinkle in the environment:
                 * 64-bit executables are stored under $JAVA_HOME/bin/os_arch
                 * 32-bit executables are stored under $JAVA_HOME/bin
                 */

               
String os_arch = System.getProperty("os.arch");
               
if ("SunOS".equals(System.getProperty("os.name")) &&
                   
("sparcv9".equals(os_arch) || "amd64".equals(os_arch))) {
                    exePath
= home + File.separator + "bin" + File.separator +
                        os_arch
+ File.separator + exe;
               
} else {
                    exePath
= home + File.separator + "bin" + File.separator + exe;
               
}
           
} else {
                exePath
= exe;
           
}
           
// Quote only if necessary in case the quote arg value is bogus
           
if (hasWhitespace(exe)) {
                exePath
= quote + exePath + quote;
           
}

           
String xrun = "transport=" + transport().name() +
                         
",address=" + address +
                         
",suspend=" + (wait? 'y' : 'n');
           
// Quote only if necessary in case the quote arg value is bogus
           
if (hasWhitespace(xrun)) {
                xrun
= quote + xrun + quote;
           
}

           
String command = exePath + ' ' +
                             options
+ ' ' +
                             
"-Xdebug " +
                             
"-Xrunjdwp:" + xrun + ' ' +
                             mainClassAndArgs
;

           
// System.err.println("Command: \"" + command + '"');
            vm
= launch(tokenizeCommand(command, quote.charAt(0)), address, listenKey,
                        transportService
());
       
} finally {
            transportService
().stopListening(listenKey);
       
}

       
return vm;
   
}

   
public String name() {
       
return "com.sun.jdi.CommandLineLaunch";
   
}

   
public String description() {
       
return getString("sun.description");

   
}
}