blob: bba1d827b1c1aea7a1da53c6d644838c08a3694f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.crossfire.connect;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.jsdt.debug.core.jsdi.VirtualMachine;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.AttachingConnector;
import org.eclipse.wst.jsdt.debug.internal.crossfire.jsdi.CFVirtualMachine;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.CFTransportService;
import org.eclipse.wst.jsdt.debug.internal.crossfire.transport.JSON;
import org.eclipse.wst.jsdt.debug.transport.Connection;
import org.eclipse.wst.jsdt.debug.transport.DebugSession;
import org.eclipse.wst.jsdt.debug.transport.TransportService;
/**
* Attaching connector for Crossfire
*
* @since 1.0
*/
public class CrossfireAttachingConnector implements AttachingConnector {
public static final String CROSSFIRE_REMOTE_ATTACH_CONNECTOR_ID = "crossfire.remote.attach.connector"; //$NON-NLS-1$
/**
* Constructor
*/
public CrossfireAttachingConnector() {
}
/*
* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector#defaultArguments()
*/
public Map defaultArguments() {
HashMap args = new HashMap(5);
args.put(HostArgument.HOST, new HostArgument(null));
args.put(PortArgument.PORT, new PortArgument(5000));
args.put(TimeoutArgument.TIMEOUT, new TimeoutArgument());
args.put(CompatArgument.PRE03, new CompatArgument());
//XXX hack because there is no good way to find the Firefox executable on Win
if(!Platform.OS_WIN32.equals(Platform.getOS())) {
args.put(BrowserArgument.BROWSER, new BrowserArgument());
}
return args;
}
/*
* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector#description()
*/
public String description() {
return Messages.attach_connector_desc;
}
/*
* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector#name()
*/
public String name() {
return Messages.crossfire_remote_attach;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector#id()
*/
public String id() {
return CROSSFIRE_REMOTE_ATTACH_CONNECTOR_ID;
}
/*
* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.core.jsdi.connect.AttachingConnector#attach
* (java.util.Map)
*/
public VirtualMachine attach(Map arguments) throws IOException {
String str = (String) arguments.get(BrowserArgument.BROWSER);
//XXX hack because there is no good way to find the Firefox executable on Win
boolean browser = Boolean.valueOf(str).booleanValue() && !Platform.OS_WIN32.equals(Platform.getOS());
if (browser && !HostArgument.isLocalhost((String) arguments.get(HostArgument.HOST))) {
// we cannot auto launch the browser on a different host
throw new IOException(Messages.cannot_launch_browser_not_localhost);
}
Connection c = null;
if (browser) {
c = launchForBrowser(arguments);
} else {
c = launch(arguments);
}
DebugSession session = new DebugSession(c);
String pre03 = (String) arguments.get(CompatArgument.PRE03);
if(pre03 != null) {
JSON.setPre03Compat(Boolean.valueOf(pre03).booleanValue());
}
return new CFVirtualMachine(session);
}
/**
* Launches the browser and connects to it. This method will poll for the
* browser to be launched but only for a fixed timeout.
*
* @param arguments
* @return the created connection or <code>null</code> if the attempt to
* connect times out, the browser process terminates before we can
* connect
* @throws IOException
*/
Connection launchForBrowser(final Map arguments) throws IOException {
String host = (String) arguments.get(HostArgument.HOST);
String port = (String) arguments.get(PortArgument.PORT);
StringBuffer buffer = new StringBuffer("firefox -ProfileManager -load-fb-modules -crossfire-server-port ").append(port); //$NON-NLS-1$
Process p = Runtime.getRuntime().exec(buffer.toString());
TransportService service = new CFTransportService();
String timeoutstr = (String) arguments.get(TimeoutArgument.TIMEOUT);
int timeout = Integer.parseInt(timeoutstr);
buffer = new StringBuffer();
buffer.append(host).append(':').append(Integer.parseInt(port));
long timer = System.currentTimeMillis() + 20000;
Connection c = null;
while (p != null && System.currentTimeMillis() < timer && c == null) {
try {
c = service.attach(buffer.toString(), timeout,timeout);
} catch (IOException ioe) {
// ignore while pinging to connect
try {
Thread.sleep(200);
} catch (InterruptedException e) {
//do nothing
}
}
}
if (c == null) {
throw new IOException(NLS.bind(Messages.failed_to_attach_to_auto_browser, new String[] {host, port }));
}
return c;
}
/**
* Tries to connect to the given
*
* @param arguments
* @return the {@link Connection} or throws an exception
* @throws IOException
*/
Connection launch(Map arguments) throws IOException {
TransportService service = new CFTransportService();
String host = (String) arguments.get(HostArgument.HOST);
String port = (String) arguments.get(PortArgument.PORT);
String timeoutstr = (String) arguments.get(TimeoutArgument.TIMEOUT);
int timeout = Integer.parseInt(timeoutstr);
StringBuffer buffer = new StringBuffer();
buffer.append(host).append(':').append(Integer.parseInt(port));
return service.attach(buffer.toString(), timeout, timeout);
}
}