/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.debug.core.zend.debugger;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.Enumeration;
import java.util.Hashtable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.php.debug.core.debugger.parameters.IDebugParametersInitializer;
import org.eclipse.php.debug.core.debugger.parameters.IWebDebugParametersInitializer;
import org.eclipse.php.internal.debug.core.*;
import org.eclipse.php.internal.debug.core.launching.PHPLaunch;
import org.eclipse.php.internal.debug.core.launching.PHPLaunchUtilities;
import org.eclipse.php.internal.debug.daemon.DaemonPlugin;
/**
* A debug session initializer. There are two ways to initialize debug session
* (configurable in launch configuration dialog):
* <ul>
* <li>Open an internal Web browser that will issue a request to the debug
* server</li>
* <li>Use URL connection to send the request to the the debug server directly
* </li>
* </ul>
*/
@SuppressWarnings("restriction")
public class PHPWebServerDebuggerInitializer implements IDebuggerInitializer {
private static final String URL_ENCODING = "UTF-8"; //$NON-NLS-1$
public void debug(ILaunch launch) throws DebugException {
DaemonPlugin.getDefault().makeSureDebuggerInitialized(null);
IDebugParametersInitializer parametersInitializer = DebugParametersInitializersRegistry
.getBestMatchDebugParametersInitializer(launch);
if (launch instanceof PHPLaunch) {
((PHPLaunch) launch).pretendRunning(true);
}
boolean openInBrowser = false;
try {
openInBrowser = launch.getLaunchConfiguration().getAttribute(IPHPDebugConstants.OPEN_IN_BROWSER, false);
} catch (CoreException e) {
// Should not happened
}
try {
if (openInBrowser) {
openBrowser(launch, parametersInitializer);
} else {
openUrlConnection(launch, parametersInitializer);
}
} finally {
if (launch instanceof PHPLaunch)
((PHPLaunch) launch).pretendRunning(false);
}
}
/**
* Start the debug session by opening a browser that will actually trigger
* the URL connection to the debug server (with Zend Debugger installed).
*
* @param launch
* @param parametersInitializer
* @throws DebugException
*/
protected void openBrowser(ILaunch launch, IDebugParametersInitializer parametersInitializer)
throws DebugException {
boolean runWithDebug = true;
try {
runWithDebug = launch.getLaunchConfiguration().getAttribute(IPHPDebugConstants.RUN_WITH_DEBUG_INFO, true);
} catch (CoreException e) {
// Should not happen
}
URL requestURL = parametersInitializer.getRequestURL(launch);
String launchURL = requestURL.toString();
if (runWithDebug && !ILaunchManager.RUN_MODE.equals(launch.getLaunchMode())) {
String query = PHPLaunchUtilities.generateQuery(launch, parametersInitializer);
if (launchURL.indexOf('?') == -1) {
launchURL = launchURL + '?' + query;
} else {
launchURL = launchURL + '&' + query;
}
}
PHPDebugUtil.openLaunchURL(launchURL);
}
/**
* Issue the request to the debug server using URL connection mechanism
*
* @param launch
* @param parametersInitializer
* @throws DebugException
*/
protected void openUrlConnection(ILaunch launch, IDebugParametersInitializer parametersInitializer)
throws DebugException {
URL requestURL = parametersInitializer.getRequestURL(launch);
try {
// We only support this kind of debug session initializer here:
if (parametersInitializer instanceof IWebDebugParametersInitializer) {
IWebDebugParametersInitializer webParametersInitializer = (IWebDebugParametersInitializer) parametersInitializer;
StringBuilder getParams = new StringBuilder("?"); //$NON-NLS-1$
// Initialize debug parameters (using cookies):
Hashtable<String, String> debugParameters = parametersInitializer.getDebugParameters(launch);
if (debugParameters != null) {
Enumeration<String> k = debugParameters.keys();
while (k.hasMoreElements()) {
String key = k.nextElement();
String value = debugParameters.get(key);
getParams.append(URLEncoder.encode(key, URL_ENCODING)).append('=')
.append(URLEncoder.encode(value, URL_ENCODING));
if (k.hasMoreElements()) {
getParams.append('&');
}
}
}
// Initialize with additional GET parameters
String requestMethod = webParametersInitializer.getRequestMethod(launch);
if (IWebDebugParametersInitializer.GET_METHOD.equals(requestMethod)) {
Hashtable<String, String> requestParameters = webParametersInitializer.getRequestParameters(launch);
if (requestParameters != null) {
Enumeration<String> k = requestParameters.keys();
while (k.hasMoreElements()) {
String key = k.nextElement();
String value = requestParameters.get(key);
getParams.append('&');
getParams.append(URLEncoder.encode(key, URL_ENCODING)).append('=')
.append(URLEncoder.encode(value, URL_ENCODING));
}
}
}
requestURL = new URL(requestURL.getProtocol(), requestURL.getHost(), requestURL.getPort(),
requestURL.getPath() + getParams.toString());
// Open the connection:
if (PHPDebugPlugin.DEBUG) {
System.out.println("Opening URL connection: " //$NON-NLS-1$
+ requestURL.toString());
}
HttpURLConnection urlConection = (HttpURLConnection) requestURL.openConnection();
urlConection.setDoInput(true);
urlConection.setDoOutput(true);
if (requestMethod != null) {
urlConection.setRequestMethod(requestMethod);
}
// Add additional headers
Hashtable<String, String> headers = webParametersInitializer.getRequestHeaders(launch);
if (headers != null) {
Enumeration<String> k = headers.keys();
while (k.hasMoreElements()) {
String key = k.nextElement();
String value = URLEncoder.encode(headers.get(key), URL_ENCODING);
if (PHPDebugPlugin.DEBUG) {
System.out.println("Adding HTTP header: " + key //$NON-NLS-1$
+ "=" + value); //$NON-NLS-1$
}
urlConection.addRequestProperty(key, value);
}
}
// Set cookies
Hashtable<String, String> cookies = webParametersInitializer.getRequestCookies(launch);
if (cookies != null) {
StringBuilder cookieBuf = new StringBuilder();
Enumeration<String> k = cookies.keys();
while (k.hasMoreElements()) {
String key = k.nextElement();
String value = cookies.get(key);
cookieBuf.append(URLEncoder.encode(key, URL_ENCODING)).append('=')
.append(URLEncoder.encode(value, URL_ENCODING));
if (k.hasMoreElements()) {
cookieBuf.append("; "); //$NON-NLS-1$
}
}
if (PHPDebugPlugin.DEBUG) {
System.out.println("Setting cookies: " //$NON-NLS-1$
+ cookieBuf.toString());
}
urlConection.addRequestProperty("Cookie", //$NON-NLS-1$
cookieBuf.toString());
}
DataOutputStream outputStream = new DataOutputStream(urlConection.getOutputStream());
try {
// Initialize with additional POST parameters
if (requestMethod == IWebDebugParametersInitializer.POST_METHOD) {
Hashtable<String, String> requestParameters = webParametersInitializer
.getRequestParameters(launch);
if (requestParameters != null) {
StringBuilder postParams = new StringBuilder();
Enumeration<String> k = requestParameters.keys();
while (k.hasMoreElements()) {
String key = k.nextElement();
String value = requestParameters.get(key);
postParams.append(URLEncoder.encode(key, URL_ENCODING)).append('=')
.append(URLEncoder.encode(value, URL_ENCODING));
if (k.hasMoreElements()) {
postParams.append('&');
}
}
outputStream.writeBytes(postParams.toString());
}
}
// Add raw data
String rawData = webParametersInitializer.getRequestRawData(launch);
if (rawData != null) {
outputStream.writeBytes(rawData);
}
} finally {
outputStream.flush();
outputStream.close();
}
String headerKey = urlConection.getHeaderFieldKey(1);
if (headerKey == null) {
Logger.log(Logger.WARNING, "No HeaderKey returned by server. Most likely not started"); //$NON-NLS-1$
String errorMessage = PHPDebugCoreMessages.DebuggerConnection_Problem_1;
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, null));
}
for (int i = 1; (headerKey = urlConection.getHeaderFieldKey(i)) != null; i++) {
if (headerKey.equals("X-Zend-Debug-Server")) { //$NON-NLS-1$
String headerValue = urlConection.getHeaderField(headerKey);
if (!headerValue.equals("OK")) { //$NON-NLS-1$
Logger.log(Logger.WARNING, "Unexpected Header Value returned by Server. " //$NON-NLS-1$
+ headerValue);
String errorMessage = PHPDebugCoreMessages.DebuggerConnection_Problem_2 + " - " //$NON-NLS-1$
+ headerValue;
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, null));
}
break;
}
}
InputStream inputStream = urlConection.getInputStream();
while (inputStream.read() != -1) {
// do nothing on the content returned by standard stream
}
inputStream.close();
}
} catch (UnknownHostException e) {
String errorMessage = PHPDebugCoreMessages.DebuggerConnection_Problem_4 + requestURL.getHost();
Logger.logException(errorMessage, e);
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, e));
} catch (ConnectException e) {
String errorMessage = PHPDebugCoreMessages.DebuggerConnection_Problem_5
+ requestURL.toString().substring(0, requestURL.toString().indexOf('?'));
Logger.logException(errorMessage, e);
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, e));
} catch (IOException e) {
String errorMessage = PHPDebugCoreMessages.DebuggerConnection_Problem_5
+ requestURL.toString().substring(0, requestURL.toString().indexOf('?'));
Logger.logException(errorMessage, e);
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, e));
} catch (Exception e) {
Logger.logException("Unexpected exception communicating with Web server", e); //$NON-NLS-1$
String errorMessage = e.getMessage();
throw new DebugException(new Status(IStatus.ERROR, PHPDebugPlugin.getID(),
IPHPDebugConstants.INTERNAL_ERROR, errorMessage, e));
}
}
}