001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdi.internal.connect;
011:
012: import java.io.IOException;
013: import java.io.InterruptedIOException;
014: import com.ibm.icu.text.MessageFormat;
015: import java.util.HashMap;
016: import java.util.Map;
017:
018: import org.eclipse.jdi.internal.VirtualMachineImpl;
019: import org.eclipse.jdi.internal.VirtualMachineManagerImpl;
020:
021: import com.sun.jdi.VirtualMachine;
022: import com.sun.jdi.connect.Connector;
023: import com.sun.jdi.connect.IllegalConnectorArgumentsException;
024: import com.sun.jdi.connect.LaunchingConnector;
025: import com.sun.jdi.connect.VMStartException;
026:
027: public class SocketRawLaunchingConnectorImpl extends ConnectorImpl
028: implements LaunchingConnector {
029: /** Time that a launched VM is given to connect to us. */
030: private static final int ACCEPT_TIMEOUT = 10000;
031:
032: /** Raw command to start the debugged application VM. */
033: private String fCommand;
034: /** Address from which to listen for a connection after the raw command is run. */
035: private String fAddress;
036:
037: /**
038: * Creates new SocketAttachingConnectorImpl.
039: */
040: public SocketRawLaunchingConnectorImpl(
041: VirtualMachineManagerImpl virtualMachineManager) {
042: super (virtualMachineManager);
043:
044: // Create communication protocol specific transport.
045: SocketTransportImpl transport = new SocketTransportImpl();
046: setTransport(transport);
047: }
048:
049: /**
050: * @return Returns the default arguments.
051: */
052: public Map defaultArguments() {
053: HashMap arguments = new HashMap(3);
054:
055: // Command
056: StringArgumentImpl strArg = new StringArgumentImpl(
057: "command", ConnectMessages.SocketRawLaunchingConnectorImpl_Raw_command_to_start_the_debugged_application_VM_1, ConnectMessages.SocketRawLaunchingConnectorImpl_Command_2, true); //$NON-NLS-1$
058: arguments.put(strArg.name(), strArg);
059:
060: // Address
061: strArg = new StringArgumentImpl(
062: "address", ConnectMessages.SocketRawLaunchingConnectorImpl_Address_from_which_to_listen_for_a_connection_after_the_raw_command_is_run_3, ConnectMessages.SocketRawLaunchingConnectorImpl_Address_4, true); //$NON-NLS-1$
063: arguments.put(strArg.name(), strArg);
064:
065: // Quote
066: strArg = new StringArgumentImpl(
067: "quote", ConnectMessages.SocketRawLaunchingConnectorImpl_Character_used_to_combine_space_delimited_text_into_a_single_command_line_argument_5, ConnectMessages.SocketRawLaunchingConnectorImpl_Quote_6, true); //$NON-NLS-1$
068: strArg.setValue("\""); //$NON-NLS-1$
069: arguments.put(strArg.name(), strArg);
070:
071: return arguments;
072: }
073:
074: /**
075: * @return Returns a short identifier for the connector.
076: */
077: public String name() {
078: return "com.sun.jdi.RawCommandLineLaunch"; //$NON-NLS-1$
079: }
080:
081: /**
082: * @return Returns a human-readable description of this connector and its purpose.
083: */
084: public String description() {
085: return ConnectMessages.SocketRawLaunchingConnectorImpl_Launches_target_using_user_specified_command_line_and_attaches_to_it_7;
086: }
087:
088: /**
089: * Retrieves connection arguments.
090: */
091: private void getConnectionArguments(Map connectionArgs)
092: throws IllegalConnectorArgumentsException {
093: String attribute = ""; //$NON-NLS-1$
094: try {
095: attribute = "command"; //$NON-NLS-1$
096: fCommand = ((Connector.StringArgument) connectionArgs
097: .get(attribute)).value();
098: attribute = "address"; //$NON-NLS-1$
099: fAddress = ((Connector.StringArgument) connectionArgs
100: .get(attribute)).value();
101: attribute = "quote"; //$NON-NLS-1$
102: ((Connector.StringArgument) connectionArgs.get(attribute))
103: .value();
104: } catch (ClassCastException e) {
105: throw new IllegalConnectorArgumentsException(
106: ConnectMessages.SocketRawLaunchingConnectorImpl_Connection_argument_is_not_of_the_right_type_8,
107: attribute);
108: } catch (NullPointerException e) {
109: throw new IllegalConnectorArgumentsException(
110: ConnectMessages.SocketRawLaunchingConnectorImpl_Necessary_connection_argument_is_null_9,
111: attribute);
112: } catch (NumberFormatException e) {
113: throw new IllegalConnectorArgumentsException(
114: ConnectMessages.SocketRawLaunchingConnectorImpl_Connection_argument_is_not_a_number_10,
115: attribute);
116: }
117: }
118:
119: /**
120: * Launches an application and connects to its VM.
121: * @return Returns a connected Virtual Machine.
122: */
123: public VirtualMachine launch(Map connectionArgs)
124: throws IOException, IllegalConnectorArgumentsException,
125: VMStartException {
126: getConnectionArguments(connectionArgs);
127:
128: // A listening connector is used that waits for a connection of the VM that is started up.
129: // Note that port number zero means that a free port is chosen.
130: SocketListeningConnectorImpl listenConnector = new SocketListeningConnectorImpl(
131: virtualMachineManager());
132: Map args = listenConnector.defaultArguments();
133: ((Connector.IntegerArgument) args.get("port")).setValue(fAddress); //$NON-NLS-1$
134: ((Connector.IntegerArgument) args.get("timeout")).setValue(ACCEPT_TIMEOUT); //$NON-NLS-1$
135: listenConnector.startListening(args);
136:
137: // Start VM.
138: Process proc = Runtime.getRuntime().exec(fCommand);
139:
140: // The accept times out it the VM does not connect.
141: VirtualMachineImpl virtualMachine;
142: try {
143: virtualMachine = (VirtualMachineImpl) listenConnector
144: .accept(args);
145: } catch (InterruptedIOException e) {
146: proc.destroy();
147: String message = MessageFormat
148: .format(
149: ConnectMessages.SocketLaunchingConnectorImpl_VM_did_not_connect_within_given_time___0__ms_1,
150: new String[] { ((Connector.IntegerArgument) args
151: .get("timeout")).value() }); //$NON-NLS-1$
152: throw new VMStartException(message, proc);
153: }
154:
155: virtualMachine.setLaunchedProcess(proc);
156: return virtualMachine;
157: }
158: }
|